mirror of
https://gitee.com/technical-laohu/mpay.git
synced 2025-09-17 17:26:40 +08:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
872afd10cb | ||
|
924042aa5e | ||
|
5b69aded08 | ||
|
5826a7f6e1 | ||
|
98c90dffcf | ||
|
e524424628 | ||
|
a6b5133cc3 | ||
|
748356cc6b | ||
|
e4952f6389 | ||
|
ba8df721d7 | ||
|
a3d15ee7e2 | ||
|
2cd473019b | ||
|
a8bb0d7513 | ||
|
ee49c2a0d0 | ||
|
374fc75423 | ||
|
fa75d580b8 | ||
|
1ac1c2fd13 | ||
|
d570aa88b3 | ||
|
a05a5710af | ||
|
b3dd6ba3f0 | ||
|
d0dd5a3f9b | ||
|
ccb94768d3 | ||
|
7c35519e65 | ||
|
d0fe56bade | ||
|
0a270541c7 | ||
|
62181cf33d | ||
|
1f98974d5a | ||
|
a59a22fe82 | ||
|
e3d7efa60f |
12
.env
12
.env
@ -1,12 +0,0 @@
|
|||||||
APP_DEBUG = true
|
|
||||||
|
|
||||||
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
|
*.env
|
||||||
|
|
||||||
extend/*
|
extend/*
|
||||||
!extend/ImgCaptcha.php
|
|
||||||
!extend/payclient.zip
|
|
||||||
!extend/Plugin.php
|
|
||||||
|
|
||||||
vendor/*
|
vendor/*
|
||||||
!vendor/vendor.zip
|
!vendor/vendor.zip
|
||||||
|
|
||||||
runtime/*
|
runtime/*
|
||||||
|
|
||||||
app/*
|
app/controller/TestController.php
|
||||||
!app/controller/TestController.php
|
|
||||||
|
config/extend/*
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
## ✨ 演示站点
|
## ✨ 演示站点
|
||||||
|
|
||||||
访问 [在线演示](http://demo.stspwsc.com/) 快速体验。
|
#### 访问 [在线演示](http://demo.stspwsc.com/) 快速体验。
|
||||||
|
|
||||||
## 📊 项目说明
|
## 📊 项目说明
|
||||||
|
|
||||||
@ -408,7 +408,7 @@ V免签是一款开源免费适用于个人收款使用的收款程序,原理
|
|||||||
|
|
||||||
码支付微信PC监听,是老胡使用python写的小工具,可以监听电脑桌面打开的窗口和内容信息,非侵入微信应用内部,版本升级不影响监听。需要将被监听的微信聊天界面单独拖出来成独立窗口。
|
码支付微信PC监听,是老胡使用python写的小工具,可以监听电脑桌面打开的窗口和内容信息,非侵入微信应用内部,版本升级不影响监听。需要将被监听的微信聊天界面单独拖出来成独立窗口。
|
||||||
|
|
||||||
[PC监听软件下载wxmonitor.zip](assets/20250217_103606_wxmonitor.zip)
|
[PC监听软件下载wxmonitor_v1.2.zip](assets/wxmonitor_v1.4.zip)
|
||||||
|
|
||||||
##### 配置信息
|
##### 配置信息
|
||||||
|
|
||||||
@ -444,6 +444,7 @@ V免签是一款开源免费适用于个人收款使用的收款程序,原理
|
|||||||
社群答疑、插件定制、技术交流,添加微信拉群,请备注:**码支付**
|
社群答疑、插件定制、技术交流,添加微信拉群,请备注:**码支付**
|
||||||
|
|
||||||
微信:**K103516**
|
微信:**K103516**
|
||||||
|
备用:**HU1094551889**
|
||||||
|
|
||||||
<img src="assets/wxqrcode.png" width=480 />
|
<img src="assets/wxqrcode.png" width=480 />
|
||||||
|
|
||||||
@ -460,6 +461,8 @@ V免签是一款开源免费适用于个人收款使用的收款程序,原理
|
|||||||
| 云峰 | 8.88 |
|
| 云峰 | 8.88 |
|
||||||
| 零零 | 200 |
|
| 零零 | 200 |
|
||||||
| 子染 | 88 |
|
| 子染 | 88 |
|
||||||
|
| John | 100 |
|
||||||
|
| 辰起 | 8.88 |
|
||||||
|
|
||||||
## 🔗 友情链接
|
## 🔗 友情链接
|
||||||
|
|
||||||
|
BIN
app/app.zip
Normal file
BIN
app/app.zip
Normal file
Binary file not shown.
@ -13,7 +13,7 @@ class ConsoleController extends BaseController
|
|||||||
// 后台主页
|
// 后台主页
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
View::assign('version', 'v1');
|
View::assign('version', 'V1');
|
||||||
return View::fetch();
|
return View::fetch();
|
||||||
}
|
}
|
||||||
// 管理菜单
|
// 管理菜单
|
||||||
@ -28,6 +28,12 @@ class ConsoleController extends BaseController
|
|||||||
{
|
{
|
||||||
// 加载菜单配置
|
// 加载菜单配置
|
||||||
$message = \Plugin::getNotifyMessage();
|
$message = \Plugin::getNotifyMessage();
|
||||||
|
if (empty($message)) {
|
||||||
|
$message = [
|
||||||
|
["id" => 1, "title" => "应用更新", "children" => []],
|
||||||
|
["id" => 2, "title" => "官方消息", "children" => []],
|
||||||
|
];
|
||||||
|
}
|
||||||
return json($message);
|
return json($message);
|
||||||
}
|
}
|
||||||
// 首页仪表盘
|
// 首页仪表盘
|
||||||
|
@ -7,85 +7,177 @@ namespace app\controller;
|
|||||||
use think\facade\Db;
|
use think\facade\Db;
|
||||||
use think\Request;
|
use think\Request;
|
||||||
use think\facade\View;
|
use think\facade\View;
|
||||||
|
use think\facade\Log;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
class InstallController
|
class InstallController
|
||||||
{
|
{
|
||||||
|
private const INSTALL_LOCK_FILE = 'install.lock';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接数据库
|
||||||
|
* @return \think\db\Connection
|
||||||
|
*/
|
||||||
|
private function connectDatabase()
|
||||||
|
{
|
||||||
|
return Db::connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首页,检查是否已安装,若已安装则跳转到登录页,否则显示安装页面
|
||||||
|
* @return \think\response\Redirect|\think\response\View
|
||||||
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
// 检查是否已经安装过
|
|
||||||
if ($this->checkLock()) {
|
if ($this->checkLock()) {
|
||||||
return redirect('User/login');
|
return redirect('User/login');
|
||||||
};
|
}
|
||||||
return View::fetch();
|
return View::fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安装操作,检查环境、保存数据库配置信息
|
||||||
|
* @param Request $request
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
public function install(Request $request)
|
public function install(Request $request)
|
||||||
{
|
{
|
||||||
// 检查是否已经安装过
|
|
||||||
if ($this->checkLock()) {
|
if ($this->checkLock()) {
|
||||||
return json(backMsg(1, '已经安装'));
|
return json(backMsg(1, '已经安装'));
|
||||||
};
|
}
|
||||||
// 检查环境
|
|
||||||
$envCheck = $this->checkEnvironment();
|
$envCheck = $this->checkEnvironment();
|
||||||
if ($envCheck !== true) {
|
if ($envCheck !== true) {
|
||||||
return json(backMsg(1, $envCheck));
|
return json(backMsg(1, $envCheck));
|
||||||
};
|
|
||||||
// 获取表单提交的数据库配置信息
|
|
||||||
$dbConfig = $request->post();
|
|
||||||
// 保存数据库配置信息到配置文件
|
|
||||||
if ($this->saveDbConfig($dbConfig) === false) {
|
|
||||||
return json(backMsg(1, '配置保存失败'));
|
|
||||||
} else {
|
|
||||||
return json(backMsg(0, '配置保存成功'));
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
// 初始化数据库
|
|
||||||
|
$dbConfig = $request->post();
|
||||||
|
try {
|
||||||
|
$this->validateDbConfig($dbConfig);
|
||||||
|
$this->saveDbConfig($dbConfig);
|
||||||
|
return json(backMsg(0, '配置保存成功'));
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(backMsg(1, $e->getMessage()));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error("保存数据库配置失败: " . $e->getMessage());
|
||||||
|
return json(backMsg(1, '配置保存失败'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化数据库,创建表并初始化数据
|
||||||
|
* @param Request $request
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
public function init(Request $request)
|
public function init(Request $request)
|
||||||
{
|
{
|
||||||
// 检查是否已经安装过
|
|
||||||
if ($this->checkLock()) {
|
if ($this->checkLock()) {
|
||||||
return backMsg(1, '已经安装');
|
return json(backMsg(1, '已经安装'));
|
||||||
};
|
}
|
||||||
// 获取表单提交的数据库配置信息
|
|
||||||
$dbConfig = $request->post();
|
$dbConfig = $request->post();
|
||||||
|
$startTime = microtime(true);
|
||||||
|
|
||||||
// 连接数据库并建表
|
try {
|
||||||
$is_succ_tb = $this->createTables();
|
$this->validateInitData($dbConfig);
|
||||||
|
$this->connectDatabase()->transaction(function () use ($dbConfig) {
|
||||||
// 初始化数据记录
|
$this->createTables();
|
||||||
$is_succ_data = $this->initData($dbConfig);
|
$this->initData($dbConfig);
|
||||||
|
});
|
||||||
// 安装检测
|
|
||||||
if (!$is_succ_tb) {
|
|
||||||
return json(backMsg(1, '数据表创建失败'));
|
|
||||||
}
|
|
||||||
if (!$is_succ_data) {
|
|
||||||
return json(backMsg(1, '数据初始化失败'));
|
|
||||||
}
|
|
||||||
// 安装成功,写入安装锁文件
|
|
||||||
$this->setLock();
|
$this->setLock();
|
||||||
|
$endTime = microtime(true);
|
||||||
|
Log::info("数据库初始化完成,耗时: " . ($endTime - $startTime) . " 秒");
|
||||||
return json(backMsg(0, '安装成功'));
|
return json(backMsg(0, '安装成功'));
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(backMsg(1, $e->getMessage()));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error("数据库初始化失败: " . $e->getMessage());
|
||||||
|
return json(backMsg(1, '数据库初始化失败'));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查环境,包括 PHP 版本、文件上传写入权限、Fileinfo 扩展
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
private function checkEnvironment()
|
private function checkEnvironment()
|
||||||
{
|
{
|
||||||
// 检查PHP版本
|
|
||||||
if (version_compare(PHP_VERSION, '8.0', '<')) {
|
if (version_compare(PHP_VERSION, '8.0', '<')) {
|
||||||
return 'PHP 版本必须大于等于 8.0';
|
return 'PHP 版本必须大于等于 8.0';
|
||||||
}
|
}
|
||||||
// 检查文件上传写入权限
|
|
||||||
if (!is_writable(sys_get_temp_dir())) {
|
if (!is_writable(sys_get_temp_dir())) {
|
||||||
return '文件上传目录没有写入权限';
|
return '文件上传目录没有写入权限';
|
||||||
}
|
}
|
||||||
// 检查Fileinfo扩展是否安装
|
|
||||||
if (!extension_loaded('fileinfo')) {
|
if (!extension_loaded('fileinfo')) {
|
||||||
return 'Fileinfo 扩展未安装';
|
return 'Fileinfo 扩展未安装';
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
private function saveDbConfig($dbConfig)
|
|
||||||
|
/**
|
||||||
|
* 验证数据库配置信息
|
||||||
|
* @param array $dbConfig
|
||||||
|
* @throws ValidateException
|
||||||
|
*/
|
||||||
|
private function validateDbConfig(array $dbConfig)
|
||||||
|
{
|
||||||
|
$validate = new Validate();
|
||||||
|
$rule = [
|
||||||
|
'host' => 'require',
|
||||||
|
'name' => 'require',
|
||||||
|
'user' => 'require',
|
||||||
|
'pass' => 'require',
|
||||||
|
'port' => 'require|integer',
|
||||||
|
];
|
||||||
|
if (!$validate->rule($rule)->check($dbConfig)) {
|
||||||
|
throw new ValidateException($validate->getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证初始化数据信息
|
||||||
|
* @param array $dbConfig
|
||||||
|
* @throws ValidateException
|
||||||
|
*/
|
||||||
|
private function validateInitData(array $dbConfig)
|
||||||
|
{
|
||||||
|
$validate = new Validate();
|
||||||
|
$rule = [
|
||||||
|
'nickname' => 'require',
|
||||||
|
'username' => 'require',
|
||||||
|
'password' => 'require'
|
||||||
|
];
|
||||||
|
if (!$validate->rule($rule)->check($dbConfig)) {
|
||||||
|
throw new ValidateException($validate->getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存数据库配置信息到 .env 文件
|
||||||
|
* @param array $dbConfig
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
private function saveDbConfig(array $dbConfig)
|
||||||
{
|
{
|
||||||
$envPath = app()->getRootPath() . '.env';
|
$envPath = app()->getRootPath() . '.env';
|
||||||
$envContent = <<<EOT
|
$envContent = $this->generateEnvContent($dbConfig);
|
||||||
|
if (file_put_contents($envPath, $envContent) === false) {
|
||||||
|
throw new \Exception("无法写入 .env 文件");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 .env 文件内容
|
||||||
|
* @param array $dbConfig
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function generateEnvContent(array $dbConfig): string
|
||||||
|
{
|
||||||
|
return <<<EOT
|
||||||
APP_DEBUG = false
|
APP_DEBUG = false
|
||||||
|
|
||||||
DB_TYPE = mysql
|
DB_TYPE = mysql
|
||||||
@ -94,136 +186,150 @@ DB_NAME = {$dbConfig['name']}
|
|||||||
DB_USER = {$dbConfig['user']}
|
DB_USER = {$dbConfig['user']}
|
||||||
DB_PASS = {$dbConfig['pass']}
|
DB_PASS = {$dbConfig['pass']}
|
||||||
DB_PORT = {$dbConfig['port']}
|
DB_PORT = {$dbConfig['port']}
|
||||||
DB_CHARSET = {$dbConfig['charset']}
|
|
||||||
DB_PREFIX = mpay_
|
DB_PREFIX = mpay_
|
||||||
|
|
||||||
DEFAULT_LANG = zh-cn
|
DEFAULT_LANG = zh-cn
|
||||||
EOT;
|
EOT;
|
||||||
return file_put_contents($envPath, $envContent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建数据库表
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
private function createTables()
|
private function createTables()
|
||||||
{
|
{
|
||||||
// 连接数据库
|
$db = $this->connectDatabase();
|
||||||
$db = Db::connect();
|
$tables = $this->getTableCreationSqls();
|
||||||
if ($db === false) {
|
|
||||||
return false;
|
foreach ($tables as $tableName => $sql) {
|
||||||
|
try {
|
||||||
|
$db->execute("DROP TABLE IF EXISTS `$tableName`;");
|
||||||
|
$db->execute($sql);
|
||||||
|
Log::info("$tableName 表创建成功");
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw new \Exception("创建 $tableName 表失败: " . $e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 创建order表的 SQL 语句
|
|
||||||
$sql = "CREATE TABLE `mpay_order` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`pid` int(11) NOT NULL DEFAULT '0' COMMENT '商户ID',
|
|
||||||
`order_id` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '订单号',
|
|
||||||
`type` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '支付类型',
|
|
||||||
`out_trade_no` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '商户订单号',
|
|
||||||
`notify_url` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '异步通知地址',
|
|
||||||
`return_url` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '跳转通知地址',
|
|
||||||
`name` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '商品名称',
|
|
||||||
`really_price` float NOT NULL DEFAULT '0' COMMENT '实际支付金额',
|
|
||||||
`money` float NOT NULL DEFAULT '0' COMMENT '订单价格',
|
|
||||||
`clientip` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '用户IP地址',
|
|
||||||
`device` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '设备类型',
|
|
||||||
`param` varchar(720) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '扩展参数',
|
|
||||||
`state` tinyint(4) NOT NULL DEFAULT '0' COMMENT '订单状态',
|
|
||||||
`patt` tinyint(4) NOT NULL DEFAULT '0' COMMENT '开启回调监听',
|
|
||||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '订单创建时间',
|
|
||||||
`close_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '订单关闭时间',
|
|
||||||
`pay_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
|
|
||||||
`platform_order` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '收款平台订单号',
|
|
||||||
`aid` int(11) NOT NULL DEFAULT '0' COMMENT '收款账号ID',
|
|
||||||
`cid` int(11) NOT NULL DEFAULT '0' COMMENT '收款码ID',
|
|
||||||
`delete_time` timestamp NULL DEFAULT NULL COMMENT '软删除',
|
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;";
|
|
||||||
|
|
||||||
// 执行 SQL 语句创建表
|
|
||||||
$db->execute("DROP TABLE IF EXISTS `mpay_order`;");
|
|
||||||
$db->execute($sql);
|
|
||||||
|
|
||||||
// 创建pay_account表的 SQL 语句
|
|
||||||
$sql = "CREATE TABLE `mpay_pay_account` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '收款平台ID',
|
|
||||||
`pid` int(11) NOT NULL DEFAULT '0' COMMENT '用户ID',
|
|
||||||
`platform` varchar(255) NOT NULL DEFAULT '' COMMENT '收款平台',
|
|
||||||
`account` varchar(255) NOT NULL DEFAULT '' COMMENT '账号',
|
|
||||||
`password` varchar(255) NOT NULL DEFAULT '' COMMENT '密码',
|
|
||||||
`state` tinyint(4) NOT NULL DEFAULT '1' COMMENT '启用',
|
|
||||||
`pattern` tinyint(4) NOT NULL DEFAULT '1' COMMENT '账号监听模式',
|
|
||||||
`params` text NOT NULL COMMENT '自定义查询',
|
|
||||||
`delete_time` timestamp NULL DEFAULT NULL COMMENT '软删除',
|
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;";
|
|
||||||
|
|
||||||
// 执行 SQL 语句创建表
|
|
||||||
$db->execute("DROP TABLE IF EXISTS `mpay_pay_account`;");
|
|
||||||
$db->execute($sql);
|
|
||||||
|
|
||||||
// 创建pay_channel表的 SQL 语句
|
|
||||||
$sql = "CREATE TABLE `mpay_pay_channel` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '渠道ID',
|
|
||||||
`account_id` int(11) NOT NULL DEFAULT '0' COMMENT '收款平台ID',
|
|
||||||
`channel` varchar(255) NOT NULL DEFAULT '' COMMENT '收款通道',
|
|
||||||
`type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '保存类型',
|
|
||||||
`qrcode` varchar(255) NOT NULL DEFAULT '' COMMENT '二维码',
|
|
||||||
`last_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最近使用',
|
|
||||||
`state` tinyint(4) NOT NULL DEFAULT '1' COMMENT '启用',
|
|
||||||
`delete_time` timestamp NULL DEFAULT NULL COMMENT '软删除',
|
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;";
|
|
||||||
|
|
||||||
// 执行 SQL 语句创建表
|
|
||||||
$db->execute("DROP TABLE IF EXISTS `mpay_pay_channel`;");
|
|
||||||
$db->execute($sql);
|
|
||||||
|
|
||||||
// 创建user表的 SQL 语句
|
|
||||||
$sql = "CREATE TABLE `mpay_user` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`pid` int(11) NOT NULL DEFAULT '0' COMMENT '商户ID',
|
|
||||||
`secret_key` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '商户秘钥',
|
|
||||||
`nickname` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '用户昵称',
|
|
||||||
`username` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '账号',
|
|
||||||
`password` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '密码',
|
|
||||||
`state` tinyint(4) NOT NULL DEFAULT '1' COMMENT '启用状态 0:禁用 1:启用',
|
|
||||||
`role` tinyint(4) NOT NULL DEFAULT '0' COMMENT '用户角色 0:普通用户 1:管理员',
|
|
||||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`delete_time` timestamp NULL DEFAULT NULL COMMENT '软删除',
|
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
|
||||||
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;";
|
|
||||||
|
|
||||||
// 执行 SQL 语句创建表
|
|
||||||
$db->execute("DROP TABLE IF EXISTS `mpay_user`;");
|
|
||||||
$db->execute($sql);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function initData($dbConfig)
|
/**
|
||||||
|
* 获取表创建的 SQL 语句
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getTableCreationSqls(): array
|
||||||
{
|
{
|
||||||
// 连接数据库
|
return [
|
||||||
$db = Db::connect();
|
'mpay_order' => "CREATE TABLE `mpay_order` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`pid` int(11) NOT NULL DEFAULT 0,
|
||||||
|
`order_id` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`type` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`out_trade_no` 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,
|
||||||
|
`clientip` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`device` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`param` varchar(720) NOT NULL DEFAULT '',
|
||||||
|
`state` tinyint(4) NOT NULL DEFAULT 0,
|
||||||
|
`patt` tinyint(4) NOT NULL DEFAULT 0,
|
||||||
|
`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,
|
||||||
|
`delete_time` datetime DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
INDEX `idx_order_id` (`order_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;",
|
||||||
|
'mpay_pay_account' => "CREATE TABLE `mpay_pay_account` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`pid` int(11) NOT NULL DEFAULT 0,
|
||||||
|
`platform` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`account` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`password` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`state` tinyint(4) NOT NULL DEFAULT 1,
|
||||||
|
`pattern` tinyint(4) NOT NULL DEFAULT 1,
|
||||||
|
`params` text NOT NULL,
|
||||||
|
`delete_time` datetime DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) 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(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 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,
|
||||||
|
`secret_key` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`nickname` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`username` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`password` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`state` tinyint(4) NOT NULL DEFAULT 1,
|
||||||
|
`role` tinyint(4) NOT NULL DEFAULT 0,
|
||||||
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`delete_time` datetime DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化数据
|
||||||
|
* @param array $dbConfig
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
private function initData(array $dbConfig)
|
||||||
|
{
|
||||||
|
$db = $this->connectDatabase();
|
||||||
$info = [
|
$info = [
|
||||||
'secret_key' => md5(1000 . time() . mt_rand()),
|
'secret_key' => md5(1000 . time() . mt_rand()),
|
||||||
'nickname' => $dbConfig['nickname'],
|
'nickname' => $dbConfig['nickname'],
|
||||||
'username' => $dbConfig['username'],
|
'username' => $dbConfig['username'],
|
||||||
'password' => password_hash($dbConfig['password'], PASSWORD_DEFAULT),
|
'password' => password_hash($dbConfig['password'], PASSWORD_DEFAULT),
|
||||||
|
'create_time' => date('Y-m-d H:i:s'),
|
||||||
];
|
];
|
||||||
// 初始化数据的 SQL 语句
|
|
||||||
$sql = "INSERT INTO `mpay_user` (`id`, `pid`, `secret_key`, `nickname`, `username`, `password`, `state`, `role`) VALUES (1, 1000, :secret_key, :nickname, :username, :password, 1, 1);";
|
|
||||||
|
|
||||||
// 执行 SQL 语句插入初始数据
|
$sql = "INSERT INTO `mpay_user` (`id`, `pid`, `secret_key`, `nickname`, `username`, `password`, `state`, `role`, `create_time`) VALUES (1, 1000, :secret_key, :nickname, :username, :password, 1, 1, :create_time);";
|
||||||
$is_succ = $db->execute($sql, $info);
|
|
||||||
if (!$is_succ) {
|
try {
|
||||||
return false;
|
$db->execute($sql, $info);
|
||||||
|
Log::info("mpay_user 表数据初始化成功");
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw new \Exception("初始化 mpay_user 表数据失败: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否已安装
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function checkLock()
|
private function checkLock()
|
||||||
{
|
{
|
||||||
$path = runtime_path() . 'install.lock';
|
$path = runtime_path() . self::INSTALL_LOCK_FILE;
|
||||||
return file_exists($path);
|
return file_exists($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置安装锁
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
private function setLock()
|
private function setLock()
|
||||||
{
|
{
|
||||||
$path = runtime_path() . 'install.lock';
|
$path = runtime_path() . self::INSTALL_LOCK_FILE;
|
||||||
file_put_contents($path, time());
|
if (file_put_contents($path, time()) === false) {
|
||||||
|
throw new \Exception("无法写入安装锁文件");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,20 @@ class PayController
|
|||||||
View::assign($act_order->toArray());
|
View::assign($act_order->toArray());
|
||||||
$passtime = strtotime($act_order->close_time) - time();
|
$passtime = strtotime($act_order->close_time) - time();
|
||||||
View::assign('passtime', $passtime > 0 ? $passtime : 0);
|
View::assign('passtime', $passtime > 0 ? $passtime : 0);
|
||||||
|
// Alipay免输
|
||||||
|
if (preg_match('/^alipay4#\d+$/', $channel->channel)) {
|
||||||
|
$chan = request()->get('chan', '');
|
||||||
|
if ($chan && $chan == 'Alipayf') {
|
||||||
|
$payurl = \payclient\AliPayf::getPayUrl($act_order->order_id, $act_order->money, $channel->qrcode, 1);
|
||||||
|
View::assign('payUrl', $payurl['data'] ?? $payurl['msg']);
|
||||||
|
View::assign('payclient', 'Alipayf');
|
||||||
|
} else {
|
||||||
|
$payurl = \payclient\AliPayf::getPayUrl($act_order->order_id, $act_order->money, $channel->qrcode);
|
||||||
|
}
|
||||||
|
View::assign('payUrl', $payurl['data'] ?? $payurl['msg']);
|
||||||
|
} else {
|
||||||
View::assign('payUrl', $channel->qrcode);
|
View::assign('payUrl', $channel->qrcode);
|
||||||
|
}
|
||||||
View::assign('code_type', $channel->type);
|
View::assign('code_type', $channel->type);
|
||||||
return View::fetch();
|
return View::fetch();
|
||||||
} else {
|
} else {
|
||||||
@ -159,15 +172,24 @@ class PayController
|
|||||||
foreach ($activeOrders as $order) {
|
foreach ($activeOrders as $order) {
|
||||||
// 支付方式核对
|
// 支付方式核对
|
||||||
$is_payway = $order->type == $new_order['payway'];
|
$is_payway = $order->type == $new_order['payway'];
|
||||||
|
if ($new_order['payway'] == '') $is_payway = true;
|
||||||
// 支付渠道核对
|
// 支付渠道核对
|
||||||
$is_channel = $cids[$order->cid] == $new_order['channel'];
|
$is_channel = $cids[$order->cid] == $new_order['channel'];
|
||||||
// 金额核对
|
// 金额核对
|
||||||
$is_money = $order->really_price == $new_order['price'];
|
$is_money = $order->really_price == $new_order['price'];
|
||||||
// 订单核对
|
// 订单核对
|
||||||
if ($is_payway && $is_channel && $is_money) {
|
if ($is_payway && $is_channel && $is_money) {
|
||||||
|
// 是否免输
|
||||||
|
if (isset($new_order['remark'])) {
|
||||||
|
if ($new_order['remark'] == $order->order_id) {
|
||||||
$res = $this->updateOrderState($order, $new_order['order_no']);
|
$res = $this->updateOrderState($order, $new_order['order_no']);
|
||||||
$notify[] = $res;
|
$notify[] = $res;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$res = $this->updateOrderState($order, $new_order['order_no']);
|
||||||
|
$notify[] = $res;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$notify) $notify = ['code' => 0, 'msg' => '收款通知无匹配订单'];
|
if (!$notify) $notify = ['code' => 0, 'msg' => '收款通知无匹配订单'];
|
||||||
@ -222,7 +244,7 @@ class PayController
|
|||||||
$config = PayAccount::getAccountConfig($req_aid);
|
$config = PayAccount::getAccountConfig($req_aid);
|
||||||
if ($config === false) return json(['code' => 4, 'msg' => '监听收款配置错误']);
|
if ($config === false) return json(['code' => 4, 'msg' => '监听收款配置错误']);
|
||||||
// 登陆账号
|
// 登陆账号
|
||||||
$pay_config = ['username' => $config['account'], 'password' => $config['password']];
|
$pay_config = ['username' => $config['account'], 'password' => $config['password'], 'aid' => $config['aid']];
|
||||||
// 配置参数
|
// 配置参数
|
||||||
$params = $config['params'];
|
$params = $config['params'];
|
||||||
// 实例监听客户端
|
// 实例监听客户端
|
||||||
@ -320,6 +342,10 @@ class PayController
|
|||||||
// 添加扩展参数
|
// 添加扩展参数
|
||||||
// $notify = array_merge($notify, unserialize($param->param));
|
// $notify = array_merge($notify, unserialize($param->param));
|
||||||
$notify['param'] = unserialize($param->param);
|
$notify['param'] = unserialize($param->param);
|
||||||
|
// 删除空值
|
||||||
|
foreach ($notify as $key => $val) {
|
||||||
|
if ($val === '') unset($notify[$key]);
|
||||||
|
}
|
||||||
return $notify;
|
return $notify;
|
||||||
}
|
}
|
||||||
// 请求外部资源
|
// 请求外部资源
|
||||||
|
@ -74,4 +74,9 @@ class PayManageController extends BaseController
|
|||||||
View::assign(['id' => $id]);
|
View::assign(['id' => $id]);
|
||||||
return View::fetch();
|
return View::fetch();
|
||||||
}
|
}
|
||||||
|
// 收款统计
|
||||||
|
public function payStatistics()
|
||||||
|
{
|
||||||
|
return View::fetch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,6 +162,10 @@ class OrderController extends BaseController
|
|||||||
// 添加扩展参数
|
// 添加扩展参数
|
||||||
// $notify = array_merge($notify, unserialize($param->param));
|
// $notify = array_merge($notify, unserialize($param->param));
|
||||||
$notify['param'] = unserialize($param->param);
|
$notify['param'] = unserialize($param->param);
|
||||||
|
// 删除空值
|
||||||
|
foreach ($notify as $key => $val) {
|
||||||
|
if ($val === '') unset($notify[$key]);
|
||||||
|
}
|
||||||
return $notify;
|
return $notify;
|
||||||
}
|
}
|
||||||
// 请求外部资源
|
// 请求外部资源
|
||||||
|
@ -7,6 +7,9 @@ namespace app\controller\api;
|
|||||||
use app\BaseController;
|
use app\BaseController;
|
||||||
use app\model\PayAccount;
|
use app\model\PayAccount;
|
||||||
use app\model\PayChannel;
|
use app\model\PayChannel;
|
||||||
|
use app\model\Order;
|
||||||
|
use think\facade\Db;
|
||||||
|
use \think\facade\Log;
|
||||||
|
|
||||||
class PayManageController extends BaseController
|
class PayManageController extends BaseController
|
||||||
{
|
{
|
||||||
@ -92,6 +95,7 @@ class PayManageController extends BaseController
|
|||||||
if ($check) {
|
if ($check) {
|
||||||
return json(backMsg(1, '编号已存在'));
|
return json(backMsg(1, '编号已存在'));
|
||||||
}
|
}
|
||||||
|
$info['last_time'] = date('Y-m-d H:i:s');
|
||||||
$res = PayChannel::create($info);
|
$res = PayChannel::create($info);
|
||||||
if ($res) {
|
if ($res) {
|
||||||
return json(backMsg(0, '添加成功'));
|
return json(backMsg(0, '添加成功'));
|
||||||
@ -124,23 +128,48 @@ class PayManageController extends BaseController
|
|||||||
// 上传二维码图片
|
// 上传二维码图片
|
||||||
public function uploadQrcode()
|
public function uploadQrcode()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
// 获取上传的文件
|
||||||
$img = $this->request->file('codeimg');
|
$img = $this->request->file('codeimg');
|
||||||
if (!$img) {
|
if (!$img) {
|
||||||
return json(backMsg(1, '请选择要上传的文件'));
|
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'];
|
$allowedTypes = ['image/png', 'image/jpeg', 'image/gif'];
|
||||||
$fileMimeType = $img->getMime();
|
$fileMimeType = $img->getMime();
|
||||||
if (!in_array($fileMimeType, $allowedTypes)) {
|
if (!in_array($fileMimeType, $allowedTypes)) {
|
||||||
return json(backMsg(1, '只允许上传 PNG、JPEG 或 GIF 格式的图片'));
|
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 = 'img_' . time() . '_' . uniqid() . '.' . $img->getOriginalExtension();
|
||||||
|
|
||||||
|
// 过滤文件名,防止路径遍历攻击
|
||||||
|
$filename = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', $filename);
|
||||||
|
|
||||||
// 设置文件保存路径
|
// 设置文件保存路径
|
||||||
$path = public_path() . '/files/qrcode/';
|
$path = public_path() . '/files/qrcode/';
|
||||||
if (!is_dir($path)) {
|
if (!is_dir($path)) {
|
||||||
mkdir($path, 0755, true);
|
if (!mkdir($path, 0755, true)) {
|
||||||
|
return json(backMsg(1, '创建目录失败'));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 移动文件到指定目录
|
// 移动文件到指定目录
|
||||||
$info = $img->move($path, $filename);
|
$info = $img->move($path, $filename);
|
||||||
if ($info) {
|
if ($info) {
|
||||||
@ -149,6 +178,10 @@ class PayManageController extends BaseController
|
|||||||
} else {
|
} else {
|
||||||
return json(backMsg(1, '上传失败'));
|
return json(backMsg(1, '上传失败'));
|
||||||
}
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('上传过程中出现异常: ' . $e->getMessage());
|
||||||
|
return json(backMsg(1, '上传过程中出现异常,请稍后重试'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 获取账号交易流水
|
// 获取账号交易流水
|
||||||
public function getAccountTrade()
|
public function getAccountTrade()
|
||||||
@ -161,7 +194,7 @@ class PayManageController extends BaseController
|
|||||||
if ($config === false) return json(backMsg(1, '账号配置文件错误'));
|
if ($config === false) return json(backMsg(1, '账号配置文件错误'));
|
||||||
if ($req_aid != $config['aid'] || $req_pid != session('pid')) return json(backMsg(1, '监听收款配置不一致'));
|
if ($req_aid != $config['aid'] || $req_pid != session('pid')) return json(backMsg(1, '监听收款配置不一致'));
|
||||||
// 登陆账号
|
// 登陆账号
|
||||||
$pay_config = ['username' => $config['account'], 'password' => $config['password']];
|
$pay_config = ['username' => $config['account'], 'password' => $config['password'], 'aid' => $config['aid']];
|
||||||
// 收款查询
|
// 收款查询
|
||||||
$params = $config['params'];
|
$params = $config['params'];
|
||||||
// 实例监听客户端
|
// 实例监听客户端
|
||||||
@ -177,4 +210,73 @@ class PayManageController extends BaseController
|
|||||||
return json(['code' => 1, 'msg' => $records['msg']]);
|
return json(['code' => 1, 'msg' => $records['msg']]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function payStatisticsList()
|
||||||
|
{
|
||||||
|
$query = $this->request->get();
|
||||||
|
$limit = $query['limit'] ?? 10;
|
||||||
|
$page = $query['page'] ?? 1;
|
||||||
|
$start_time = $query['time_start'] ?? date('Y-m-d H:i:s', strtotime('today'));
|
||||||
|
$end_time = $query['time_end'] ?? date('Y-m-d H:i:s', strtotime('tomorrow') - 1);
|
||||||
|
// 确保日期时间格式正确
|
||||||
|
$start_time = date('Y-m-d H:i:s', strtotime($start_time));
|
||||||
|
$end_time = date('Y-m-d H:i:s', strtotime($end_time));
|
||||||
|
|
||||||
|
$accounts = Db::table('mpay_pay_account', 'PayAccount')
|
||||||
|
->alias('PayAccount')
|
||||||
|
->join('mpay_order Order', 'PayAccount.id = Order.aid AND Order.delete_time IS NULL AND Order.state = 1', 'LEFT')
|
||||||
|
->field([
|
||||||
|
'PayAccount.*',
|
||||||
|
'SUM(CASE WHEN DATE(Order.pay_time) = CURDATE() THEN Order.really_price ELSE 0 END) as day',
|
||||||
|
'SUM(CASE WHEN DATE(Order.pay_time) = DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN Order.really_price ELSE 0 END) as yesterday',
|
||||||
|
'SUM(CASE WHEN YEARWEEK(Order.pay_time, 1) = YEARWEEK(CURDATE(), 1) THEN Order.really_price ELSE 0 END) as week',
|
||||||
|
'SUM(CASE WHEN DATE_FORMAT(Order.pay_time, "%Y-%m") = DATE_FORMAT(CURDATE(), "%Y-%m") THEN Order.really_price ELSE 0 END) as month',
|
||||||
|
'SUM(CASE WHEN YEAR(Order.pay_time) = YEAR(CURDATE()) THEN Order.really_price ELSE 0 END) as year',
|
||||||
|
'SUM(IFNULL(Order.really_price, 0)) as total',
|
||||||
|
"SUM(CASE WHEN Order.pay_time BETWEEN '$start_time' AND '$end_time' THEN Order.really_price ELSE 0 END) as income"
|
||||||
|
])
|
||||||
|
->where('PayAccount.delete_time IS NULL')
|
||||||
|
->group('PayAccount.id')
|
||||||
|
->order('PayAccount.id', 'DESC')
|
||||||
|
->paginate(['list_rows' => $limit, 'page' => $page]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 0,
|
||||||
|
'msg' => 'OK',
|
||||||
|
'count' => $accounts->total(),
|
||||||
|
'data' => $accounts->items()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收款统计
|
||||||
|
// public function payStatisticsList()
|
||||||
|
// {
|
||||||
|
// $query = $this->request->get();
|
||||||
|
// // 定义统计字段
|
||||||
|
// $fields = [
|
||||||
|
// "SUM(IF(DATE(pay_time) = CURDATE(), really_price, 0)) as day",
|
||||||
|
// "SUM(IF(DATE(pay_time) = CURDATE() - INTERVAL 1 DAY, really_price, 0)) as yesterday",
|
||||||
|
// "SUM(IF(YEARWEEK(pay_time, 1) = YEARWEEK(CURDATE(), 1), really_price, 0)) as week",
|
||||||
|
// "SUM(IF(DATE_FORMAT(pay_time, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m'), really_price, 0)) as month",
|
||||||
|
// "SUM(IF(YEAR(pay_time) = YEAR(CURDATE()), really_price, 0)) as year",
|
||||||
|
// "SUM(really_price) as total"
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// $where = ['state', 1;
|
||||||
|
|
||||||
|
// // 合并 pay_account 表字段和统计字段
|
||||||
|
// $allFields = array_merge([PayAccount::getTable() . '.*'], $fields);
|
||||||
|
|
||||||
|
// $accounts = PayAccount::hasWhere('order', $where, '*', 'LEFT')
|
||||||
|
// ->field($allFields)
|
||||||
|
// ->group(PayAccount::getTable() . '.id')
|
||||||
|
// ->order('id', 'desc')
|
||||||
|
// ->paginate(['list_rows' => $query['limit'] ?? 10, 'page' => $query['page'] ?? 1]);
|
||||||
|
|
||||||
|
// if ($accounts) {
|
||||||
|
// return json(['code' => 0, 'msg' => PayAccount::getLastSql(), 'count' => $accounts->total(), 'data' => $accounts->items()]);
|
||||||
|
// } else {
|
||||||
|
// return json(['code' => 1, 'msg' => '无数据记录', 'count' => 0, 'data' => []]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ class Order extends BaseModel
|
|||||||
// 商品金额
|
// 商品金额
|
||||||
'money' => $data['money'],
|
'money' => $data['money'],
|
||||||
// 实际成交金额
|
// 实际成交金额
|
||||||
'really_price' => self::checkMoney($data['money'], $data['type'], $channel['aid'], $channel['cid']),
|
'really_price' => self::checkMoney($data['money'], $data['type'], $channel['aid'], $channel['cid'], $channel['chan']),
|
||||||
// 用户IP
|
// 用户IP
|
||||||
'clientip' => isset($data['clientip']) ? $data['clientip'] : '',
|
'clientip' => isset($data['clientip']) ? $data['clientip'] : '',
|
||||||
// 设备类型
|
// 设备类型
|
||||||
@ -48,6 +48,8 @@ class Order extends BaseModel
|
|||||||
'state' => 0,
|
'state' => 0,
|
||||||
// 开启监听:1, 关闭监听:0
|
// 开启监听:1, 关闭监听:0
|
||||||
'patt' => $channel['patt'],
|
'patt' => $channel['patt'],
|
||||||
|
// 平台
|
||||||
|
'platform' => $channel['platform'],
|
||||||
// 订单创建时间
|
// 订单创建时间
|
||||||
'create_time' => self::getFormatTime($my_time),
|
'create_time' => self::getFormatTime($my_time),
|
||||||
// 订单关闭时间
|
// 订单关闭时间
|
||||||
@ -70,41 +72,32 @@ class Order extends BaseModel
|
|||||||
public static function serchOrders($query)
|
public static function serchOrders($query)
|
||||||
{
|
{
|
||||||
$select = [];
|
$select = [];
|
||||||
$_select = [];
|
$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',];
|
||||||
$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',];
|
|
||||||
foreach ($query as $key => $value) {
|
foreach ($query as $key => $value) {
|
||||||
if (in_array($key, $allow_field) && isset($value)) {
|
if (in_array($key, $allow_field) && isset($value)) {
|
||||||
if ($key === 'name') {
|
if ($key === 'name') {
|
||||||
$select[] = ['Order.' . $key, 'like', '%' . $value . '%'];
|
$select[] = [$key, 'like', '%' . $value . '%'];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($key === 'create_time_start') {
|
if ($key === 'create_time_start') {
|
||||||
$select[] = ['Order.' . 'create_time', '>', $value];
|
$select[] = ['create_time', '>', $value];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($key === 'create_time_end') {
|
if ($key === 'create_time_end') {
|
||||||
$select[] = ['Order.' . 'create_time', '<', $value];
|
$select[] = ['create_time', '<', $value];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($key === 'platform') {
|
$select[] = [$key, '=', $value];
|
||||||
$_select['platform'] = $value;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$select[] = ['Order.' . $key, '=', $value];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self::with('payAccount')
|
return self::where($select);
|
||||||
->hasWhere('payAccount', function ($query) use ($_select) {
|
|
||||||
$query->where($_select);
|
|
||||||
})
|
|
||||||
->where($select);
|
|
||||||
}
|
}
|
||||||
// 查询订单详细
|
// 查询订单详细
|
||||||
public static function showOrderDetail($id)
|
public static function showOrderDetail($id)
|
||||||
{
|
{
|
||||||
$order = self::find($id);
|
$order = self::find($id);
|
||||||
$a_list = PayAccount::find($order->aid);
|
$a_list = PayAccount::withTrashed()->find($order->aid);
|
||||||
$c_list = PayChannel::find($order->cid);
|
$c_list = PayChannel::withTrashed()->find($order->cid);
|
||||||
if (!$order) {
|
if (!$order) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -145,7 +138,7 @@ class Order extends BaseModel
|
|||||||
if (!$channel_info) return backMsg(3, '用户账户无可用收款通道');
|
if (!$channel_info) return backMsg(3, '用户账户无可用收款通道');
|
||||||
// 选取收款通道
|
// 选取收款通道
|
||||||
$patt = PayAccount::find($channel_info->account_id);
|
$patt = PayAccount::find($channel_info->account_id);
|
||||||
$channel = ['aid' => $channel_info->account_id, 'cid' => $channel_info->id, 'patt' => $patt->getData('pattern')];
|
$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']]);
|
PayChannel::update(['last_time' => self::getFormatTime(), 'id' => $channel['cid']]);
|
||||||
return backMsg(0, 'ok', $channel);
|
return backMsg(0, 'ok', $channel);
|
||||||
}
|
}
|
||||||
@ -162,9 +155,13 @@ class Order extends BaseModel
|
|||||||
// return $params;
|
// return $params;
|
||||||
// }
|
// }
|
||||||
// 检查金额
|
// 检查金额
|
||||||
private static function checkMoney($money, $type, $aid, $cid): float
|
private static function checkMoney($money, $type, $aid, $cid, $chan): float
|
||||||
{
|
{
|
||||||
$money = (float) $money;
|
$money = (float) $money;
|
||||||
|
// Alipay免输
|
||||||
|
if (preg_match('/^alipay4#\d+$/', $chan)) {
|
||||||
|
return $money;
|
||||||
|
}
|
||||||
// 查询有效订单
|
// 查询有效订单
|
||||||
$query = self::scope('activeOrder')->where(['type' => $type, 'aid' => $aid, 'cid' => $cid]);
|
$query = self::scope('activeOrder')->where(['type' => $type, 'aid' => $aid, 'cid' => $cid]);
|
||||||
$activeOrders = $query->column('really_price');
|
$activeOrders = $query->column('really_price');
|
||||||
@ -191,7 +188,9 @@ class Order extends BaseModel
|
|||||||
// 生成订单号
|
// 生成订单号
|
||||||
private static function createOrderID(string $prefix = ''): string
|
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)
|
public function scopeActiveOrder($query)
|
||||||
@ -211,6 +210,6 @@ class Order extends BaseModel
|
|||||||
// 模型多对一关联
|
// 模型多对一关联
|
||||||
public function payAccount()
|
public function payAccount()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(PayAccount::class, 'aid', 'id');
|
return $this->belongsTo(PayAccount::class, 'id', 'aid');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,31 @@ class PayAccount extends BaseModel
|
|||||||
$select[] = [$key, '=', $value];
|
$select[] = [$key, '=', $value];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self::withCount(['payChannel' => 'channel'])->where($select);
|
return self::withCount(['payChannel' => 'channel_num'])->withSum(['order' => function ($query, &$alias) {
|
||||||
|
$query->whereDay('pay_time')->where('state', 1);
|
||||||
|
$alias = 'income';
|
||||||
|
}], 'really_price')->where($select);
|
||||||
|
}
|
||||||
|
public static function findAccount($query)
|
||||||
|
{
|
||||||
|
$select = [];
|
||||||
|
$allow_field = ['state', 'platform', 'account', 'pattern'];
|
||||||
|
foreach ($query as $key => $value) {
|
||||||
|
if (in_array($key, $allow_field) && isset($value)) {
|
||||||
|
if ($key === 'account') {
|
||||||
|
$select[] = [$key, 'like', '%' . $value . '%'];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$select[] = [$key, '=', $value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self::where($select);
|
||||||
}
|
}
|
||||||
// 获取账号配置
|
// 获取账号配置
|
||||||
public static function getAccountConfig($aid, $pid = null): array|bool
|
public static function getAccountConfig($aid, $pid = null): array|bool
|
||||||
{
|
{
|
||||||
$aid_info = self::find($aid);
|
$aid_info = self::find($aid);
|
||||||
|
if (!$aid_info) return false;
|
||||||
// 插件配置
|
// 插件配置
|
||||||
$platform = PluginController::getPluginInfo($aid_info->getData('platform'));
|
$platform = PluginController::getPluginInfo($aid_info->getData('platform'));
|
||||||
// 查询参数
|
// 查询参数
|
||||||
@ -85,4 +104,9 @@ class PayAccount extends BaseModel
|
|||||||
{
|
{
|
||||||
return $this->hasMany(PayChannel::class, 'account_id', 'id');
|
return $this->hasMany(PayChannel::class, 'account_id', 'id');
|
||||||
}
|
}
|
||||||
|
// 一对多关联
|
||||||
|
public function order()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Order::class, 'aid', 'id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
BIN
assets/微信PC监控_v1.4.exe
Normal file
BIN
assets/微信PC监控_v1.4.exe
Normal file
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' => '',
|
|
||||||
'version' => '1.0',
|
|
||||||
'state' => 1,
|
|
||||||
),
|
|
||||||
1 =>
|
|
||||||
array (
|
|
||||||
'platform' => 'sqbpay',
|
|
||||||
'name' => '收钱吧',
|
|
||||||
'class_name' => 'ShouQianBa',
|
|
||||||
'price' => NULL,
|
|
||||||
'describe' => '主流移动支付全能收 信用卡,花呗都能用,生意帮手收钱吧,移动收款就用它!',
|
|
||||||
'website' => 'https://www.shouqianba.com',
|
|
||||||
'helplink' => '',
|
|
||||||
'version' => '1.0',
|
|
||||||
'state' => 1,
|
|
||||||
),
|
|
||||||
2 =>
|
|
||||||
array (
|
|
||||||
'platform' => 'alipay',
|
|
||||||
'name' => '支付宝',
|
|
||||||
'class_name' => 'AliPay',
|
|
||||||
'price' => NULL,
|
|
||||||
'describe' => '支持支付宝个人收款码、经营码收款,监听回调',
|
|
||||||
'website' => 'https://www.alipay.com',
|
|
||||||
'helplink' => '',
|
|
||||||
'version' => '1.0',
|
|
||||||
'state' => 1,
|
|
||||||
),
|
|
||||||
);
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
class Plugin
|
class Plugin
|
||||||
{
|
{
|
||||||
private static $siteUrl = 'https://api.zhaidashi.cn';
|
private static $siteUrl = 'https://api.qcjy.cc';
|
||||||
// 获取全部插件(含本地)
|
// 获取全部插件(含本地)
|
||||||
public static function getAllPlugins(array $local_plugin = []): array
|
public static function getAllPlugins(array $local_plugin = []): array
|
||||||
{
|
{
|
||||||
@ -63,10 +63,12 @@ class Plugin
|
|||||||
public static function getNotifyMessage(): array
|
public static function getNotifyMessage(): array
|
||||||
{
|
{
|
||||||
$message = cache('message');
|
$message = cache('message');
|
||||||
if ($message) return json_decode($message, true);
|
if ($message) return $message;
|
||||||
$message = self::getHttpResponse(self::$siteUrl . '/MpayApi', ['action' => 'message']);
|
$message = self::getHttpResponse(self::$siteUrl . '/MpayApi', ['action' => 'message'], [], 3);
|
||||||
cache('message', $message, 36000);
|
$info = json_decode($message, true);
|
||||||
return json_decode($message, true);
|
if ($info === null) return [];
|
||||||
|
if ($info['code'] === 0) cache('message', $info['data'], 36000);
|
||||||
|
return $info['data'];
|
||||||
}
|
}
|
||||||
// 安装插件
|
// 安装插件
|
||||||
public static function installPlugin($platform): array
|
public static function installPlugin($platform): array
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
BIN
public/files/qrcode/img_1747104593_6822b351cab62.jpg
Normal file
BIN
public/files/qrcode/img_1747104593_6822b351cab62.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
@ -82,7 +82,7 @@
|
|||||||
<div class="layui-side-scroll">
|
<div class="layui-side-scroll">
|
||||||
<div id="sideMenu"></div>
|
<div id="sideMenu"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="version"><p>版本号:<?php echo $version ?></p><p>by techhaha</p></div>
|
<div id="version"><p>版本号:<?php echo $version ?></p><p>by 技术老胡</p></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 视 图 页 面 -->
|
<!-- 视 图 页 面 -->
|
||||||
<div class="layui-body">
|
<div class="layui-body">
|
||||||
|
@ -8,9 +8,6 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>开发文档</title>
|
<title>开发文档</title>
|
||||||
</head>
|
</head>
|
||||||
<link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/KaTeX/0.7.1/katex.min.css">
|
|
||||||
<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">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
font-family: "Helvetica Neue", "Helvetica", "Microsoft Yahei", "微软雅黑", "Lantinghei SC", "STXihei", "WenQuanYi Micro Hei", Arial, sans-serif;
|
font-family: "Helvetica Neue", "Helvetica", "Microsoft Yahei", "微软雅黑", "Lantinghei SC", "STXihei", "WenQuanYi Micro Hei", Arial, sans-serif;
|
||||||
@ -339,13 +336,111 @@
|
|||||||
list-style-type: decimal !important;
|
list-style-type: decimal !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
/* 新增样式 */
|
||||||
|
.doc-container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-nav {
|
||||||
|
position: fixed;
|
||||||
|
left: 20px;
|
||||||
|
top: 100px;
|
||||||
|
width: 200px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 992px) {
|
||||||
|
.doc-nav {
|
||||||
|
display: none;
|
||||||
|
/* 小屏幕隐藏导航栏 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-nav a {
|
||||||
|
display: block;
|
||||||
|
padding: 8px 12px;
|
||||||
|
color: #333;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-nav a:hover {
|
||||||
|
background: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
margin: 20px 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table th {
|
||||||
|
background: #f8f9fa;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 12px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
padding: 12px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:nth-child(even) {
|
||||||
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:hover {
|
||||||
|
background: #f1f3f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
display: block;
|
||||||
|
padding: 15px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 40px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 2px solid #eee;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<!-- <a href="javascript:window.print();" class="print-btn">打印(Print)</a> -->
|
<!-- <a href="javascript:window.print();" class="print-btn">打印(Print)</a> -->
|
||||||
<!-- MarkDown Content -->
|
<!-- MarkDown Content -->
|
||||||
|
<div class="doc-container">
|
||||||
|
<!-- 新增导航菜单 -->
|
||||||
|
<div class="doc-nav">
|
||||||
|
<a href="#toc2">协议规则</a>
|
||||||
|
<a href="#pay0">页面跳转支付</a>
|
||||||
|
<a href="#pay1">API接口支付</a>
|
||||||
|
<a href="#pay2">支付结果通知</a>
|
||||||
|
<a href="#pay3">MD5签名算法</a>
|
||||||
|
<a href="#pay4">支付方式列表</a>
|
||||||
|
<a href="#pay5">设备类型列表</a>
|
||||||
|
</div>
|
||||||
<h3 id="toc2"><a name="协议规则" class="reference-link"></a><span
|
<h3 id="toc2"><a name="协议规则" class="reference-link"></a><span
|
||||||
class="header-link octicon octicon-link"></span>协议规则</h3>
|
class="header-link octicon octicon-link"></span>协议规则
|
||||||
|
</h3>
|
||||||
<p>请求数据格式:application/x-www-form-urlencode</p>
|
<p>请求数据格式:application/x-www-form-urlencode</p>
|
||||||
<p>返回数据格式:JSON</p>
|
<p>返回数据格式:JSON</p>
|
||||||
<p>签名算法:MD5</p>
|
<p>签名算法:MD5</p>
|
||||||
@ -353,7 +448,9 @@
|
|||||||
<h3 id="pay0"><a name="页面跳转支付" class="reference-link"></a><span
|
<h3 id="pay0"><a name="页面跳转支付" class="reference-link"></a><span
|
||||||
class="header-link octicon octicon-link"></span>页面跳转支付</h3>
|
class="header-link octicon octicon-link"></span>页面跳转支付</h3>
|
||||||
<p>此接口可用于用户前台直接发起支付,使用form表单跳转或拼接成url跳转。</p>
|
<p>此接口可用于用户前台直接发起支付,使用form表单跳转或拼接成url跳转。</p>
|
||||||
<p>URL地址:<a href="javascript:void(0);"><?php echo $domain ?>/submit.php</a></p>
|
<p>URL地址:<a href="javascript:void(0);">
|
||||||
|
<?php echo $domain ?>/submit.php
|
||||||
|
</a></p>
|
||||||
<p>请求方式:POST 或 GET(推荐POST,不容易被劫持或屏蔽)</p>
|
<p>请求方式:POST 或 GET(推荐POST,不容易被劫持或屏蔽)</p>
|
||||||
<p>请求参数说明:</p>
|
<p>请求参数说明:</p>
|
||||||
<table>
|
<table>
|
||||||
@ -454,7 +551,9 @@
|
|||||||
<h3 id="pay1"><a name="API接口支付" class="reference-link"></a><span
|
<h3 id="pay1"><a name="API接口支付" class="reference-link"></a><span
|
||||||
class="header-link octicon octicon-link"></span>API接口支付</h3>
|
class="header-link octicon octicon-link"></span>API接口支付</h3>
|
||||||
<p>此接口可用于服务器后端发起支付请求,会返回支付二维码链接或支付跳转url。</p>
|
<p>此接口可用于服务器后端发起支付请求,会返回支付二维码链接或支付跳转url。</p>
|
||||||
<p>URL地址:<a href="javascript:void(0);"><?php echo $domain ?>/mapi.php</a></p>
|
<p>URL地址:<a href="javascript:void(0);">
|
||||||
|
<?php echo $domain ?>/mapi.php
|
||||||
|
</a></p>
|
||||||
<p>请求方式:POST</p>
|
<p>请求方式:POST</p>
|
||||||
<p>请求参数说明:</p>
|
<p>请求参数说明:</p>
|
||||||
<table>
|
<table>
|
||||||
@ -604,8 +703,9 @@
|
|||||||
<td>支付跳转url</td>
|
<td>支付跳转url</td>
|
||||||
<td>payurl</td>
|
<td>payurl</td>
|
||||||
<td>String</td>
|
<td>String</td>
|
||||||
<td><a
|
<td><a href="javascript:void(0);">
|
||||||
href="javascript:void(0);"><?php echo $domain ?>/pay/wxpay/202010903/</a>
|
<?php echo $domain ?>/pay/wxpay/202010903/
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>如果返回该字段,则直接跳转到该url支付</td>
|
<td>如果返回该字段,则直接跳转到该url支付</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -790,579 +890,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<h3 id="api1"><a name="[API]查询商户信息" class="reference-link"></a><span
|
</div>
|
||||||
class="header-link octicon octicon-link"></span>[API]查询商户信息</h3>
|
|
||||||
<p>URL地址:<a
|
|
||||||
href="javascript:void(0);"><?php echo $domain ?>/api.php?act=query&pid={商户ID}&key={商户密钥}</a>
|
|
||||||
</p>
|
|
||||||
<p>请求参数说明:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>必填</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>操作类型</td>
|
|
||||||
<td>act</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>query</td>
|
|
||||||
<td>此API固定值</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户ID</td>
|
|
||||||
<td>pid</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1001</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户密钥</td>
|
|
||||||
<td>key</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p>返回结果:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>返回状态码</td>
|
|
||||||
<td>code</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1为成功,其它值为失败</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户ID</td>
|
|
||||||
<td>pid</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1001</td>
|
|
||||||
<td>商户ID</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户密钥</td>
|
|
||||||
<td>key</td>
|
|
||||||
<td>String(32)</td>
|
|
||||||
<td>89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i</td>
|
|
||||||
<td>商户密钥</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户状态</td>
|
|
||||||
<td>active</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1为正常,0为封禁</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户余额</td>
|
|
||||||
<td>money</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>0.00</td>
|
|
||||||
<td>商户所拥有的余额</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>结算方式</td>
|
|
||||||
<td>type</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1:支付宝,2:微信,3:QQ,4:银行卡</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>结算账号</td>
|
|
||||||
<td>account</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td><a href="javascript:void(0);">admin@pay.com</a></td>
|
|
||||||
<td>结算的支付宝账号</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>结算姓名</td>
|
|
||||||
<td>username</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>张三</td>
|
|
||||||
<td>结算的支付宝姓名</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>订单总数</td>
|
|
||||||
<td>orders</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>30</td>
|
|
||||||
<td>订单总数统计</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>今日订单</td>
|
|
||||||
<td>order_today</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>15</td>
|
|
||||||
<td>今日订单数量</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>昨日订单</td>
|
|
||||||
<td>order_lastday</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>15</td>
|
|
||||||
<td>昨日订单数量</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h3 id="api2"><a name="[API]查询结算记录" class="reference-link"></a><span
|
|
||||||
class="header-link octicon octicon-link"></span>[API]查询结算记录</h3>
|
|
||||||
<p>URL地址:<a
|
|
||||||
href="javascript:void(0);"><?php echo $domain ?>/api.php?act=settle&pid={商户ID}&key={商户密钥}</a>
|
|
||||||
</p>
|
|
||||||
<p>请求参数说明:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>必填</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>操作类型</td>
|
|
||||||
<td>act</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>settle</td>
|
|
||||||
<td>此API固定值</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户ID</td>
|
|
||||||
<td>pid</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1001</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户密钥</td>
|
|
||||||
<td>key</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p>返回结果:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>返回状态码</td>
|
|
||||||
<td>code</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1为成功,其它值为失败</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>返回信息</td>
|
|
||||||
<td>msg</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>查询结算记录成功!</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>结算记录</td>
|
|
||||||
<td>data</td>
|
|
||||||
<td>Array</td>
|
|
||||||
<td>结算记录列表</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h3 id="api3"><a name="[API]查询单个订单" class="reference-link"></a><span
|
|
||||||
class="header-link octicon octicon-link"></span>[API]查询单个订单</h3>
|
|
||||||
<p>URL地址:<a
|
|
||||||
href="javascript:void(0);"><?php echo $domain ?>/api.php?act=order&pid={商户ID}&key={商户密钥}&out_trade_no={商户订单号}</a>
|
|
||||||
</p>
|
|
||||||
<p>请求参数说明:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>必填</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>操作类型</td>
|
|
||||||
<td>act</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>order</td>
|
|
||||||
<td>此API固定值</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户ID</td>
|
|
||||||
<td>pid</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1001</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户密钥</td>
|
|
||||||
<td>key</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>系统订单号</td>
|
|
||||||
<td>trade_no</td>
|
|
||||||
<td>选择</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>20160806151343312</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户订单号</td>
|
|
||||||
<td>out_trade_no</td>
|
|
||||||
<td>选择</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>20160806151343349</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p>提示:系统订单号 和 商户订单号 二选一传入即可,如果都传入以系统订单号为准!</p>
|
|
||||||
<p>返回结果:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>返回状态码</td>
|
|
||||||
<td>code</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1为成功,其它值为失败</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>返回信息</td>
|
|
||||||
<td>msg</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>查询订单号成功!</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>易支付订单号</td>
|
|
||||||
<td>trade_no</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>2016080622555342651</td>
|
|
||||||
<td>聚合易支付订单号</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户订单号</td>
|
|
||||||
<td>out_trade_no</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>20160806151343349</td>
|
|
||||||
<td>商户系统内部的订单号</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>第三方订单号</td>
|
|
||||||
<td>api_trade_no</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>20160806151343349</td>
|
|
||||||
<td>支付宝微信等接口方订单号</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>支付方式</td>
|
|
||||||
<td>type</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>alipay</td>
|
|
||||||
<td><a href="#pay4">支付方式列表</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户ID</td>
|
|
||||||
<td>pid</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1001</td>
|
|
||||||
<td>发起支付的商户ID</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>创建订单时间</td>
|
|
||||||
<td>addtime</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>2016-08-06 22:55:52</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>完成交易时间</td>
|
|
||||||
<td>endtime</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>2016-08-06 22:55:52</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商品名称</td>
|
|
||||||
<td>name</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>VIP会员</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商品金额</td>
|
|
||||||
<td>money</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>1.00</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>支付状态</td>
|
|
||||||
<td>status</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>0</td>
|
|
||||||
<td>1为支付成功,0为未支付</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>业务扩展参数</td>
|
|
||||||
<td>param</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td></td>
|
|
||||||
<td>默认留空</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>支付者账号</td>
|
|
||||||
<td>buyer</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td></td>
|
|
||||||
<td>默认留空</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h3 id="api4"><a name="[API]批量查询订单" class="reference-link"></a><span
|
|
||||||
class="header-link octicon octicon-link"></span>[API]批量查询订单</h3>
|
|
||||||
<p>URL地址:<a
|
|
||||||
href="javascript:void(0);"><?php echo $domain ?>/api.php?act=orders&pid={商户ID}&key={商户密钥}</a>
|
|
||||||
</p>
|
|
||||||
<p>请求参数说明:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>必填</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>操作类型</td>
|
|
||||||
<td>act</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>orders</td>
|
|
||||||
<td>此API固定值</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户ID</td>
|
|
||||||
<td>pid</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1001</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户密钥</td>
|
|
||||||
<td>key</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>查询订单数量</td>
|
|
||||||
<td>limit</td>
|
|
||||||
<td>否</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>20</td>
|
|
||||||
<td>返回的订单数量,最大50</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>页码</td>
|
|
||||||
<td>page</td>
|
|
||||||
<td>否</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>当前查询的页码</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p>返回结果:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>返回状态码</td>
|
|
||||||
<td>code</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1为成功,其它值为失败</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>返回信息</td>
|
|
||||||
<td>msg</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>查询结算记录成功!</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>订单列表</td>
|
|
||||||
<td>data</td>
|
|
||||||
<td>Array</td>
|
|
||||||
<td></td>
|
|
||||||
<td>订单列表</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h3 id="api5"><a name="[API]提交订单退款" class="reference-link"></a><span
|
|
||||||
class="header-link octicon octicon-link"></span>[API]提交订单退款</h3>
|
|
||||||
<p>需要先在商户后台开启订单退款API接口开关,才能调用该接口发起订单退款</p>
|
|
||||||
<p>URL地址:<a href="javascript:void(0);"><?php echo $domain ?>/api.php?act=refund</a></p>
|
|
||||||
<p>请求方式:POST</p>
|
|
||||||
<p>请求参数说明:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>必填</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>商户ID</td>
|
|
||||||
<td>pid</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1001</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户密钥</td>
|
|
||||||
<td>key</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>易支付订单号</td>
|
|
||||||
<td>trade_no</td>
|
|
||||||
<td>特殊可选</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>20160806151343349021</td>
|
|
||||||
<td>易支付订单号</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>商户订单号</td>
|
|
||||||
<td>out_trade_no</td>
|
|
||||||
<td>特殊可选</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>20160806151343349</td>
|
|
||||||
<td>订单支付时传入的商户订单号,商家自定义且保证商家系统中唯一</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>退款金额</td>
|
|
||||||
<td>money</td>
|
|
||||||
<td>是</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>1.50</td>
|
|
||||||
<td>少数通道需要与原订单金额一致</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p>注:trade_no、out_trade_no 不能同时为空,如果都传了以trade_no为准</p>
|
|
||||||
<p>返回结果:</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>字段名</th>
|
|
||||||
<th>变量名</th>
|
|
||||||
<th>类型</th>
|
|
||||||
<th>示例值</th>
|
|
||||||
<th>描述</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>返回状态码</td>
|
|
||||||
<td>code</td>
|
|
||||||
<td>Int</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1为成功,其它值为失败</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>返回信息</td>
|
|
||||||
<td>msg</td>
|
|
||||||
<td>String</td>
|
|
||||||
<td>退款成功</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- /MarkDown Content -->
|
<!-- /MarkDown Content -->
|
||||||
</body>
|
</body>
|
||||||
<html>
|
<html>
|
@ -113,7 +113,7 @@
|
|||||||
</a></li>
|
</a></li>
|
||||||
<?php }else{ ?>
|
<?php }else{ ?>
|
||||||
<li><a href="/User/login" class="a-head-btn bdr-5 bg-color-white">登录</a></li>
|
<li><a href="/User/login" class="a-head-btn bdr-5 bg-color-white">登录</a></li>
|
||||||
<li><a href="/" class="a-head-btn bdr-5 bg-color-0055ff">注册</a></li>
|
<!-- <li><a href="/" class="a-head-btn bdr-5 bg-color-0055ff">注册</a></li> -->
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -127,7 +127,7 @@
|
|||||||
<div class="title-heading mt-4">
|
<div class="title-heading mt-4">
|
||||||
<h1 class="heading mb-3">码支付<small class="text-success" style="font-size: 50%">
|
<h1 class="heading mb-3">码支付<small class="text-success" style="font-size: 50%">
|
||||||
[ˈheɪloʊ]</small></h1>
|
[ˈheɪloʊ]</small></h1>
|
||||||
<p class="para-desc text-muted">源支付,扫码支付,免签支付,聚合支付,码支付免签约,聚合支付平台。</p>
|
<p class="para-desc text-muted">基于易支付接口开发的免签收款工具,方便个人在线收款。</p>
|
||||||
<div class="mt-4 pt-2">
|
<div class="mt-4 pt-2">
|
||||||
<a href="/User/login" class="btn btn-primary mr-2"><svg xmlns="http://www.w3.org/2000/svg"
|
<a href="/User/login" class="btn btn-primary mr-2"><svg xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img"
|
xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img"
|
||||||
@ -322,7 +322,7 @@
|
|||||||
document.write(new Date().getFullYear());
|
document.write(new Date().getFullYear());
|
||||||
</script>2024 <a href="/">码支付</a> - All
|
</script>2024 <a href="/">码支付</a> - All
|
||||||
rights reserved<span class="sep"> | </span><a href="https://beian.miit.gov.cn/"
|
rights reserved<span class="sep"> | </span><a href="https://beian.miit.gov.cn/"
|
||||||
target="_blank" rel="noreferrer nofollow">湘ICP备2023031541号-2</a>
|
target="_blank" rel="noreferrer nofollow">湘ICP备********号</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -54,17 +54,10 @@
|
|||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">端口</label>
|
<label class="layui-form-label">端口</label>
|
||||||
<div class="layui-input-block">
|
<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">
|
autocomplete="off" class="layui-input" value="3306">
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">数据库</label>
|
<label class="layui-form-label">数据库</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
@ -76,7 +69,7 @@
|
|||||||
<label class="layui-form-label">用户名</label>
|
<label class="layui-form-label">用户名</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<input type="text" name="user" required lay-verify="required" placeholder="请输入数据库用户名"
|
<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>
|
</div>
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
@ -90,21 +83,21 @@
|
|||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">管理员昵称</label>
|
<label class="layui-form-label">管理员昵称</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<input type="text" name="nickname" required lay-verify="required" placeholder="请输入管理员昵称"
|
<input type="text" name="nickname" required lay-verify="required" placeholder="设置管理员昵称"
|
||||||
autocomplete="off" class="layui-input" value="勇敢牛牛">
|
autocomplete="off" class="layui-input" value="Mpay">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">管理员账号</label>
|
<label class="layui-form-label">管理员账号</label>
|
||||||
<div class="layui-input-block">
|
<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">
|
autocomplete="off" class="layui-input" value="admin">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">管理员密码</label>
|
<label class="layui-form-label">管理员密码</label>
|
||||||
<div class="layui-input-block">
|
<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">
|
autocomplete="off" class="layui-input">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -39,9 +39,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-inline">
|
<div class="layui-inline">
|
||||||
<label class="layui-form-label">用户ID</label>
|
<label class="layui-form-label">平台流水号</label>
|
||||||
<div class="layui-input-inline">
|
<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>
|
</div>
|
||||||
<div class="layui-inline">
|
<div class="layui-inline">
|
||||||
@ -203,13 +204,26 @@
|
|||||||
(async () => {
|
(async () => {
|
||||||
const data = await fetch('/api/Plugin/pluginOption').then(res => res.json());
|
const data = await fetch('/api/Plugin/pluginOption').then(res => res.json());
|
||||||
let option_str = `<option value="">收款平台</option>`;
|
let option_str = `<option value="">收款平台</option>`;
|
||||||
|
let platforms = {};
|
||||||
data.forEach(val => {
|
data.forEach(val => {
|
||||||
option_str += `<option value="${val.platform}">${val.name}</option>`;
|
option_str += `<option value="${val.platform}">${val.name}</option>`;
|
||||||
|
platforms[val.platform] = val.name;
|
||||||
});
|
});
|
||||||
const select = document.querySelector('select[name="platform"]');
|
const select = document.querySelector('select[name="platform"]');
|
||||||
select.innerHTML = option_str;
|
select.innerHTML = option_str;
|
||||||
form.render('select');
|
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}]`;
|
||||||
|
}
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const where = {};
|
||||||
|
urlParams.forEach((value, key) => {
|
||||||
|
where[key] = value;
|
||||||
|
});
|
||||||
// 表格列参数
|
// 表格列参数
|
||||||
let cols = [[
|
let cols = [[
|
||||||
{ type: 'checkbox' },
|
{ type: 'checkbox' },
|
||||||
@ -222,7 +236,7 @@
|
|||||||
{ 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: '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: '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: '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: '收款平台[账号:终端]', 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>' }
|
{ 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>' }
|
||||||
]]
|
]]
|
||||||
// 表格渲染
|
// 表格渲染
|
||||||
@ -230,6 +244,7 @@
|
|||||||
id: 'orders-table',
|
id: 'orders-table',
|
||||||
elem: '#orders-table',
|
elem: '#orders-table',
|
||||||
url: '/api/Order/getOrders',
|
url: '/api/Order/getOrders',
|
||||||
|
where: where,
|
||||||
page: true,
|
page: true,
|
||||||
cols: cols,
|
cols: cols,
|
||||||
skin: 'line',
|
skin: 'line',
|
||||||
@ -256,7 +271,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
})()
|
||||||
// 事件处理
|
// 事件处理
|
||||||
|
|
||||||
// 表格单元格事件
|
// 表格单元格事件
|
||||||
|
@ -6,6 +6,44 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>收银台</title>
|
<title>收银台</title>
|
||||||
<link rel="stylesheet" href="/component/pear/css/pear.css" />
|
<link rel="stylesheet" href="/component/pear/css/pear.css" />
|
||||||
|
<script>
|
||||||
|
function detectBrowserEnvironment() {
|
||||||
|
const userAgent = navigator.userAgent.toLowerCase();
|
||||||
|
let environment = 'other';
|
||||||
|
if (userAgent.includes('micromessenger')) {
|
||||||
|
if (userAgent.includes('miniprogram')) {
|
||||||
|
environment = 'wxapp'; // 微信小程序
|
||||||
|
} else if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
|
||||||
|
environment = 'wxphone'; // 手机微信
|
||||||
|
} else {
|
||||||
|
environment = 'wxpc'; // PC微信
|
||||||
|
}
|
||||||
|
} else if (userAgent.includes('aliapp') || userAgent.includes('alipayclient')) {
|
||||||
|
if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
|
||||||
|
environment = 'aliphone'; // 手机支付宝
|
||||||
|
} else {
|
||||||
|
environment = 'alipc'; // PC支付宝
|
||||||
|
}
|
||||||
|
} else if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
|
||||||
|
// 先判断是否是已知的手机APP内置浏览器,如果不是则认为是手机浏览器
|
||||||
|
if (!userAgent.includes('micromessenger') && !userAgent.includes('aliapp') && !userAgent.includes('qq')) {
|
||||||
|
environment = 'phone'; // 手机浏览器
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
environment = 'pc'; // 剩下的情况认为是PC浏览器
|
||||||
|
}
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
const payCode = '<?php echo $payUrl; ?>';
|
||||||
|
const codeType = '<?php echo htmlentities($code_type); ?>';
|
||||||
|
const payType = '<?php echo htmlentities($type); ?>';
|
||||||
|
const order = '<?php echo htmlentities($order_id); ?>';
|
||||||
|
const environment = detectBrowserEnvironment();
|
||||||
|
const payclient = '<?php echo htmlentities($payclient ?? ""); ?>';
|
||||||
|
if (payclient == 'Alipayf' && environment == 'aliphone') {
|
||||||
|
window.location.href = payCode;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background: #f7f7f7;
|
background: #f7f7f7;
|
||||||
@ -134,6 +172,12 @@
|
|||||||
</span><span>元</span></div>
|
</span><span>元</span></div>
|
||||||
<div class="qrcode"><img id="qrcode" src="/static/img/loading.gif">
|
<div class="qrcode"><img id="qrcode" src="/static/img/loading.gif">
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 添加跳转按钮 -->
|
||||||
|
<div style="margin: 16px auto;display: none;">
|
||||||
|
<button id="openApp" class="layui-btn layui-btn-normal">
|
||||||
|
打开支付应用
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="msg">
|
<div class="msg">
|
||||||
<p>请付款 <span class="note">
|
<p>请付款 <span class="note">
|
||||||
<?php echo htmlentities($really_price); ?>
|
<?php echo htmlentities($really_price); ?>
|
||||||
@ -151,39 +195,6 @@
|
|||||||
<script src="/component/layui/layui.js"></script>
|
<script src="/component/layui/layui.js"></script>
|
||||||
<script src="/static/js/awesome-qr.min.js"></script>
|
<script src="/static/js/awesome-qr.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function detectBrowserEnvironment() {
|
|
||||||
const userAgent = navigator.userAgent.toLowerCase();
|
|
||||||
let environment = 'other';
|
|
||||||
if (userAgent.includes('micromessenger')) {
|
|
||||||
if (userAgent.includes('miniprogram')) {
|
|
||||||
environment = 'wxapp'; // 微信小程序
|
|
||||||
} else if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
|
|
||||||
environment = 'wxphone'; // 手机微信
|
|
||||||
} else {
|
|
||||||
environment = 'wxpc'; // PC微信
|
|
||||||
}
|
|
||||||
} else if (userAgent.includes('aliapp') || userAgent.includes('alipayclient')) {
|
|
||||||
if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
|
|
||||||
environment = 'aliphone'; // 手机支付宝
|
|
||||||
} else {
|
|
||||||
environment = 'alipc'; // PC支付宝
|
|
||||||
}
|
|
||||||
} else if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
|
|
||||||
// 先判断是否是已知的手机APP内置浏览器,如果不是则认为是手机浏览器
|
|
||||||
if (!userAgent.includes('micromessenger') && !userAgent.includes('aliapp') && !userAgent.includes('qq')) {
|
|
||||||
environment = 'phone'; // 手机浏览器
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
environment = 'pc'; // 剩下的情况认为是PC浏览器
|
|
||||||
}
|
|
||||||
return environment;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
const payCode = '<?php echo htmlentities($payUrl); ?>';
|
|
||||||
const codeType = '<?php echo htmlentities($code_type); ?>';
|
|
||||||
const payType = '<?php echo htmlentities($type); ?>';
|
|
||||||
const order = '<?php echo htmlentities($order_id); ?>';
|
|
||||||
const QR = AwesomeQR.AwesomeQR;
|
const QR = AwesomeQR.AwesomeQR;
|
||||||
(async () => {
|
(async () => {
|
||||||
// 支付类型
|
// 支付类型
|
||||||
@ -201,7 +212,16 @@
|
|||||||
}
|
}
|
||||||
// 生成二维码
|
// 生成二维码
|
||||||
if (codeType == 0) {
|
if (codeType == 0) {
|
||||||
|
if (payType === 'alipay' && environment === 'pc') {
|
||||||
|
// 解析网址
|
||||||
|
const url = new URL(payCode);
|
||||||
|
const queryParams = new URLSearchParams(url.search);
|
||||||
|
const qrcode = queryParams.get('qrcode');
|
||||||
|
const decodedQrcode = decodeURIComponent(qrcode);
|
||||||
|
document.getElementById('qrcode').src = await getQrcode(decodedQrcode, QR);
|
||||||
|
} else {
|
||||||
document.getElementById('qrcode').src = await getQrcode(payCode, QR);
|
document.getElementById('qrcode').src = await getQrcode(payCode, QR);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('qrcode').src = payCode;
|
document.getElementById('qrcode').src = payCode;
|
||||||
}
|
}
|
||||||
@ -278,12 +298,35 @@
|
|||||||
/* <?php } ?> */
|
/* <?php } ?> */
|
||||||
|
|
||||||
// 环境判断
|
// 环境判断
|
||||||
const environment = detectBrowserEnvironment();
|
|
||||||
if (payType === 'wxpay' && environment === 'aliphone') {
|
if (payType === 'wxpay' && environment === 'aliphone') {
|
||||||
layer.alert('请使用微信打开此页面');
|
layer.alert('请使用微信打开此页面');
|
||||||
} else if (payType === 'alipay' && environment === 'wxphone') {
|
} else if (payType === 'alipay' && environment === 'wxphone') {
|
||||||
layer.alert('请使用支付宝打开此页面');
|
layer.alert('请使用支付宝打开此页面');
|
||||||
}
|
}
|
||||||
|
// 添加按钮控制逻辑
|
||||||
|
const openAppBtn = document.getElementById('openApp');
|
||||||
|
if (environment === 'phone') {
|
||||||
|
openAppBtn.parentNode.style.display = 'block';
|
||||||
|
if (payType === 'wxpay') {
|
||||||
|
openAppBtn.innerText = '截图并打开微信';
|
||||||
|
openAppBtn.className = 'layui-btn layui-btn-green';
|
||||||
|
openAppBtn.onclick = function () {
|
||||||
|
window.location.href = 'weixin://';
|
||||||
|
};
|
||||||
|
} else if (payType === 'alipay') {
|
||||||
|
openAppBtn.innerText = '打开支付宝付款';
|
||||||
|
openAppBtn.className = 'layui-btn layui-btn-normal';
|
||||||
|
openAppBtn.onclick = function () {
|
||||||
|
if (codeType == 0) {
|
||||||
|
const payUrl = encodeURIComponent(payCode);
|
||||||
|
window.location.href = 'alipays://platformapi/startapp?appId=20000067&&url=' + payUrl;
|
||||||
|
} else {
|
||||||
|
const currentUrl = encodeURIComponent(window.location.href);
|
||||||
|
window.location.href = 'alipays://platformapi/startapp?appId=20000067&&url=' + currentUrl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
// 生成二维码
|
// 生成二维码
|
||||||
async function getQrcode(text, QR) {
|
async function getQrcode(text, QR) {
|
||||||
const qrcodeUrl = await new Promise((resolve) => {
|
const qrcodeUrl = await new Promise((resolve) => {
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
<option value="wxpay2">赞赏码</option>
|
<option value="wxpay2">赞赏码</option>
|
||||||
<option value="wxpay3">经营码</option>
|
<option value="wxpay3">经营码</option>
|
||||||
<option value="wxpay4">商家码</option>
|
<option value="wxpay4">商家码</option>
|
||||||
|
<option value="wxpay5">店员码</option>
|
||||||
<!-- <?php } ?> -->
|
<!-- <?php } ?> -->
|
||||||
<!-- <?php if ($platform == 'alipay') { ?> -->
|
<!-- <?php if ($platform == 'alipay') { ?> -->
|
||||||
<option value="alipay1">收钱码</option>
|
<option value="alipay1">收钱码</option>
|
||||||
@ -60,7 +61,7 @@
|
|||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<blockquote class="layui-elem-quote">
|
<blockquote class="layui-elem-quote">
|
||||||
<!-- <?php if ($platform == 'wxpay') { ?> -->
|
<!-- <?php if ($platform == 'wxpay') { ?> -->
|
||||||
<p><strong>手机监控:</strong>微信个人码与经营码只能二选一,不能同时添加,商家码监听需要关注“微信收款商业版”公众号,赞赏码正常添加。</p>
|
<p><strong>手机监控:</strong>微信个人码与经营码只能二选一,不能同时添加,且经营码只能通过个人码通道1添加成功,不然不回调;商家码监听需要关注“微信收款商业版”公众号,赞赏码和店员码正常添加。</p>
|
||||||
<p><strong>电脑监控:</strong>所有收款码均可监控,需要将收款通知聊天窗口单独拖出来</p>
|
<p><strong>电脑监控:</strong>所有收款码均可监控,需要将收款通知聊天窗口单独拖出来</p>
|
||||||
<!-- <?php } ?> -->
|
<!-- <?php } ?> -->
|
||||||
<!-- <?php if ($platform == 'alipay') { ?> -->
|
<!-- <?php if ($platform == 'alipay') { ?> -->
|
||||||
|
@ -106,10 +106,11 @@
|
|||||||
<script src="/component/layui/layui.js"></script>
|
<script src="/component/layui/layui.js"></script>
|
||||||
<script src="/component/pear/pear.js"></script>
|
<script src="/component/pear/pear.js"></script>
|
||||||
<script>
|
<script>
|
||||||
layui.use(['table', 'form', 'common', 'util'], function () {
|
layui.use(['table', 'form', 'common', 'dropdown', 'util'], function () {
|
||||||
let table = layui.table;
|
let table = layui.table;
|
||||||
let form = layui.form;
|
let form = layui.form;
|
||||||
let common = layui.common;
|
let common = layui.common;
|
||||||
|
let dropdown = layui.dropdown;
|
||||||
let util = layui.util;
|
let util = layui.util;
|
||||||
|
|
||||||
// 渲染插件选项
|
// 渲染插件选项
|
||||||
@ -130,10 +131,11 @@
|
|||||||
{ title: '账 号', field: 'account', align: 'center' },
|
{ title: '账 号', field: 'account', align: 'center' },
|
||||||
{ title: '启用状态', field: 'state', align: 'center', templet: '#account-state' },
|
{ title: '启用状态', field: 'state', align: 'center', templet: '#account-state' },
|
||||||
{ title: '监听模式', field: 'pattern', align: 'center' },
|
{ title: '监听模式', field: 'pattern', align: 'center' },
|
||||||
{ title: '监听地址 / 自定义模版', field: 'checkUrl', align: 'center', minWidth: 300, event: 'copy', templet: '#account-checkUrl' },
|
{ title: '监听地址 / 自定义模版', field: 'checkUrl', align: 'center', minWidth: 240, event: 'copy', templet: '#account-checkUrl' },
|
||||||
{ title: '收款平台流水', field: 'trade', align: 'center', templet: '#account-trade' },
|
{ title: '收款平台流水', field: 'trade', align: 'center', templet: '#account-trade' },
|
||||||
{ title: '收款码数量', field: 'channel', align: 'center', templet: '<div><a href="javascript:;" lay-event="channelList"><span class="layui-badge layui-bg-green">{{= d.channel }}</span></a></div>' },
|
{ title: '收款码数量', field: 'channel_num', align: 'center', templet: '<div><a href="javascript:;" lay-event="channelList"><span class="layui-badge layui-bg-green">{{= d.channel_num }}</span></a></div>' },
|
||||||
{ title: '操作', align: 'center', fixed: 'right', templet: '<div><a href="javascript:;" class="layui-font-green" lay-event="edit"><strong>编辑</strong></a></div>' }
|
{ title: '今日收款', field: 'income', align: 'center', templet: '<div><strong>{{# return d.income ?? 0 }}</strong></div>' },
|
||||||
|
{ title: '操作', align: 'center', fixed: 'right', templet: '<div><a href="javascript:;" class="layui-font-green edit" data-aid="{{= d.id }}"><strong>编辑</strong></a></div>' }
|
||||||
]]
|
]]
|
||||||
|
|
||||||
table.render({
|
table.render({
|
||||||
@ -148,7 +150,17 @@
|
|||||||
title: '刷新',
|
title: '刷新',
|
||||||
layEvent: 'refresh',
|
layEvent: 'refresh',
|
||||||
icon: 'layui-icon-refresh',
|
icon: 'layui-icon-refresh',
|
||||||
}, 'filter', 'print', 'exports']
|
}, 'filter', 'print', 'exports'],
|
||||||
|
done: function () {
|
||||||
|
dropdown.render({
|
||||||
|
elem: '.edit',
|
||||||
|
align: 'center',
|
||||||
|
data: [{ title: '编辑', id: 1 }, { type: '-' }, { title: '二维码', id: 2 }, { title: '收款统计', id: 3 }, { title: '收款明细', id: 4 }],
|
||||||
|
click: function (data, othis) {
|
||||||
|
account.doEdit(data, this.elem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 事件处理
|
// 事件处理
|
||||||
@ -168,13 +180,7 @@
|
|||||||
table.on('toolDouble(account-table)', function (obj) {
|
table.on('toolDouble(account-table)', function (obj) {
|
||||||
if (obj.event === 'copy') {
|
if (obj.event === 'copy') {
|
||||||
const text = obj.tr[0].querySelector('td[data-field="checkUrl"]>div').innerText;
|
const text = obj.tr[0].querySelector('td[data-field="checkUrl"]>div').innerText;
|
||||||
if (navigator.clipboard) {
|
copyText(text);
|
||||||
navigator.clipboard.writeText(text).then(() => {
|
|
||||||
layer.msg('复制成功');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
layer.msg('复制失败,请手动复制');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 表格头部按钮事件
|
// 表格头部按钮事件
|
||||||
@ -232,6 +238,27 @@
|
|||||||
// 操作方法
|
// 操作方法
|
||||||
let account = {};
|
let account = {};
|
||||||
|
|
||||||
|
// 编辑操作
|
||||||
|
account.doEdit = function (data, elem) {
|
||||||
|
const type = data.id;
|
||||||
|
const id = elem.attr('data-aid');
|
||||||
|
switch (type) {
|
||||||
|
case 1:
|
||||||
|
account.editAccount(id);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
account.channelList(id);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
account.tradeList(id);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
account.orderList(id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// 编辑
|
// 编辑
|
||||||
account.editAccount = function (id) {
|
account.editAccount = function (id) {
|
||||||
layer.open({
|
layer.open({
|
||||||
@ -243,6 +270,29 @@
|
|||||||
content: `/PayManage/editAccount?id=${id}`,
|
content: `/PayManage/editAccount?id=${id}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 收款统计
|
||||||
|
account.tradeList = function (aid) {
|
||||||
|
// 先尝试关闭已存在的标签
|
||||||
|
if (parent.layui.tab) {
|
||||||
|
parent.layui.tab.delTabByElem('content', 'payStatistics');
|
||||||
|
}
|
||||||
|
// 重新打开标签
|
||||||
|
parent.layui.tab.addTabOnlyByElem('content',
|
||||||
|
{ id: 'payStatistics', title: '收款统计', url: `/PayManage/payStatistics`, close: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// 终端列表
|
||||||
|
account.orderList = function (aid) {
|
||||||
|
// 先尝试关闭已存在的标签
|
||||||
|
if (parent.layui.tab) {
|
||||||
|
parent.layui.tab.delTabByElem('content', 'order');
|
||||||
|
}
|
||||||
|
// 重新打开标签
|
||||||
|
parent.layui.tab.addTabOnlyByElem('content',
|
||||||
|
{ id: 'order', title: '订单管理', url: `/Order/index?aid=${aid}`, close: true }
|
||||||
|
)
|
||||||
|
parent.layui.tab.changeTabTitleById('content', 'order', `【${aid}】订单明细`);
|
||||||
|
}
|
||||||
// 终端列表
|
// 终端列表
|
||||||
account.channelList = function (id) {
|
account.channelList = function (id) {
|
||||||
layer.open({
|
layer.open({
|
||||||
@ -331,6 +381,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>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
133
view/pay_manage/pay_statistics.html
Normal file
133
view/pay_manage/pay_statistics.html
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>收款管理</title>
|
||||||
|
<link rel="stylesheet" href="/component/pear/css/pear.css" />
|
||||||
|
<style>
|
||||||
|
.account-trade {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="pear-container">
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<form class="layui-form layui-form-pane" action="" id="serch-form">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">时间段</label>
|
||||||
|
<div class="layui-inline" id="create_time">
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<input type="text" name="time_start" autocomplete="off" placeholder="开始"
|
||||||
|
class="layui-input">
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-mid">-</div>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<input type="text" name="time_end" autocomplete="off" placeholder="结束"
|
||||||
|
class="layui-input">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-inline">
|
||||||
|
<button type="submit" class="pear-btn pear-btn-md pear-btn-primary" lay-submit
|
||||||
|
lay-filter="query">
|
||||||
|
<i class="layui-icon layui-icon-search"></i>
|
||||||
|
查询
|
||||||
|
</button>
|
||||||
|
<button type="button" lay-on="reset" class="pear-btn pear-btn-md">
|
||||||
|
<i class="layui-icon layui-icon-refresh"></i>
|
||||||
|
重置
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<table id="account-table" lay-filter="account-table"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="/component/layui/layui.js"></script>
|
||||||
|
<script src="/component/pear/pear.js"></script>
|
||||||
|
<script>
|
||||||
|
layui.use(['table', 'form', 'common', 'dropdown', 'util'], function () {
|
||||||
|
let table = layui.table;
|
||||||
|
let form = layui.form;
|
||||||
|
let common = layui.common;
|
||||||
|
let dropdown = layui.dropdown;
|
||||||
|
let util = layui.util;
|
||||||
|
let laydate = layui.laydate;
|
||||||
|
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);
|
||||||
|
const endOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59);
|
||||||
|
laydate.render({
|
||||||
|
elem: '#create_time',
|
||||||
|
range: ['input[name="time_start"]', 'input[name="time_end"]'],
|
||||||
|
rangeLinked: true,
|
||||||
|
type: 'datetime',
|
||||||
|
fullPanel: true,
|
||||||
|
weekStart: 1,
|
||||||
|
// 当天开始日期 - 当天结束日期
|
||||||
|
value: util.toDateString(startOfDay, 'yyyy-MM-dd HH:mm:ss') + ' - ' + util.toDateString(endOfDay, 'yyyy-MM-dd HH:mm:ss')
|
||||||
|
});
|
||||||
|
|
||||||
|
let cols = [[
|
||||||
|
{ type: 'checkbox' },
|
||||||
|
{ title: '平 台', field: 'platform', align: 'center', templet: '' },
|
||||||
|
{ title: '账 号', field: 'account', align: 'center' },
|
||||||
|
{ title: '时段查询收款', field: 'income', align: 'center', templet: '<div><strong>{{# return d.income ?? 0 }}</strong></div>' },
|
||||||
|
{ title: '今日收款', field: 'day', align: 'center', templet: '<div><strong>{{# return d.day ?? 0 }}</strong></div>' },
|
||||||
|
{ title: '昨日收款', field: 'yesterday', align: 'center', templet: '<div><strong>{{# return d.yesterday ?? 0 }}</strong></div>' },
|
||||||
|
{ title: '本周收款', field: 'week', align: 'center', templet: '<div><strong>{{# return d.week ?? 0 }}</strong></div>' },
|
||||||
|
{ title: '本月收款', field: 'month', align: 'center', templet: '<div><strong>{{# return d.month ?? 0 }}</strong></div>' },
|
||||||
|
{ title: '当年收款', field: 'year', align: 'center', templet: '<div><strong>{{# return d.year ?? 0 }}</strong></div>' },
|
||||||
|
{ title: '总计收款', field: 'total', align: 'center', templet: '<div><strong>{{# return d.total ?? 0 }}</strong></div>' },
|
||||||
|
]]
|
||||||
|
|
||||||
|
table.render({
|
||||||
|
id: 'account-table',
|
||||||
|
elem: '#account-table',
|
||||||
|
url: '/api/PayManage/payStatisticsList',
|
||||||
|
page: true,
|
||||||
|
cols: cols,
|
||||||
|
skin: 'line',
|
||||||
|
defaultToolbar: [{
|
||||||
|
title: '刷新',
|
||||||
|
layEvent: 'refresh',
|
||||||
|
icon: 'layui-icon-refresh',
|
||||||
|
}, 'filter', 'print', 'exports'],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单自定义事件监听
|
||||||
|
form.on('submit(query)', function (obj) {
|
||||||
|
const field = obj.field;
|
||||||
|
let new_field = {};
|
||||||
|
for (const key in field) {
|
||||||
|
if (field.hasOwnProperty.call(field, key)) {
|
||||||
|
const value = field[key];
|
||||||
|
if (value) {
|
||||||
|
new_field[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.reload('account-table', { where: new_field });
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
// 监听重置按钮
|
||||||
|
util.on({
|
||||||
|
reset: function () {
|
||||||
|
document.querySelector('#serch-form').reset();
|
||||||
|
table.reload('account-table', { where: {} });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -19,6 +19,23 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.infomsg {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-left: 10px;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.infomsg div:first-child {
|
||||||
|
width: 100%;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infomsg div:last-child {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -55,22 +72,26 @@
|
|||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">API 接口</label>
|
<label class="layui-form-label">API 接口</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid" style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div class="layui-form-mid infomsg">
|
||||||
|
<div>
|
||||||
<?php echo $url ?>
|
<?php echo $url ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo" data-info="<?php echo $url ?>"
|
</div>
|
||||||
style="float: right;" title="复制"><span
|
<div><a href="javascript:;" lay-on="copyinfo" data-info="<?php echo $url ?>"
|
||||||
class="icon pear-icon pear-icon-survey"></span></a>
|
title="复制"><span class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">商户 PID</label>
|
<label class="layui-form-label">商户 PID</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid" style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div class="layui-form-mid infomsg">
|
||||||
|
<div>
|
||||||
<?php echo $pid ?>
|
<?php echo $pid ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo" data-info="<?php echo $pid ?>"
|
</div>
|
||||||
style="float: right;" title="复制"><span
|
<div><a href="javascript:;" lay-on="copyinfo" data-info="<?php echo $pid ?>"
|
||||||
class="icon pear-icon pear-icon-survey"></span></a>
|
title="复制"><span class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -78,11 +99,13 @@
|
|||||||
<label class="layui-form-label">商户密钥 <a href="javascript:;" lay-on="resetKey"
|
<label class="layui-form-label">商户密钥 <a href="javascript:;" lay-on="resetKey"
|
||||||
title="重置密钥"><span class="icon pear-icon pear-icon-refresh"></span></a></label>
|
title="重置密钥"><span class="icon pear-icon pear-icon-refresh"></span></a></label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid infomsg">
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div>
|
||||||
<?php echo $secret_key ?>
|
<?php echo $secret_key ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo" data-info="<?php echo $secret_key ?>"
|
</div>
|
||||||
style="float: right;" title="复制"><span
|
<div>
|
||||||
|
<a href="javascript:;" lay-on="copyinfo"
|
||||||
|
data-info="<?php echo $secret_key ?>" title="复制"><span
|
||||||
class="icon pear-icon pear-icon-survey"></span></a>
|
class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -90,6 +113,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="layui-card">
|
<div class="layui-card">
|
||||||
<div class="layui-card-header">聚合码定时任务<span class="layui-font-gray"> · 监控有效期订单</span></div>
|
<div class="layui-card-header">聚合码定时任务<span class="layui-font-gray"> · 监控有效期订单</span></div>
|
||||||
@ -98,11 +122,12 @@
|
|||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">订单监控</label>
|
<label class="layui-form-label">订单监控</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid infomsg">
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div>
|
||||||
<?php echo $orderurl ?>
|
<?php echo $orderurl ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo" data-info="<?php echo $orderurl ?>"
|
</div>
|
||||||
style="float: right;" title="复制"><span
|
<div><a href="javascript:;" lay-on="copyinfo"
|
||||||
|
data-info="<?php echo $orderurl ?>" title="复制"><span
|
||||||
class="icon pear-icon pear-icon-survey"></span></a>
|
class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -111,6 +136,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="layui-col-md6">
|
<div class="layui-col-md6">
|
||||||
|
|
||||||
<div class="layui-card">
|
<div class="layui-card">
|
||||||
@ -123,54 +149,61 @@
|
|||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">Webhook</label>
|
<label class="layui-form-label">Webhook</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid infomsg">
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div>
|
||||||
<?php echo $url . 'mpayNotify' ?>
|
<?php echo $url . 'mpayNotify' ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo"
|
</div>
|
||||||
data-info="<?php echo $url . 'mpayNotify' ?>" style="float: right;"
|
<div><a href="javascript:;" lay-on="copyinfo"
|
||||||
title="复制"><span class="icon pear-icon pear-icon-survey"></span></a>
|
data-info="<?php echo $url . 'mpayNotify' ?>" title="复制"><span
|
||||||
|
class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">消息模版</label>
|
<label class="layui-form-label">消息模版</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid infomsg">
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div>{"action": "mpay","data": "[msg]","time":"[timestamp]","sign":
|
||||||
{"action": "mpay","data": "[msg]","time":"[timestamp]","sign": "[sign]"}
|
"[sign]"}
|
||||||
<a href="javascript:;" lay-on="copyinfo"
|
</div>
|
||||||
|
<div><a href="javascript:;" lay-on="copyinfo"
|
||||||
data-info='{"action": "mpay","data": "[msg]","time":"[timestamp]","sign": "[sign]"}'
|
data-info='{"action": "mpay","data": "[msg]","time":"[timestamp]","sign": "[sign]"}'
|
||||||
style="float: right;" title="复制"><span
|
title="复制"><span
|
||||||
class="icon pear-icon pear-icon-survey"></span></a>
|
class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">Secret</label>
|
<label class="layui-form-label">Secret</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid infomsg">
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div>
|
||||||
<?php echo $secret_key ?>
|
<?php echo $secret_key ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo"
|
</div>
|
||||||
data-info="<?php echo $secret_key ?>" style="float: right;"
|
<div><a href="javascript:;" lay-on="copyinfo"
|
||||||
title="复制"><span class="icon pear-icon pear-icon-survey"></span></a>
|
data-info="<?php echo $secret_key ?>" title="复制"><span
|
||||||
|
class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">成功关键字</label>
|
<label class="layui-form-label">成功关键字</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid infomsg">
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div>200</div>
|
||||||
200
|
<div><a href="javascript:;" lay-on="copyinfo" data-info="200"
|
||||||
<a href="javascript:;" lay-on="copyinfo" data-info="200"
|
title="复制"><span
|
||||||
style="float: right;" title="复制"><span
|
|
||||||
class="icon pear-icon pear-icon-survey"></span></a>
|
class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset class="layui-elem-field">
|
<fieldset class="layui-elem-field">
|
||||||
<legend style="font-size: 14px;">应用转发规则·多重匹配</legend>
|
<legend style="font-size: 14px;">应用转发规则·多重匹配</legend>
|
||||||
@ -179,26 +212,28 @@
|
|||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">微信支付</label>
|
<label class="layui-form-label">微信支付</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid infomsg">
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div>
|
||||||
<?php echo '并且 是 APP包名 相等 com.tencent.mm<br />并且 是 通知标题 相等 微信支付<br />[空格]或者 是 通知标题 相等 微信收款助手<br />[空格]或者 是 通知标题 相等 微信收款商业版' ?>
|
<?php echo '并且 是 APP包名 相等 com.tencent.mm<br />并且 是 通知标题 相等 微信支付<br />[空格]或者 是 通知标题 相等 微信收款助手<br />[空格]或者 是 通知标题 相等 微信收款商业版' ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo"
|
</div>
|
||||||
|
<div><a href="javascript:;" lay-on="copyinfo"
|
||||||
data-info='<?php echo "并且 是 APP包名 相等 com.tencent.mm\n并且 是 通知标题 相等 微信支付\n[空格]或者 是 通知标题 相等 微信收款助手\n[空格]或者 是 通知标题 相等 微信收款商业版" ?>'
|
data-info='<?php echo "并且 是 APP包名 相等 com.tencent.mm\n并且 是 通知标题 相等 微信支付\n[空格]或者 是 通知标题 相等 微信收款助手\n[空格]或者 是 通知标题 相等 微信收款商业版" ?>'
|
||||||
style="float: right;" title="复制"><span
|
title="复制"><span class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
class="icon pear-icon pear-icon-survey"></span></a>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item" pane>
|
<div class="layui-form-item" pane>
|
||||||
<label class="layui-form-label">支付宝</label>
|
<label class="layui-form-label">支付宝</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid infomsg">
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
<div>
|
||||||
<?php echo '并且 是 APP包名 相等 com.eg.android.AlipayGphone<br />并且 是 通知标题 包含 元<br />[空格]或者 是 通知内容 包含 元' ?>
|
<?php echo '并且 是 APP包名 相等 com.eg.android.AlipayGphone<br />并且 是 通知标题 包含 元<br />[空格]或者 是 通知内容 包含 元' ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo"
|
</div>
|
||||||
|
<div><a href="javascript:;" lay-on="copyinfo"
|
||||||
data-info='<?php echo "并且 是 APP包名 相等 com.eg.android.AlipayGphone\n并且 是 通知标题 包含 元\n[空格]或者 是 通知内容 包含 元" ?>'
|
data-info='<?php echo "并且 是 APP包名 相等 com.eg.android.AlipayGphone\n并且 是 通知标题 包含 元\n[空格]或者 是 通知内容 包含 元" ?>'
|
||||||
style="float: right;" title="复制"><span
|
title="复制"><span class="icon pear-icon pear-icon-survey"></span></a>
|
||||||
class="icon pear-icon pear-icon-survey"></span></a>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -221,13 +256,7 @@
|
|||||||
util.on({
|
util.on({
|
||||||
'copyinfo': (ele) => {
|
'copyinfo': (ele) => {
|
||||||
const info = ele.attr('data-info');
|
const info = ele.attr('data-info');
|
||||||
if (navigator.clipboard) {
|
copyText(info);
|
||||||
navigator.clipboard.writeText(info).then(() => {
|
|
||||||
layer.msg('复制成功');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
layer.msg('复制失败,请手动复制');
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
'resetKey': (ele) => {
|
'resetKey': (ele) => {
|
||||||
layer.confirm('重置密钥后,将无法使用原密钥,是否继续?', { icon: 3, title: '重置密钥' }, function (index) {
|
layer.confirm('重置密钥后,将无法使用原密钥,是否继续?', { icon: 3, title: '重置密钥' }, function (index) {
|
||||||
@ -262,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 || '人无横财不富,马无夜草不肥'; })
|
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>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
BIN
view/view.zip
Normal file
BIN
view/view.zip
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user