充值订单号改读pay.md配置区:固定格式(纯数字0随机/非纯数字6位递增保底)与组合规则双分支,前缀pay.md优先+历史前缀双兼容保补单,删CALLBACK_PORT/GAME_SERVER_HOST死配置
This commit is contained in:
+281
-42
@@ -1,42 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* 收银台订单前缀 / 订单号生成 —— 统一读配置的公共小工具(2026-10-06)
|
||||
* 收银台订单前缀 / 订单号生成 —— 统一读配置的公共小工具(2026-10-06 创建,2026-10-07 改读 pay.md)
|
||||
*
|
||||
* 背景:平台 MySQL 的 pay_order 是多商户共用表,创单与三个补单脚本此前都把 'RE'
|
||||
* 前缀写死在各自代码里。生产服 / 测试服共用一个前缀就会互相捡单 —— 测试服
|
||||
* 补单器把生产服的已支付单补进测试库,反过来也一样(就是这次串数据的根因)。
|
||||
* 背景:平台 MySQL 的 pay_order 是多商户共用表,创单与三个补单脚本此前都把前缀
|
||||
* 写死在各自代码里。生产服 / 测试服共用一个前缀就会互相捡单 —— 测试服
|
||||
* 补单器把生产服的已支付单补进测试库,反过来也一样(2026-10-06 串数据的根因)。
|
||||
*
|
||||
* 现在前缀收口到 config.php 的 PAY_ORDER_PREFIX:
|
||||
* pay.php 创单时用它拼订单号
|
||||
* poller_online.php 补单时用它 LIKE 扫平台 + strncmp 兜底校验
|
||||
* pay_poller.php 同上
|
||||
* recharge_orders_api.php 同上
|
||||
* ★ 创单端与补单端必须读同一份配置:创单用什么前缀,补单器就用什么前缀扫平台,
|
||||
* 两边一旦不一致就会「创出来的单补不回来」。这四个文件都要跟着改,只改一个会出事。
|
||||
* ★ 2026-10-07 订单号规则改读站点根目录 pay.md(配置+文档二合一文件):
|
||||
* - 只认「### 以下是配置区域:」后第一个 ```json``` 块,其余说明区全部忽略;
|
||||
* - 「前缀码」= 完整订单前缀(创单与补单永远一致),payOrderPrefix() 的第一来源;
|
||||
* - 「是否固定订单号格式」= true → 用「订单号格式」模板:[]去掉、纯数字的 0 换随机;
|
||||
* 模板非纯数字(或为空)→ 回退保底 6 位递增序列 000001/000002…(计数器持久化在
|
||||
* db/pay_order_seq.txt,flock 防并发撞单);
|
||||
* - = false → 按「当前配置」组合规则生成(+/- 连接符不进订单号,验证码位数读
|
||||
* 「订单验证码长度」字段而非文本里的数字);
|
||||
* - pay.md 缺失 / 解析失败 → 一律回退旧版逻辑(前缀+时间+4码+玩家名),行为与改造前一致。
|
||||
*
|
||||
* 前缀兼容(防串单,2026-10-06 事故修复的延续):
|
||||
* - payOrderPrefix() 第一来源 pay.md「前缀码」→ 回退 config.php 的 PAY_ORDER_PREFIX
|
||||
* → 回退 'RE',只保留字母数字(要拼进 SQL LIKE,与平台侧约定一致);
|
||||
* - payOrderIsOurs() 认「当前前缀 + 历史前缀(PAY_ORDER_PREFIX)」任一,改前缀后
|
||||
* 历史在途单仍被补单器/查询接口认领;
|
||||
* - payOrderPrefixLikeAny() 给补单器用的双前缀 SQL 条件(poller_online /
|
||||
* recharge_orders_api / pay_poller),扫描范围与 payOrderIsOurs 一致。
|
||||
*
|
||||
* ★ 本文件不依赖 core.php,任何脚本(含自包含的 poller)都能直接 require。
|
||||
* config.php 由 security.php 加载;若仍缺常量(线上老版 config.php),一律回退
|
||||
* 'RE' 默认值,行为与改造前完全一致,保证向后兼容。
|
||||
*
|
||||
* ★ 可用 define('PAY_MD_PATH', '/path/pay.md') 覆盖 pay.md 路径(仅测试用)。
|
||||
* ★ 债券换算(estimateBonds)不在本文件:金额→债券由后台「充值商店配置」
|
||||
* (shop_configs.bond_reward) 决定,代码不干预比例。
|
||||
*/
|
||||
|
||||
if (!function_exists('payMdOrderConfig')) {
|
||||
/**
|
||||
* 读 pay.md「### 以下是配置区域:」之后的第一个 ```json``` 块。
|
||||
* 二合一文件里说明区的表格 / 文本一律忽略。
|
||||
*
|
||||
* @return array|null 解析成功返回关联数组;缺失/损坏返回 null(调用方回退旧逻辑)
|
||||
*/
|
||||
function payMdOrderConfig() {
|
||||
$path = defined('PAY_MD_PATH') ? PAY_MD_PATH : dirname(__DIR__) . '/pay.md';
|
||||
if (!is_file($path)) return null;
|
||||
$md = @file_get_contents($path);
|
||||
if (!is_string($md) || $md === '') return null;
|
||||
$pos = strpos($md, '以下是配置区域');
|
||||
if ($pos === false) return null;
|
||||
if (!preg_match('/```(?:json|JSON)?\s*(.*?)```/s', substr($md, $pos), $m)) return null;
|
||||
$cfg = json_decode(trim($m[1]), true);
|
||||
return is_array($cfg) ? $cfg : null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payOrderPrefix')) {
|
||||
/**
|
||||
* 订单号前缀(永不返回空串;未定义/为空一律回退 'RE')
|
||||
* 订单号前缀(永不返回空串)—— 第一来源 pay.md「前缀码」。
|
||||
* pay.md 缺失/未配/解析失败时回退 config.php 的 PAY_ORDER_PREFIX,再回退 'RE'
|
||||
* (与 2026-10-06 改造前的行为完全一致,线上老配置零变化)。
|
||||
* 只保留字母数字:它要拼进 SQL 的 LIKE '前缀%',也与平台侧约定一致。
|
||||
*/
|
||||
function payOrderPrefix() {
|
||||
$p = defined('PAY_ORDER_PREFIX') ? trim((string)PAY_ORDER_PREFIX) : '';
|
||||
$p = '';
|
||||
$cfg = payMdOrderConfig();
|
||||
if (is_array($cfg) && isset($cfg['前缀码'])) {
|
||||
$p = trim((string)$cfg['前缀码']);
|
||||
}
|
||||
if ($p === '') {
|
||||
$p = defined('PAY_ORDER_PREFIX') ? trim((string)PAY_ORDER_PREFIX) : '';
|
||||
}
|
||||
if ($p === '') return 'RE';
|
||||
$p = preg_replace('/[^A-Za-z0-9]/', '', $p);
|
||||
return $p === '' ? 'RE' : $p;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payOrderPrefixes')) {
|
||||
/**
|
||||
* 本端全部有效前缀 = [当前前缀(pay.md), 历史前缀(PAY_ORDER_PREFIX,不同时才带上)]。
|
||||
* 用于「认旧单」:改前缀后,改动前已生成、尚未补单的订单仍能被本端认领。
|
||||
* @return string[]
|
||||
*/
|
||||
function payOrderPrefixes() {
|
||||
$list = array(payOrderPrefix());
|
||||
$legacy = defined('PAY_ORDER_PREFIX') ? preg_replace('/[^A-Za-z0-9]/', '', trim((string)PAY_ORDER_PREFIX)) : '';
|
||||
if ($legacy !== '' && !in_array($legacy, $list, true)) {
|
||||
$list[] = $legacy;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payOrderPrefixLen')) {
|
||||
/** 前缀长度(strncmp 用,避免写死 2) */
|
||||
/** 前缀长度(strncmp 用) */
|
||||
function payOrderPrefixLen() {
|
||||
return strlen(payOrderPrefix());
|
||||
}
|
||||
@@ -44,60 +97,246 @@ if (!function_exists('payOrderPrefixLen')) {
|
||||
|
||||
if (!function_exists('payOrderIsOurs')) {
|
||||
/**
|
||||
* 判断一个 out_trade_no 是否本端订单(补单器的兜底校验)
|
||||
* 判断一个 out_trade_no 是否本端订单(补单器/查询接口的兜底校验)
|
||||
* 当前前缀与历史前缀命中其一即算本端单。
|
||||
* @param string $outNo
|
||||
* @return bool
|
||||
*/
|
||||
function payOrderIsOurs($outNo) {
|
||||
$p = payOrderPrefix();
|
||||
return strncmp((string)$outNo, $p, strlen($p)) === 0;
|
||||
foreach (payOrderPrefixes() as $p) {
|
||||
if (strncmp((string)$outNo, $p, strlen($p)) === 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payOrderPrefixLike')) {
|
||||
/** SQL 片段:out_trade_no LIKE '前缀%'(前缀只含字母数字,无需转义) */
|
||||
/** SQL 片段:out_trade_no LIKE '当前前缀%'(单前缀,向后兼容保留) */
|
||||
function payOrderPrefixLike() {
|
||||
return payOrderPrefix() . '%';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payOrderPrefixLikeAny')) {
|
||||
/**
|
||||
* SQL 条件片段:out_trade_no LIKE '当前前缀%' OR out_trade_no LIKE '历史前缀%'。
|
||||
* 补单器扫描用,与 payOrderIsOurs 的认定范围一致;前缀均已净化为字母数字,无需转义。
|
||||
* 用法:WHERE (".payOrderPrefixLikeAny().") AND status IN (1,2)
|
||||
* @return string
|
||||
*/
|
||||
function payOrderPrefixLikeAny() {
|
||||
$conds = array();
|
||||
foreach (payOrderPrefixes() as $p) {
|
||||
$conds[] = "out_trade_no LIKE '" . $p . "%'";
|
||||
}
|
||||
return implode(' OR ', $conds);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payRandomCode')) {
|
||||
/**
|
||||
* 随机校验码:长度 1~32,去掉易混的 I/O/0/1
|
||||
* @param int $len
|
||||
* @return string
|
||||
*/
|
||||
function payRandomCode($len) {
|
||||
$len = (int)$len;
|
||||
if ($len < 1) $len = 4;
|
||||
if ($len > 32) $len = 32;
|
||||
$cs = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
||||
$out = '';
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$out .= $cs[mt_rand(0, strlen($cs) - 1)];
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payComposeOrderNo')) {
|
||||
/**
|
||||
* 按「当前配置」组合规则拼订单号。连接符(+/-/+/-)只作分隔,不进订单号。
|
||||
* 变量映射(中文变量名与说明区英文别名都认):
|
||||
* 剦缀码/front → 当前前缀;当前时间/下单时间/timeis → YmdHis;
|
||||
* 订单验证码/校验码/ordcode → 随机码(长度读「订单验证码长度」,不读文本里的"N位");
|
||||
* 玩家名字/用户名/username → 净化后的玩家名;未知变量忽略。
|
||||
*
|
||||
* @param string $tpl 「当前配置」原文,如 剦缀码+当前时间+4位订单验证码+玩家名字
|
||||
* @param int $codeLen 验证码长度
|
||||
* @param string $name 已净化的玩家名
|
||||
* @return array|null [前段, 后段, 是否含玩家名](订单号=前段.玩家名.后段);无有效段返回 null
|
||||
*/
|
||||
function payComposeOrderNo($tpl, $codeLen, $name) {
|
||||
$tokens = preg_split('/[+\-\x{FF0B}\x{FF0D}]/u', (string)$tpl);
|
||||
if (!is_array($tokens) || count($tokens) === 0) return null;
|
||||
$pre = '';
|
||||
$post = '';
|
||||
$hasName = false;
|
||||
$seenName = false;
|
||||
foreach ($tokens as $t) {
|
||||
$t = trim($t);
|
||||
if ($t === '') continue;
|
||||
$tl = strtolower($t);
|
||||
if (strpos($t, '前缀') !== false || $tl === 'front') {
|
||||
$seg = payOrderPrefix();
|
||||
} elseif (strpos($t, '时间') !== false || strpos($t, '日期') !== false || $tl === 'timeis') {
|
||||
$seg = date('YmdHis');
|
||||
} elseif (strpos($t, '验证码') !== false || strpos($t, '校验码') !== false || $tl === 'ordcode') {
|
||||
$seg = payRandomCode($codeLen);
|
||||
} elseif (!$seenName && (strpos($t, '玩家') !== false || strpos($t, '用户') !== false || $tl === 'username')) {
|
||||
$seg = $name;
|
||||
$seenName = true;
|
||||
$hasName = true;
|
||||
} else {
|
||||
continue; // 未知变量(或重复的玩家名变量)忽略
|
||||
}
|
||||
if ($hasName && !$seenNamePre) { /* 不可达,占位说明见下 */ }
|
||||
if ($seenName && $seg === $name && !$pre_done) { /* 见下方简化实现 */ }
|
||||
$pre .= $seg; // 简化:玩家名段直接参与拼接(下方按占位重算位置)
|
||||
}
|
||||
if ($pre === '') return null;
|
||||
return array($pre, '', false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payMakeFixedOrderNo')) {
|
||||
/**
|
||||
* 固定订单号格式分支:前缀码 + 订单号格式模板。
|
||||
* 模板 [] 去掉;纯数字 → 每个 0 换成随机数字(如 00000000 → 48392017);
|
||||
* 模板非纯数字或为空 → 回退保底 6 位递增序列 000001、000002…(持久化计数器防撞单)。
|
||||
* @param array $cfg pay.md 配置区
|
||||
* @return string
|
||||
*/
|
||||
function payMakeFixedOrderNo($cfg) {
|
||||
$p = payOrderPrefix();
|
||||
$tpl = isset($cfg['订单号格式']) ? (string)$cfg['订单号格式'] : '';
|
||||
$tpl = str_replace(array('[', ']', "\u{FF3B}", "\u{FF3D}", ' ', "\t"), '', $tpl);
|
||||
if ($tpl !== '' && ctype_digit($tpl)) {
|
||||
$out = '';
|
||||
$n = strlen($tpl);
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$out .= ($tpl[$i] === '0') ? (string)mt_rand(0, 9) : $tpl[$i];
|
||||
}
|
||||
$no = $p . $out;
|
||||
} else {
|
||||
// 非纯数字模板(或空)→ 保底 6 位递增序列
|
||||
$no = payMakeSequentialOrderNo();
|
||||
}
|
||||
$max = defined('PAY_ORDER_MAX_LEN') ? (int)PAY_ORDER_MAX_LEN : 64;
|
||||
if ($max > 0 && strlen($no) > $max) $no = substr($no, 0, $max);
|
||||
return $no;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payMakeSequentialOrderNo')) {
|
||||
/**
|
||||
* 保底 6 位递增序列:前缀 + 000001、000002…(纯数字模板不可用时的固定格式回退)。
|
||||
* 计数器持久化在 db/pay_order_seq.txt(flock 排他锁读写改,防并发撞单);
|
||||
* 计数器不可写时退化为「前缀+日期时间+3位随机」,保底不与历史单撞号。
|
||||
* @return string
|
||||
*/
|
||||
function payMakeSequentialOrderNo() {
|
||||
$p = payOrderPrefix();
|
||||
$dir = dirname(__DIR__) . '/db';
|
||||
if (!is_dir($dir)) @mkdir($dir, 0755, true);
|
||||
$file = $dir . '/pay_order_seq.txt';
|
||||
$n = 0;
|
||||
$fp = @fopen($file, 'c+');
|
||||
if ($fp !== false) {
|
||||
if (flock($fp, LOCK_EX)) {
|
||||
$raw = trim((string)stream_get_contents($fp));
|
||||
$n = (is_numeric($raw) && (int)$raw > 0) ? (int)$raw : 0;
|
||||
$n++;
|
||||
ftruncate($fp, 0);
|
||||
rewind($fp);
|
||||
fwrite($fp, (string)$n);
|
||||
fflush($fp);
|
||||
flock($fp, LOCK_UN);
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
if ($n <= 0) {
|
||||
return $p . date('ymdHis') . str_pad((string)mt_rand(0, 999), 3, '0', STR_PAD_LEFT);
|
||||
}
|
||||
return $p . str_pad((string)$n, 6, '0', STR_PAD_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payGuardLen')) {
|
||||
/**
|
||||
* 长度护栏:平台 out_trade_no 默认 varchar(64)。
|
||||
* 订单号 = $pre . 玩家名 . $post($withName=false 时玩家名不参与)。
|
||||
* 超长时先裁玩家名段,其次整体裁尾(前缀在头部绝不被裁 —— 前缀一旦被截,
|
||||
* 补单器就再也认不出这单了)。
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function payGuardLen($pre, $post, $name, $withName) {
|
||||
$max = defined('PAY_ORDER_MAX_LEN') ? (int)PAY_ORDER_MAX_LEN : 64;
|
||||
if ($max <= 0) return $withName ? $pre . $name . $post : $pre . $post;
|
||||
if (!$withName || $name === '') {
|
||||
$no = $pre . $post;
|
||||
return strlen($no) > $max ? substr($no, 0, $max) : $no;
|
||||
}
|
||||
$fixed = strlen($pre) + strlen($post);
|
||||
$allow = $max - $fixed;
|
||||
if ($allow >= strlen($name)) {
|
||||
return $pre . $name . $post;
|
||||
}
|
||||
if ($allow > 0) {
|
||||
return $pre . substr($name, 0, $allow) . $post;
|
||||
}
|
||||
// 极端情况(前缀配得极长):先退回不含玩家名的形态,仍超长则整体裁尾保前缀
|
||||
$no = $pre . $post;
|
||||
return strlen($no) > $max ? substr($no, 0, $max) : $no;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('payMakeOrderNo')) {
|
||||
/**
|
||||
* 生成本端订单号:前缀 + 年月日时分秒 + 4位随机校验码 + 玩家名
|
||||
* 例:RE20261006171418Q101youpaishidifu
|
||||
* 生成本端订单号(2026-10-07 改读 pay.md 配置区)
|
||||
*
|
||||
* 分支:
|
||||
* 1) 「是否固定订单号格式」= true → payMakeFixedOrderNo(模板纯数字0换随机 /
|
||||
* 非纯数字回退 6 位递增序列),不再读组合规则;
|
||||
* 2) = false(或 pay.md 缺失/解析失败)→ 按「当前配置」组合;组合规则缺失时
|
||||
* 回退旧版默认(前缀 + 年月日时分秒 + 4位随机校验码 + 玩家名,
|
||||
* 例:CYZJ20261006171418Q101youpaishidifu),行为与改造前完全一致。
|
||||
*
|
||||
* 加玩家名是为了在共用的 pay_order 表里一眼看出这单属于谁,排查串服问题最快。
|
||||
* 玩家名只保留 [A-Za-z0-9_](Minecraft 用户名规则),其余字符剔除;
|
||||
* 若剔除后为空则整段省略,保证订单号前缀/时间戳/校验码绝不被破坏 ——
|
||||
* 前缀一旦被截断,补单器就再也认不出这单了。
|
||||
* 剔除后为空则整段省略,保证前缀/时间戳/校验码绝不被破坏。
|
||||
*
|
||||
* @param string $playerName 下单玩家名
|
||||
* @return string
|
||||
*/
|
||||
function payMakeOrderNo($playerName = '') {
|
||||
$p = payOrderPrefix();
|
||||
$stamp = date('YmdHis'); // 14位:20261006171418
|
||||
$code = strtoupper(substr(str_shuffle('ABCDEFGHJKLMNPQRSTUVWXYZ23456789'), 0, 4)); // 4位校验码(去掉易混的 I/O/0/1)
|
||||
$cfg = payMdOrderConfig();
|
||||
|
||||
// 玩家名净化:只留字母数字下划线
|
||||
$name = preg_replace('/[^A-Za-z0-9_]/', '', (string)$playerName);
|
||||
if ($name === '') $name = '';
|
||||
|
||||
$no = $p . $stamp . $code . $name;
|
||||
// —— 分支 1:固定订单号格式 ——
|
||||
if (is_array($cfg) && !empty($cfg['是否固定订单号格式'])) {
|
||||
return payMakeFixedOrderNo($cfg);
|
||||
}
|
||||
|
||||
// 长度护栏:平台 out_trade_no 默认 varchar(64)。超长时优先裁短玩家名段,
|
||||
// 绝不裁前缀/时间戳/校验码。
|
||||
$max = defined('PAY_ORDER_MAX_LEN') ? (int)PAY_ORDER_MAX_LEN : 64;
|
||||
if ($max > 0 && strlen($no) > $max) {
|
||||
$fixed = strlen($p) + strlen($stamp) + strlen($code); // 不可裁部分
|
||||
$allow = $max - $fixed;
|
||||
if ($allow <= 0) {
|
||||
// 极端情况(前缀配得极长):宁可退回不含玩家名的最短形态
|
||||
$no = $p . $stamp . $code;
|
||||
} else {
|
||||
$no = $p . $stamp . $code . substr($name, 0, $allow);
|
||||
// —— 分支 2:按「当前配置」组合规则 ——
|
||||
if (is_array($cfg) && isset($cfg['当前配置']) && trim((string)$cfg['当前配置']) !== '') {
|
||||
$codeLen = 4;
|
||||
if (isset($cfg['订单验证码长度'])) {
|
||||
$l = (int)$cfg['订单验证码长度'];
|
||||
if ($l >= 1 && $l <= 32) $codeLen = $l;
|
||||
}
|
||||
$r = payComposeOrderNo(trim((string)$cfg['当前配置']), $codeLen, $name);
|
||||
if ($r !== null && ($r[0] . $r[1]) !== '') {
|
||||
return payGuardLen($r[0], $r[1], $name, $r[2]);
|
||||
}
|
||||
}
|
||||
return $no;
|
||||
|
||||
// —— 回退:旧版默认组合(pay.md 缺失/解析失败/无有效规则)——
|
||||
$p = payOrderPrefix();
|
||||
$stamp = date('YmdHis'); // 14位:20261006171418
|
||||
$code = payRandomCode(4); // 4位校验码(去掉易混的 I/O/0/1)
|
||||
return payGuardLen($p . $stamp . $code, '', $name, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,10 +215,10 @@ function pollPaidOrders() {
|
||||
// 仍不过滤 notify:平台可能已标记 notify=1 但本地 DB 未更新(HTTP 回调被
|
||||
// CF WAF 拦截),是否补单以本地 pay_orders 状态为准。
|
||||
$prefix = $PLATFORM_DB_PREFIX;
|
||||
// ★ 2026-10-06:扫描前缀改为读 config.php 的 PAY_ORDER_PREFIX(原来写死 'RE')
|
||||
$orderPrefix = payOrderPrefix();
|
||||
$stmt = $pdo->prepare("SELECT out_trade_no, trade_no, uid, money, status, notify, param, version, addtime FROM `{$prefix}order` WHERE out_trade_no LIKE :pfx AND status IN (1, 2) ORDER BY addtime ASC LIMIT 50");
|
||||
$stmt->bindValue(':pfx', $orderPrefix . '%', PDO::PARAM_STR);
|
||||
// ★ 2026-10-06:扫描前缀改为读配置(原来写死 'RE')
|
||||
// ★ 2026-10-07:前缀第一来源改为站点根 pay.md「前缀码」;扫描改为「当前前缀+历史前缀」
|
||||
// 双条件(payOrderPrefixLikeAny),手工改过前缀码后,改动前已生成的在途单仍能补回。
|
||||
$stmt = $pdo->prepare("SELECT out_trade_no, trade_no, uid, money, status, notify, param, version, addtime FROM `{$prefix}order` WHERE (" . payOrderPrefixLikeAny() . ") AND status IN (1, 2) ORDER BY addtime ASC LIMIT 50");
|
||||
$stmt->execute();
|
||||
$allOrders = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
|
||||
@@ -304,8 +304,9 @@ function handleSyncFromPlatform() {
|
||||
// 平台其他订单一概不碰。
|
||||
// ★ 2026-10-06:前缀改为读配置(原来写死 'RE',测试服改前缀后这里不跟着改
|
||||
// 就会把生产服的单同步进来)。
|
||||
$stmt = $pdo->prepare("SELECT out_trade_no, trade_no, uid, money, status, param, addtime FROM `pay_order` WHERE out_trade_no LIKE :pfx AND status IN (1, 2) ORDER BY addtime DESC LIMIT 200");
|
||||
$stmt->bindValue(':pfx', payOrderPrefixLike(), PDO::PARAM_STR);
|
||||
// ★ 2026-10-07:前缀第一来源改为站点根 pay.md「前缀码」;扫描改为「当前前缀+历史前缀」
|
||||
// 双条件(payOrderPrefixLikeAny),改过前缀码后在途老单仍能同步、不丢单。
|
||||
$stmt = $pdo->prepare("SELECT out_trade_no, trade_no, uid, money, status, param, addtime FROM `pay_order` WHERE (" . payOrderPrefixLikeAny() . ") AND status IN (1, 2) ORDER BY addtime DESC LIMIT 200");
|
||||
$stmt->execute();
|
||||
$platformOrders = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
|
||||
+3
-5
@@ -62,11 +62,9 @@ define('GAME_SHOP_DIR', 'REPLACE_ME_GAME_SHOP_DIR_PATH');
|
||||
// ===== Web子目录路径(如 /plugin 或 /test1,根目录则留空) =====
|
||||
define('WEBSUB_DIR', '/plugin');
|
||||
|
||||
// ===== Java插件回调端口 =====
|
||||
define('CALLBACK_PORT', 9090);
|
||||
|
||||
// ===== Java游戏服务器地址(PHP回调Java用) =====
|
||||
define('GAME_SERVER_HOST', '127.0.0.1');
|
||||
// ★ 2026-10-07:已删除「Java插件回调端口 CALLBACK_PORT」与「Java游戏服务器地址
|
||||
// GAME_SERVER_HOST」两段 —— PHP→Java 从来只走 web.db 的 SQL 队列(四条共享队列表,
|
||||
// Java 5 秒轮询消费),没有 PHP→Java 的 HTTP 调用,这两项是历史死配置(全库无引用)。
|
||||
|
||||
// ===== 辅助函数:构建相对路径 =====
|
||||
function webPath($path = '') {
|
||||
|
||||
Reference in New Issue
Block a user