mirror of
https://gitee.com/technical-laohu/mpay.git
synced 2026-02-14 21:44:27 +08:00
Compare commits
12 Commits
v1.2.2
...
98c90dffcf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98c90dffcf | ||
|
|
e524424628 | ||
|
|
a6b5133cc3 | ||
|
|
748356cc6b | ||
|
|
e4952f6389 | ||
|
|
ba8df721d7 | ||
|
|
a3d15ee7e2 | ||
|
|
2cd473019b | ||
|
|
a8bb0d7513 | ||
|
|
ee49c2a0d0 | ||
|
|
374fc75423 | ||
|
|
fa75d580b8 |
12
.env
12
.env
@@ -1,12 +0,0 @@
|
||||
APP_DEBUG = false
|
||||
|
||||
DB_TYPE = mysql
|
||||
DB_HOST = 127.0.0.1
|
||||
DB_NAME = mpay
|
||||
DB_USER = mpay
|
||||
DB_PASS = 123456
|
||||
DB_PORT = 3306
|
||||
DB_CHARSET = utf8mb4
|
||||
DB_PREFIX = mpay_
|
||||
|
||||
DEFAULT_LANG = zh-cn
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -2,14 +2,12 @@
|
||||
*.env
|
||||
|
||||
extend/*
|
||||
!extend/ImgCaptcha.php
|
||||
!extend/payclient.zip
|
||||
!extend/Plugin.php
|
||||
|
||||
vendor/*
|
||||
!vendor/vendor.zip
|
||||
|
||||
runtime/*
|
||||
|
||||
app/*
|
||||
!app/controller/TestController.php
|
||||
app/controller/TestController.php
|
||||
|
||||
config/extend/*
|
||||
@@ -408,7 +408,7 @@ V免签是一款开源免费适用于个人收款使用的收款程序,原理
|
||||
|
||||
码支付微信PC监听,是老胡使用python写的小工具,可以监听电脑桌面打开的窗口和内容信息,非侵入微信应用内部,版本升级不影响监听。需要将被监听的微信聊天界面单独拖出来成独立窗口。
|
||||
|
||||
[PC监听软件下载wxmonitor_v1.2.zip](assets/20250217_103606_wxmonitor_v1.2.zip)
|
||||
[PC监听软件下载wxmonitor_v1.2.zip](assets/wxmonitor_v1.4.zip)
|
||||
|
||||
##### 配置信息
|
||||
|
||||
|
||||
@@ -132,7 +132,6 @@ class InstallController
|
||||
'user' => 'require',
|
||||
'pass' => 'require',
|
||||
'port' => 'require|integer',
|
||||
'charset' => 'require'
|
||||
];
|
||||
if (!$validate->rule($rule)->check($dbConfig)) {
|
||||
throw new ValidateException($validate->getError());
|
||||
@@ -187,7 +186,6 @@ DB_NAME = {$dbConfig['name']}
|
||||
DB_USER = {$dbConfig['user']}
|
||||
DB_PASS = {$dbConfig['pass']}
|
||||
DB_PORT = {$dbConfig['port']}
|
||||
DB_CHARSET = {$dbConfig['charset']}
|
||||
DB_PREFIX = mpay_
|
||||
|
||||
DEFAULT_LANG = zh-cn
|
||||
@@ -227,8 +225,8 @@ EOT;
|
||||
`order_id` varchar(255) NOT NULL DEFAULT '',
|
||||
`type` varchar(255) NOT NULL DEFAULT '',
|
||||
`out_trade_no` varchar(255) NOT NULL DEFAULT '',
|
||||
`notify_url` varchar(255) NOT NULL DEFAULT '',
|
||||
`return_url` varchar(255) NOT NULL DEFAULT '',
|
||||
`notify_url` varchar(512) NOT NULL DEFAULT '',
|
||||
`return_url` varchar(512) NOT NULL DEFAULT '',
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`really_price` decimal(10, 2) NOT NULL DEFAULT 0.00,
|
||||
`money` decimal(10, 2) NOT NULL DEFAULT 0.00,
|
||||
@@ -240,6 +238,7 @@ EOT;
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
`close_time` datetime DEFAULT NULL,
|
||||
`pay_time` datetime DEFAULT NULL,
|
||||
`platform` varchar(15) NOT NULL DEFAULT '',
|
||||
`platform_order` varchar(255) NOT NULL DEFAULT '',
|
||||
`aid` int(11) NOT NULL DEFAULT 0,
|
||||
`cid` int(11) NOT NULL DEFAULT 0,
|
||||
@@ -258,18 +257,18 @@ EOT;
|
||||
`params` text NOT NULL,
|
||||
`delete_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;",
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;",
|
||||
'mpay_pay_channel' => "CREATE TABLE `mpay_pay_channel` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`account_id` int(11) NOT NULL DEFAULT 0,
|
||||
`channel` varchar(255) NOT NULL DEFAULT '',
|
||||
`type` tinyint(4) NOT NULL DEFAULT 0,
|
||||
`qrcode` varchar(255) NOT NULL DEFAULT '',
|
||||
`qrcode` varchar(512) NOT NULL DEFAULT '',
|
||||
`last_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
`state` tinyint(4) NOT NULL DEFAULT 1,
|
||||
`delete_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;",
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;",
|
||||
'mpay_user' => "CREATE TABLE `mpay_user` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pid` int(11) NOT NULL DEFAULT 0,
|
||||
@@ -282,7 +281,7 @@ EOT;
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
`delete_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;"
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;",
|
||||
];
|
||||
}
|
||||
|
||||
@@ -333,31 +332,4 @@ EOT;
|
||||
throw new \Exception("无法写入安装锁文件");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数据库结构
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
if ($this->checkLock()) {
|
||||
return json(backMsg(1, '已经安装'));
|
||||
}
|
||||
|
||||
$db = $this->connectDatabase();
|
||||
try {
|
||||
$result = $db->query("SHOW COLUMNS FROM `mpay_pay_account` WHERE Field = 'params'");
|
||||
if ($result && $result[0]['Type'] != 'text') {
|
||||
$sql = "ALTER TABLE `mpay_pay_account` MODIFY COLUMN `params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '自定义查询' AFTER `pattern`;";
|
||||
$is_succ = $db->execute($sql);
|
||||
if (!$is_succ) {
|
||||
throw new \Exception("修改 mpay_pay_account 表 params 列类型失败");
|
||||
}
|
||||
}
|
||||
return json(backMsg(0, '数据库结构检查并更新完成'));
|
||||
} catch (\Exception $e) {
|
||||
Log::error("更新数据库结构失败: " . $e->getMessage());
|
||||
return json(backMsg(1, '数据库结构更新失败'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ class PayController
|
||||
foreach ($activeOrders as $order) {
|
||||
// 支付方式核对
|
||||
$is_payway = $order->type == $new_order['payway'];
|
||||
if ($new_order['payway'] == '') $is_payway = true;
|
||||
// 支付渠道核对
|
||||
$is_channel = $cids[$order->cid] == $new_order['channel'];
|
||||
// 金额核对
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace app\controller\api;
|
||||
use app\BaseController;
|
||||
use app\model\PayAccount;
|
||||
use app\model\PayChannel;
|
||||
use \think\facade\Log;
|
||||
|
||||
class PayManageController extends BaseController
|
||||
{
|
||||
@@ -125,30 +126,59 @@ class PayManageController extends BaseController
|
||||
// 上传二维码图片
|
||||
public function uploadQrcode()
|
||||
{
|
||||
$img = $this->request->file('codeimg');
|
||||
if (!$img) {
|
||||
return json(backMsg(1, '请选择要上传的文件'));
|
||||
}
|
||||
// 验证文件类型
|
||||
$allowedTypes = ['image/png', 'image/jpeg', 'image/gif'];
|
||||
$fileMimeType = $img->getMime();
|
||||
if (!in_array($fileMimeType, $allowedTypes)) {
|
||||
return json(backMsg(1, '只允许上传PNG、JPEG或GIF格式的图片'));
|
||||
}
|
||||
// 生成唯一文件名
|
||||
$filename = 'img_' . time() . '_' . uniqid() . '.' . $img->getOriginalExtension();
|
||||
// 设置文件保存路径
|
||||
$path = public_path() . '/files/qrcode/';
|
||||
if (!is_dir($path)) {
|
||||
mkdir($path, 0755, true);
|
||||
}
|
||||
// 移动文件到指定目录
|
||||
$info = $img->move($path, $filename);
|
||||
if ($info) {
|
||||
$imgpath = '/files/qrcode/' . $filename;
|
||||
return json(backMsg(0, '上传成功', ['imgpath' => $imgpath]));
|
||||
} else {
|
||||
return json(backMsg(1, '上传失败'));
|
||||
try {
|
||||
// 获取上传的文件
|
||||
$img = $this->request->file('codeimg');
|
||||
if (!$img) {
|
||||
return json(backMsg(1, '请选择要上传的文件'));
|
||||
}
|
||||
|
||||
// 验证文件大小,防止大文件攻击
|
||||
$maxSize = 2 * 1024 * 1024; // 2MB
|
||||
if ($img->getSize() > $maxSize) {
|
||||
return json(backMsg(1, '文件大小不能超过 2MB'));
|
||||
}
|
||||
|
||||
// 验证文件类型,防止恶意文件上传
|
||||
$allowedTypes = ['image/png', 'image/jpeg', 'image/gif'];
|
||||
$fileMimeType = $img->getMime();
|
||||
if (!in_array($fileMimeType, $allowedTypes)) {
|
||||
return json(backMsg(1, '只允许上传 PNG、JPEG 或 GIF 格式的图片'));
|
||||
}
|
||||
|
||||
// 二次验证文件类型,通过文件内容判断
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$realMimeType = finfo_file($finfo, $img->getRealPath());
|
||||
finfo_close($finfo);
|
||||
if (!in_array($realMimeType, $allowedTypes)) {
|
||||
return json(backMsg(1, '文件类型验证失败,请上传有效的图片文件'));
|
||||
}
|
||||
|
||||
// 生成唯一文件名,避免文件名冲突
|
||||
$filename = 'img_' . time() . '_' . uniqid() . '.' . $img->getOriginalExtension();
|
||||
|
||||
// 过滤文件名,防止路径遍历攻击
|
||||
$filename = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', $filename);
|
||||
|
||||
// 设置文件保存路径
|
||||
$path = public_path() . '/files/qrcode/';
|
||||
if (!is_dir($path)) {
|
||||
if (!mkdir($path, 0755, true)) {
|
||||
return json(backMsg(1, '创建目录失败'));
|
||||
}
|
||||
}
|
||||
|
||||
// 移动文件到指定目录
|
||||
$info = $img->move($path, $filename);
|
||||
if ($info) {
|
||||
$imgpath = '/files/qrcode/' . $filename;
|
||||
return json(backMsg(0, '上传成功', ['imgpath' => $imgpath]));
|
||||
} else {
|
||||
return json(backMsg(1, '上传失败'));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('上传过程中出现异常: ' . $e->getMessage());
|
||||
return json(backMsg(1, '上传过程中出现异常,请稍后重试'));
|
||||
}
|
||||
}
|
||||
// 获取账号交易流水
|
||||
|
||||
@@ -48,6 +48,8 @@ class Order extends BaseModel
|
||||
'state' => 0,
|
||||
// 开启监听:1, 关闭监听:0
|
||||
'patt' => $channel['patt'],
|
||||
// 平台
|
||||
'platform' => $channel['platform'],
|
||||
// 订单创建时间
|
||||
'create_time' => self::getFormatTime($my_time),
|
||||
// 订单关闭时间
|
||||
@@ -70,41 +72,32 @@ class Order extends BaseModel
|
||||
public static function serchOrders($query)
|
||||
{
|
||||
$select = [];
|
||||
$_select = [];
|
||||
$allow_field = ['id', 'order_id', 'pid', 'type', 'out_trade_no', 'notify_url', 'return_url', 'name', 'really_price', 'money', 'clientip', 'device', 'state', 'create_time_start', 'create_time_end', 'close_time', 'pay_time', 'platform', 'platform_order', 'aid', 'cid',];
|
||||
$allow_field = ['id', 'order_id', 'pid', 'type', 'out_trade_no', 'name', 'really_price', 'money', 'state', 'create_time_start', 'create_time_end', 'close_time', 'pay_time', 'platform', 'platform_order', 'aid', 'cid',];
|
||||
foreach ($query as $key => $value) {
|
||||
if (in_array($key, $allow_field) && isset($value)) {
|
||||
if ($key === 'name') {
|
||||
$select[] = ['Order.' . $key, 'like', '%' . $value . '%'];
|
||||
$select[] = [$key, 'like', '%' . $value . '%'];
|
||||
continue;
|
||||
}
|
||||
if ($key === 'create_time_start') {
|
||||
$select[] = ['Order.' . 'create_time', '>', $value];
|
||||
$select[] = ['create_time', '>', $value];
|
||||
continue;
|
||||
}
|
||||
if ($key === 'create_time_end') {
|
||||
$select[] = ['Order.' . 'create_time', '<', $value];
|
||||
$select[] = ['create_time', '<', $value];
|
||||
continue;
|
||||
}
|
||||
if ($key === 'platform') {
|
||||
$_select['platform'] = $value;
|
||||
continue;
|
||||
}
|
||||
$select[] = ['Order.' . $key, '=', $value];
|
||||
$select[] = [$key, '=', $value];
|
||||
}
|
||||
}
|
||||
return self::with('payAccount')
|
||||
->hasWhere('payAccount', function ($query) use ($_select) {
|
||||
$query->where($_select);
|
||||
})
|
||||
->where($select);
|
||||
return self::where($select);
|
||||
}
|
||||
// 查询订单详细
|
||||
public static function showOrderDetail($id)
|
||||
{
|
||||
$order = self::find($id);
|
||||
$a_list = PayAccount::find($order->aid);
|
||||
$c_list = PayChannel::find($order->cid);
|
||||
$a_list = PayAccount::withTrashed()->find($order->aid);
|
||||
$c_list = PayChannel::withTrashed()->find($order->cid);
|
||||
if (!$order) {
|
||||
return [];
|
||||
}
|
||||
@@ -145,7 +138,7 @@ class Order extends BaseModel
|
||||
if (!$channel_info) return backMsg(3, '用户账户无可用收款通道');
|
||||
// 选取收款通道
|
||||
$patt = PayAccount::find($channel_info->account_id);
|
||||
$channel = ['aid' => $channel_info->account_id, 'cid' => $channel_info->id, 'patt' => $patt->getData('pattern'), 'chan' => $channel_info->channel];
|
||||
$channel = ['aid' => $channel_info->account_id, 'cid' => $channel_info->id, 'patt' => $patt->getData('pattern'), 'chan' => $channel_info->channel, 'platform' => $patt->getData('platform')];
|
||||
PayChannel::update(['last_time' => self::getFormatTime(), 'id' => $channel['cid']]);
|
||||
return backMsg(0, 'ok', $channel);
|
||||
}
|
||||
@@ -195,7 +188,9 @@ class Order extends BaseModel
|
||||
// 生成订单号
|
||||
private static function createOrderID(string $prefix = ''): string
|
||||
{
|
||||
return $prefix . date('Ymd') . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
|
||||
$date = date('YmdHis');
|
||||
$rand = rand(1000, 9999);
|
||||
return $prefix . $date . $rand;
|
||||
}
|
||||
// 查询有效期内的未支付订单
|
||||
public function scopeActiveOrder($query)
|
||||
|
||||
@@ -30,6 +30,7 @@ class PayAccount extends BaseModel
|
||||
public static function getAccountConfig($aid, $pid = null): array|bool
|
||||
{
|
||||
$aid_info = self::find($aid);
|
||||
if (!$aid_info) return false;
|
||||
// 插件配置
|
||||
$platform = PluginController::getPluginInfo($aid_info->getData('platform'));
|
||||
// 查询参数
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 后台菜单配置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
[
|
||||
'id' => 'console',
|
||||
'title' => '平台首页',
|
||||
'icon' => 'icon pear-icon pear-icon-home',
|
||||
'type' => 1,
|
||||
'openType' => '_iframe',
|
||||
'href' => 'Console/console',
|
||||
],
|
||||
[
|
||||
'id' => 'order',
|
||||
'title' => '订单管理',
|
||||
'icon' => 'icon pear-icon pear-icon-survey',
|
||||
'type' => 1,
|
||||
'openType' => '_iframe',
|
||||
'href' => '/Order/index',
|
||||
],
|
||||
[
|
||||
'id' => 'payManage',
|
||||
'title' => '账号管理',
|
||||
'icon' => 'icon pear-icon pear-icon-security',
|
||||
'type' => 1,
|
||||
'openType' => '_iframe',
|
||||
'href' => '/PayManage/index',
|
||||
],
|
||||
[
|
||||
'id' => 'pluginManage',
|
||||
'title' => '插件管理',
|
||||
'icon' => 'icon pear-icon pear-icon-modular',
|
||||
'type' => 1,
|
||||
'openType' => '_iframe',
|
||||
'href' => '/Plugin/index',
|
||||
],
|
||||
[
|
||||
'id' => 'userCenter',
|
||||
'title' => '用户中心',
|
||||
'icon' => 'icon pear-icon pear-icon-user',
|
||||
'type' => 1,
|
||||
'openType' => '_iframe',
|
||||
'href' => '/User/index',
|
||||
],
|
||||
// [
|
||||
// 'id' => 'system',
|
||||
// 'title' => '系统设置',
|
||||
// 'icon' => 'icon pear-icon pear-icon-import',
|
||||
// 'type' => 1,
|
||||
// 'openType' => '_iframe',
|
||||
// 'href' => '/System/index',
|
||||
// ],
|
||||
// [
|
||||
// 'id' => 'pay',
|
||||
// 'title' => '支付管理',
|
||||
// 'icon' => 'icon pear-icon pear-icon-import',
|
||||
// 'type' => 0,
|
||||
// 'href' => '',
|
||||
// 'children' => [
|
||||
// [
|
||||
// 'id' => 'pay_qrcode_list',
|
||||
// 'title' => '收款账户',
|
||||
// 'icon' => 'icon pear-icon pear-icon-import',
|
||||
// 'type' => 1,
|
||||
// 'openType' => '_iframe',
|
||||
// 'href' => '/PayQrcode/index',
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
];
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 支付插件列表
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return array (
|
||||
0 =>
|
||||
array (
|
||||
'platform' => 'wxpay',
|
||||
'name' => '微信支付',
|
||||
'class_name' => 'WxPay',
|
||||
'price' => NULL,
|
||||
'describe' => '支持微信个人收款码、赞赏码、经营码、商家码收款,监听回调',
|
||||
'website' => 'https://weixin.qq.com',
|
||||
'helplink' => 'https://f0bmwzqjtq2.feishu.cn/docx/JBshdZWokoWzLmxSKQWcSd4Jncg',
|
||||
'version' => '1.0',
|
||||
'state' => 1,
|
||||
),
|
||||
1 =>
|
||||
array (
|
||||
'platform' => 'alipay',
|
||||
'name' => '支付宝',
|
||||
'class_name' => 'AliPay',
|
||||
'price' => NULL,
|
||||
'describe' => '支持支付宝个人收款码、经营码收款,监听回调',
|
||||
'website' => 'https://www.alipay.com',
|
||||
'helplink' => 'https://f0bmwzqjtq2.feishu.cn/docx/GfltdDrjxoYXwexhtX8ckDCBn9f',
|
||||
'version' => '1.0',
|
||||
'state' => 1,
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'platform' => 'sqbpay',
|
||||
'name' => '收钱吧',
|
||||
'class_name' => 'ShouQianBa',
|
||||
'price' => NULL,
|
||||
'describe' => '主流移动支付全能收 信用卡,花呗都能用,生意帮手收钱吧,移动收款就用它!',
|
||||
'website' => 'https://www.shouqianba.com',
|
||||
'helplink' => 'https://f0bmwzqjtq2.feishu.cn/docx/WwN7dRqmuoozlIxgiuFclZhCnte',
|
||||
'version' => '1.0',
|
||||
'state' => 1,
|
||||
),
|
||||
);
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
class Plugin
|
||||
{
|
||||
private static $siteUrl = 'https://api.zhaidashi.cn';
|
||||
private static $siteUrl = 'https://api.qcjy.cc';
|
||||
// 获取全部插件(含本地)
|
||||
public static function getAllPlugins(array $local_plugin = []): array
|
||||
{
|
||||
|
||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
@@ -8,8 +8,6 @@
|
||||
<head>
|
||||
<title>开发文档</title>
|
||||
</head>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="https://cdn.jsdelivr.net/gh/pandao/editor.md@1.5.0/css/editormd.min.css">
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family: "Helvetica Neue", "Helvetica", "Microsoft Yahei", "微软雅黑", "Lantinghei SC", "STXihei", "WenQuanYi Micro Hei", Arial, sans-serif;
|
||||
|
||||
@@ -54,17 +54,10 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">端口</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="port" required lay-verify="required" placeholder="请输入数据库名称"
|
||||
<input type="text" name="port" required lay-verify="required" placeholder="请输入端口号"
|
||||
autocomplete="off" class="layui-input" value="3306">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">编码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="charset" required lay-verify="required" placeholder="请输入数据库名称"
|
||||
autocomplete="off" class="layui-input" value="utf8mb4">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">数据库</label>
|
||||
<div class="layui-input-block">
|
||||
@@ -76,7 +69,7 @@
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="user" required lay-verify="required" placeholder="请输入数据库用户名"
|
||||
autocomplete="off" class="layui-input" value="root">
|
||||
autocomplete="off" class="layui-input" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
@@ -90,21 +83,21 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">管理员昵称</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="nickname" required lay-verify="required" placeholder="请输入管理员昵称"
|
||||
autocomplete="off" class="layui-input" value="勇敢牛牛">
|
||||
<input type="text" name="nickname" required lay-verify="required" placeholder="设置管理员昵称"
|
||||
autocomplete="off" class="layui-input" value="Mpay">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">管理员账号</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="username" required lay-verify="required" placeholder="请输入管理员用户名"
|
||||
<input type="text" name="username" required lay-verify="required" placeholder="设置管理员用户名"
|
||||
autocomplete="off" class="layui-input" value="admin">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">管理员密码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="password" name="password" required lay-verify="required" placeholder="请输入管理员密码"
|
||||
<input type="password" name="password" required lay-verify="required" placeholder="设置登陆密码"
|
||||
autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
@@ -39,9 +39,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">用户ID</label>
|
||||
<label class="layui-form-label">平台流水号</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="pid" autocomplete="off" class="layui-input" placeholder="请输入">
|
||||
<input type="text" name="platform_order" autocomplete="off" class="layui-input"
|
||||
placeholder="请输入">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
@@ -203,60 +204,68 @@
|
||||
(async () => {
|
||||
const data = await fetch('/api/Plugin/pluginOption').then(res => res.json());
|
||||
let option_str = `<option value="">收款平台</option>`;
|
||||
let platforms = {};
|
||||
data.forEach(val => {
|
||||
option_str += `<option value="${val.platform}">${val.name}</option>`;
|
||||
platforms[val.platform] = val.name;
|
||||
});
|
||||
const select = document.querySelector('select[name="platform"]');
|
||||
select.innerHTML = option_str;
|
||||
form.render('select');
|
||||
// 会话存储
|
||||
sessionStorage.setItem('platforms', JSON.stringify(platforms));
|
||||
let platformTpl = (d) => {
|
||||
let platforms = JSON.parse(sessionStorage.getItem('platforms')) || {};
|
||||
let platformName = platforms[d.platform] || '已卸载';
|
||||
return `${platformName} [${d.aid}:${d.cid}]`;
|
||||
}
|
||||
// 表格列参数
|
||||
let cols = [[
|
||||
{ type: 'checkbox' },
|
||||
{ title: '订单号', field: 'order_id', align: 'center', minWidth: 165, templet: '<div><a href="javascript:;" class="layui-font-blue" lay-event="showOrder">{{= d.order_id }}</a></div>' },
|
||||
// { title: '用户', field: 'pid', align: 'center', width: 85 },
|
||||
{ title: '商家订单号', field: 'out_trade_no', align: 'center', minWidth: 180 },
|
||||
{ title: '商品', field: 'name', align: 'center', minWidth: 180 },
|
||||
{ title: '订单金额', field: 'money', align: 'center', minWidth: 85 },
|
||||
{ title: '成交金额', field: 'really_price', align: 'center', minWidth: 85 },
|
||||
{ title: '支付状态', field: 'state', align: 'center', minWidth: 85, templet: '<div>{{# if(d.state==1){return`<span class="layui-badge layui-bg-green">成功</span>`}else{if(new Date(d.close_time)>new Date("<?php echo $servertime ?>")){return`<span class="layui-badge layui-bg-orange">等待</span>`}else{return`<span class="layui-badge layui-bg-gray">过期</span>`} } }}</div>' },
|
||||
{ title: '支付时间', field: 'pay_time', align: 'center', minWidth: 160, templet: '<div>{{= d.pay_time == d.create_time ? "- -" : d.pay_time}}</div>' },
|
||||
{ title: '支付平台', field: 'type', align: 'center', width: 120, templet: '<div>{{# if(d.type=="wxpay"){return`<div class="paytype"><img src="/static/img/wxpay.ico"width="15"><span>微信支付</span></div>`}if(d.type=="alipay"){return`<div class="paytype"><img src="/static/img/alipay.ico"width="15"><span>支付宝</span></div>`}if(d.type=="unionpay"){return`<div class="paytype"><img src="/static/img/unionpay.ico"width="15"><span>云闪付</span></div>`} }}</div>' },
|
||||
{ title: '收款平台[账号:终端]', field: 'platform', align: 'center', minWidth: 160, templet: platformTpl },
|
||||
{ title: '操作', align: 'center', width: 120, fixed: 'right', templet: '<div><strong><a href="javascript:;" data-id="{{= d.id }}" class="layui-font-green {{= d.state==1 ? "orderSet-paid" : "orderSet-paying" }}">设置</a></strong></div>' }
|
||||
]]
|
||||
// 表格渲染
|
||||
table.render({
|
||||
id: 'orders-table',
|
||||
elem: '#orders-table',
|
||||
url: '/api/Order/getOrders',
|
||||
page: true,
|
||||
cols: cols,
|
||||
skin: 'line',
|
||||
toolbar: '#order-toolbar',
|
||||
defaultToolbar: [{
|
||||
title: '刷新',
|
||||
layEvent: 'refresh',
|
||||
icon: 'layui-icon-refresh',
|
||||
}, 'filter', 'print', 'exports'],
|
||||
done: function () {
|
||||
dropdown.render({
|
||||
elem: '.orderSet-paying',
|
||||
data: [{ title: '改已支付', type: 1 }, { type: '-' }, { title: '手动补单', type: 3 }, { title: '删除订单', type: 0 }],
|
||||
click: function (data, othis) {
|
||||
order.setOrder(data, this.elem);
|
||||
}
|
||||
});
|
||||
dropdown.render({
|
||||
elem: '.orderSet-paid',
|
||||
data: [{ title: '改未支付', type: 2 }, { type: '-' }, { title: '重新通知', type: 4 }, { title: '删除订单', type: 0 }],
|
||||
click: function (data, othis) {
|
||||
order.setOrder(data, this.elem);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
})()
|
||||
// 表格列参数
|
||||
let cols = [[
|
||||
{ type: 'checkbox' },
|
||||
{ title: '订单号', field: 'order_id', align: 'center', minWidth: 165, templet: '<div><a href="javascript:;" class="layui-font-blue" lay-event="showOrder">{{= d.order_id }}</a></div>' },
|
||||
// { title: '用户', field: 'pid', align: 'center', width: 85 },
|
||||
{ title: '商家订单号', field: 'out_trade_no', align: 'center', minWidth: 180 },
|
||||
{ title: '商品', field: 'name', align: 'center', minWidth: 180 },
|
||||
{ title: '订单金额', field: 'money', align: 'center', minWidth: 85 },
|
||||
{ title: '成交金额', field: 'really_price', align: 'center', minWidth: 85 },
|
||||
{ title: '支付状态', field: 'state', align: 'center', minWidth: 85, templet: '<div>{{# if(d.state==1){return`<span class="layui-badge layui-bg-green">成功</span>`}else{if(new Date(d.close_time)>new Date("<?php echo $servertime ?>")){return`<span class="layui-badge layui-bg-orange">等待</span>`}else{return`<span class="layui-badge layui-bg-gray">过期</span>`} } }}</div>' },
|
||||
{ title: '支付时间', field: 'pay_time', align: 'center', minWidth: 160, templet: '<div>{{= d.pay_time == d.create_time ? "- -" : d.pay_time}}</div>' },
|
||||
{ title: '支付平台', field: 'type', align: 'center', width: 120, templet: '<div>{{# if(d.type=="wxpay"){return`<div class="paytype"><img src="/static/img/wxpay.ico"width="15"><span>微信支付</span></div>`}if(d.type=="alipay"){return`<div class="paytype"><img src="/static/img/alipay.ico"width="15"><span>支付宝</span></div>`}if(d.type=="unionpay"){return`<div class="paytype"><img src="/static/img/unionpay.ico"width="15"><span>云闪付</span></div>`} }}</div>' },
|
||||
{ title: '收款平台[账号:终端]', field: 'platform', align: 'center', minWidth: 160, templet: '<div>{{# return`${d.payAccount.platform} [${d.aid}:${d.cid}]` }}</div>' },
|
||||
{ title: '操作', align: 'center', width: 120, fixed: 'right', templet: '<div><strong><a href="javascript:;" data-id="{{= d.id }}" class="layui-font-green {{= d.state==1 ? "orderSet-paid" : "orderSet-paying" }}">设置</a></strong></div>' }
|
||||
]]
|
||||
// 表格渲染
|
||||
table.render({
|
||||
id: 'orders-table',
|
||||
elem: '#orders-table',
|
||||
url: '/api/Order/getOrders',
|
||||
page: true,
|
||||
cols: cols,
|
||||
skin: 'line',
|
||||
toolbar: '#order-toolbar',
|
||||
defaultToolbar: [{
|
||||
title: '刷新',
|
||||
layEvent: 'refresh',
|
||||
icon: 'layui-icon-refresh',
|
||||
}, 'filter', 'print', 'exports'],
|
||||
done: function () {
|
||||
dropdown.render({
|
||||
elem: '.orderSet-paying',
|
||||
data: [{ title: '改已支付', type: 1 }, { type: '-' }, { title: '手动补单', type: 3 }, { title: '删除订单', type: 0 }],
|
||||
click: function (data, othis) {
|
||||
order.setOrder(data, this.elem);
|
||||
}
|
||||
});
|
||||
dropdown.render({
|
||||
elem: '.orderSet-paid',
|
||||
data: [{ title: '改未支付', type: 2 }, { type: '-' }, { title: '重新通知', type: 4 }, { title: '删除订单', type: 0 }],
|
||||
click: function (data, othis) {
|
||||
order.setOrder(data, this.elem);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// 事件处理
|
||||
|
||||
// 表格单元格事件
|
||||
|
||||
@@ -305,9 +305,10 @@
|
||||
openAppBtn.className = 'layui-btn layui-btn-normal';
|
||||
openAppBtn.onclick = function () {
|
||||
if (codeType == 0) {
|
||||
window.location.href = 'alipays://platformapi/startapp?appId=20000067&&url=' + payCode;
|
||||
const payUrl = encodeURIComponent(payCode);
|
||||
window.location.href = 'alipays://platformapi/startapp?appId=20000067&&url=' + payUrl;
|
||||
} else {
|
||||
const currentUrl = window.location.href;
|
||||
const currentUrl = encodeURIComponent(window.location.href);
|
||||
window.location.href = 'alipays://platformapi/startapp?appId=20000067&&url=' + currentUrl;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<option value="wxpay2">赞赏码</option>
|
||||
<option value="wxpay3">经营码</option>
|
||||
<option value="wxpay4">商家码</option>
|
||||
<option value="wxpay5">店员码</option>
|
||||
<!-- <?php } ?> -->
|
||||
<!-- <?php if ($platform == 'alipay') { ?> -->
|
||||
<option value="alipay1">收钱码</option>
|
||||
@@ -60,7 +61,7 @@
|
||||
<div class="layui-form-item">
|
||||
<blockquote class="layui-elem-quote">
|
||||
<!-- <?php if ($platform == 'wxpay') { ?> -->
|
||||
<p><strong>手机监控:</strong>微信个人码与经营码只能二选一,不能同时添加,商家码监听需要关注“微信收款商业版”公众号,赞赏码正常添加。</p>
|
||||
<p><strong>手机监控:</strong>微信个人码与经营码只能二选一,不能同时添加,且经营码只能通过个人码通道1添加成功,不然不回调;商家码监听需要关注“微信收款商业版”公众号,赞赏码和店员码正常添加。</p>
|
||||
<p><strong>电脑监控:</strong>所有收款码均可监控,需要将收款通知聊天窗口单独拖出来</p>
|
||||
<!-- <?php } ?> -->
|
||||
<!-- <?php if ($platform == 'alipay') { ?> -->
|
||||
|
||||
@@ -168,13 +168,7 @@
|
||||
table.on('toolDouble(account-table)', function (obj) {
|
||||
if (obj.event === 'copy') {
|
||||
const text = obj.tr[0].querySelector('td[data-field="checkUrl"]>div').innerText;
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
layer.msg('复制成功');
|
||||
});
|
||||
} else {
|
||||
layer.msg('复制失败,请手动复制');
|
||||
}
|
||||
copyText(text);
|
||||
}
|
||||
});
|
||||
// 表格头部按钮事件
|
||||
@@ -331,6 +325,34 @@
|
||||
}
|
||||
}
|
||||
})
|
||||
// 复制文本到剪贴板
|
||||
function copyText(text) {
|
||||
if (navigator.clipboard && window.isSecureContext === false) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
layer.msg('复制成功');
|
||||
}).catch(err => {
|
||||
copyToClipboardFallback(text);
|
||||
});
|
||||
} else {
|
||||
copyToClipboardFallback(text);
|
||||
}
|
||||
}
|
||||
// 传统复制文本到剪贴板
|
||||
function copyToClipboardFallback(text) {
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = text;
|
||||
textarea.style.position = 'fixed';
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
layer.msg('复制成功');
|
||||
} catch (err) {
|
||||
layer.msg('复制失败,请手动复制');
|
||||
} finally {
|
||||
document.body.removeChild(textarea);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -256,13 +256,7 @@
|
||||
util.on({
|
||||
'copyinfo': (ele) => {
|
||||
const info = ele.attr('data-info');
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(info).then(() => {
|
||||
layer.msg('复制成功');
|
||||
});
|
||||
} else {
|
||||
layer.msg('复制失败,请手动复制');
|
||||
}
|
||||
copyText(info);
|
||||
},
|
||||
'resetKey': (ele) => {
|
||||
layer.confirm('重置密钥后,将无法使用原密钥,是否继续?', { icon: 3, title: '重置密钥' }, function (index) {
|
||||
@@ -297,8 +291,34 @@
|
||||
|
||||
});
|
||||
fetch('https://v1.hitokoto.cn?c=d&c=i&c=k&encode=text').then(res => res.text()).then(data => { document.getElementById('yiyan').innerHTML = data || '人无横财不富,马无夜草不肥'; })
|
||||
|
||||
|
||||
// 复制文本到剪贴板
|
||||
function copyText(text) {
|
||||
if (navigator.clipboard && window.isSecureContext === false) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
layer.msg('复制成功');
|
||||
}).catch(err => {
|
||||
copyToClipboardFallback(text);
|
||||
});
|
||||
} else {
|
||||
copyToClipboardFallback(text);
|
||||
}
|
||||
}
|
||||
// 传统复制文本到剪贴板
|
||||
function copyToClipboardFallback(text) {
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = text;
|
||||
textarea.style.position = 'fixed';
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
layer.msg('复制成功');
|
||||
} catch (err) {
|
||||
layer.msg('复制失败,请手动复制');
|
||||
} finally {
|
||||
document.body.removeChild(textarea);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user