mirror of
https://gitee.com/technical-laohu/mpay.git
synced 2025-11-09 04:03:43 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9c804c1e5 | ||
|
|
2515515182 | ||
|
|
87563d01d7 | ||
|
|
16f4438a16 | ||
|
|
29c894faae | ||
|
|
a5d09d0a26 | ||
|
|
504aa6c284 | ||
|
|
e65c0e9173 | ||
|
|
2c1ece3eb2 | ||
|
|
ebcac8a9aa | ||
|
|
4eef7f0797 | ||
|
|
dfb8edff22 | ||
|
|
05c1b08e95 | ||
|
|
de848ab32b | ||
|
|
3f5866ea16 | ||
|
|
fb2f8f2f2c | ||
|
|
62989e4100 | ||
|
|
eeb877bd87 | ||
|
|
e9f64988a9 | ||
|
|
f62d4cd103 | ||
|
|
331b0b2d56 | ||
|
|
e5871d91c5 |
@@ -369,7 +369,7 @@ V免签是一款开源免费适用于个人收款使用的收款程序,原理
|
|||||||
|
|
||||||
##### **转发规则**
|
##### **转发规则**
|
||||||
|
|
||||||
添加应用转发规则,**微信**和**支付宝**需要分别设置
|
添加应用转发规则,**微信**和**支付宝**需要分别设置,请注意选择**应用**规则
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ class IndexController
|
|||||||
}
|
}
|
||||||
public function test()
|
public function test()
|
||||||
{
|
{
|
||||||
|
return View::fetch();
|
||||||
return app()->getBasePath();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,15 @@ class InstallController
|
|||||||
{
|
{
|
||||||
// 检查是否已经安装过
|
// 检查是否已经安装过
|
||||||
if ($this->checkLock()) {
|
if ($this->checkLock()) {
|
||||||
return backMsg(1, '已经安装');
|
return json(backMsg(1, '已经安装'));
|
||||||
|
};
|
||||||
|
// 检查环境
|
||||||
|
$envCheck = $this->checkEnvironment();
|
||||||
|
if ($envCheck !== true) {
|
||||||
|
return json(backMsg(1, $envCheck));
|
||||||
};
|
};
|
||||||
// 获取表单提交的数据库配置信息
|
// 获取表单提交的数据库配置信息
|
||||||
$dbConfig = $request->post();
|
$dbConfig = $request->post();
|
||||||
|
|
||||||
// 保存数据库配置信息到配置文件
|
// 保存数据库配置信息到配置文件
|
||||||
if ($this->saveDbConfig($dbConfig) === false) {
|
if ($this->saveDbConfig($dbConfig) === false) {
|
||||||
return json(backMsg(1, '配置保存失败'));
|
return json(backMsg(1, '配置保存失败'));
|
||||||
@@ -62,7 +66,22 @@ class InstallController
|
|||||||
$this->setLock();
|
$this->setLock();
|
||||||
return json(backMsg(0, '安装成功'));
|
return json(backMsg(0, '安装成功'));
|
||||||
}
|
}
|
||||||
|
private function checkEnvironment()
|
||||||
|
{
|
||||||
|
// 检查PHP版本
|
||||||
|
if (version_compare(PHP_VERSION, '8.0', '<')) {
|
||||||
|
return 'PHP版本必须大于等于8.0';
|
||||||
|
}
|
||||||
|
// 检查文件上传写入权限
|
||||||
|
if (!is_writable(sys_get_temp_dir())) {
|
||||||
|
return '文件上传目录没有写入权限';
|
||||||
|
}
|
||||||
|
// 检查Fileinfo扩展是否安装
|
||||||
|
if (!extension_loaded('fileinfo')) {
|
||||||
|
return 'Fileinfo扩展未安装';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
private function saveDbConfig($dbConfig)
|
private function saveDbConfig($dbConfig)
|
||||||
{
|
{
|
||||||
$envPath = app()->getRootPath() . '.env';
|
$envPath = app()->getRootPath() . '.env';
|
||||||
|
|||||||
@@ -20,70 +20,41 @@ class PayController
|
|||||||
'POST' => $request->post(),
|
'POST' => $request->post(),
|
||||||
default => []
|
default => []
|
||||||
};
|
};
|
||||||
if (!$req_data) {
|
if (!$req_data) return '参数错误';
|
||||||
return '参数错误';
|
// 验证签名
|
||||||
}
|
|
||||||
$key = User::where('pid', $req_data['pid'])->where('state', 1)->value('secret_key');
|
$key = User::where('pid', $req_data['pid'])->where('state', 1)->value('secret_key');
|
||||||
if (!$key) {
|
if (!$key) return '用户禁用或不存在';
|
||||||
return '用户禁用或不存在';
|
|
||||||
}
|
|
||||||
$sign_str = self::getSign($req_data, $key);
|
$sign_str = self::getSign($req_data, $key);
|
||||||
if ($req_data['sign'] === $sign_str) {
|
if ($req_data['sign'] !== $sign_str) return '签名错误';
|
||||||
// 检查商户订单
|
// 检查商户订单
|
||||||
$out_trade_no = Order::where('out_trade_no', $req_data['out_trade_no'])->value('out_trade_no');
|
$out_trade_no = Order::where('out_trade_no', $req_data['out_trade_no'])->value('out_trade_no');
|
||||||
if (!$out_trade_no) {
|
if ($out_trade_no) return '订单提交重复';
|
||||||
// 创建新订单
|
// 创建新订单
|
||||||
$order_id = Order::createOrder($req_data);
|
$order_id = Order::createOrder($req_data);
|
||||||
if ($order_id) {
|
if (!$order_id) return '创建订单失败';
|
||||||
return redirect("/Pay/console/{$order_id}");
|
return redirect("/Pay/console/{$order_id}");
|
||||||
} else {
|
|
||||||
return '创建订单失败';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return '订单提交重复';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return '签名错误';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// api提交订单
|
// api提交订单
|
||||||
public function mapi(Request $request)
|
public function mapi(Request $request)
|
||||||
{
|
{
|
||||||
if ($request->isPost()) {
|
if (!$request->isPost()) return '请使用POST方式提交';
|
||||||
$req_data = $request->post();
|
$req_data = $request->post();
|
||||||
if (!$req_data) {
|
if (!$req_data) $req_data = $request->get();
|
||||||
$req_data = $request->get();
|
if (!$req_data) return '参数错误';
|
||||||
if (!$req_data) {
|
// 验证签名
|
||||||
return '参数错误';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return '请使用POST方式提交';
|
|
||||||
}
|
|
||||||
$key = User::where('pid', $req_data['pid'])->where('state', 1)->value('secret_key');
|
$key = User::where('pid', $req_data['pid'])->where('state', 1)->value('secret_key');
|
||||||
if (!$key) {
|
if (!$key) return '用户禁用或不存在';
|
||||||
return '用户禁用或不存在';
|
|
||||||
}
|
|
||||||
$sign_str = self::getSign($req_data, $key);
|
$sign_str = self::getSign($req_data, $key);
|
||||||
if ($req_data['sign'] === $sign_str) {
|
if ($req_data['sign'] !== $sign_str) return '签名错误';
|
||||||
// 检查商户订单
|
// 检查商户订单
|
||||||
$out_trade_no = Order::where('out_trade_no', $req_data['out_trade_no'])->value('out_trade_no');
|
$out_trade_no = Order::where('out_trade_no', $req_data['out_trade_no'])->value('out_trade_no');
|
||||||
if (!$out_trade_no) {
|
if ($out_trade_no) return '订单提交重复';
|
||||||
// 创建新订单
|
// 创建新订单
|
||||||
$order_id = Order::createOrder($req_data);
|
$order_id = Order::createOrder($req_data);
|
||||||
if ($order_id) {
|
if (!$order_id) return '创建订单失败';
|
||||||
$payurl = $request->domain() . "/Pay/console/{$order_id}";
|
$payurl = $request->domain() . "/Pay/console/{$order_id}";
|
||||||
$info = ['code' => 1, 'msg' => '订单创建成功', 'trade_no' => $order_id, 'qrcode' => $payurl];
|
$info = ['code' => 1, 'msg' => '订单创建成功', 'trade_no' => $order_id, 'qrcode' => $payurl];
|
||||||
return json($info);
|
return json($info);
|
||||||
} else {
|
|
||||||
return '创建订单失败';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return '订单提交重复';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return '签名错误';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 收银台
|
// 收银台
|
||||||
public function console($order_id = '')
|
public function console($order_id = '')
|
||||||
@@ -126,7 +97,12 @@ class PayController
|
|||||||
$sign = self::getSign($notify, $user_key);
|
$sign = self::getSign($notify, $user_key);
|
||||||
$notify['sign'] = $sign;
|
$notify['sign'] = $sign;
|
||||||
// 跳转通知URL
|
// 跳转通知URL
|
||||||
$res_return_url = $act_order->return_url . '?' . http_build_query($notify);
|
$res_return_url = '';
|
||||||
|
if (strpos($act_order->return_url, '?')) {
|
||||||
|
$res_return_url = $act_order->return_url . '&' . http_build_query($notify);
|
||||||
|
} else {
|
||||||
|
$res_return_url = $act_order->return_url . '?' . http_build_query($notify);
|
||||||
|
}
|
||||||
// 响应消息
|
// 响应消息
|
||||||
$data['order_id'] = $act_order->order_id;
|
$data['order_id'] = $act_order->order_id;
|
||||||
$data['passtime'] = $passtime > 0 ? $passtime : 0;
|
$data['passtime'] = $passtime > 0 ? $passtime : 0;
|
||||||
@@ -190,7 +166,7 @@ class PayController
|
|||||||
// 支付渠道核对
|
// 支付渠道核对
|
||||||
$is_channel = $cids[$order->cid] == $new_order['channel'];
|
$is_channel = $cids[$order->cid] == $new_order['channel'];
|
||||||
// 金额核对
|
// 金额核对
|
||||||
$is_money = $order->money == $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) {
|
||||||
$res = $this->updateOrderState($order, $new_order['order_no']);
|
$res = $this->updateOrderState($order, $new_order['order_no']);
|
||||||
@@ -216,7 +192,13 @@ class PayController
|
|||||||
$sign = self::getSign($notify, $user_key);
|
$sign = self::getSign($notify, $user_key);
|
||||||
$notify['sign'] = $sign;
|
$notify['sign'] = $sign;
|
||||||
// 异步通知
|
// 异步通知
|
||||||
$res_notify = self::getHttpResponse($order->notify_url . '?' . http_build_query($notify));
|
$notify_url = '';
|
||||||
|
if (strpos($order->notify_url, '?')) {
|
||||||
|
$notify_url = $order->notify_url . '&' . http_build_query($notify);
|
||||||
|
} else {
|
||||||
|
$notify_url = $order->notify_url . '?' . http_build_query($notify);
|
||||||
|
}
|
||||||
|
$res_notify = self::getHttpResponse($notify_url);
|
||||||
if ($res_notify === 'success') {
|
if ($res_notify === 'success') {
|
||||||
return ['order' => $order->order_id, 'code' => 1, 'msg' => 'notify success'];
|
return ['order' => $order->order_id, 'code' => 1, 'msg' => 'notify success'];
|
||||||
} else {
|
} else {
|
||||||
@@ -230,9 +212,8 @@ class PayController
|
|||||||
$req_pid = $req_info['pid'];
|
$req_pid = $req_info['pid'];
|
||||||
$req_aid = $req_info['aid'];
|
$req_aid = $req_info['aid'];
|
||||||
// 获取订单
|
// 获取订单
|
||||||
$order_path = runtime_path() . '/order.json';
|
$new_order = cache('order');
|
||||||
if (!file_exists($order_path)) return json(['code' => 3, 'msg' => '订单文件不存在']);
|
if (!$new_order) return json(['code' => 3, 'msg' => '没有找到新订单缓存']);
|
||||||
$new_order = json_decode(file_get_contents($order_path), true);
|
|
||||||
// 检测新订单
|
// 检测新订单
|
||||||
if ($new_order['code'] !== 1) return json($new_order);
|
if ($new_order['code'] !== 1) return json($new_order);
|
||||||
// 订单列表
|
// 订单列表
|
||||||
@@ -266,38 +247,31 @@ class PayController
|
|||||||
return json(['code' => 0, 'msg' => '查询空订单'], 320);
|
return json(['code' => 0, 'msg' => '查询空订单'], 320);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// [定时任务]监听新订单,生成JSON文件信息
|
// [定时任务]监听新订单,生成缓存
|
||||||
public function checkOrder($pid = '', $sign = '')
|
public function checkOrder($pid = '', $sign = '')
|
||||||
{
|
{
|
||||||
if (!($pid && $sign)) {
|
if (!($pid && $sign)) return '参数错误';
|
||||||
return '参数错误';
|
|
||||||
}
|
|
||||||
$is_user = User::checkUser($pid, $sign);
|
$is_user = User::checkUser($pid, $sign);
|
||||||
$path = runtime_path() . 'order.json';
|
|
||||||
if ($is_user) {
|
if ($is_user) {
|
||||||
$orders = Order::scope('activeOrder')->field('id,pid,aid,cid,patt')->select();
|
$orders = Order::scope('activeOrder')->field('id,pid,aid,cid,patt')->select();
|
||||||
if (!file_exists($path)) {
|
$old_info = cache('order');
|
||||||
file_put_contents($path, '[]');
|
|
||||||
}
|
|
||||||
$old_info = file_get_contents($path);
|
|
||||||
$num = count($orders);
|
$num = count($orders);
|
||||||
if ($num > 0) {
|
if ($num > 0) {
|
||||||
$info = ['code' => 1, 'msg' => "有{$num}个新订单"];
|
$info = ['code' => 1, 'msg' => "有{$num}个新订单"];
|
||||||
$order_list = ['code' => 1, 'msg' => "有{$num}个新订单", 'orders' => $orders];
|
$order_list = ['code' => 1, 'msg' => "有{$num}个新订单", 'orders' => $orders];
|
||||||
if ($old_info !== json_encode($order_list)) {
|
if ($old_info !== $order_list) {
|
||||||
file_put_contents($path, json_encode($order_list));
|
cache('order', $order_list);
|
||||||
}
|
}
|
||||||
return json($info);
|
return json($info);
|
||||||
} else {
|
} else {
|
||||||
$info = ['code' => 0, 'msg' => '没有新订单'];
|
$info = ['code' => 0, 'msg' => '没有新订单'];
|
||||||
if ($old_info !== json_encode($info, 320)) {
|
if ($old_info !== $info) {
|
||||||
file_put_contents($path, json_encode($info, 320));
|
cache('order', $info);
|
||||||
}
|
}
|
||||||
return json($info);
|
return json($info);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$info = ['code' => 2, 'msg' => '签名错误'];
|
$info = ['code' => 2, 'msg' => '签名错误'];
|
||||||
file_put_contents($path, json_encode($info, 320));
|
|
||||||
return json($info);
|
return json($info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,10 +282,13 @@ class PayController
|
|||||||
$action = isset($info['action']) ? $info['action'] : '';
|
$action = isset($info['action']) ? $info['action'] : '';
|
||||||
if ($action === 'mpay') {
|
if ($action === 'mpay') {
|
||||||
$data = json_decode($info['data'], true);
|
$data = json_decode($info['data'], true);
|
||||||
|
if (!is_array($data)) return 200;
|
||||||
|
if (!isset($data['aid']) || !isset($data['pid'])) return 202;
|
||||||
$config = PayAccount::getAccountConfig($data['aid'], $data['pid']);
|
$config = PayAccount::getAccountConfig($data['aid'], $data['pid']);
|
||||||
$payclient_path = "\\payclient\\{$config['payclass']}";
|
$payclient_path = "\\payclient\\{$config['payclass']}";
|
||||||
$Payclient = new $payclient_path($info, $config);
|
$Payclient = new $payclient_path($info, $config);
|
||||||
$res = $Payclient->notify();
|
$res = $Payclient->notify();
|
||||||
|
if (is_int($res)) return $res;
|
||||||
$this->payHeart($res, $config);
|
$this->payHeart($res, $config);
|
||||||
return 200;
|
return 200;
|
||||||
} else {
|
} else {
|
||||||
@@ -348,7 +325,8 @@ class PayController
|
|||||||
'sign_type' => 'MD5',
|
'sign_type' => 'MD5',
|
||||||
];
|
];
|
||||||
// 添加扩展参数
|
// 添加扩展参数
|
||||||
$notify = array_merge($notify, unserialize($param->param));
|
// $notify = array_merge($notify, unserialize($param->param));
|
||||||
|
$notify['param'] = unserialize($param->param);
|
||||||
return $notify;
|
return $notify;
|
||||||
}
|
}
|
||||||
// 请求外部资源
|
// 请求外部资源
|
||||||
|
|||||||
@@ -125,14 +125,27 @@ class PayManageController extends BaseController
|
|||||||
public function uploadQrcode()
|
public function uploadQrcode()
|
||||||
{
|
{
|
||||||
$img = $this->request->file('codeimg');
|
$img = $this->request->file('codeimg');
|
||||||
|
if (!$img) {
|
||||||
|
return json(backMsg(1, '请选择要上传的文件'));
|
||||||
|
}
|
||||||
|
// 验证文件类型
|
||||||
|
$allowedTypes = ['image/png', 'image/jpeg', 'image/gif'];
|
||||||
|
$fileMimeType = $img->getMime();
|
||||||
|
if (!in_array($fileMimeType, $allowedTypes)) {
|
||||||
|
return json(backMsg(1, '只允许上传PNG、JPEG或GIF格式的图片'));
|
||||||
|
}
|
||||||
|
// 生成唯一文件名
|
||||||
|
$filename = 'img_' . time() . '_' . uniqid() . '.' . $img->getOriginalExtension();
|
||||||
|
// 设置文件保存路径
|
||||||
$path = public_path() . '/files/qrcode/';
|
$path = public_path() . '/files/qrcode/';
|
||||||
if (!is_dir($path)) {
|
if (!is_dir($path)) {
|
||||||
mkdir($path, 0777, true);
|
mkdir($path, 0755, true);
|
||||||
}
|
}
|
||||||
$info = $img->move($path, 'img' . time() . '.' . $img->getOriginalExtension());
|
// 移动文件到指定目录
|
||||||
|
$info = $img->move($path, $filename);
|
||||||
if ($info) {
|
if ($info) {
|
||||||
$imgpath = '/files/qrcode/';
|
$imgpath = '/files/qrcode/' . $filename;
|
||||||
return json(backMsg(0, '上传成功', ['imgpath' => $imgpath . $info->getFilename()]));
|
return json(backMsg(0, '上传成功', ['imgpath' => $imgpath]));
|
||||||
} else {
|
} else {
|
||||||
return json(backMsg(1, '上传失败'));
|
return json(backMsg(1, '上传失败'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ class Order extends BaseModel
|
|||||||
// 订单有效期
|
// 订单有效期
|
||||||
private static $activity_time = 180;
|
private static $activity_time = 180;
|
||||||
// 新建订单
|
// 新建订单
|
||||||
public static function createOrder($data)
|
public static function createOrder($data): string|false
|
||||||
{
|
{
|
||||||
$my_time = time();
|
$my_time = time();
|
||||||
$channel = self::setChannel($data['pid'], $data['type']);
|
$channel = self::setChannel($data['pid'], $data['type']);
|
||||||
if(!$channel) return false;
|
if (!$channel) return false;
|
||||||
$new_order = [
|
$new_order = [
|
||||||
// 订单号
|
// 订单号
|
||||||
'order_id' => self::createOrderID('H'),
|
'order_id' => self::createOrderID('H'),
|
||||||
@@ -42,7 +42,7 @@ class Order extends BaseModel
|
|||||||
// 设备类型
|
// 设备类型
|
||||||
'device' => isset($data['device']) ? $data['device'] : '',
|
'device' => isset($data['device']) ? $data['device'] : '',
|
||||||
// 业务扩展参数
|
// 业务扩展参数
|
||||||
'param' => serialize(self::getParams($data)),
|
'param' => serialize(isset($data['param']) ? $data['param'] : ''),
|
||||||
// 等待/过期:0, 支付成功:1
|
// 等待/过期:0, 支付成功:1
|
||||||
'state' => 0,
|
'state' => 0,
|
||||||
// 开启监听:1, 关闭监听:0
|
// 开启监听:1, 关闭监听:0
|
||||||
@@ -122,10 +122,10 @@ class Order extends BaseModel
|
|||||||
$channel_infos = PayChannel::whereIn('account_id', $aids)->where('state', 1)->order('last_time', 'asc')->select();
|
$channel_infos = PayChannel::whereIn('account_id', $aids)->where('state', 1)->order('last_time', 'asc')->select();
|
||||||
if (!$channel_infos || !$aids) return [];
|
if (!$channel_infos || !$aids) return [];
|
||||||
// 微信/支付宝收款处理
|
// 微信/支付宝收款处理
|
||||||
|
$channel_info = null;
|
||||||
foreach ($channel_infos as $key => $value) {
|
foreach ($channel_infos as $key => $value) {
|
||||||
$check_wx = preg_match('/^wxpay\d+#/i', $value->channel);
|
$check_wx = preg_match('/^wxpay\d+#/i', $value->channel);
|
||||||
$check_ali = preg_match('/^alipay\d+#/i', $value->channel);
|
$check_ali = preg_match('/^alipay\d+#/i', $value->channel);
|
||||||
$channel_info = null;
|
|
||||||
if ($check_wx && $type === 'wxpay') {
|
if ($check_wx && $type === 'wxpay') {
|
||||||
$channel_info = $channel_infos[$key];
|
$channel_info = $channel_infos[$key];
|
||||||
break;
|
break;
|
||||||
@@ -140,7 +140,7 @@ class Order extends BaseModel
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!$channel_info) return [];
|
if (!$channel_info) return [];
|
||||||
// 选取收款通道
|
// 选取收款通道
|
||||||
$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')];
|
||||||
@@ -148,17 +148,17 @@ class Order extends BaseModel
|
|||||||
return $channel;
|
return $channel;
|
||||||
}
|
}
|
||||||
// 获取扩展参数数组
|
// 获取扩展参数数组
|
||||||
private static function getParams(array $data): array
|
// private static function getParams(array $data): array
|
||||||
{
|
// {
|
||||||
$keys = ['pid', 'type', 'out_trade_no', 'notify_url', 'return_url', 'name', 'money', 'sign', 'sign_type'];
|
// $keys = ['pid', 'type', 'out_trade_no', 'notify_url', 'return_url', 'name', 'money', 'sign', 'sign_type'];
|
||||||
$params = [];
|
// $params = [];
|
||||||
foreach ($data as $key => $value) {
|
// foreach ($data as $key => $value) {
|
||||||
if (!in_array($key, $keys)) {
|
// if (!in_array($key, $keys)) {
|
||||||
$params[$key] = $value;
|
// $params[$key] = $value;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return $params;
|
// return $params;
|
||||||
}
|
// }
|
||||||
// 检查金额
|
// 检查金额
|
||||||
private static function checkMoney($money, $type, $aid, $cid): float
|
private static function checkMoney($money, $type, $aid, $cid): float
|
||||||
{
|
{
|
||||||
|
|||||||
2
extend/.gitignore
vendored
2
extend/.gitignore
vendored
@@ -1 +1 @@
|
|||||||
/payclient
|
payclient
|
||||||
@@ -49,13 +49,23 @@ class Plugin
|
|||||||
// 获取平台所有支持插件
|
// 获取平台所有支持插件
|
||||||
public static function getAllPlugin(): array
|
public static function getAllPlugin(): array
|
||||||
{
|
{
|
||||||
|
$app_plugin = cache('app_plugin');
|
||||||
|
if ($app_plugin) {
|
||||||
|
return json_decode($app_plugin, true);
|
||||||
|
}
|
||||||
$app_plugin = self::getHttpResponse(self::$siteUrl . '/mpay/getplugins');
|
$app_plugin = self::getHttpResponse(self::$siteUrl . '/mpay/getplugins');
|
||||||
|
cache('app_plugin', $app_plugin, 36000);
|
||||||
return json_decode($app_plugin, true);
|
return json_decode($app_plugin, true);
|
||||||
}
|
}
|
||||||
// 获取通知消息
|
// 获取通知消息
|
||||||
public static function getNotifyMessage(): array
|
public static function getNotifyMessage(): array
|
||||||
{
|
{
|
||||||
|
$message = cache('message');
|
||||||
|
if ($message) {
|
||||||
|
return json_decode($message, true);
|
||||||
|
}
|
||||||
$message = self::getHttpResponse(self::$siteUrl . '/mpay/message');
|
$message = self::getHttpResponse(self::$siteUrl . '/mpay/message');
|
||||||
|
cache('message', $message, 36000);
|
||||||
return json_decode($message, true);
|
return json_decode($message, true);
|
||||||
}
|
}
|
||||||
// 请求外部资源
|
// 请求外部资源
|
||||||
|
|||||||
Binary file not shown.
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
header('content-type: application/json; charset=utf-8');
|
|
||||||
$path = '../runtime/order.json';
|
|
||||||
if (!file_exists($path)) {
|
|
||||||
exit('{"code":3,"msg":"文件不存在"}');
|
|
||||||
} else {
|
|
||||||
exit(file_get_contents($path));
|
|
||||||
}
|
|
||||||
BIN
public/static/img/unionpay.ico
Normal file
BIN
public/static/img/unionpay.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/static/img/unionpay.jpg
Normal file
BIN
public/static/img/unionpay.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -1,14 +0,0 @@
|
|||||||
<?php
|
|
||||||
function encrypt($string, $key) {
|
|
||||||
$method = "AES-256-CBC";
|
|
||||||
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method));
|
|
||||||
$encrypted = openssl_encrypt($string, $method, $key, 0, $iv);
|
|
||||||
// 将iv和加密字符串拼接起来
|
|
||||||
return base64_encode($iv . $encrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
$key = "your-encryption-key"; // 这里应该是一个安全的密钥
|
|
||||||
$string = "Hello, World!";
|
|
||||||
$encryptedString = encrypt($string, $key);
|
|
||||||
|
|
||||||
echo $encryptedString; // 输出加密字符串
|
|
||||||
@@ -751,6 +751,10 @@
|
|||||||
<td>wxpay</td>
|
<td>wxpay</td>
|
||||||
<td>微信支付</td>
|
<td>微信支付</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>unionpay</td>
|
||||||
|
<td>云闪付</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h3 id="pay5"><a name="设备类型列表" class="reference-link"></a><span
|
<h3 id="pay5"><a name="设备类型列表" class="reference-link"></a><span
|
||||||
|
|||||||
@@ -5,6 +5,19 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>订单明细</title>
|
<title>订单明细</title>
|
||||||
<link rel="stylesheet" href="/component/pear/css/pear.css" />
|
<link rel="stylesheet" href="/component/pear/css/pear.css" />
|
||||||
|
<style>
|
||||||
|
.paytype {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paytype>span {
|
||||||
|
margin-left: 3px;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="pear-container">
|
<body class="pear-container">
|
||||||
@@ -56,6 +69,7 @@
|
|||||||
<option value="">请选择</option>
|
<option value="">请选择</option>
|
||||||
<option value="wxpay">微信支付</option>
|
<option value="wxpay">微信支付</option>
|
||||||
<option value="alipay">支付宝</option>
|
<option value="alipay">支付宝</option>
|
||||||
|
<option value="unionpay">云闪付</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -207,7 +221,7 @@
|
|||||||
{ title: '成交金额', field: 'really_price', align: 'center', minWidth: 85 },
|
{ title: '成交金额', field: 'really_price', align: 'center', minWidth: 85 },
|
||||||
{ title: '支付状态', field: 'state', align: 'center', minWidth: 85, templet: '<div>{{# if(d.state==1){return`<span class="layui-badge layui-bg-green">成功</span>`}else{if(new Date(d.close_time)>new Date("<?php echo $servertime ?>")){return`<span class="layui-badge layui-bg-orange">等待</span>`}else{return`<span class="layui-badge layui-bg-gray">过期</span>`} } }}</div>' },
|
{ title: '支付状态', field: '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`<img src="/static/img/wxpay.ico"width="15"><span>微信支付</span>`}if(d.type=="alipay"){return`<img src="/static/img/alipay.ico"width="15"><span>支付宝</span>`} }}</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: '<div>{{# return`${d.payAccount.platform} [${d.aid}:${d.cid}]` }}</div>' },
|
||||||
{ title: '操作', align: 'center', width: 120, fixed: 'right', templet: '<div><strong><a href="javascript:;" data-id="{{= d.id }}" class="layui-font-green {{= d.state==1 ? "orderSet-paid" : "orderSet-paying" }}">设置</a></strong></div>' }
|
{ 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>' }
|
||||||
]]
|
]]
|
||||||
|
|||||||
@@ -23,6 +23,15 @@
|
|||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paytype {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paytype>strong {
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
.alipay {
|
.alipay {
|
||||||
color: #1677ff;
|
color: #1677ff;
|
||||||
}
|
}
|
||||||
@@ -30,6 +39,10 @@
|
|||||||
.wxpay {
|
.wxpay {
|
||||||
color: #1AAD19;
|
color: #1AAD19;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unionpay {
|
||||||
|
color: #d81e06;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -54,8 +67,8 @@
|
|||||||
<div class="layui-row">
|
<div class="layui-row">
|
||||||
<div class="layui-col-xs3"><label class="layui-form-label"><strong>收款方式</strong></label></div>
|
<div class="layui-col-xs3"><label class="layui-form-label"><strong>收款方式</strong></label></div>
|
||||||
<div class="layui-col-xs9">
|
<div class="layui-col-xs9">
|
||||||
<div class="list">
|
<div class="list paytype">
|
||||||
<?php $payway=['alipay'=>'支付宝','wxpay'=>'微信支付'];$payway_img=['alipay'=>'/static/img/alipay.ico','wxpay'=>'/static/img/wxpay.ico'];echo "<img src='{$payway_img[$type]}'width='16'><strong class='{$type}'>{$payway[$type]}</strong>" ?>
|
<?php $payway=['alipay'=>'支付宝','wxpay'=>'微信支付','unionpay'=>'云闪付'];$payway_img=['alipay'=>'/static/img/alipay.ico','wxpay'=>'/static/img/wxpay.ico','unionpay'=>'/static/img/unionpay.ico'];echo "<img src='{$payway_img[$type]}'width='16'><strong class='{$type}'>{$payway[$type]}</strong>" ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>订单明细</title>
|
<title>支付测试</title>
|
||||||
<link rel="stylesheet" href="/component/pear/css/pear.css" />
|
<link rel="stylesheet" href="/component/pear/css/pear.css" />
|
||||||
<style>
|
<style>
|
||||||
.paybtn {
|
.paybtn {
|
||||||
@@ -60,6 +60,10 @@
|
|||||||
<img src="/static/img/alipay.ico" width="16">
|
<img src="/static/img/alipay.ico" width="16">
|
||||||
<span>支付宝</span>
|
<span>支付宝</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="pear-btn unionpay">
|
||||||
|
<img src="/static/img/unionpay.ico" width="16">
|
||||||
|
<span>云闪付</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -91,6 +95,9 @@
|
|||||||
document.querySelector('.alipay').addEventListener('click', function () {
|
document.querySelector('.alipay').addEventListener('click', function () {
|
||||||
crateOrder('alipay');
|
crateOrder('alipay');
|
||||||
});
|
});
|
||||||
|
document.querySelector('.unionpay').addEventListener('click', function () {
|
||||||
|
crateOrder('unionpay');
|
||||||
|
});
|
||||||
// 创建订单
|
// 创建订单
|
||||||
function crateOrder(paytype) {
|
function crateOrder(paytype) {
|
||||||
form.submit('paytest', function (data) {
|
form.submit('paytest', function (data) {
|
||||||
|
|||||||
@@ -150,6 +150,35 @@
|
|||||||
</div>
|
</div>
|
||||||
<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>
|
||||||
|
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>
|
<script>
|
||||||
const payCode = '<?php echo htmlentities($payUrl); ?>';
|
const payCode = '<?php echo htmlentities($payUrl); ?>';
|
||||||
const codeType = '<?php echo htmlentities($code_type); ?>';
|
const codeType = '<?php echo htmlentities($code_type); ?>';
|
||||||
@@ -166,6 +195,9 @@
|
|||||||
} else if (payType === 'alipay') {
|
} else if (payType === 'alipay') {
|
||||||
payTpeyImg.src = '/static/img/alipay.jpg';
|
payTpeyImg.src = '/static/img/alipay.jpg';
|
||||||
payTypeText.innerText = '请使用支付宝扫码支付'
|
payTypeText.innerText = '请使用支付宝扫码支付'
|
||||||
|
} else if (payType === 'unionpay') {
|
||||||
|
payTpeyImg.src = '/static/img/unionpay.jpg';
|
||||||
|
payTypeText.innerText = '请使用云闪付扫码支付'
|
||||||
}
|
}
|
||||||
// 生成二维码
|
// 生成二维码
|
||||||
if (codeType == 0) {
|
if (codeType == 0) {
|
||||||
@@ -244,6 +276,14 @@
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
/* <?php } ?> */
|
/* <?php } ?> */
|
||||||
|
|
||||||
|
// 环境判断
|
||||||
|
const environment = detectBrowserEnvironment();
|
||||||
|
if (payType === 'wxpay' && environment === 'aliphone') {
|
||||||
|
layer.alert('请使用微信打开此页面');
|
||||||
|
} else if (payType === 'alipay' && environment === 'wxphone') {
|
||||||
|
layer.alert('请使用支付宝打开此页面');
|
||||||
|
}
|
||||||
// 生成二维码
|
// 生成二维码
|
||||||
async function getQrcode(text, QR) {
|
async function getQrcode(text, QR) {
|
||||||
const qrcodeUrl = await new Promise((resolve) => {
|
const qrcodeUrl = await new Promise((resolve) => {
|
||||||
|
|||||||
@@ -28,14 +28,14 @@
|
|||||||
<select class="type" lay-filter="select-type">
|
<select class="type" lay-filter="select-type">
|
||||||
<option value="">请选择</option>
|
<option value="">请选择</option>
|
||||||
<!-- <?php if ($platform == 'wxpay') { ?> -->
|
<!-- <?php if ($platform == 'wxpay') { ?> -->
|
||||||
<option value="wxpay1">个人码</option>
|
<option value="wxpay1">个人码/经营码</option>
|
||||||
<option value="wxpay2">赞赏码</option>
|
<option value="wxpay2">赞赏码</option>
|
||||||
<!-- <option value="wxpay3">经营码</option>
|
<option value="wxpay3" disabled >经营码</option>
|
||||||
<option value="wxpay4">商家码</option> -->
|
<option value="wxpay4">商家码</option>
|
||||||
<!-- <?php } ?> -->
|
<!-- <?php } ?> -->
|
||||||
<!-- <?php if ($platform == 'alipay') { ?> -->
|
<!-- <?php if ($platform == 'alipay') { ?> -->
|
||||||
<option value="alipay1">收钱码</option>
|
<option value="alipay1">收钱码/经营码</option>
|
||||||
<!-- <option value="alipay2">经营码</option> -->
|
<option value="alipay2" disabled>经营码</option>
|
||||||
<!-- <?php } ?> -->
|
<!-- <?php } ?> -->
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -181,9 +181,9 @@
|
|||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<div class="layui-form-mid layui-elip"
|
<div class="layui-form-mid layui-elip"
|
||||||
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
style="margin-left: 10px;color: #5f5f5f;float: none;">
|
||||||
<?php echo '并且 是 APP包名 相等 com.tencent.mm<br />并且 是 通知标题 相等 微信支付<br />[空格]或者 是 通知标题 相等 微信收款助手' ?>
|
<?php echo '并且 是 APP包名 相等 com.tencent.mm<br />并且 是 通知标题 相等 微信支付<br />[空格]或者 是 通知标题 相等 微信收款助手<br />[空格]或者 是 通知标题 相等 微信收款商业版' ?>
|
||||||
<a href="javascript:;" lay-on="copyinfo"
|
<a href="javascript:;" lay-on="copyinfo"
|
||||||
data-info='<?php echo "并且 是 APP包名 相等 com.tencent.mm\n并且 是 通知标题 相等 微信支付\n[空格]或者 是 通知标题 相等 微信收款助手" ?>'
|
data-info='<?php echo "并且 是 APP包名 相等 com.tencent.mm\n并且 是 通知标题 相等 微信支付\n[空格]或者 是 通知标题 相等 微信收款助手\n[空格]或者 是 通知标题 相等 微信收款商业版" ?>'
|
||||||
style="float: right;" 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>
|
||||||
|
|||||||
Reference in New Issue
Block a user