仰望星辰工作室

better-staridc-MNBT

better-staridc-MNBT/ MPHX/lib/pay.function.php 4.9 KB · 111 行 原始文件
Z zfhsh first commit 1 天前
1<?php
2/**
3 * 支付公共函数(V1.81 P3)
4 *
5 * 订单结算逻辑(原 user/notify_url.php / return_url.php 中的处理),
6 * 供支付插件回调验签后统一调用。
7 *
8 * 依赖:$DB, $conf, $date(由调用方作用域提供,或通过 global 引入)
9 */
10
11if (!function_exists('mnbt_pay_log')) {
12 /**
13 * 记录支付日志。
14 * @param string $content
15 * @param string $status
16 * @param string $orderNo
17 * @return mixed
18 */
19 function mnbt_pay_log($content, $status = '记录', $orderNo = '')
20 {
21 global $DB;
22 $suffix = $orderNo ? ' 订单' . $orderNo : '';
23 return mnbt_log('支付回调', '支付回调', $content . $suffix, $status, $DB);
24 }
25}
26
27if (!function_exists('mnbt_pay_settle_order')) {
28 /**
29 * 处理支付成功的订单。
30 *
31 * 由支付插件在回调验签通过后调用,执行订单的业务逻辑(一键部署/域名购买),
32 * 标记订单完成,并触发 order.paid action。
33 *
34 * @param string $out_trade_no 商户订单号
35 * @param string $trade_status 交易状态(支付宝: TRADE_SUCCESS)
36 * @param string $money 实付金额
37 * @return array ['ok'=>bool, 'msg'=>string]
38 */
39 function mnbt_pay_settle_order($out_trade_no, $trade_status, $money)
40 {
41 global $DB, $conf, $date;
42
43 if ($trade_status != 'TRADE_SUCCESS') {
44 mnbt_pay_log('支付状态非成功:' . $trade_status, '回调失败', $out_trade_no);
45 return ['ok' => false, 'msg' => 'trade_status=' . $trade_status];
46 }
47
48 $ddxx = $DB->get_row_prepare("SELECT * FROM `MN_dd` WHERE `ddh` = ? limit 1", [$out_trade_no]);
49 if (!$ddxx) {
50 mnbt_pay_log('订单不存在', '回调异常', $out_trade_no);
51 return ['ok' => false, 'msg' => '订单不存在'];
52 }
53
54 if ((string)$ddxx['qk'] === 'true') {
55 mnbt_pay_log('订单重复回调,已处理', '重复回调', $out_trade_no);
56 return ['ok' => true, 'msg' => '该订单已被系统处理'];
57 }
58
59 if (isset($ddxx['je']) && (string)$ddxx['je'] !== '' && (string)$money !== '' && (float)$ddxx['je'] != (float)$money) {
60 mnbt_pay_log('订单金额不一致,应付' . $ddxx['je'] . '实付' . $money, '回调异常', $out_trade_no);
61 return ['ok' => false, 'msg' => '订单金额不一致'];
62 }
63
64 $ddxx_cs = json_decode($ddxx['cs'], true);
65 if (!is_array($ddxx_cs)) {
66 mnbt_pay_log('订单参数解析失败', '回调异常', $out_trade_no);
67 return ['ok' => false, 'msg' => '订单参数解析失败'];
68 }
69
70 // 原子翻转订单状态:并发回调下只有 affected_rows>0 的一方获得处理权,防止重复触发 order.paid
71 // (query_prepare 返回值仅表示执行成功与否,受影响行数需经 $DB->affected() 获取)
72 $DB->query_prepare("update `MN_dd` set `qk` = 'true' where `ddh` = ? and `qk` <> 'true'", [$out_trade_no]);
73 if ((int)$DB->affected() === 0) {
74 // 翻转失败说明订单已被其他并发请求处理,直接返回成功让网关停止重发,不触发任何业务钩子
75 mnbt_pay_log('订单已被其他请求处理,跳过', '重复回调', $out_trade_no);
76 return ['ok' => true, 'msg' => '该订单已被系统处理'];
77 }
78
79 if ($ddxx['lx'] == 'yjbs') {
80 // 一键部署
81 $ddxx_xid = $ddxx_cs['gmid'] ?? 0;
82 $bscx = $DB->get_row_prepare("SELECT * FROM `MN_bs` WHERE `id` = ? limit 1", [$ddxx_xid]);
83 if (!$bscx) {
84 mnbt_pay_log('一键部署程序不存在ID' . $ddxx_xid, '处理失败', $out_trade_no);
85 return ['ok' => false, 'msg' => '程序不存在'];
86 }
87 $bs_tj = json_decode($bscx['tj'], true);
88 if (!is_array($bs_tj)) $bs_tj = [];
89 if (!in_array($ddxx_cs['user'], $bs_tj)) array_push($bs_tj, $ddxx_cs['user']);
90 $tj_jg = json_encode($bs_tj, 256);
91 if (!$DB->query_prepare("update `MN_bs` set `tj` =? where `id`=?", [$tj_jg, $ddxx_xid])) {
92 mnbt_pay_log('一键部署购买写入失败 用户' . ($ddxx_cs['user'] ?? ''), '处理失败', $out_trade_no);
93 return ['ok' => false, 'msg' => '程序购买写入失败'];
94 }
95 mnbt_pay_log('一键部署购买处理成功 用户' . ($ddxx_cs['user'] ?? ''), '处理成功', $out_trade_no);
96 // ymgm(域名购买)业务已迁移至 domain_shop 插件,由 order.paid 钩子处理
97 } else {
98 // 其他业务类型(如余额充值):核心不处理具体业务,仅标记订单完成并触发 order.paid 钩子,
99 // 由对应插件(如 balance 插件)在 order.paid 回调中处理。
100 mnbt_pay_log('扩展业务类型 ' . $ddxx['lx'] . ',交由 order.paid 钩子处理', '处理成功', $out_trade_no);
101 }
102
103 // 订单状态已在业务处理前原子翻转为 'true',此处无需再更新
104 mnbt_pay_log('订单处理完成 类型' . $ddxx['lx'] . ' 金额' . $money, '处理成功', $out_trade_no);
105 $order_row = $DB->get_row_prepare("SELECT * FROM MN_dd WHERE ddh=? limit 1", [$out_trade_no]);
106 if (function_exists('mnbt_do_action')) {
107 mnbt_do_action('order.paid', $order_row ?: $ddxx, ['money' => $money, 'source' => 'pay_plugin']);
108 }
109 return ['ok' => true, 'msg' => '支付成功'];
110 }
111}