Compare commits

...
44 Commits
Author SHA1 Message Date
OG Backup a437868f6e Merge branch 'master' of https://git.20031227.de5.net/og/Pro 2026-06-14 14:20:01 +08:00
OG Backup 171f8fce5c backup: 线上最终版本全量备份
包含所有线上运行的改动:
- 代理编辑功能修复(码率/占成/返水率保存)
- CORS跨域修复(Pcapi构造函数统一Origin)
- 支付通道(ccpay/epay新增)
- 代理报表洗码量显示
- AlinPay金额调整
- 代理/会员编辑页面优化
- 多语言更新
2026-06-14 14:19:49 +08:00
fengshao1227 788b8a0af3 revert+fix: 回滚充值扣费折算(恢复全额上分)+取消提现手续费
业务调整:客户不让用户承担手续费,改为客户自行预存代付账户余额(全额上分全额提现)。
1) 回滚 alin_recharge_settle 的代收费率折算,恢复充值全额上分
2) apply_withdraw/apply_withdraw_bank 提现手续费默认值 1→0,取消提现手续费
2026-06-03 19:31:14 +08:00
fengshao1227 ccf0af4ed2 fix: AlinPay充值上分按代收手续费率折算,客户承担手续费,防代付账户被掏空
根因:AlinPay代收时从平台代付账户扣手续费(回调real_amount仍是充值全额),
但系统全额上分→客户余额>账户实收→提现必差手续费那块,账户越提越空。
改为按ALIN_VN配置collection_fee_rate(%)折算上分额:充100万→上分99万(1%费率),
上分/扣代理同步折算,使客户余额=账户实收,代付永远够。back_money仍记全额供审计。
2026-06-03 19:12:26 +08:00
fengshao1227 dd84f674b0 fix: 彻底解耦存取款显隐与agent_type,只按pay_channel下发(防错配复发)
根因:登录/用户信息接口死卡 agent_type==1 才下发支付渠道,靠运营手动保持
agent_type 与 pay_channel 一致,一改错(如人工线配在线通道)用户就没存取款。
改为只看 pay_channel:OPR=人工(下发收款信息),非空非OPR=在线(下发币种/链),空=隐藏。
顺带修复 get_user_info 此前缺 OPR 分支导致人工线用户刷新丢充值信息的隐患。
覆盖移动端(Portal)+PC,均走此接口。170 错配存量已单独 UPDATE 修复。
2026-06-01 23:45:15 +08:00
fengshao1227 f67439bfe2 fix: 修复顶级代理(agent_parent_id=0)无法编辑保存(总账号给一级代理改参数报'上级错误')
do_edit 原逻辑 parent_id<=0 直接 die(parent_error),且后续全程访问 agentParent 做封顶校验,
导致顶级代理(一级总代)永远无法编辑保存。改为:顶级代理构造不设限虚拟上级,
封顶校验自动放行,封底校验(不得低于下级最高费率)与写入逻辑保持不变。对非顶级代理零影响。
2026-06-01 23:11:33 +08:00
fengshao1227 6012eff994 fix: '近一周'记录查询改为最近7天滚动窗口(含昨天),修复周一查不到昨天记录
time_interval=3 原为'本周自然周',周一时本周从今天起、昨天属上周故查无数据,
与前端'近一周/Gần một tuần'语义不符。改为 date(d)-6 ~ date(d) 最近7天滚动,
任意一天都含昨天且无星期边界问题。仅会员记录查询(onlinechip/admin Pcapi),
代理结算 Settle.php 的本周/上周保持自然周不变。
2026-06-01 15:27:50 +08:00
fengshao1227 e56ce3b132 fix: 修复结算(洗码/返水)周界查询在周日(date(w)=0)算成下周
Settle.php xima()/rebate() 的本周/上周周界同样受 date(w) 周日=0 影响,
周日会把本周算成下周、上周算成本周, 导致代理结算页查无未结数据或周次错位.
统一 date(w)->date(w)?:7, -7 上周偏移保留, 周一~周六零影响.
2026-05-31 20:15:42 +08:00
fengshao1227 a94b9f7fcc fix: 修复会员记录/报表查询'本周'在周日(date(w)=0)时间范围算成下周导致查无数据
PHP date(w) 周日返回0, date(d)-date(w)+1 在周日会把本周一推到下周一,
整个本周区间变成未来时间, 注单/记录查询返回0条(仅周日触发, 周一~周六正常).
用 date(w)?:7 将周日按第7天计算, 对周一~周六零影响.
覆盖 onlinechip/Pcapi(会员端 get_user_bets 等3处) + admin/Pcapi(3处)。
2026-05-31 20:09:18 +08:00
fengshao1227 fbeb9787dc feat(agent-report): 注单查询新增今日注单自动刷新开关(默认开,10秒刷新当前查询)
原自动刷新仅在线管理(online=1)进入时生效;现普通注单查询页也支持,
带开关(localStorage持久化)+倒计时显示,免手动点刷新。
2026-05-30 22:27:51 +08:00
fengshao1227 750a5472fa fix(alinpay): 网关域名 fallback 由 fantianchuangshi.com 迁至 hypayment.net
第三方支付网关改版迁移域名。DB配置已补 domain 字段, 同步更新代码回退默认值。
appid/secret/product_id/请求格式不变, 经账户查询验证新网关可用。
2026-05-29 21:35:01 +08:00
fengshao1227 ca2513bb7a feat(agent-home): 首页今日投注统计(tpbet)默认时间统一为 08:00:00~次日07:59:59 2026-05-29 21:17:13 +08:00
fengshao1227 2d7b15c1ad feat(agent-report): 统一全部报表默认时间为 今天08:00:00~次日07:59:59
Report.php 中 18 个报表(上下水/游戏/注单/上下分/台桌/棋牌等)默认时间
从 今天00:00~此刻 统一为 今天08:00:00~次日07:59:59(博彩日), 与结算报表一致。
保留2个默认'全部时间'(startTime=0)的查询不变。
2026-05-29 21:15:24 +08:00
fengshao1227 e763c561f1 feat(agent-report): 结算报表默认时间改为08:00~次日07:59:59, 码量列改名码粮
- Report::settle 默认日期边界 07:00/06:59:59 → 08:00/07:59:59(博彩日)
- code_amount 翻译 码量/碼量/Code amount → 码粮/碼糧/Rebate(代理后台全局)
2026-05-29 21:04:21 +08:00
fengshao1227 3ac1c2bf42 fix(agent): 代理编辑校验失败改用必须确认的弹窗, 让操作员看清原因
返水率/码率/占股超过上级上限时后端已返回具体原因(含上级上限值),
但前端用 layer.msg 一闪而过易被忽略, 误以为'改不动'。改为 layer.alert
必须点确认, 确保看清失败原因(如'返水率不能超过所属代理的返水率 0!')。
2026-05-29 11:44:46 +08:00
fengshao1227 020dd802d6 feat(agent): 编辑代理费率时检测下级未结算注单并二次确认
洗码率/返水率/占成率在下注未结算期间被修改, 结算(openingBet)会按新值
参与代理分账, 导致本局佣金与下注时预期不符。新增编辑时检测: 费率确有
变动且下级存在近1小时内 is_end=0 的注单时返回 code=2, 前端弹框二次
确认, 确认后带 confirm_pending 重提。纯增量护栏, 不改结算逻辑。
2026-05-29 06:43:21 +08:00
fengshao1227 50d131aa75 fix: 会员编辑保存后字段被清零
1. JS里agent_commission系列字段被注释掉,每次编辑保存抽水率被重置为0
2. rebate_rate为0时PHP不保存,导致无法设为0
2026-05-29 05:44:17 +08:00
fengshao1227 bcf604dc0a fix: CORS改为回显Origin,去掉白名单限制和credentials 2026-05-28 14:37:33 +08:00
fengshao1227 0f952a36a5 fix: CORS头冲突修复 — 删除方法级重复header,统一由构造函数处理
根因:构造函数设 Access-Control-Allow-Origin: 具体域名 + Credentials: true,
但每个方法又覆盖成 Origin: *,导致 Credentials+通配符冲突,浏览器拒绝请求。
删除全部41处方法级CORS头,只保留构造函数的白名单机制。
2026-05-28 14:29:43 +08:00
fengshao1227 24c71fa7a0 Revert "feat: 线上自助充值不再扣代理余额(系统直充)"
This reverts commit 0bf387f7d5.
2026-05-24 20:55:06 +08:00
fengshao1227 0bf387f7d5 feat: 线上自助充值不再扣代理余额(系统直充)
会员通过第三方支付通道线上充值时,不再检查/扣减总代理余额。
真金白银从支付通道进来,直接加分给会员。

改动覆盖全部9个支付通道trait:
- 删除下单时的代理余额检查(不再拦截"余额不足")
- 回调时只检查代理是否存在,不检查余额
- 不扣减代理money字段
- 充值记录标记为"系统直充"而非"扣取总代理余分"

代理手动给会员上分(信用盘模式)不受影响,仍然扣代理自己的分。
2026-05-24 19:25:05 +08:00
testadmin 0186f561c4 fix: Pro 路单查询补查 luck_six/dragon_seven/panda_eight
PC/Game 前端路单走的是 Pro 的 deal/waybill API,不是 Socket 的
2026-05-02 00:06:07 +08:00
testadmin 3997bbd3cb fix: alinPay.php 补漏 limit_agent 空数组放行逻辑 2026-04-26 20:32:45 +08:00
testadmin c2fa69ddcb fix: 校验 agent_type 与 pay_channel 一致性,防止人工上分+在线渠道错配 2026-04-26 20:23:51 +08:00
testadmin 13cd0cbea4 fix: 移除 limit_agent 白名单限制,所有代理下会员均可充值/提现
- config.php: area_id=3 的 limit_agent 改为空数组
- Order.php/epayPay.php/ccpayPay.php: 空数组时跳过白名单检查
2026-04-26 20:10:26 +08:00
testadmin a7edf5347d fix: 新建代理默认 area_id=3(越南),修复无地区代理下会员无法充值 2026-04-26 13:29:47 +08:00
testadmin 2e9462d7a3 feat: 接入 CCpay 第三支付通道(越南银行QR代收)
- extend/pay/Ccpay.php: SDK封装(签名/验签/下单/查询)
- traits/ccpayPay.php: 下单/回调/结算/轮询,pay_channel_id=9
- config.php: pay_list 加 ccpay 配置
- Pcapi/Order: 注册 ccpayPay trait
2026-04-20 11:15:16 +08:00
testadmin ffc77b4f3f fix(epay): 补发 /pay/submit 请求触发插件 submit() 写入 usdtpro 金额 2026-04-16 23:53:00 +08:00
testadmin 9ca6c646db fix(epay): createOrderApi 补传 clientip 参数(mapi.php 必填) 2026-04-16 23:49:52 +08:00
testadmin f3eb260841 fix(epay): usdtpro 指纹金额改由 epay 侧权威计算,避免精度漂移导致充值不到账
- epay_online_order 改为调用 epay mapi.php(createOrderApi)
- 让 epay 自己走完 Pay::create → Plugin::loadForSubmit → usdtpro_plugin::submit
- 从返回 jump url 解析 trade_no,再查 epay.pre_order 读取权威 usdtpro
- 错误返回统一 encrypt_data + Success/Data 加密结构,前端能正确显示
- 所有错误文案改为越南语用户友好版(代理余额不足→"Hạn mức nạp mỗi lần ... VND")
- 代理余额不足场景额外返回 max_amount 字段,前端可用作输入上限提示
- 移除 epay_create_usdt_pre_order 自算方法
2026-04-16 23:49:08 +08:00
testadmin 56c9b1591d fix(epay): PDO bind key 不应带冒号(TP5 自动加 :) 2026-04-16 23:25:20 +08:00
testadmin 93ea9cdc41 feat(epay): 内嵌二维码模式 + 订单状态轮询接口
- epay_online_order: 直接跨库写 epay.pre_order,自算 usdtpro 指纹金额(对齐 usdtpro_plugin::submit 算法)
- 返回值新增 qrcode 字段(address/amount/expires_at),前端内嵌渲染,无需跳转 pay.g7g7.top
- 保留 url 字段兼容老调用方
- 新增 epay_order_status: 前端轮询订单状态(0=待支付/1=已到账/2=超时)
2026-04-16 23:13:25 +08:00
li 2df6527b75 feat(order): wappay/index 越南地区追加 USDT(Epay) 支付选项
- Order::wappay/index: area_id=3 时合并 pay_list['epay']['type'] 到 payMethod,
  每个选项带 pay_routes 映射到对应 online_order_fac
- wappay.html: select 的 option 加 data-url,JS 按选中项查路由
- 兼容旧行为:未设置 pay_routes 时 fallback 到原 online_order_fac
2026-04-16 00:07:40 +08:00
li e0de54a9e9 feat: 接入彩虹易支付(USDT TRC20)充值通道
- 新增 extend/pay/Epay.php 易支付协议实现(MD5签名、buildPayUrl、queryOrder、verifyNotifyCallback)
- 新增 traits/epayPay.php 提供 epay_online_order 和 epay_recharge_callback,独立结算事务
- config.php 加 pay_list.epay 配置段 (pid=1000, key已配, pay.g7g7.top)
- Order.php / Pcapi.php 引入 epayPay trait

支付流程: 用户下单 -> 返回 pay.g7g7.top 跳转 URL -> 用户付款USDT -> 易支付异步回调 -> 验签 -> 结算加余额
通道标识: pay_channel_id=8, pay_channel_name=epay
订单号前缀: P (区别 AlinPay 的 E)
2026-04-15 23:06:20 +08:00
黎小北 490df4c4c5 修复因缺少boot_id导致路子换靴后恢复 2026-03-25 01:19:33 +08:00
黎小北 3786a0ea99 换靴后旧路子残留 2026-03-24 23:48:15 +08:00
li 75e9bafb54 fix: 牛牛操作端刷新后恢复牌面显示 - showCardNn读取正确字段round.show_card 2026-03-15 19:43:04 +08:00
liandClaude Sonnet 4.6 d69322a7fb fix: 自注册/Line注册用户 bet_type 改为 1,修复移动端看不到桌子
doRegister() 和 lineAuth() 中 bet_type 硬编码为 3,
而所有 active 桌子均为 bet_type=1,导致 all_table()
查询结果为空返回"获取信息失败"。
同步修复数据库存量 10 条受影响用户记录。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 16:47:01 +08:00
li 90ab7ccb43 fix: alinPay响应统一encrypt_data加密格式 2026-03-13 00:32:02 +08:00
li dfd9f37253 fix: alinPay参数类型强转+空响应处理+错误日志增强 2026-03-13 00:27:44 +08:00
li 81869255c1 fix: 更新alinPay充值逻辑及Pcapi控制器 2026-03-12 23:41:05 +08:00
li b95c137fa6 fix: 引入alinPay trait并配置越南区代理ID 2026-03-12 23:35:10 +08:00
li f8e948b577 fix: add CORS headers to Pcapi controller constructor 2026-03-12 23:29:02 +08:00
li 79123e079f feat: 对接越南AlinPay支付网关(代收+代付)
- 新增 AlinPay 网关核心类:签名/验签/代收/代付/查询/账户接口
- 新增 alinPay trait:充值发起 + 代收回调结算(事务+行锁)
- 修改 admin/agent Report:提现审批自动路由 ALIN_VN 发起代付
- 新增 Pcapi:银行卡提现申请 + 越南银行列表接口
- 修改 Crypto:代付回调/订单查询/账户查询入口
- 新增越南区 area_list(id=3) + alinPay pay_list 配置
- DDL: user_withdraw 表增加 pay_channel/ext 字段
2026-03-12 22:24:49 +08:00
29 changed files with 2589 additions and 240 deletions
+15
View File
@@ -0,0 +1,15 @@
-- AlinPay 越南代付对接 - 数据库变更
-- 执行时间: 2026-03-12
-- 1. user_withdraw 表增加支付渠道和扩展字段
ALTER TABLE `cg_user_withdraw`
ADD COLUMN `pay_channel` varchar(50) NOT NULL DEFAULT '' COMMENT '支付渠道: USDT, YBF, ALIN_VN' AFTER `type`,
ADD COLUMN `ext` text NULL COMMENT '扩展字段JSON: 银行卡信息等' AFTER `pay_channel`;
-- 2. pay_channel 表插入 AlinPay 配置(secret 需从三方后台获取后替换)
INSERT INTO `cg_pay_channel` (`name`, `key`, `value`, `status`) VALUES (
'越南AlinPay',
'ALIN_VN',
'{"app_id":"276a857ff36814028b772724","secret":"660a4EB682d3787b5b43DC424Ab46e6348F5f4dB","collection_product_id":11,"payment_product_id":14}',
1
);
+4
View File
@@ -200,6 +200,9 @@ class Agent extends Common{
if( empty($pay_channel) ){ if( empty($pay_channel) ){
die(json_encode(['code'=>0,'msg'=>'请选择支付渠道'])); die(json_encode(['code'=>0,'msg'=>'请选择支付渠道']));
} }
if( $agent_type == 2 && $pay_channel != 'OPR' ){
die(json_encode(['code'=>0,'msg'=>'人工上分模式只能选OPR渠道']));
}
if( !in_array($type_xima,[1,2]) ){ if( !in_array($type_xima,[1,2]) ){
die(json_encode(['code'=>0,'msg'=>'洗码方式错误'])); die(json_encode(['code'=>0,'msg'=>'洗码方式错误']));
} }
@@ -433,6 +436,7 @@ class Agent extends Common{
$data['price_tc_ths'] = $price_tc_ths; $data['price_tc_ths'] = $price_tc_ths;
$data['price_tc_hjths'] = $price_tc_hjths; $data['price_tc_hjths'] = $price_tc_hjths;
$data['area_id'] = 3;
$data['referral_code'] = getRandCode(); $data['referral_code'] = getRandCode();
// $data['agent_commission_tc'] = $agent_commission_tc; // $data['agent_commission_tc'] = $agent_commission_tc;
// $data['agent_commission_tc_banker'] = $agent_commission_tc_banker; // $data['agent_commission_tc_banker'] = $agent_commission_tc_banker;
+6 -6
View File
@@ -1240,8 +1240,8 @@ class Pcapi extends Controller{
$startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y'));
$endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1;
}elseif($time_interval == 3){ }elseif($time_interval == 3){
$startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y"));
$endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); $endTime = mktime(23,59,59,date("m"),date("d"),date("Y"));
} }
$betWhere = array(); $betWhere = array();
$betWhere['create_time'] = array('between',[$startTime,$endTime]); $betWhere['create_time'] = array('between',[$startTime,$endTime]);
@@ -1571,8 +1571,8 @@ class Pcapi extends Controller{
$startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y'));
$endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1;
}elseif($time_interval == 3){ }elseif($time_interval == 3){
$startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y"));
$endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); $endTime = mktime(23,59,59,date("m"),date("d"),date("Y"));
} }
$betWhere = array(); $betWhere = array();
$betWhere['create_time'] = array('between',[$startTime,$endTime]); $betWhere['create_time'] = array('between',[$startTime,$endTime]);
@@ -1639,8 +1639,8 @@ class Pcapi extends Controller{
$startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y'));
$endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1;
}elseif($time_interval == 3){ }elseif($time_interval == 3){
$startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y"));
$endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); $endTime = mktime(23,59,59,date("m"),date("d"),date("Y"));
} }
$betWhere = array(); $betWhere = array();
$betWhere['create_time'] = array('between',[$startTime,$endTime]); $betWhere['create_time'] = array('between',[$startTime,$endTime]);
+50 -7
View File
@@ -3,6 +3,7 @@
namespace app\admin\controller; namespace app\admin\controller;
use pay\Usdt; use pay\Usdt;
use pay\AlinPay;
use think\Db; use think\Db;
use think\Request; use think\Request;
use think\Session; use think\Session;
@@ -405,19 +406,61 @@ class Report extends Common{
die(json_encode(['code'=>0,'msg'=>'非待审核状态无法操作!'])); die(json_encode(['code'=>0,'msg'=>'非待审核状态无法操作!']));
} }
// 审核通过 // 根据支付渠道路由
$payChannel = $withdraw['pay_channel'] ?: 'USDT';
$withdrawResult = [];
if($payChannel == 'ALIN_VN'){
// 越南AlinPay代付
$ext = json_decode($withdraw['ext'], true) ?: [];
$pay_list = config('pay_list');
$notifyUrl = $pay_list['alinPay']['payment_notify_url'];
$alinPay = new AlinPay();
$res = $alinPay->createPayment(
$withdraw['order_no'],
sprintf('%.2f', $withdraw['amount']),
$ext['accountName'] ?? '',
$ext['accountNumber'] ?? '',
$ext['bankCode'] ?? '',
$ext['bankName'] ?? '',
$notifyUrl
);
$withdrawResult = [
'status' => (is_array($res) && isset($res['code']) && $res['code'] == 200) ? true : false,
'type' => 'ALIN_VN',
'out_trade_no' => $res['data']['trade_no'] ?? '',
'err_msg' => $res['message'] ?? '请求失败',
];
}else{
// 默认USDT
$Usdt = new Usdt(); $Usdt = new Usdt();
$res = $Usdt->applyUserWithdraw($withdraw['order_no'],$withdraw['to_address'],$withdraw['amount']); $res = $Usdt->applyUserWithdraw($withdraw['order_no'],$withdraw['to_address'],$withdraw['amount']);
if($res['code'] == 0){ $withdrawResult = [
Db::name('user_withdraw')->where('id',$id)->update([ 'status' => $res['code'] == 0 ? true : false,
'type' => $res['processor']['asset'] ?? 'USDT',
'from_address' => $res['processor']['from_addr'] ?? '',
'err_msg' => $res['debug'] ?? '',
];
}
if($withdrawResult['status']){
$updateData = [
'status' => 'AGREE', 'status' => 'AGREE',
'type' => $res['processor']['asset'], 'type' => $withdrawResult['type'] ?? '',
'from_address' => $res['processor']['from_addr'],
'audit_time' => time(), 'audit_time' => time(),
'operator_source' => 2, 'operator_source' => 2,
'operator_id' => $user_info['id'], 'operator_id' => $user_info['id'],
'operator_username' => $user_info['admin'], 'operator_username' => $user_info['admin'],
]); ];
if(!empty($withdrawResult['from_address'])){
$updateData['from_address'] = $withdrawResult['from_address'];
}
if(!empty($withdrawResult['out_trade_no'])){
$updateData['out_trade_no'] = $withdrawResult['out_trade_no'];
}
Db::name('user_withdraw')->where('id',$id)->update($updateData);
die(json_encode(['code'=>1,'msg'=>'审核通过!'])); die(json_encode(['code'=>1,'msg'=>'审核通过!']));
}else{ }else{
Db::startTrans(); Db::startTrans();
@@ -430,7 +473,7 @@ class Report extends Common{
// 更新记录 // 更新记录
Db::name('user_withdraw')->where('id',$id)->update([ Db::name('user_withdraw')->where('id',$id)->update([
'status' => 'FAIL', 'status' => 'FAIL',
'err_msg' => $res['debug'], 'err_msg' => $withdrawResult['err_msg'],
'audit_time' => time(), 'audit_time' => time(),
'operator_source' => 2, 'operator_source' => 2,
'operator_id' => $user_info['id'], 'operator_id' => $user_info['id'],
+46 -2
View File
@@ -565,13 +565,25 @@ class Agent Extends Common{
if(!$user || $user['agent'] == 0){ if(!$user || $user['agent'] == 0){
die(json_encode(['code'=>0,'msg'=>$lang['error_id']])); die(json_encode(['code'=>0,'msg'=>$lang['error_id']]));
} }
// 顶级代理(agent_parent_id=0)无真实上级:构造一个不设限的虚拟上级,使所有"不得高于上级"封顶校验自动放行;
// "不得低于下级"封底校验与写入逻辑保持不变(顶级代理仍受其下级最高费率约束)。
if($parent_id <= 0){ if($parent_id <= 0){
die(json_encode(['code'=>0,'msg'=>$lang['parent_error']])); $agentParent = [
} 'limit_low' => 0, 'limit_high' => 99999999999,
'limit_low_tie' => 0, 'limit_high_tie' => 99999999999,
'limit_low_pair' => 0, 'limit_high_pair' => 99999999999,
'limit_low_nn' => 0, 'limit_high_nn' => 0,
'agent_ximalv' => 100, 'agent_ximalv_dt' => 100,
'agent_ximalv_nn' => 100, 'agent_ximalv_tc' => 100,
'agent_cs' => 100, 'rebate_rate' => 100,
'agent_parent_id' => 0,
];
}else{
$agentParent = Db::name('user')->where('id',$parent_id)->find(); $agentParent = Db::name('user')->where('id',$parent_id)->find();
if(!$agentParent || $agentParent['agent'] == 0){ if(!$agentParent || $agentParent['agent'] == 0){
die(json_encode(['code'=>0,'msg'=>$lang['parent_error']])); die(json_encode(['code'=>0,'msg'=>$lang['parent_error']]));
} }
}
if(!$nickname){ if(!$nickname){
die(json_encode(['code'=>0,'msg'=>$lang['empty_nickname']])); die(json_encode(['code'=>0,'msg'=>$lang['empty_nickname']]));
} }
@@ -682,6 +694,38 @@ class Agent Extends Common{
die(json_encode(['code'=>0,'msg'=>$lang['rebate_cannot_lower_agent'].' '.$childMaxRebateRate.'%'])); die(json_encode(['code'=>0,'msg'=>$lang['rebate_cannot_lower_agent'].' '.$childMaxRebateRate.'%']));
} }
// —— 时序风险检测 ——
// 洗码率/返水率/占成率在「下注未结算」期间被修改,结算(openingBet)会按新值参与代理分账,
// 导致本局佣金与下注时预期不符。仅当上述费率确有变化、且该代理下级存在未结算注单时,要求二次确认。
// 限红(limit_*)不参与结算、赔率(price_*)代理端只读,故不在检测范围。
$confirm_pending = Request::instance()->post('confirm_pending');
$rateChanged = (
abs($agent_ximalv - (float)$user['agent_ximalv']) > 0.001 ||
abs($agent_ximalv_dt - (float)$user['agent_ximalv_dt']) > 0.001 ||
abs($agent_ximalv_nn - (float)$user['agent_ximalv_nn']) > 0.001 ||
abs($agent_ximalv_tc - (float)$user['agent_ximalv_tc']) > 0.001 ||
abs($agent_cs - (float)$user['agent_cs']) > 0.001 ||
abs((float)$rebate_rate - (float)$user['rebate_rate']) > 0.001
);
if($rateChanged && !$confirm_pending){
// bet 表位于 DB2 连接(与 Report 模块一致);下级注单路径匹配沿用全站约定的两段 LIKE。
// create_time 限定近 1 小时,规避历史异常残留的 is_end=0 注单造成的误报。
$pendingCount = Db::connect('DB2')->name('bet')
->where('is_end', 0)
->where('create_time', '>=', time() - 3600)
->where(function($q) use ($user_id){
$q->where('agent_parent_id_path', 'like', '%,'.$user_id.',%')
->whereOr('agent_parent_id_path', 'like', $user_id.',%');
})
->count();
if($pendingCount > 0){
die(json_encode([
'code' => 2,
'pending' => $pendingCount,
'msg' => '该代理下级当前有 '.$pendingCount.' 笔注单尚未结算。本次修改的洗码率 / 返水率 / 占成率将按新值参与这些注单的代理分账,可能使本局佣金与下注时预期不符。确定仍要立即保存吗?',
]));
}
}
// 拼装数据创建代理 // 拼装数据创建代理
$user_data = array(); $user_data = array();
+2 -2
View File
@@ -260,13 +260,13 @@ class Login extends Controller {
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
} }
$where = array(); $where = array();
+1 -3
View File
@@ -760,9 +760,7 @@ class Player Extends Common{
$user_data['agent_ximalv_nn'] = $agent_ximalv_nn; $user_data['agent_ximalv_nn'] = $agent_ximalv_nn;
$user_data['agent_ximalv_tc'] = $agent_ximalv_tc; $user_data['agent_ximalv_tc'] = $agent_ximalv_tc;
$user_data['manager_id'] = $manager_id; $user_data['manager_id'] = $manager_id;
if ($rebate_rate){ $user_data['rebate_rate'] = $rebate_rate ?: 0;
$user_data['rebate_rate'] = $rebate_rate;
}
$user_data['update_time'] = time(); $user_data['update_time'] = time();
$user_data['remarks'] = $remark; $user_data['remarks'] = $remark;
$result = Db::name('user')->where('id',$user_id)->update($user_data); $result = Db::name('user')->where('id',$user_id)->update($user_data);
+70 -43
View File
@@ -2,6 +2,7 @@
namespace app\agent\controller; namespace app\agent\controller;
use pay\Usdt; use pay\Usdt;
use pay\Ybf; use pay\Ybf;
use pay\AlinPay;
use \think\Controller; use \think\Controller;
use think\Lang; use think\Lang;
use \think\Session; use \think\Session;
@@ -35,17 +36,17 @@ class Report Extends Common{
$game_id = intval(Request::instance()->get('game_id')); $game_id = intval(Request::instance()->get('game_id'));
$export = intval(Request::instance()->get('export')); $export = intval(Request::instance()->get('export'));
// 转换日期时间(默认:今天07:00:00 ~ 明天06:59:59 // 转换日期时间(默认:今天08:00:00 ~ 明天07:59:59
if ($startDate) { if ($startDate) {
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
} else { } else {
$startTime = strtotime(date('Y-m-d') . ' 07:00:00'); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s', $startTime); $get['startDate'] = date('Y-m-d H:i:s', $startTime);
} }
if ($endDate) { if ($endDate) {
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
} else { } else {
$endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 06:59:59'); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s', $endTime); $get['endDate'] = date('Y-m-d H:i:s', $endTime);
} }
@@ -308,14 +309,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
@@ -504,13 +505,13 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
} }
@@ -1031,13 +1032,13 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
} }
@@ -2053,14 +2054,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
@@ -2171,14 +2172,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
@@ -2268,14 +2269,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
@@ -2644,8 +2645,8 @@ class Report Extends Common{
die(json_encode(['code'=>0,'msg'=>'非待审核状态无法操作!'])); die(json_encode(['code'=>0,'msg'=>'非待审核状态无法操作!']));
} }
// 审核通过 // 审核通过 - 根据提现记录的支付渠道路由
$withdrawChannel = "YBF"; $withdrawChannel = $withdraw['pay_channel'] ?: 'YBF';
$withdrawResult = []; $withdrawResult = [];
if($withdrawChannel == "USDT"){ if($withdrawChannel == "USDT"){
$Usdt = new Usdt(); $Usdt = new Usdt();
@@ -2665,13 +2666,35 @@ class Report Extends Common{
'type' => 'YBF', 'type' => 'YBF',
'err_msg' => $res['message'], 'err_msg' => $res['message'],
]; ];
}else if($withdrawChannel == "ALIN_VN"){
// 越南AlinPay代付
$ext = json_decode($withdraw['ext'], true) ?: [];
$pay_list = config('pay_list');
$notifyUrl = $pay_list['alinPay']['payment_notify_url'];
$alinPay = new AlinPay();
$res = $alinPay->createPayment(
$withdraw['order_no'],
sprintf('%.2f', $withdraw['amount']),
$ext['accountName'] ?? '',
$ext['accountNumber'] ?? '',
$ext['bankCode'] ?? '',
$ext['bankName'] ?? '',
$notifyUrl
);
$withdrawResult = [
'status' => (is_array($res) && isset($res['code']) && $res['code'] == 200) ? true : false,
'type' => 'ALIN_VN',
'out_trade_no' => $res['data']['trade_no'] ?? '',
'err_msg' => $res['message'] ?? '请求失败',
];
} }
if(empty($withdrawResult)){ if(empty($withdrawResult)){
die(json_encode(['code'=>0,'msg'=>'未配置支付渠道!'])); die(json_encode(['code'=>0,'msg'=>'未配置支付渠道!']));
} }
if($withdrawResult['status']){ if($withdrawResult['status']){
Db::name('user_withdraw')->where('id',$id)->update([ $updateData = [
'status' => 'AGREE', 'status' => 'AGREE',
'type' => $withdrawResult['type'] ?? '', 'type' => $withdrawResult['type'] ?? '',
'from_address' => $withdrawResult['from_address'] ?? '', 'from_address' => $withdrawResult['from_address'] ?? '',
@@ -2680,7 +2703,11 @@ class Report Extends Common{
'operator_id' => $user_info['id'], 'operator_id' => $user_info['id'],
'operator_username' => $user_info['username'], 'operator_username' => $user_info['username'],
'operator_nickname' => $user_info['nickname'] 'operator_nickname' => $user_info['nickname']
]); ];
if(!empty($withdrawResult['out_trade_no'])){
$updateData['out_trade_no'] = $withdrawResult['out_trade_no'];
}
Db::name('user_withdraw')->where('id',$id)->update($updateData);
die(json_encode(['code'=>1,'msg'=>'审核通过!'])); die(json_encode(['code'=>1,'msg'=>'审核通过!']));
}else{ }else{
Db::startTrans(); Db::startTrans();
@@ -2792,14 +2819,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
@@ -2842,13 +2869,13 @@ class Report Extends Common{
if ($startDate) { if ($startDate) {
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
} else { } else {
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s', $startTime); $get['startDate'] = date('Y-m-d H:i:s', $startTime);
} }
if ($endDate) { if ($endDate) {
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
} else { } else {
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s', $endTime); $get['endDate'] = date('Y-m-d H:i:s', $endTime);
} }
@@ -3048,14 +3075,14 @@ class Report Extends Common{
if ($startDate) { if ($startDate) {
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
} else { } else {
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s', $startTime); $get['startDate'] = date('Y-m-d H:i:s', $startTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
if ($endDate) { if ($endDate) {
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
} else { } else {
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s', $endTime); $get['endDate'] = date('Y-m-d H:i:s', $endTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
@@ -3141,14 +3168,14 @@ class Report Extends Common{
if ($startDate) { if ($startDate) {
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
} else { } else {
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s', $startTime); $get['startDate'] = date('Y-m-d H:i:s', $startTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
if ($endDate) { if ($endDate) {
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
} else { } else {
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s', $endTime); $get['endDate'] = date('Y-m-d H:i:s', $endTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
@@ -3248,14 +3275,14 @@ class Report Extends Common{
if ($startDate) { if ($startDate) {
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
} else { } else {
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s', $startTime); $get['startDate'] = date('Y-m-d H:i:s', $startTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
if ($endDate) { if ($endDate) {
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
} else { } else {
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s', $endTime); $get['endDate'] = date('Y-m-d H:i:s', $endTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
@@ -3339,14 +3366,14 @@ class Report Extends Common{
if ($startDate) { if ($startDate) {
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
} else { } else {
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s', $startTime); $get['startDate'] = date('Y-m-d H:i:s', $startTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
if ($endDate) { if ($endDate) {
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
} else { } else {
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s', $endTime); $get['endDate'] = date('Y-m-d H:i:s', $endTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
@@ -3452,14 +3479,14 @@ class Report Extends Common{
if ($startDate) { if ($startDate) {
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
} else { } else {
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s', $startTime); $get['startDate'] = date('Y-m-d H:i:s', $startTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
if ($endDate) { if ($endDate) {
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
} else { } else {
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s', $endTime); $get['endDate'] = date('Y-m-d H:i:s', $endTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
@@ -3547,14 +3574,14 @@ class Report Extends Common{
if ($startDate) { if ($startDate) {
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
} else { } else {
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s', $startTime); $get['startDate'] = date('Y-m-d H:i:s', $startTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
if ($endDate) { if ($endDate) {
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
} else { } else {
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s', $endTime); $get['endDate'] = date('Y-m-d H:i:s', $endTime);
$this->assign('get', $get); $this->assign('get', $get);
} }
@@ -3656,14 +3683,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
@@ -3868,14 +3895,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
@@ -3967,14 +3994,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
@@ -4073,14 +4100,14 @@ class Report Extends Common{
if($startDate){ if($startDate){
$startTime = strtotime($startDate); $startTime = strtotime($startDate);
}else{ }else{
$startTime = strtotime(date('Y-m-d')); $startTime = strtotime(date('Y-m-d') . ' 08:00:00');
$get['startDate'] = date('Y-m-d H:i:s',$startTime); $get['startDate'] = date('Y-m-d H:i:s',$startTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
if($endDate){ if($endDate){
$endTime = strtotime($endDate); $endTime = strtotime($endDate);
}else{ }else{
$endTime = time(); $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59');
$get['endDate'] = date('Y-m-d H:i:s',$endTime); $get['endDate'] = date('Y-m-d H:i:s',$endTime);
$this->assign('get',$get); $this->assign('get',$get);
} }
+8 -8
View File
@@ -30,12 +30,12 @@ class Settle Extends Common{
if($timeLength == 1 || $timeLength == 2){ if($timeLength == 1 || $timeLength == 2){
if($timeLength == 1){ if($timeLength == 1){
//上周时间 //上周时间
$weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1-7,date("Y"))); $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-(date("w")?:7)+1-7,date("Y")));
$weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7-7,date("Y"))); $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-(date("w")?:7)+7-7,date("Y")));
}elseif($timeLength == 2){ }elseif($timeLength == 2){
//本周时间 //本周时间
$weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1,date("Y"))); $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-(date("w")?:7)+1,date("Y")));
$weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y"))); $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-(date("w")?:7)+7,date("Y")));
} }
$startTime = strtotime($weekStart); $startTime = strtotime($weekStart);
$endTime = strtotime($weekEnd); $endTime = strtotime($weekEnd);
@@ -474,12 +474,12 @@ class Settle Extends Common{
if($timeLength == 1 || $timeLength == 2){ if($timeLength == 1 || $timeLength == 2){
if($timeLength == 1){ if($timeLength == 1){
//上周时间 //上周时间
$weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1-7,date("Y"))); $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-(date("w")?:7)+1-7,date("Y")));
$weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7-7,date("Y"))); $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-(date("w")?:7)+7-7,date("Y")));
}elseif($timeLength == 2){ }elseif($timeLength == 2){
//本周时间 //本周时间
$weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1,date("Y"))); $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-(date("w")?:7)+1,date("Y")));
$weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y"))); $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-(date("w")?:7)+7,date("Y")));
} }
$startTime = strtotime($weekStart); $startTime = strtotime($weekStart);
$endTime = strtotime($weekEnd); $endTime = strtotime($weekEnd);
+1 -1
View File
@@ -301,7 +301,7 @@ return [
'betting_money' => 'Bet money', 'betting_money' => 'Bet money',
'code_washing_amount' => 'Code washing amount', 'code_washing_amount' => 'Code washing amount',
'odd_code_fee' => 'Odd code fee', 'odd_code_fee' => 'Odd code fee',
'code_amount' => 'Code amount', 'code_amount' => 'Rebate',
'settled_code_amount' => 'Settled code amount', 'settled_code_amount' => 'Settled code amount',
'unsettled_code_amount' => 'Unsettled code amount', 'unsettled_code_amount' => 'Unsettled code amount',
'unsettled_rebate_amount' => 'Unsettled rebate amount', 'unsettled_rebate_amount' => 'Unsettled rebate amount',
+1 -1
View File
@@ -301,7 +301,7 @@ return [
'betting_money' => '下注金额', 'betting_money' => '下注金额',
'code_washing_amount' => '洗码量', 'code_washing_amount' => '洗码量',
'odd_code_fee' => '注单码费', 'odd_code_fee' => '注单码费',
'code_amount' => '码', 'code_amount' => '码',
'settled_code_amount' => '已结码量', 'settled_code_amount' => '已结码量',
'unsettled_code_amount' => '未结码量', 'unsettled_code_amount' => '未结码量',
'unsettled_rebate_amount' => '未结返水', 'unsettled_rebate_amount' => '未结返水',
+1 -1
View File
@@ -301,7 +301,7 @@ return [
'betting_money' => '下注金額', 'betting_money' => '下注金額',
'code_washing_amount' => '洗碼量', 'code_washing_amount' => '洗碼量',
'odd_code_fee' => '注單碼費', 'odd_code_fee' => '注單碼費',
'code_amount' => '碼', 'code_amount' => '碼',
'settled_code_amount' => '已結碼量', 'settled_code_amount' => '已結碼量',
'unsettled_code_amount' => '未結碼量', 'unsettled_code_amount' => '未結碼量',
'unsettled_rebate_amount' => '未結返水', 'unsettled_rebate_amount' => '未結返水',
+36 -1
View File
@@ -269,7 +269,12 @@
dataType: 'JSON', dataType: 'JSON',
success: function (data) { success: function (data) {
if (data.code == 0) { if (data.code == 0) {
layer.msg(data.msg); // 校验未通过:用必须点确认的弹窗代替一闪而过的 toast,确保操作员看清失败原因
// (如返水率/码率/占股超过上级上限时,后端会返回具体上限值)
layer.alert(data.msg, {
title: lang.message,
icon: 0
});
} else if (data.code == 1) { } else if (data.code == 1) {
layer.alert(data.msg,{ layer.alert(data.msg,{
title:lang.message, title:lang.message,
@@ -277,6 +282,36 @@
x_admin_close(); x_admin_close();
parent.location.reload(); parent.location.reload();
}); });
} else if (data.code == 2) {
// 时序风险:下级有未结算注单,二次确认后带 confirm_pending 重新提交
layer.confirm(data.msg, {
title: lang.message,
btn: ['确定保存', '取消']
}, function (idx) {
layer.close(idx);
query.confirm_pending = 1;
$.ajax({
url: '/agent/do_edit',
data: query,
type: 'POST',
dataType: 'JSON',
success: function (d) {
if (d.code == 0) {
layer.alert(d.msg, {
title: lang.message,
icon: 0
});
} else if (d.code == 1) {
layer.alert(d.msg, {
title: lang.message
}, function () {
x_admin_close();
parent.location.reload();
});
}
}
});
});
} }
} }
}) })
-2
View File
@@ -644,13 +644,11 @@
//query.mobile = $('#mobile').val(); //query.mobile = $('#mobile').val();
//query.bet_type = $('#bet_type').val(); //query.bet_type = $('#bet_type').val();
query.win_limit = $('#win_limit').val(); query.win_limit = $('#win_limit').val();
/*
query.agent_commission = $('#agent_commission').val(); query.agent_commission = $('#agent_commission').val();
query.agent_commission_dt = $('#agent_commission_dt').val(); query.agent_commission_dt = $('#agent_commission_dt').val();
query.agent_commission_nn = $('#agent_commission_nn').val(); query.agent_commission_nn = $('#agent_commission_nn').val();
query.agent_commission_tc = $('#agent_commission_tc').val(); query.agent_commission_tc = $('#agent_commission_tc').val();
query.agent_commission_tc_banker = $('#agent_commission_tc_banker').val(); query.agent_commission_tc_banker = $('#agent_commission_tc_banker').val();
*/
query.limit_low = $('#limit_low').val(); query.limit_low = $('#limit_low').val();
query.limit_high = $('#limit_high').val(); query.limit_high = $('#limit_high').val();
query.limit_low_tie = $('#limit_low_tie').val(); query.limit_low_tie = $('#limit_low_tie').val();
+39 -8
View File
@@ -77,7 +77,10 @@
<div class="gap"> <div class="gap">
<button class="layui-btn search-btn" id="search" onclick="showShadow()">{$lang['search']}</button> <button class="layui-btn search-btn" id="search" onclick="showShadow()">{$lang['search']}</button>
<a class="layui-btn search-btn" onclick="showShadow()" href="javascript:location.replace(location.href);">{$lang['refresh']}</a> <a class="layui-btn search-btn" onclick="showShadow()" href="javascript:location.replace(location.href);">{$lang['refresh']}</a>
<button class="layui-btn search-btn countDown">5</button> <label style="margin-left:6px;line-height:38px;cursor:pointer;font-weight:normal;vertical-align:middle;">
<input type="checkbox" id="autoRefresh" style="vertical-align:middle;"> 自动刷新
</label>
<button type="button" class="layui-btn search-btn countDown" style="display:none;">10</button>
</div> </div>
</div> </div>
</form> </form>
@@ -187,16 +190,44 @@
$(function(){ $(function(){
var online = $('#online').val(); var online = $('#online').val();
var refreshUrl = $('#refreshUrl').val(); var refreshUrl = $('#refreshUrl').val();
var countDown = 10; var INTERVAL = 10; // 自动刷新间隔(秒)
if(online == 1){ var countDown = INTERVAL;
$('.countDown').show(); var autoTimer = null;
setInterval(function(){
function startAuto(reloadFn){
countDown = INTERVAL;
$('.countDown').show().html(countDown);
autoTimer = setInterval(function(){
countDown = countDown - 1; countDown = countDown - 1;
$('.countDown').html(countDown); $('.countDown').html(countDown);
if(countDown == 0){ if(countDown <= 0){
location.href = refreshUrl; reloadFn();
} }
},1000); }, 1000);
}
function stopAuto(){
if(autoTimer){ clearInterval(autoTimer); autoTimer = null; }
$('.countDown').hide();
}
if(online == 1){
// 从“在线管理”进入:保持原有自动刷新行为
startAuto(function(){ location.href = refreshUrl; });
}else{
// 注单查询:可开关的今日实时自动刷新(默认开,刷新当前查询条件)
var saved = localStorage.getItem('bet_auto_refresh');
var enabled = (saved === null) ? true : (saved === '1');
$('#autoRefresh').prop('checked', enabled);
if(enabled){ startAuto(function(){ location.replace(location.href); }); }
$('#autoRefresh').on('change', function(){
if($(this).is(':checked')){
localStorage.setItem('bet_auto_refresh','1');
startAuto(function(){ location.replace(location.href); });
}else{
localStorage.setItem('bet_auto_refresh','0');
stopAuto();
}
});
} }
}) })
+40
View File
@@ -281,6 +281,13 @@ return [
'default_wt_agent' => 566, 'default_wt_agent' => 566,
'limit_agent' => [87, 1371], 'limit_agent' => [87, 1371],
], ],
'3' => [
'name' => '越南',
'pay' => 'alinPay',
'default_agent' => 111,
'default_wt_agent' => 111,
'limit_agent' => [],
],
], ],
'limit_list' => [ 'limit_list' => [
@@ -343,5 +350,38 @@ return [
'1' => '在線繳費' '1' => '在線繳費'
] ]
], ],
'alinPay' => [//越南AlinPay
'online_order_fac' => 'alin_online_order',//越南
'notify_url' => 'https://api.g7g7.top/order/alin_recharge_callback',//代收回调地址
'payment_notify_url' => 'https://api.g7g7.top/crypto/alin_payment_callback',//代付回调地址
'callback_url' => '',
'type' => [
'11' => '越南代收'
]
],
'epay' => [//彩虹易支付(USDT/支付宝/微信 聚合)
'online_order_fac' => 'epay_online_order',
'notify_url' => 'https://api.g7g7.top/order/epay_recharge_callback',// 异步回调
'callback_url' => 'https://api.g7g7.top/order/epay_return',// 同步跳转回业务
'api_url' => 'https://pay.g7g7.top',
'pid' => '1000',
'key' => 'bf7b83653f5c056a6103e26263a75fa1',
'goods_name' => '账户充值',
'type' => [
'usdt' => 'USDT支付',
// 'alipay' => '支付宝',
// 'wxpay' => '微信支付',
]
],
'ccpay' => [//CCmerchant越南银行代收
'online_order_fac' => 'ccpay_online_order',
'notify_url' => 'https://api.g7g7.top/order/ccpay_recharge_callback',
'callback_url' => '',
'api_url' => 'https://c.gmobvfxllc.com/gateway/api/trade',
'mch_no' => 'M8822026041910000352',
'pay_secret' => '820281b0d0b24a6bb701d8fc1c31a197',
'timeout' => 600,
'type' => ['pay' => 'CCpay越南银行'],
],
] ]
]; ];
+1 -1
View File
@@ -245,7 +245,7 @@ class Index Extends Common{
// 验证靴ID // 验证靴ID
if($boot_id > 0){ if($boot_id > 0){
$ns = Db::name($numberTabTable)->where(array('game_id' => $game_id, 'boot_id' => $boot_id, 'bet_status' => 3))->field('result,pair')->order('start_time ASC,id ASC')->select(); $ns = Db::name($numberTabTable)->where(array('game_id' => $game_id, 'boot_id' => $boot_id, 'bet_status' => 3))->field('result,pair,luck_six,dragon_seven,panda_eight')->order('start_time ASC,id ASC')->select();
if($forecast == 1){ if($forecast == 1){
// 庄问路 // 庄问路
$ns[] = array('result'=>1,'pair'=>0); $ns[] = array('result'=>1,'pair'=>0);
+1 -1
View File
@@ -275,7 +275,7 @@ function waybill($ns){
$showRoadLocation = array(); $showRoadLocation = array();
foreach($showRoad as $k => $v){ foreach($showRoad as $k => $v){
foreach($v as $key => $val){ foreach($v as $key => $val){
$pushData = array('show_x' => $k + 1, 'show_y' =>$key + 1, 'result' => $val['result'], 'pair' => $val['pair']); $pushData = array('show_x' => $k + 1, 'show_y' =>$key + 1, 'result' => $val['result'], 'pair' => $val['pair'], 'luck_six' => $val['luck_six'] ?? 0, 'dragon_seven' => $val['dragon_seven'] ?? 0, 'panda_eight' => $val['panda_eight'] ?? 0);
array_push($showRoadLocation,$pushData); array_push($showRoadLocation,$pushData);
} }
} }
@@ -2,6 +2,7 @@
namespace app\onlinechip\controller; namespace app\onlinechip\controller;
use pay\Ybf; use pay\Ybf;
use pay\AlinPay;
use think\Cache; use think\Cache;
use \think\Controller; use \think\Controller;
use think\Db; use think\Db;
@@ -230,6 +231,90 @@ class Crypto Extends Controller{
return $sign == $data['sign']; return $sign == $data['sign'];
} }
/**
* AlinPay 越南代付回调
*/
public function alin_payment_callback()
{
$post = Request::instance()->post();
$json = json_encode($post, JSON_UNESCAPED_UNICODE);
addLogToFile('越南代付回调原始数据:' . $json, 'alin_callback', 'alin');
if (!is_array($post) || empty($post['out_trade_no']) || empty($post['sign'])) {
exit('fail');
}
// 记录回调日志
$logId = Db::name('pay_callback_log')->insertGetId([
'pay_channel' => 'ALIN_PAYMENT',
'type' => 'payment',
'json' => $json,
'create_time' => date('Y-m-d H:i:s'),
]);
try {
$alinPay = new AlinPay();
$res = $alinPay->paymentCallback($post, $logId);
exit($res ?: 'fail');
} catch (\Exception $e) {
addLogToFile('越南代付回调异常:' . $e->getMessage(), 'alin_callback_error', 'alin');
exit('fail');
}
}
/**
* AlinPay 越南代收查询
*/
public function alin_query_order()
{
$orderNo = Request::instance()->post('order_no');
if (!$orderNo) {
return json(['code' => 0, 'msg' => '缺少订单号']);
}
try {
$alinPay = new AlinPay();
$result = $alinPay->queryOrder($orderNo);
return json($result);
} catch (\Exception $e) {
return json(['code' => 0, 'msg' => $e->getMessage()]);
}
}
/**
* AlinPay 越南代付查询
*/
public function alin_query_payment()
{
$orderNo = Request::instance()->post('order_no');
if (!$orderNo) {
return json(['code' => 0, 'msg' => '缺少订单号']);
}
try {
$alinPay = new AlinPay();
$result = $alinPay->queryPayment($orderNo);
return json($result);
} catch (\Exception $e) {
return json(['code' => 0, 'msg' => $e->getMessage()]);
}
}
/**
* AlinPay 账户余额查询
*/
public function alin_query_account()
{
try {
$alinPay = new AlinPay();
$result = $alinPay->queryAccount();
return json($result);
} catch (\Exception $e) {
return json(['code' => 0, 'msg' => $e->getMessage()]);
}
}
/** /**
* 记录日志 * 记录日志
* @param $type * @param $type
+47 -13
View File
@@ -13,6 +13,9 @@ class Order Extends Controller{
use traits\tingPay; use traits\tingPay;
use traits\happyPay; use traits\happyPay;
use traits\hengfuPay; use traits\hengfuPay;
use traits\alinPay;
use traits\epayPay;
use traits\ccpayPay;
public function __construct() public function __construct()
{ {
@@ -33,10 +36,23 @@ class Order Extends Controller{
} }
$pay_method = $area_list[$user['area_id']]['pay']; $pay_method = $area_list[$user['area_id']]['pay'];
if($user && $user['api_token'] == $api_token){ if($user && $user['api_token'] == $api_token){
$this->assign('online_order_fac',$pay_list[$pay_method]['online_order_fac']); $payMethod = $pay_list[$pay_method]['type'];
$this->assign('payMethod',$pay_list[$pay_method]['type']); $pay_routes = [];
$this->assign('client',1); foreach($payMethod as $k => $v){
$this->assign('user_info',$user); $pay_routes[$k] = $pay_list[$pay_method]['online_order_fac'];
}
// 越南地区追加 USDT (Epay)
if($user['area_id'] == 3 && !empty($pay_list['epay']['type'])){
foreach($pay_list['epay']['type'] as $k => $v){
$payMethod[$k] = $v;
$pay_routes[$k] = $pay_list['epay']['online_order_fac'];
}
}
$this->assign('online_order_fac', $pay_list[$pay_method]['online_order_fac']);
$this->assign('payMethod', $payMethod);
$this->assign('pay_routes', $pay_routes);
$this->assign('client', 1);
$this->assign('user_info', $user);
return $this->fetch(); return $this->fetch();
}else{ }else{
exit('页面错误,请退出再登录!'); exit('页面错误,请退出再登录!');
@@ -54,10 +70,26 @@ class Order Extends Controller{
} }
$pay_method = $area_list[$user['area_id']]['pay']; $pay_method = $area_list[$user['area_id']]['pay'];
if($user && $user['api_token'] == $api_token){ if($user && $user['api_token'] == $api_token){
$this->assign('online_order_fac',$pay_list[$pay_method]['online_order_fac']); // 主通道(按 area_list 的 pay 配置)
$this->assign('payMethod',$pay_list[$pay_method]['type']); $payMethod = $pay_list[$pay_method]['type'];
$this->assign('client',2); $pay_routes = [];
$this->assign('user_info',$user); foreach($payMethod as $k => $v){
$pay_routes[$k] = $pay_list[$pay_method]['online_order_fac'];
}
// 越南地区追加 USDT (Epay) 通道作为第二选项
if($user['area_id'] == 3 && !empty($pay_list['epay']['type'])){
foreach($pay_list['epay']['type'] as $k => $v){
$payMethod[$k] = $v;
$pay_routes[$k] = $pay_list['epay']['online_order_fac'];
}
}
$this->assign('online_order_fac', $pay_list[$pay_method]['online_order_fac']); // 兼容旧模板
$this->assign('payMethod', $payMethod);
$this->assign('pay_routes', $pay_routes);
$this->assign('client', 2);
$this->assign('user_info', $user);
return $this->fetch(); return $this->fetch();
}else{ }else{
exit('页面错误,请退出再登录!'); exit('页面错误,请退出再登录!');
@@ -82,8 +114,9 @@ class Order Extends Controller{
$zdlIdArr = explode(',',$user['agent_parent_id_path']); $zdlIdArr = explode(',',$user['agent_parent_id_path']);
$area_list = config('area_list'); $area_list = config('area_list');
//判断是否金流支线,如果不是的话,不允许充值 //判断是否金流支线,如果不是的话,不允许充值
$isAllow = false; $limitAgents = $area_list[$user['area_id']]['limit_agent'];
foreach($area_list[$user['area_id']]['limit_agent'] as $allowAgentId){ $isAllow = empty($limitAgents);
foreach($limitAgents as $allowAgentId){
if(in_array($allowAgentId,$zdlIdArr)){ if(in_array($allowAgentId,$zdlIdArr)){
$isAllow = true; $isAllow = true;
} }
@@ -152,9 +185,10 @@ class Order Extends Controller{
$user = Db::name('user')->where(array('id' => $user_id))->find(); $user = Db::name('user')->where(array('id' => $user_id))->find();
$zdlIdArr = explode(',',$user['agent_parent_id_path']); $zdlIdArr = explode(',',$user['agent_parent_id_path']);
$area_list = config('area_list'); $area_list = config('area_list');
//判断是否金流支线,如果不是的话,不允许充值 //判断是否金流支线,如果不是的话,不允许提现
$isAllow = false; $limitAgents = $area_list[$user['area_id']]['limit_agent'];
foreach($area_list[$user['area_id']]['limit_agent'] as $allowAgentId){ $isAllow = empty($limitAgents);
foreach($limitAgents as $allowAgentId){
if(in_array($allowAgentId,$zdlIdArr)){ if(in_array($allowAgentId,$zdlIdArr)){
$isAllow = true; $isAllow = true;
} }
+140 -131
View File
@@ -16,8 +16,23 @@ use Waybill\WaybillToning;
use Waybill\WaybillRoulette; use Waybill\WaybillRoulette;
class Pcapi extends Controller{ class Pcapi extends Controller{
use traits\alinPay;
use traits\epayPay;
use traits\ccpayPay;
public function __construct(){ public function __construct(){
parent::__construct(); parent::__construct();
// CORS headers
$origin = Request::instance()->header('origin');
if($origin){
header('Access-Control-Allow-Origin: '.$origin);
} else {
header('Access-Control-Allow-Origin: *');
}
header('Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization');
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE,OPTIONS');
if(Request::instance()->isOptions()){
exit();
}
$actionName = Request::instance()->action(); $actionName = Request::instance()->action();
if(in_array($actionName,['doregister'])){ if(in_array($actionName,['doregister'])){
if(Session::has('is_post') && Session::get($actionName.'_is_post') == 0){ if(Session::has('is_post') && Session::get($actionName.'_is_post') == 0){
@@ -35,9 +50,6 @@ class Pcapi extends Controller{
} }
public function get_version(){ public function get_version(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
return json(config('app_version')); return json(config('app_version'));
} }
public function get_system_info(){ public function get_system_info(){
@@ -51,9 +63,6 @@ class Pcapi extends Controller{
} }
//试玩登录 //试玩登录
public function demologin(){ public function demologin(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -106,9 +115,6 @@ class Pcapi extends Controller{
//保持在线--心跳 //保持在线--心跳
public function keepOnline(){ public function keepOnline(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -132,9 +138,6 @@ class Pcapi extends Controller{
} }
//登录optimum //登录optimum
public function login(){ public function login(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -194,7 +197,7 @@ class Pcapi extends Controller{
$find['pay_channel'] = ''; $find['pay_channel'] = '';
$find['pay_channel_currency'] = []; $find['pay_channel_currency'] = [];
$find['pay_channel_coin_chain'] = []; $find['pay_channel_coin_chain'] = [];
if($topAgent['agent_type'] == 1){ if($topAgent['pay_channel'] && $topAgent['pay_channel'] != 'OPR'){
// 现金线走支付渠道 // 现金线走支付渠道
$find['pay_channel'] = $topAgent['pay_channel']; $find['pay_channel'] = $topAgent['pay_channel'];
$find['pay_channel_currency'] = []; $find['pay_channel_currency'] = [];
@@ -208,7 +211,7 @@ class Pcapi extends Controller{
$find['pay_channel_coin_chain'] = json_decode($payChannelInfo['coin_chain'],true); $find['pay_channel_coin_chain'] = json_decode($payChannelInfo['coin_chain'],true);
} }
} }
} elseif ($topAgent['agent_type'] == 2 && $topAgent['pay_channel'] == 'OPR') { // 人工转帐上分,前端显示充值信息 } elseif ($topAgent['pay_channel'] == 'OPR') { // 人工转帐上分,前端显示充值信息(不依赖 agent_type,只看 pay_channel)
$find['pay_channel'] = $topAgent['pay_channel']; $find['pay_channel'] = $topAgent['pay_channel'];
$find['pay_channel_address'] = $topAgent['pay_channel_address']; $find['pay_channel_address'] = $topAgent['pay_channel_address'];
} }
@@ -240,9 +243,6 @@ class Pcapi extends Controller{
} }
// 获取用户信息 // 获取用户信息
public function get_user_info(){ public function get_user_info(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -270,7 +270,7 @@ class Pcapi extends Controller{
$find['pay_channel'] = ''; $find['pay_channel'] = '';
$find['pay_channel_currency'] = []; $find['pay_channel_currency'] = [];
$find['pay_channel_coin_chain'] = []; $find['pay_channel_coin_chain'] = [];
if($topAgent['agent_type'] == 1){ if($topAgent['pay_channel'] && $topAgent['pay_channel'] != 'OPR'){
// 现金线走支付渠道 // 现金线走支付渠道
$find['pay_channel'] = $topAgent['pay_channel']; $find['pay_channel'] = $topAgent['pay_channel'];
$find['pay_channel_currency'] = []; $find['pay_channel_currency'] = [];
@@ -284,6 +284,9 @@ class Pcapi extends Controller{
$find['pay_channel_coin_chain'] = json_decode($payChannelInfo['coin_chain'],true); $find['pay_channel_coin_chain'] = json_decode($payChannelInfo['coin_chain'],true);
} }
} }
} elseif($topAgent['pay_channel'] == 'OPR'){ // 人工转帐上分:与 login 保持一致下发收款信息(此前 get_user_info 缺失,刷新会丢)
$find['pay_channel'] = 'OPR';
$find['pay_channel_address'] = $topAgent['pay_channel_address'];
} }
$find['manager'] = []; $find['manager'] = [];
if($find['bet_type'] == 2){ if($find['bet_type'] == 2){
@@ -309,9 +312,6 @@ class Pcapi extends Controller{
} }
//用户钱 //用户钱
public function user_money(){ public function user_money(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -335,9 +335,6 @@ class Pcapi extends Controller{
} }
//修改密码 //修改密码
public function update_password(){ public function update_password(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -375,9 +372,6 @@ class Pcapi extends Controller{
} }
//打赏 //打赏
public function to_tip(){ public function to_tip(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -421,9 +415,6 @@ class Pcapi extends Controller{
} }
//好路 //好路
public function good_road(){ public function good_road(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -459,9 +450,6 @@ class Pcapi extends Controller{
} }
//返回全部桌子 //返回全部桌子
public function all_table(){ public function all_table(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -1204,9 +1192,6 @@ class Pcapi extends Controller{
} }
//返回单张桌子 //返回单张桌子
public function singletable(){ public function singletable(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
// $json_arr = Request::instance()->post(); // $json_arr = Request::instance()->post();
@@ -1755,9 +1740,6 @@ class Pcapi extends Controller{
} }
//今日最佳 //今日最佳
public function optimum(){ public function optimum(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -1783,9 +1765,6 @@ class Pcapi extends Controller{
} }
//游戏记录 //游戏记录
public function get_user_bets(){ public function get_user_bets(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -1814,8 +1793,8 @@ class Pcapi extends Controller{
$startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y'));
$endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1;
}elseif($time_interval == 3){ }elseif($time_interval == 3){
$startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y"));
$endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); $endTime = mktime(23,59,59,date("m"),date("d"),date("Y"));
} }
$betWhere = array(); $betWhere = array();
$betWhere['create_time'] = array('between',[$startTime,$endTime]); $betWhere['create_time'] = array('between',[$startTime,$endTime]);
@@ -2303,9 +2282,6 @@ class Pcapi extends Controller{
} }
//上下分记录 //上下分记录
public function recharge_record(){ public function recharge_record(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2325,8 +2301,8 @@ class Pcapi extends Controller{
$startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y'));
$endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1;
}elseif($time_interval == 3){ }elseif($time_interval == 3){
$startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y"));
$endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); $endTime = mktime(23,59,59,date("m"),date("d"),date("Y"));
} }
$betWhere = array(); $betWhere = array();
$betWhere['create_time'] = array('between',[$startTime,$endTime]); $betWhere['create_time'] = array('between',[$startTime,$endTime]);
@@ -2372,9 +2348,6 @@ class Pcapi extends Controller{
} }
//上下分记录 //上下分记录
public function tip_record(){ public function tip_record(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2393,8 +2366,8 @@ class Pcapi extends Controller{
$startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y'));
$endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1;
}elseif($time_interval == 3){ }elseif($time_interval == 3){
$startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y"));
$endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); $endTime = mktime(23,59,59,date("m"),date("d"),date("Y"));
} }
$betWhere = array(); $betWhere = array();
$betWhere['create_time'] = array('between',[$startTime,$endTime]); $betWhere['create_time'] = array('between',[$startTime,$endTime]);
@@ -2434,9 +2407,6 @@ class Pcapi extends Controller{
} }
//开结果后获取会员的下注信息及计算其输赢数目 //开结果后获取会员的下注信息及计算其输赢数目
public function user_bet_baccarat(){ public function user_bet_baccarat(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2593,9 +2563,6 @@ class Pcapi extends Controller{
} }
//开结果后获取会员的下注信息及计算其输赢数目 //开结果后获取会员的下注信息及计算其输赢数目
public function user_bet_dt(){ public function user_bet_dt(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2684,9 +2651,6 @@ class Pcapi extends Controller{
//开结果后获取会员的下注信息及计算其输赢数目 //开结果后获取会员的下注信息及计算其输赢数目
public function user_bet_nn(){ public function user_bet_nn(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2719,9 +2683,6 @@ class Pcapi extends Controller{
} }
//开结果后获取会员的下注信息及计算其输赢数目 //开结果后获取会员的下注信息及计算其输赢数目
public function user_bet_tc(){ public function user_bet_tc(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2754,9 +2715,6 @@ class Pcapi extends Controller{
} }
//开结果后获取会员的下注信息及计算其输赢数目 //开结果后获取会员的下注信息及计算其输赢数目
public function user_bet_toning(){ public function user_bet_toning(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2788,9 +2746,6 @@ class Pcapi extends Controller{
} }
//开结果后获取会员的下注信息及计算其输赢数目 //开结果后获取会员的下注信息及计算其输赢数目
public function user_bet_dice(){ public function user_bet_dice(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2821,9 +2776,6 @@ class Pcapi extends Controller{
} }
} }
public function user_bet_roulette(){ public function user_bet_roulette(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2855,9 +2807,6 @@ class Pcapi extends Controller{
} }
//快速提现 //快速提现
public function show_withdrawal(){ public function show_withdrawal(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2885,9 +2834,6 @@ class Pcapi extends Controller{
} }
//确认提现 //确认提现
public function withdrawal(){ public function withdrawal(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -2968,9 +2914,6 @@ class Pcapi extends Controller{
} }
//充值信息 //充值信息
public function show_recharge(){ public function show_recharge(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -3007,9 +2950,6 @@ class Pcapi extends Controller{
} }
//确认充值 //确认充值
public function recharge(){ public function recharge(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -3066,9 +3006,6 @@ class Pcapi extends Controller{
} }
//游戏记录 //游戏记录
public function get_rob_bet(){ public function get_rob_bet(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -3284,9 +3221,6 @@ class Pcapi extends Controller{
//电话呼入 //电话呼入
public function online_call(){ public function online_call(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
$phone = Request::instance()->post('phone'); $phone = Request::instance()->post('phone');
if($phone){ if($phone){
$table_info = Db::name('table')->where('phone',$phone)->find(); $table_info = Db::name('table')->where('phone',$phone)->find();
@@ -3316,9 +3250,6 @@ class Pcapi extends Controller{
* DateTime: 2019/12/12 12:53 * DateTime: 2019/12/12 12:53
*/ */
public function doRegister(){ public function doRegister(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST');
if($data = Request::instance()->post()){ if($data = Request::instance()->post()){
$data = decrypt_data($data); $data = decrypt_data($data);
$username = isset($data['username'])?$data['username']:''; $username = isset($data['username'])?$data['username']:'';
@@ -3432,7 +3363,7 @@ class Pcapi extends Controller{
$insertData['price_tc_hjths'] = $agentParent['price_tc_hjths']; $insertData['price_tc_hjths'] = $agentParent['price_tc_hjths'];
$insertData['area_id'] = $agentParent['area_id']; $insertData['area_id'] = $agentParent['area_id'];
$insertData['bet_type'] = 3; $insertData['bet_type'] = 1;
$insertData['reg_time'] = time(); $insertData['reg_time'] = time();
if(getIp()){ if(getIp()){
@@ -3647,7 +3578,7 @@ class Pcapi extends Controller{
$insertData['price_tc_ths'] = $agentParent['price_tc_ths']; $insertData['price_tc_ths'] = $agentParent['price_tc_ths'];
$insertData['price_tc_hjths'] = $agentParent['price_tc_hjths']; $insertData['price_tc_hjths'] = $agentParent['price_tc_hjths'];
$insertData['area_id'] = $agentParent['area_id']; $insertData['area_id'] = $agentParent['area_id'];
$insertData['bet_type'] = 3; $insertData['bet_type'] = 1;
$insertData['reg_time'] = time(); $insertData['reg_time'] = time();
if(getIp()){ if(getIp()){
@@ -3672,9 +3603,6 @@ class Pcapi extends Controller{
//登录 //登录
public function lineLogin(){ public function lineLogin(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -3747,9 +3675,6 @@ class Pcapi extends Controller{
} }
public function app_entrance(){ public function app_entrance(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$entrance = array(); $entrance = array();
$entrance['HallUrl'] = HallUrl; $entrance['HallUrl'] = HallUrl;
@@ -3765,9 +3690,6 @@ class Pcapi extends Controller{
} }
//api用户通过接口获取铺信息 //api用户通过接口获取铺信息
public function api_get_info(){ public function api_get_info(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$appId = intval(Request::instance()->post("appId")); $appId = intval(Request::instance()->post("appId"));
$nonceStr = trim(Request::instance()->post("nonceStr")); $nonceStr = trim(Request::instance()->post("nonceStr"));
@@ -3816,9 +3738,6 @@ class Pcapi extends Controller{
// 用户充值记录 // 用户充值记录
public function user_recharge() public function user_recharge()
{ {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()) { if(Request::instance()->isPost()) {
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if ($json_arr) { if ($json_arr) {
@@ -3854,9 +3773,6 @@ class Pcapi extends Controller{
// 用户提现记录 // 用户提现记录
public function user_withdraw() public function user_withdraw()
{ {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()) { if(Request::instance()->isPost()) {
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if ($json_arr) { if ($json_arr) {
@@ -3892,9 +3808,6 @@ class Pcapi extends Controller{
//申请提现 //申请提现
public function apply_withdraw(){ public function apply_withdraw(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr){ if($json_arr){
@@ -3917,7 +3830,7 @@ class Pcapi extends Controller{
$system = Db::name('system')->find(); $system = Db::name('system')->find();
$money = $user['money']; $money = $user['money'];
$withdrawMoney = empty($system['withdraw_money']) ? 100 : $system['withdraw_money']; $withdrawMoney = empty($system['withdraw_money']) ? 100 : $system['withdraw_money'];
$withdrawFee = empty($system['withdraw_fee']) ? 1 : $system['withdraw_fee']; $withdrawFee = empty($system['withdraw_fee']) ? 0 : $system['withdraw_fee'];
// 计算积分兑换 // 计算积分兑换
$amountMoney = $withdrawMoney/100*($amount); $amountMoney = $withdrawMoney/100*($amount);
@@ -3966,11 +3879,118 @@ class Pcapi extends Controller{
} }
// 申请银行卡提现(越南AlinPay)
public function apply_withdraw_bank(){
if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post());
if($json_arr){
$userId = intval($json_arr['user_id']);
$amount = floatval($json_arr['amount']);
$accountName = trim($json_arr['account_name'] ?? '');
$accountNumber = trim($json_arr['account_number'] ?? '');
$bankCode = trim($json_arr['bank_code'] ?? '');
$bankName = trim($json_arr['bank_name'] ?? '');
if(!$amount || $amount <= 0){
return json(array('Success' => 0, 'Msg' => 'Số tiền rút không hợp lệ'));
}
if(empty($accountName)){
return json(array('Success' => 0, 'Msg' => 'Tên tài khoản không được để trống'));
}
if(empty($accountNumber)){
return json(array('Success' => 0, 'Msg' => 'Số tài khoản không được để trống'));
}
if(empty($bankName)){
return json(array('Success' => 0, 'Msg' => 'Tên ngân hàng không được để trống'));
}
$user = Db::name('user')->where(array('id' => $userId))->find();
if($user){
Db::startTrans();
$user = Db::name('user')->where(array('id' => $userId))->lock(true)->find();
$system = Db::name('system')->find();
$money = $user['money'];
$withdrawMoney = empty($system['withdraw_money']) ? 100 : $system['withdraw_money'];
$withdrawFee = empty($system['withdraw_fee']) ? 0 : $system['withdraw_fee'];
// 计算积分兑换
$amountMoney = $withdrawMoney/100*($amount);
$feeMoney = $withdrawMoney/100*($withdrawFee);
$needMoney = $amountMoney + $feeMoney;
if($needMoney > $money){
Db::rollback();
return json(array('Success' => 0, 'Msg' => 'Số dư không đủ'));
}
$afterMoney = $money - $needMoney;
// 银行卡信息存入ext
$ext = json_encode([
'accountName' => $accountName,
'accountNumber' => $accountNumber,
'bankCode' => $bankCode,
'bankName' => $bankName,
], JSON_UNESCAPED_UNICODE);
// 写入提现申请
$res = Db::name('user_withdraw')->insert([
'order_no' => createOrderNo('TX'),
'user_id' => $userId,
'amount' => $amount,
'money' => $amountMoney,
'old_money' => $money,
'new_money' => $afterMoney,
'service_fee' => $withdrawFee,
'service_fee_money' => $feeMoney,
'withdraw_rate' => $withdrawFee,
'to_address' => $accountNumber,
'pay_channel' => 'ALIN_VN',
'ext' => $ext,
'create_time' => time()
]);
if(!$res){
Db::rollback();
return json(array('Success' => 0, 'Msg' => 'Thao tác thất bại'));
}
// 扣除用户余额
$res = Db::name('user')->where('id',$userId)->update([
'money' => $afterMoney,
'update_time' => time()
]);
if(!$res){
Db::rollback();
return json(array('Success' => 0, 'Msg' => 'Thao tác thất bại'));
}
Db::commit();
return json(array('Success' => 1, 'Msg' => 'Thành công, vui lòng chờ xử lý'));
}else{
return json(array('Success' => 0, 'Msg' => 'Lấy thông tin thất bại'));
}
}
}
}
// 获取越南银行列表
public function get_bank_list_vn(){
$banks = \pay\AlinPay::getBankCodes();
$list = [];
foreach($banks as $index => $name){
if(!empty($name)){
$list[] = [
'code' => $name,
'name' => $name,
];
}
}
$data = encrypt_data(['status' => 1, 'data' => $list]);
return json(array('Success' => 1, 'Data' => $data));
}
// 取消提现 // 取消提现
public function cancel_withdraw(){ public function cancel_withdraw(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr) { if($json_arr) {
@@ -4026,9 +4046,6 @@ class Pcapi extends Controller{
*/ */
public function deposit() public function deposit()
{ {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr) { if($json_arr) {
@@ -4090,9 +4107,6 @@ class Pcapi extends Controller{
*/ */
public function get_free_seat(){ public function get_free_seat(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
if(Request::instance()->isPost()){ if(Request::instance()->isPost()){
$json_arr = decrypt_data(Request::instance()->post()); $json_arr = decrypt_data(Request::instance()->post());
if($json_arr) { if($json_arr) {
@@ -4134,11 +4148,6 @@ class Pcapi extends Controller{
* 无需鉴权,游客可访问 * 无需鉴权,游客可访问
*/ */
public function get_lobby_data(){ public function get_lobby_data(){
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE,OPTIONS');
header('Access-Control-Max-Age: 86400');
// 处理 OPTIONS 预检请求 // 处理 OPTIONS 预检请求
if(Request::instance()->isOptions()){ if(Request::instance()->isOptions()){
return response('', 200); return response('', 200);
@@ -0,0 +1,316 @@
<?php
namespace app\onlinechip\controller\traits;
use think\Db;
use think\Log;
use think\Request;
/**
* AlinPay 越南支付 Trait
* 仅包含代收(充值)相关方法
* 代付回调在 Crypto.php 中处理
*/
trait alinPay
{
/**
* 越南代收 - 发起充值
*/
public function alin_online_order()
{
// 兼容加密请求(Pcapi)和明文请求(Order)
$post = Request::instance()->post();
if (isset($post['encryptData'])) {
$post = decrypt_data($post);
if (!$post) {
return json(['status' => 0, 'message' => '数据解密失败']);
}
}
$user_id = intval($post['user_id'] ?? 0);
$money = intval($post['price'] ?? 0);
$client = intval($post['client'] ?? 0);
$username = trim($post['username'] ?? '');
$user = Db::name('user')->where([
'id' => $user_id,
'status' => 1,
'is_delete' => 0,
'agent' => 0,
])->find();
if (!$user || $user_id <= 0 || $money <= 0 || $client <= 0) {
return json(['status' => 0, 'message' => '参数错误,请稍后再试']);
}
// 判断地区支线权限
$zdlIdArr = explode(',', $user['agent_parent_id_path']);
$area_list = config('area_list');
if (!isset($area_list[$user['area_id']])) {
return json(['status' => 0, 'message' => '所在地区暂不支持充值']);
}
$limitAgents = $area_list[$user['area_id']]['limit_agent'];
$isAllow = empty($limitAgents);
foreach ($limitAgents as $allowAgentId) {
if (in_array($allowAgentId, $zdlIdArr)) {
$isAllow = true;
}
}
if (!$isAllow) {
return json(['status' => 0, 'message' => '该账号暂不支持在线充值']);
}
// 验证总代理余额
$zdlId = $zdlIdArr[0];
$zdl = Db::name('user')->where([
'id' => $zdlId,
'status' => 1,
'is_delete' => 0,
'agent' => 1,
])->find();
if (!$zdl) {
return json(['status' => 0, 'message' => '所属代理账号异常,暂不能充值']);
}
if ($zdl['money'] < $money) {
return json(['status' => 0, 'message' => '所属代理余额不足,暂不能充值']);
}
$pay_list = config('pay_list');
$pay_orderid = 'E' . date("YmdHis") . rand(100000, 999999);
$notify_url = $pay_list['alinPay']['notify_url'];
try {
$alinPay = new \pay\AlinPay();
$result = $alinPay->createOrder($pay_orderid, sprintf('%.2f', $money), $notify_url, 'uid:' . $user_id);
// 空响应处理(curl失败/DNS/超时等)
if (!is_array($result)) {
addLogToFile('代收下单:API无响应或返回非JSONresult=' . var_export($result, true), 'alin_error', 'alin');
$data = encrypt_data(['status' => 0, 'message' => '支付通道无响应,请稍后再试']);
return json(array('Success' => 1, 'Data' => $data));
}
if (isset($result['code']) && $result['code'] == 200) {
$returnUrl = $result['data']['url'] ?? '';
if (!$returnUrl) {
$data = encrypt_data(['status' => 0, 'message' => '支付地址获取失败']);
return json(array('Success' => 1, 'Data' => $data));
}
// 记录订单
$order_record = [
'pay_channel_id' => 7,
'pay_channel_name' => 'alinPay',
'user_id' => $user_id,
'order_sn' => $pay_orderid,
'appid' => $alinPay->getConfigInfo()['app_id'],
'api_key' => '',
'money' => $money,
'sign' => '',
'create_time' => time(),
'back_order_sn' => '',
'client' => $client,
];
$order_id = Db::name('order_record')->insertGetId($order_record);
// 记录日志
Db::name('order_log')->insert([
'pay_channel_id' => 7,
'pay_channel_name' => 'alinPay',
'money' => $money,
'create_time' => time(),
'remake' => 'user_id:' . $user_id . ',用户名:' . $username . ',发起充值:' . $money . ',充值时间:' . date('Y-m-d H:i:s'),
'order_id' => $order_id,
'client' => $client,
]);
$data = encrypt_data(['status' => 1, 'message' => '发起支付成功,即将跳转...', 'url' => $returnUrl]);
return json(array('Success' => 1, 'Data' => $data));
} else {
$errMsg = isset($result['message']) ? $result['message'] : '未知错误(code=' . ($result['code'] ?? 'null') . ')';
addLogToFile('代收下单失败:' . json_encode($result, JSON_UNESCAPED_UNICODE), 'alin_error', 'alin');
$data = encrypt_data(['status' => 0, 'message' => '支付发起失败:' . $errMsg]);
return json(array('Success' => 1, 'Data' => $data));
}
} catch (\Exception $e) {
addLogToFile('代收下单异常:' . $e->getMessage() . ' | file:' . $e->getFile() . ':' . $e->getLine(), 'alin_error', 'alin');
$data = encrypt_data(['status' => 0, 'message' => '支付发起失败[' . $e->getMessage() . ']']);
return json(array('Success' => 1, 'Data' => $data));
}
}
/**
* 越南代收 - 回调处理
*/
public function alin_recharge_callback()
{
$post = Request::instance()->post();
$json = json_encode($post, JSON_UNESCAPED_UNICODE);
addLogToFile('代收回调原始数据:' . $json, 'alin_callback', 'alin');
if (!is_array($post) || empty($post['out_trade_no']) || empty($post['sign'])) {
Log::record($post, 'alin_error_callback');
exit('fail');
}
// 记录回调日志
$logId = Db::name('pay_callback_log')->insertGetId([
'pay_channel' => 'ALIN_RECHARGE',
'type' => 'recharge',
'json' => $json,
'create_time' => date('Y-m-d H:i:s'),
]);
try {
$alinPay = new \pay\AlinPay();
$result = $alinPay->verifyRechargeCallback($post, $logId);
if (!$result['verified']) {
exit('fail');
}
$tradeStatus = $result['trade_status'];
// trade_status: 1=成功, -1=处理中, 2=失败
if ($tradeStatus === 1) {
$this->alin_recharge_settle($post);
exit('success');
} elseif ($tradeStatus === 2) {
// 失败,终态,确认收到
addLogToFile('代收回调失败:order=' . $post['out_trade_no'], 'alin_callback', 'alin');
exit('success');
} else {
// 处理中(-1),不返回success让网关重试
exit('fail');
}
} catch (\Exception $e) {
addLogToFile('代收回调处理异常:' . $e->getMessage(), 'alin_callback_error', 'alin');
exit('fail');
}
}
/**
* 代收成功后结算(事务保护:扣代理、写recharge表、加用户余额)
*/
private function alin_recharge_settle($data)
{
$orderNo = $data['out_trade_no'];
Db::startTrans();
try {
// 加锁读取订单,防止重复处理
$order = Db::name('order_record')->where('order_sn', $orderNo)->lock(true)->find();
if (!$order || $order['status'] == 3) {
Db::rollback();
return;
}
// 加锁读取用户
$user = Db::name('user')->where([
'id' => $order['user_id'],
'status' => 1,
'is_delete' => 0,
'agent' => 0,
])->lock(true)->find();
if (!$user) {
Db::rollback();
return;
}
$zdlIdArr = explode(',', $user['agent_parent_id_path']);
$zdlId = $zdlIdArr[0];
// 加锁读取总代理
$zdl = Db::name('user')->where([
'id' => $zdlId,
'status' => 1,
'is_delete' => 0,
'agent' => 1,
])->lock(true)->find();
if (!$zdl || $zdl['money'] < $order['money']) {
Db::rollback();
addLogToFile('代收结算失败:代理余额不足 order=' . $orderNo, 'alin_callback_error', 'alin');
return;
}
// 1. 更新订单状态为已完成
Db::name('order_record')->where('id', $order['id'])->update([
'back_money' => $data['real_amount'] ?: $data['amount'],
'back_time' => time(),
'status' => 3,
'agent_parent_id' => $user['agent_parent_id'],
'agent_parent_username' => $user['agent_parent_username'],
'zdl_id' => $zdl['id'],
'zdl_username' => $zdl['username'],
'zdl_money_before' => $zdl['money'],
'zdl_money_after' => $zdl['money'] - $order['money'],
'money_before' => $user['money'],
'money_after' => $user['money'] + $order['money'],
]);
// 2. 记录日志
Db::name('order_log')->insert([
'pay_channel_id' => 7,
'pay_channel_name' => 'alinPay',
'money' => $order['money'],
'create_time' => time(),
'remake' => '回调支付成功',
'order_id' => $order['id'],
]);
// 3. 写recharge流水表
Db::name('recharge')->insert([
'type' => 4,
'amount' => $order['money'],
'mode' => 1,
'agent_or_admin' => 3,
'controller_id' => $zdl['id'],
'controller_username' => $zdl['username'],
'controller_nickname' => $zdl['nickname'],
'controller_type' => '越南第三方充值平台充值,扣取总代理余分',
'controller_old_money' => $zdl['money'],
'controller_new_money' => $zdl['money'] - $order['money'],
'user_id' => $order['user_id'],
'user_type' => $user['agent'],
'user_agent_level' => 0,
'username_for' => $user['username'],
'nickname_for' => $user['nickname'],
'user_parent_id' => $user['agent_parent_id'],
'create_time' => time(),
'old_money' => $user['money'],
'new_money' => $user['money'] + $order['money'],
'controller_system' => 3,
'remake' => '越南AlinPay第三方充值成功',
]);
// 4. 扣代理余额
Db::name('user')->where('id', $zdl['id'])->update([
'money' => $zdl['money'] - $order['money'],
'last_recharge_out' => $order['money'],
'last_recharge_out_time' => time(),
'recharge_out_count' => $zdl['recharge_out_count'] + 1,
'recharge_out_total_amount' => $zdl['recharge_out_total_amount'] + $order['money'],
]);
// 5. 给用户加余额
Db::name('user')->where('id', $order['user_id'])->update([
'money' => $user['money'] + $order['money'],
'last_recharge' => $order['money'],
'last_recharge_time' => time(),
'recharge_count' => $user['recharge_count'] + 1,
'recharge_total_amount' => $user['recharge_total_amount'] + $order['money'],
]);
Db::commit();
addLogToFile('代收结算成功:order=' . $orderNo . ' money=' . $order['money'], 'alin_callback', 'alin');
} catch (\Exception $e) {
Db::rollback();
addLogToFile('代收结算异常:' . $e->getMessage(), 'alin_callback_error', 'alin');
}
}
}
@@ -0,0 +1,412 @@
<?php
namespace app\onlinechip\controller\traits;
use think\Db;
use think\Log;
use think\Request;
trait ccpayPay
{
public function ccpay_online_order()
{
$post = Request::instance()->post();
if (isset($post['encryptData'])) {
$post = decrypt_data($post);
if (!$post) {
$data = encrypt_data(['status' => 0, 'message' => 'Dữ liệu không hợp lệ']);
return json(['Success' => 1, 'Data' => $data]);
}
}
$user_id = intval($post['user_id'] ?? 0);
$money = intval($post['price'] ?? 0);
$client = intval($post['client'] ?? 0);
$username = trim($post['username'] ?? '');
$user = Db::name('user')->where([
'id' => $user_id,
'status' => 1,
'is_delete' => 0,
'agent' => 0,
])->find();
if (!$user || $user_id <= 0 || $money <= 0 || $client <= 0) {
$data = encrypt_data(['status' => 0, 'message' => 'Tham số không hợp lệ, vui lòng thử lại']);
return json(['Success' => 1, 'Data' => $data]);
}
$zdlIdArr = explode(',', $user['agent_parent_id_path']);
$area_list = config('area_list');
if (!isset($area_list[$user['area_id']])) {
$data = encrypt_data(['status' => 0, 'message' => 'Khu vực hiện chưa hỗ trợ nạp tiền']);
return json(['Success' => 1, 'Data' => $data]);
}
$limitAgents = $area_list[$user['area_id']]['limit_agent'];
$isAllow = empty($limitAgents);
foreach ($limitAgents as $allowAgentId) {
if (in_array($allowAgentId, $zdlIdArr)) {
$isAllow = true;
}
}
if (!$isAllow) {
$data = encrypt_data(['status' => 0, 'message' => 'Tài khoản này chưa được phép nạp online']);
return json(['Success' => 1, 'Data' => $data]);
}
$zdlId = $zdlIdArr[0];
$zdl = Db::name('user')->where([
'id' => $zdlId,
'status' => 1,
'is_delete' => 0,
'agent' => 1,
])->find();
if (!$zdl) {
$data = encrypt_data(['status' => 0, 'message' => 'Tài khoản đại lý có vấn đề, không thể nạp']);
return json(['Success' => 1, 'Data' => $data]);
}
if ($zdl['money'] < $money) {
$maxAllowed = intval($zdl['money']);
$data = encrypt_data([
'status' => 0,
'code' => 'AGENT_LIMIT',
'message' => 'Hạn mức nạp mỗi lần hiện tại là ' . number_format($maxAllowed, 0, '.', ',') . ' VND. Vui lòng nhập số tiền nhỏ hơn hoặc bằng mức trên.',
'max_amount' => $maxAllowed,
]);
return json(['Success' => 1, 'Data' => $data]);
}
$pay_list = config('pay_list');
$pay_orderid = 'C' . date('YmdHis') . rand(100000, 999999);
$notify_url = $pay_list['ccpay']['notify_url'] ?? '';
$timeout = intval($pay_list['ccpay']['timeout'] ?? 600);
try {
$ccpay = new \pay\Ccpay();
$result = $ccpay->createOrder(
$pay_orderid,
sprintf('%.0f', $money),
$notify_url,
'uid_' . $user_id
);
if (!is_array($result)) {
addLogToFile('ccpay 下单: API 无响应', 'ccpay_error', 'ccpay');
$data = encrypt_data(['status' => 0, 'message' => 'Kênh thanh toán không phản hồi, vui lòng thử lại']);
return json(['Success' => 1, 'Data' => $data]);
}
$status = intval($result['status'] ?? -1);
$resultCode = intval($result['resultCode'] ?? -1);
if ($status !== 0 || $resultCode !== 0) {
$errMsg = $result['errMsg'] ?? 'Lỗi không xác định';
addLogToFile('ccpay 下单失败: order=' . $pay_orderid . ' err=' . $errMsg . ' raw=' . json_encode($result, JSON_UNESCAPED_UNICODE), 'ccpay_error', 'ccpay');
$data = encrypt_data(['status' => 0, 'message' => 'Khởi tạo thanh toán thất bại: ' . $errMsg]);
return json(['Success' => 1, 'Data' => $data]);
}
$order_id = Db::name('order_record')->insertGetId([
'pay_channel_id' => 9,
'pay_channel_name' => 'ccpay',
'user_id' => $user_id,
'order_sn' => $pay_orderid,
'appid' => $ccpay->getConfigInfo()['mch_no'] ?? '',
'api_key' => '',
'money' => $money,
'sign' => '',
'create_time' => time(),
'back_order_sn' => $result['cpOrderNo'] ?? '',
'client' => $client,
]);
Db::name('order_log')->insert([
'pay_channel_id' => 9,
'pay_channel_name' => 'ccpay',
'money' => $money,
'create_time' => time(),
'remake' => 'user_id:' . $user_id . ',用户名:' . $username . ',CCpay发起充值:' . $money . ',时间:' . date('Y-m-d H:i:s'),
'order_id' => $order_id,
'client' => $client,
]);
$codeUrl = $result['codeUrl'] ?? '';
$qrcode = null;
$msgJson = $result['message'] ?? '';
if ($msgJson) {
$bankInfo = json_decode($msgJson, true);
if (is_array($bankInfo) && !empty($bankInfo['AccNo'])) {
$expiresAt = time() + $timeout;
$qrcode = [
'order_sn' => $pay_orderid,
'bank_account' => $bankInfo['AccNo'] ?? '',
'bank_name' => $bankInfo['AccName'] ?? '',
'bank_branch' => $bankInfo['Branch'] ?? '',
'bank_short' => $bankInfo['BankShortName'] ?? '',
'qr_data' => $bankInfo['qrcode'] ?? '',
'remark' => $bankInfo['remark'] ?? '',
'amount' => $money,
'expires_at' => $expiresAt,
'timeout_sec' => $timeout,
];
}
}
addLogToFile('ccpay 下单成功: order=' . $pay_orderid . ' cp=' . ($result['cpOrderNo'] ?? ''), 'ccpay_request', 'ccpay');
$data = encrypt_data([
'status' => 1,
'message' => 'Khởi tạo thanh toán thành công',
'url' => $codeUrl,
'qrcode' => $qrcode,
]);
return json(['Success' => 1, 'Data' => $data]);
} catch (\Exception $e) {
addLogToFile('ccpay 下单异常: ' . $e->getMessage() . ' | file:' . $e->getFile() . ':' . $e->getLine(), 'ccpay_error', 'ccpay');
$data = encrypt_data(['status' => 0, 'message' => 'Khởi tạo thanh toán thất bại: ' . $e->getMessage()]);
return json(['Success' => 1, 'Data' => $data]);
}
}
public function ccpay_order_status()
{
$post = Request::instance()->post();
if (isset($post['encryptData'])) {
$post = decrypt_data($post);
if (!$post) {
return json(['status' => 0, 'message' => '数据解密失败']);
}
}
$order_sn = trim($post['order_sn'] ?? '');
$user_id = intval($post['user_id'] ?? 0);
if ($order_sn === '' || $user_id <= 0) {
$data = encrypt_data(['status' => 0, 'message' => '参数错误']);
return json(['Success' => 1, 'Data' => $data]);
}
$order = Db::name('order_record')
->where([
'order_sn' => $order_sn,
'user_id' => $user_id,
'pay_channel_id' => 9,
])
->find();
if (!$order) {
$data = encrypt_data(['status' => 0, 'message' => '订单不存在']);
return json(['Success' => 1, 'Data' => $data]);
}
if (intval($order['status']) == 3) {
$data = encrypt_data([
'status' => 1,
'message' => 'Nạp tiền thành công',
'money' => $order['money'],
'paid_time' => $order['back_time'],
]);
return json(['Success' => 1, 'Data' => $data]);
}
$pay_list = config('pay_list');
$timeout = intval($pay_list['ccpay']['timeout'] ?? 600);
if (time() - intval($order['create_time']) > $timeout) {
$data = encrypt_data([
'status' => 2,
'message' => 'Đơn hàng đã hết hạn',
'money' => $order['money'],
]);
return json(['Success' => 1, 'Data' => $data]);
}
$data = encrypt_data([
'status' => 0,
'message' => 'Đang chờ thanh toán',
'money' => $order['money'],
]);
return json(['Success' => 1, 'Data' => $data]);
}
public function ccpay_recharge_callback()
{
$raw = file_get_contents('php://input');
$post = json_decode($raw, true);
if (!$post) {
$post = Request::instance()->post();
}
$json = json_encode($post, JSON_UNESCAPED_UNICODE);
addLogToFile('ccpay 回调原始数据: ' . $json, 'ccpay_callback', 'ccpay');
if (!is_array($post) || empty($post['mchOrderNo']) || empty($post['sign'])) {
Log::record($post, 'ccpay_error_callback');
exit('fail');
}
$logId = Db::name('pay_callback_log')->insertGetId([
'pay_channel' => 'CCPAY_RECHARGE',
'type' => 'recharge',
'json' => $json,
'create_time' => date('Y-m-d H:i:s'),
]);
try {
$ccpay = new \pay\Ccpay();
$verifyData = [];
$verifyData['status'] = strval($post['status'] ?? '');
$verifyData['mchNo'] = $post['mchNo'] ?? '';
$verifyData['resultCode'] = strval($post['resultCode'] ?? '');
$verifyData['cpOrderNo'] = $post['cpOrderNo'] ?? '';
$verifyData['mchOrderNo'] = $post['mchOrderNo'] ?? '';
$verifyData['amount'] = strval($post['amount'] ?? '');
$verifyData['payResult'] = $post['payResult'] ?? '';
$verifyData['traceTime'] = $post['traceTime'] ?? '';
$verifyData['message'] = $post['message'] ?? '';
$signData = array_filter($verifyData, function ($v) {
return $v !== '' && $v !== null;
});
$signData['sign'] = $post['sign'];
if (!$ccpay->verifySign($signData)) {
addLogToFile('ccpay 回调验签失败: ' . $json, 'ccpay_callback_error', 'ccpay');
exit('fail');
}
if ($logId && !empty($post['mchOrderNo'])) {
Db::name('pay_callback_log')->where('id', $logId)->update(['unique_no' => $post['mchOrderNo']]);
}
$payResult = strval($post['payResult'] ?? '');
if ($payResult === '0') {
$this->ccpay_recharge_settle($post);
addLogToFile('ccpay 回调成功: order=' . $post['mchOrderNo'], 'ccpay_callback', 'ccpay');
exit('success');
} else {
addLogToFile('ccpay 回调非成功状态: payResult=' . $payResult . ' order=' . $post['mchOrderNo'], 'ccpay_callback', 'ccpay');
exit('success');
}
} catch (\Exception $e) {
addLogToFile('ccpay 回调异常: ' . $e->getMessage(), 'ccpay_callback_error', 'ccpay');
exit('fail');
}
}
private function ccpay_recharge_settle($data)
{
$orderNo = $data['mchOrderNo'];
Db::startTrans();
try {
$order = Db::name('order_record')->where('order_sn', $orderNo)->lock(true)->find();
if (!$order || $order['status'] == 3) {
Db::rollback();
return;
}
$user = Db::name('user')->where([
'id' => $order['user_id'],
'status' => 1,
'is_delete' => 0,
'agent' => 0,
])->lock(true)->find();
if (!$user) {
Db::rollback();
return;
}
$zdlIdArr = explode(',', $user['agent_parent_id_path']);
$zdlId = $zdlIdArr[0];
$zdl = Db::name('user')->where([
'id' => $zdlId,
'status' => 1,
'is_delete' => 0,
'agent' => 1,
])->lock(true)->find();
if (!$zdl || $zdl['money'] < $order['money']) {
Db::rollback();
addLogToFile('ccpay 结算失败: 代理余额不足 order=' . $orderNo, 'ccpay_callback_error', 'ccpay');
return;
}
$actualMoney = isset($data['amount']) ? intval($data['amount']) : $order['money'];
Db::name('order_record')->where('id', $order['id'])->update([
'back_money' => $actualMoney,
'back_time' => time(),
'status' => 3,
'agent_parent_id' => $user['agent_parent_id'],
'agent_parent_username' => $user['agent_parent_username'],
'zdl_id' => $zdl['id'],
'zdl_username' => $zdl['username'],
'zdl_money_before' => $zdl['money'],
'zdl_money_after' => $zdl['money'] - $order['money'],
'money_before' => $user['money'],
'money_after' => $user['money'] + $order['money'],
]);
Db::name('order_log')->insert([
'pay_channel_id' => 9,
'pay_channel_name' => 'ccpay',
'money' => $order['money'],
'create_time' => time(),
'remake' => 'CCpay回调成功 cp=' . ($data['cpOrderNo'] ?? '') . ' payer=' . ($data['message'] ?? ''),
'order_id' => $order['id'],
]);
Db::name('recharge')->insert([
'type' => 4,
'amount' => $order['money'],
'mode' => 1,
'agent_or_admin' => 3,
'controller_id' => $zdl['id'],
'controller_username' => $zdl['username'],
'controller_nickname' => $zdl['nickname'],
'controller_type' => 'CCpay越南银行第三方充值,扣取总代理余分',
'controller_old_money' => $zdl['money'],
'controller_new_money' => $zdl['money'] - $order['money'],
'user_id' => $order['user_id'],
'user_type' => $user['agent'],
'user_agent_level' => 0,
'username_for' => $user['username'],
'nickname_for' => $user['nickname'],
'user_parent_id' => $user['agent_parent_id'],
'create_time' => time(),
'old_money' => $user['money'],
'new_money' => $user['money'] + $order['money'],
'controller_system' => 3,
'remake' => 'CCpay越南银行第三方充值成功',
]);
Db::name('user')->where('id', $zdl['id'])->update([
'money' => $zdl['money'] - $order['money'],
'last_recharge_out' => $order['money'],
'last_recharge_out_time' => time(),
'recharge_out_count' => $zdl['recharge_out_count'] + 1,
'recharge_out_total_amount' => $zdl['recharge_out_total_amount'] + $order['money'],
]);
Db::name('user')->where('id', $order['user_id'])->update([
'money' => $user['money'] + $order['money'],
'last_recharge' => $order['money'],
'last_recharge_time' => time(),
'recharge_count' => $user['recharge_count'] + 1,
'recharge_total_amount' => $user['recharge_total_amount'] + $order['money'],
]);
Db::commit();
addLogToFile('ccpay 结算成功: order=' . $orderNo . ' money=' . $order['money'], 'ccpay_callback', 'ccpay');
} catch (\Exception $e) {
Db::rollback();
addLogToFile('ccpay 结算异常: ' . $e->getMessage(), 'ccpay_callback_error', 'ccpay');
}
}
}
@@ -0,0 +1,523 @@
<?php
namespace app\onlinechip\controller\traits;
use think\Db;
use think\Log;
use think\Request;
/**
* 彩虹易支付 Trait
*
* 业务定位:
* - 作为 AlinPay(越南银行卡)之外的第二个充值通道,走易支付接 USDT/支付宝/微信
* - 当前主要用于 USDT TRC20 收款
*
* 对接文件:
* - extend/pay/Epay.php
* - 支付站点:https://pay.g7g7.top
*
* 公开方法:
* - epay_online_order() 发起充值,前端拿到 url 后跳转易支付
* - epay_recharge_callback() 接收易支付异步回调,验签后结算
*
* 通道编号:
* - pay_channel_id = 8AlinPay 7,本通道顺延)
* - 名称标识:epay
*/
trait epayPay
{
/**
* 易支付 - 发起充值下单(内嵌二维码模式)
*
* 直接跨库写 epay.pre_order + 计算 usdtpro 指纹金额,
* 前端内嵌渲染二维码,无需跳转 pay.g7g7.top。
*
* 返回的 Data 结构:
* {
* status: 1|0
* message: 文案
* url: 兼容字段(老前端仍可 window.open 跳转 /pay/leader/trade_no/
* qrcode: { 新字段,前端内嵌渲染
* order_sn: OG 侧订单号(用于轮询)
* usdt_address: TRC20 收款地址
* usdt_amount: 含指纹尾数的精确金额(如 10.0003
* vnd_amount: VND 原始金额
* rate: 汇率
* expires_at: 订单超时绝对时间戳
* timeout_sec: 总超时秒数
* }
* }
*/
public function epay_online_order()
{
// 兼容加密请求(Pcapi)和明文请求(Order)
$post = Request::instance()->post();
if (isset($post['encryptData'])) {
$post = decrypt_data($post);
if (!$post) {
$data = encrypt_data(['status' => 0, 'message' => 'Dữ liệu không hợp lệ']);
return json(['Success' => 1, 'Data' => $data]);
}
}
$user_id = intval($post['user_id'] ?? 0);
$money = intval($post['price'] ?? 0);
$client = intval($post['client'] ?? 0);
$username = trim($post['username'] ?? '');
// 支付子类型:usdt / alipay / wxpay 等,默认 usdt
$pay_type = trim($post['pay_type'] ?? 'usdt');
$user = Db::name('user')->where([
'id' => $user_id,
'status' => 1,
'is_delete' => 0,
'agent' => 0,
])->find();
if (!$user || $user_id <= 0 || $money <= 0 || $client <= 0) {
$data = encrypt_data(['status' => 0, 'message' => 'Tham số không hợp lệ, vui lòng thử lại']);
return json(['Success' => 1, 'Data' => $data]);
}
// 地区支线权限(与 AlinPay 一致的风控)
$zdlIdArr = explode(',', $user['agent_parent_id_path']);
$area_list = config('area_list');
if (!isset($area_list[$user['area_id']])) {
$data = encrypt_data(['status' => 0, 'message' => 'Khu vực hiện chưa hỗ trợ nạp tiền']);
return json(['Success' => 1, 'Data' => $data]);
}
$limitAgents = $area_list[$user['area_id']]['limit_agent'];
$isAllow = empty($limitAgents);
foreach ($limitAgents as $allowAgentId) {
if (in_array($allowAgentId, $zdlIdArr)) {
$isAllow = true;
}
}
if (!$isAllow) {
$data = encrypt_data(['status' => 0, 'message' => 'Tài khoản này chưa được phép nạp online']);
return json(['Success' => 1, 'Data' => $data]);
}
// 总代理余额校验
$zdlId = $zdlIdArr[0];
$zdl = Db::name('user')->where([
'id' => $zdlId,
'status' => 1,
'is_delete' => 0,
'agent' => 1,
])->find();
if (!$zdl) {
$data = encrypt_data(['status' => 0, 'message' => 'Tài khoản đại lý có vấn đề, không thể nạp']);
return json(['Success' => 1, 'Data' => $data]);
}
if ($zdl['money'] < $money) {
$maxAllowed = intval($zdl['money']);
$data = encrypt_data([
'status' => 0,
'code' => 'AGENT_LIMIT',
'message' => 'Hạn mức nạp mỗi lần hiện tại là ' . number_format($maxAllowed, 0, '.', ',') . ' VND. Vui lòng nhập số tiền nhỏ hơn hoặc bằng mức trên.',
'max_amount' => $maxAllowed,
]);
return json(['Success' => 1, 'Data' => $data]);
}
$pay_list = config('pay_list');
$pay_orderid = 'P' . date('YmdHis') . rand(100000, 999999); // P 前缀区分 AlinPay 的 E
$notify_url = $pay_list['epay']['notify_url'] ?? '';
$return_url = $pay_list['epay']['callback_url'] ?? '';
$goods_name = $pay_list['epay']['goods_name'] ?? '账户充值';
$epay_api = $pay_list['epay']['api_url'] ?? 'https://pay.g7g7.top';
$merchant_id = intval($pay_list['epay']['pid'] ?? 0);
try {
$epay = new \pay\Epay();
// 写 OG 侧订单
$order_id = Db::name('order_record')->insertGetId([
'pay_channel_id' => 8,
'pay_channel_name' => 'epay',
'user_id' => $user_id,
'order_sn' => $pay_orderid,
'appid' => strval($epay->getConfigInfo()['pid'] ?? ''),
'api_key' => '',
'money' => $money,
'sign' => '',
'create_time' => time(),
'back_order_sn' => '',
'client' => $client,
]);
Db::name('order_log')->insert([
'pay_channel_id' => 8,
'pay_channel_name' => 'epay',
'money' => $money,
'create_time' => time(),
'remake' => 'user_id:' . $user_id . ',用户名:' . $username . ',发起充值(' . $pay_type . ')' . $money . ',时间:' . date('Y-m-d H:i:s'),
'order_id' => $order_id,
'client' => $client,
]);
// 调用 epay 的 mapi.php,让 epay 自己走完整个流程:
// 1) INSERT pre_order
// 2) Channel::submit 算通道
// 3) Plugin::loadForSubmit → usdtpro_plugin::submit() 算 usdtpro 指纹金额并写入 pre_order
// 4) 返回 {type:'jump', url:'/pay/leader/TRADE_NO/'}
// 注意:usdtpro 指纹金额必须由 epay 侧算,OG 侧算会与 monitor 对账逻辑产生精度漂移,导致充值不到账
$apiResult = $epay->createOrderApi(
$pay_orderid,
$pay_type,
sprintf('%.2f', $money),
$goods_name,
$notify_url,
$return_url,
'uid:' . $user_id
);
// mapi.php 返回格式:
// {code:0, trade_no, pay_type:'jump', pay_info:'/pay/submit/TRADE_NO/'} 或
// {code:0, trade_no, payurl:'/pay/submit/TRADE_NO/'} (default 分支)
// {code:1, trade_no, payurl:'...'} (部分旧版)
$submitUrl = '';
$trade_no = '';
if (is_array($apiResult)) {
if (!empty($apiResult['trade_no'])) $trade_no = strval($apiResult['trade_no']);
if (!empty($apiResult['payurl'])) $submitUrl = $apiResult['payurl'];
elseif (!empty($apiResult['pay_info'])) $submitUrl = $apiResult['pay_info'];
elseif (!empty($apiResult['url'])) $submitUrl = $apiResult['url'];
}
if (!$submitUrl || !$trade_no) {
$errMsg = is_array($apiResult) ? (isset($apiResult['msg']) ? $apiResult['msg'] : json_encode($apiResult, JSON_UNESCAPED_UNICODE)) : 'mapi 无响应';
addLogToFile('epay mapi 下单失败:order=' . $pay_orderid . ' err=' . $errMsg, 'epay_error', 'epay');
$data = encrypt_data(['status' => 0, 'message' => 'Khởi tạo thanh toán thất bại: ' . $errMsg]);
return json(['Success' => 1, 'Data' => $data]);
}
// 触发 plugin::submit() 把 usdtpro 指纹金额写入 pre_order
// mapi 模式 Plugin::loadForSubmit 只调 mapi() 方法,usdtpro 插件没这个方法,
// 所以 usdtpro 不会被写入。必须再访问一次 /pay/submit/TRADE_NO/ 让插件 submit() 跑一次
$this->epay_trigger_plugin_submit($submitUrl);
// 跳转到用户看的页面(pay/leader/TRADE_NO/
$payUrl = str_replace('/pay/submit/', '/pay/leader/', $submitUrl);
// 默认返回结构(若后续读取 usdtpro 失败仍可回退跳转)
$qrcode = null;
if ($pay_type === 'usdt' && $trade_no) {
// 从 epay.pre_order 读 epay 已经算好的 usdtpro 指纹金额 + 通道地址
$preOrder = Db::query(
"SELECT o.`trade_no`, o.`usdtpro`, o.`realmoney`, o.`addtime`, c.`config`
FROM `epay`.`pre_order` o
LEFT JOIN `epay`.`pre_channel` c ON c.`id` = o.`channel`
WHERE o.`trade_no` = :tn LIMIT 1",
['tn' => $trade_no]
);
if (!empty($preOrder) && !empty($preOrder[0]['usdtpro'])) {
$row = $preOrder[0];
$cfg = json_decode($row['config'] ?? '{}', true) ?: [];
$timeout = intval($cfg['timeout'] ?? 600);
$expiresAt = strtotime($row['addtime']) + $timeout;
$qrcode = [
'order_sn' => $pay_orderid,
'trade_no' => $row['trade_no'],
'usdt_address' => $cfg['address'] ?? '',
'usdt_amount' => rtrim(rtrim(sprintf('%.5f', floatval($row['usdtpro'])), '0'), '.'),
'vnd_amount' => $row['realmoney'],
'rate' => strval($cfg['rate'] ?? ''),
'expires_at' => $expiresAt,
'timeout_sec' => $timeout,
];
addLogToFile('epay 下单读取 usdtpro 成功: order=' . $pay_orderid . ' trade_no=' . $trade_no . ' usdt=' . $qrcode['usdt_amount'], 'epay_request', 'epay');
} else {
addLogToFile('epay 下单 pre_order 未取到 usdtpro: order=' . $pay_orderid . ' trade_no=' . $trade_no, 'epay_error', 'epay');
}
}
$data = encrypt_data([
'status' => 1,
'message' => 'Khởi tạo thanh toán thành công',
'url' => $payUrl, // 兼容老前端
'qrcode' => $qrcode, // 新前端内嵌渲染用(usdtpro 由 epay 权威给出)
]);
return json(['Success' => 1, 'Data' => $data]);
} catch (\Exception $e) {
addLogToFile('epay 下单异常:' . $e->getMessage() . ' | file:' . $e->getFile() . ':' . $e->getLine(), 'epay_error', 'epay');
$data = encrypt_data(['status' => 0, 'message' => 'Khởi tạo thanh toán thất bại: ' . $e->getMessage()]);
return json(['Success' => 1, 'Data' => $data]);
}
}
/**
* 触发 epay plugin::submit() 写入 usdtpro 指纹金额
* 只请求不处理响应(epay 会返回 302 HTML,我们只要副作用)
*/
private function epay_trigger_plugin_submit($submitUrl)
{
try {
$ch = curl_init($submitUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_CONNECTTIMEOUT => 3,
CURLOPT_TIMEOUT => 6,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_USERAGENT => 'OG-EpayInternal/1.0',
]);
curl_exec($ch);
curl_close($ch);
} catch (\Exception $e) {
addLogToFile('epay_trigger_plugin_submit 异常:' . $e->getMessage(), 'epay_error', 'epay');
}
}
/**
* 易支付 - 订单状态轮询
*
* 前端轮询该接口,判断是否到账或已超时。
* 返回 Data 结构:
* { status: 0|1|2, message, money, paid_time }
* 0=待支付, 1=已到账, 2=已超时
*/
public function epay_order_status()
{
$post = Request::instance()->post();
if (isset($post['encryptData'])) {
$post = decrypt_data($post);
if (!$post) {
return json(['status' => 0, 'message' => '数据解密失败']);
}
}
$order_sn = trim($post['order_sn'] ?? '');
$user_id = intval($post['user_id'] ?? 0);
if ($order_sn === '' || $user_id <= 0) {
$data = encrypt_data(['status' => 0, 'message' => '参数错误']);
return json(['Success' => 1, 'Data' => $data]);
}
$order = Db::name('order_record')
->where([
'order_sn' => $order_sn,
'user_id' => $user_id,
'pay_channel_id' => 8,
])
->find();
if (!$order) {
$data = encrypt_data(['status' => 0, 'message' => '订单不存在']);
return json(['Success' => 1, 'Data' => $data]);
}
// status=3 代表已回调结算完成(见 epay_recharge_settle
if (intval($order['status']) == 3) {
$data = encrypt_data([
'status' => 1,
'message' => '充值成功',
'money' => $order['money'],
'paid_time' => $order['back_time'],
]);
return json(['Success' => 1, 'Data' => $data]);
}
// 超时判定:从 epay 配置拿 timeout,兜底 600
$pay_list = config('pay_list');
$timeout = intval($pay_list['epay']['timeout'] ?? 600);
if (time() - intval($order['create_time']) > $timeout) {
$data = encrypt_data([
'status' => 2,
'message' => '订单超时',
'money' => $order['money'],
]);
return json(['Success' => 1, 'Data' => $data]);
}
$data = encrypt_data([
'status' => 0,
'message' => '等待支付',
'money' => $order['money'],
]);
return json(['Success' => 1, 'Data' => $data]);
}
/**
* 易支付 - 异步回调处理
*
* 易支付回调是 GETpay.php 跳转后用 GET 带参数回 notify_url),
* 但也可能 POST —— 都兼容
*/
public function epay_recharge_callback()
{
$request = Request::instance();
$data = $request->post();
if (empty($data)) {
$data = $request->get();
}
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
addLogToFile('epay 回调原始数据:' . $json, 'epay_callback', 'epay');
if (!is_array($data) || empty($data['out_trade_no']) || empty($data['sign'])) {
Log::record($data, 'epay_error_callback');
exit('fail');
}
// 记录回调日志
$logId = Db::name('pay_callback_log')->insertGetId([
'pay_channel' => 'EPAY_RECHARGE',
'type' => 'recharge',
'json' => $json,
'create_time' => date('Y-m-d H:i:s'),
]);
try {
$epay = new \pay\Epay();
$result = $epay->verifyNotifyCallback($data, $logId);
if (!$result['verified']) {
exit('fail');
}
if ($result['success']) {
$this->epay_recharge_settle($data);
exit('success');
} else {
// 非 TRADE_SUCCESS —— 返 success 让对方不再重试
addLogToFile('epay 回调非成功状态,ack 防重试:order=' . ($data['out_trade_no'] ?? ''), 'epay_callback', 'epay');
exit('success');
}
} catch (\Exception $e) {
addLogToFile('epay 回调处理异常:' . $e->getMessage(), 'epay_callback_error', 'epay');
exit('fail');
}
}
/**
* 易支付结算(事务保护:加锁 扣代理 加用户 写日志)
* alin_recharge_settle 同构,只是 pay_channel 改成 epay
*/
private function epay_recharge_settle($data)
{
$orderNo = $data['out_trade_no'];
Db::startTrans();
try {
$order = Db::name('order_record')->where('order_sn', $orderNo)->lock(true)->find();
if (!$order || $order['status'] == 3) {
Db::rollback();
return;
}
$user = Db::name('user')->where([
'id' => $order['user_id'],
'status' => 1,
'is_delete' => 0,
'agent' => 0,
])->lock(true)->find();
if (!$user) {
Db::rollback();
return;
}
$zdlIdArr = explode(',', $user['agent_parent_id_path']);
$zdlId = $zdlIdArr[0];
$zdl = Db::name('user')->where([
'id' => $zdlId,
'status' => 1,
'is_delete' => 0,
'agent' => 1,
])->lock(true)->find();
if (!$zdl || $zdl['money'] < $order['money']) {
Db::rollback();
addLogToFile('epay 结算失败:代理余额不足 order=' . $orderNo, 'epay_callback_error', 'epay');
return;
}
// 实际到账金额:易支付回调中的 money 字段(CNY)
$actualMoney = isset($data['money']) ? floatval($data['money']) : $order['money'];
// 1. 更新订单
Db::name('order_record')->where('id', $order['id'])->update([
'back_money' => $actualMoney,
'back_time' => time(),
'status' => 3,
'agent_parent_id' => $user['agent_parent_id'],
'agent_parent_username' => $user['agent_parent_username'],
'zdl_id' => $zdl['id'],
'zdl_username' => $zdl['username'],
'zdl_money_before' => $zdl['money'],
'zdl_money_after' => $zdl['money'] - $order['money'],
'money_before' => $user['money'],
'money_after' => $user['money'] + $order['money'],
]);
// 2. 订单日志
Db::name('order_log')->insert([
'pay_channel_id' => 8,
'pay_channel_name' => 'epay',
'money' => $order['money'],
'create_time' => time(),
'remake' => '易支付回调成功 trade_no=' . ($data['trade_no'] ?? '') . ' type=' . ($data['type'] ?? ''),
'order_id' => $order['id'],
]);
// 3. recharge 流水
Db::name('recharge')->insert([
'type' => 4,
'amount' => $order['money'],
'mode' => 1,
'agent_or_admin' => 3,
'controller_id' => $zdl['id'],
'controller_username' => $zdl['username'],
'controller_nickname' => $zdl['nickname'],
'controller_type' => '易支付第三方充值,扣取总代理余分',
'controller_old_money' => $zdl['money'],
'controller_new_money' => $zdl['money'] - $order['money'],
'user_id' => $order['user_id'],
'user_type' => $user['agent'],
'user_agent_level' => 0,
'username_for' => $user['username'],
'nickname_for' => $user['nickname'],
'user_parent_id' => $user['agent_parent_id'],
'create_time' => time(),
'old_money' => $user['money'],
'new_money' => $user['money'] + $order['money'],
'controller_system' => 3,
'remake' => '易支付第三方充值成功(' . ($data['type'] ?? '') . ')',
]);
// 4. 扣代理
Db::name('user')->where('id', $zdl['id'])->update([
'money' => $zdl['money'] - $order['money'],
'last_recharge_out' => $order['money'],
'last_recharge_out_time' => time(),
'recharge_out_count' => $zdl['recharge_out_count'] + 1,
'recharge_out_total_amount' => $zdl['recharge_out_total_amount'] + $order['money'],
]);
// 5. 加用户
Db::name('user')->where('id', $order['user_id'])->update([
'money' => $user['money'] + $order['money'],
'last_recharge' => $order['money'],
'last_recharge_time' => time(),
'recharge_count' => $user['recharge_count'] + 1,
'recharge_total_amount' => $user['recharge_total_amount'] + $order['money'],
]);
Db::commit();
addLogToFile('epay 结算成功:order=' . $orderNo . ' money=' . $order['money'], 'epay_callback', 'epay');
} catch (\Exception $e) {
Db::rollback();
addLogToFile('epay 结算异常:' . $e->getMessage(), 'epay_callback_error', 'epay');
}
}
}
@@ -204,7 +204,7 @@
<i class="icon"></i> <i class="icon"></i>
<select class="select" name="pay_type" id="pay_type"> <select class="select" name="pay_type" id="pay_type">
<?php foreach($payMethod as $key=>$method): ?> <?php foreach($payMethod as $key=>$method): ?>
<option value ="<?=$key?>"><?=$method?></option> <option value ="<?=$key?>" data-url="/order/<?=isset($pay_routes[$key])?$pay_routes[$key]:$online_order_fac?>"><?=$method?></option>
<?php endForeach; ?> <?php endForeach; ?>
</select> </select>
</div> </div>
@@ -233,7 +233,8 @@
query.price = price; query.price = price;
query.username = username; query.username = username;
query.pay_type = pay_type; query.pay_type = pay_type;
url = '/order/<?=$online_order_fac ?>'; // 每种支付方式对应的 online_order 路由可能不同
url = $('#pay_type option:selected').data('url') || '/order/<?=$online_order_fac ?>';
//var winRef = window.open("","_blank"); //var winRef = window.open("","_blank");
$.ajax({ $.ajax({
url:url, url:url,
+388
View File
@@ -0,0 +1,388 @@
<?php
namespace pay;
use think\Db;
/**
* AlinPay 越南支付网关
* 代收(Collection): /api/order product_id=11
* 代付(Disbursement): /api/payment product_id=14
* 代收查询: /api/order/status
* 代付查询: /api/payment/status
* 账户查询: /api/account
*/
class AlinPay
{
private $config;
private $domain;
// 越南银行编码映射
private static $bankCodes = [
'Liobank','VietcomBank','VietinBank','MB','BIDV',
'Techcombank','Sacombank','ACB','Agribank','VPBank',
'TPBank','VIB','BVBank','MSB','SHB',
'Vikki Bank','Nam A Bank','HDBank','Eximbank','SeABank',
'LPBank','PVcomBank','PVcomBank Pay','SCB','Shinhan VN',
'ABBank','Kienlongbank','CAKE','VietBank','Wooribank',
'NCB','PG_Bank','BacABank','SCBVN','HSBC VN',
'BaoViet Bank','VietABank','Saigonbank','Co-op Bank',
'Timo by Ban Viet Bank','MBV','IVB','VCBNeo',
'Public Bank Viet Nam','Citibank HN','Citibank HCM',
'VBSP','VRB','Hong Leong Bank','UOB','Umee',
'GPBank','Ubank','KBank','Deutsche Bank','VNPT Money',
'Viettel Money','KBNN','MUFG Bank','ANZ','IBKHN',
'IBK HCM','Sinopac','CTBC','SMBC','Mizuho Bank HN',
'Mizuho Bank HCM','DBS HCM','Bank Of China','CIMB',
'BNP Paribas HCM','BNP Paribas HN','MEGA ICBC',
'BANGKOK BANK H','BPCE IOM','Taipei Fubon Binh Duong',
'Taipei Fubon HN','Taipei Fubon HCM','OCBC HCM',
'Home Credit','CCB','HuaNan Bank','ICBC Hà Nội',
'SIAM-SCB','JP Morgan Chase Bank','KBHN','KBHCM',
'Maybank','BIDC','CILC','BoCom',
'First Commercial Bank HN','First Commercial Bank HCM',
'Agricultural Bank of China','Keb Hana HN','Keb Hana HCM',
'NHNN','VDB','Napas','HAFIC','TNEX by MSB',
'Vinaconex - Viettel','MoMo','ZaloPay',
'Mobifone Tiendidong','PAYOO','E.SUN Commercial Bank',
'Neopay','Hpay','CFC','PTF','VFC',
'TechcomFinance','MAFC','JIVF','VFL','TFSVN',
'Bank of India- BOI','Busan-BNK','Cathay United',
'Nonghyup','Quý TDCS','SVFC','Vikki',
];
public function __construct()
{
$this->getConfig();
}
/**
* 获取配置信息
*/
private function getConfig()
{
$config = Db::name('pay_channel')->where('key', 'ALIN_VN')->value('value');
$config = json_decode($config, true);
$this->config = $config;
// 域名从配置读取,回退默认值(2026-05 第三方网关由 fantianchuangshi.com 迁至 hypayment.net
$this->domain = $config['domain'] ?? 'https://alinintermon-api.hypayment.net';
}
/**
* 生成签名
* 规则:参数按key排序 key=value&连接(空值不参与) 拼接key={secret} MD5 32位小写
* ext字段不参与签名
*
* @param array $params
* @return string
*/
public function generateSign(array $params)
{
// 移除不参与签名的字段
unset($params['sign']);
unset($params['ext']);
// 过滤空值
$params = array_filter($params, function ($val) {
return $val !== '' && $val !== null;
});
// 按key排序
ksort($params);
// 拼接
$parts = [];
foreach ($params as $key => $val) {
$parts[] = $key . '=' . $val;
}
$str = implode('&', $parts);
$str .= '&key=' . $this->config['secret'];
return md5($str);
}
/**
* 验证回调签名(时间安全比较,防timing attack
*
* @param array $params
* @return bool
*/
public function verifySign(array $params)
{
$receivedSign = $params['sign'] ?? '';
$calculatedSign = $this->generateSign($params);
return hash_equals($calculatedSign, $receivedSign);
}
/**
* 发送HTTP请求
*
* @param string $url
* @param array $data
* @return array|null
*/
private function request($url, $data)
{
$jsonData = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
addLogToFile('请求地址:' . $url, 'alin_request', 'alin');
addLogToFile('请求报文:' . $jsonData, 'alin_request', 'alin');
$header = ['Content-Type: application/json'];
$result = httpPost($url, $jsonData, $header);
addLogToFile('返回结果:' . json_encode($result, JSON_UNESCAPED_UNICODE), 'alin_response', 'alin');
return $result;
}
/**
* 代收下单(用户充值)
*
* @param string $orderNo 商户订单号
* @param string $amount 金额()
* @param string $notifyUrl 回调地址
* @param string $desc 订单描述
* @return array|null
*/
public function createOrder($orderNo, $amount, $notifyUrl, $desc = '')
{
$params = [
'app_id' => strval($this->config['app_id']),
'product_id' => strval($this->config['collection_product_id']), // 代收 product_id=11
'out_trade_no' => strval($orderNo),
'notify_url' => strval($notifyUrl),
'amount' => strval($amount),
'time' => intval(time()),
'desc' => strval($desc),
];
$params['sign'] = $this->generateSign($params);
$url = $this->domain . '/api/order';
return $this->request($url, $params);
}
/**
* 代收查询
*
* @param string $orderNo 商户订单号
* @return array|null
*/
public function queryOrder($orderNo)
{
$params = [
'app_id' => $this->config['app_id'],
'out_trade_no' => $orderNo,
'time' => time(),
];
$params['sign'] = $this->generateSign($params);
$url = $this->domain . '/api/order/status';
return $this->request($url, $params);
}
/**
* 代付下单(用户提现)
*
* @param string $orderNo 商户订单号
* @param string $amount 金额()
* @param string $accountName 账户名称
* @param string $accountNumber 卡号
* @param string $bankCode 银行编码
* @param string $bankName 银行名称
* @param string $notifyUrl 回调地址
* @param string $desc 订单描述
* @return array|null
*/
public function createPayment($orderNo, $amount, $accountName, $accountNumber, $bankCode, $bankName, $notifyUrl, $desc = '')
{
$params = [
'app_id' => strval($this->config['app_id']),
'product_id' => strval($this->config['payment_product_id']), // 代付 product_id=14
'out_trade_no' => strval($orderNo),
'notify_url' => strval($notifyUrl),
'amount' => strval($amount),
'time' => intval(time()),
'desc' => strval($desc),
];
$params['sign'] = $this->generateSign($params);
// ext不参与签名,单独附加
$params['ext'] = [
'accountName' => $accountName,
'accountNumber' => $accountNumber,
'bankCode' => $bankCode,
'bankName' => $bankName,
];
$url = $this->domain . '/api/payment';
return $this->request($url, $params);
}
/**
* 代付查询
*
* @param string $orderNo 商户订单号
* @return array|null
*/
public function queryPayment($orderNo)
{
$params = [
'app_id' => $this->config['app_id'],
'out_trade_no' => $orderNo,
'time' => time(),
];
$params['sign'] = $this->generateSign($params);
$url = $this->domain . '/api/payment/status';
return $this->request($url, $params);
}
/**
* 账户查询
*
* @return array|null
*/
public function queryAccount()
{
$params = [
'app_id' => $this->config['app_id'],
'time' => time(),
];
$params['sign'] = $this->generateSign($params);
$url = $this->domain . '/api/account';
return $this->request($url, $params);
}
/**
* 处理代收回调 仅验签+解析状态,不操作余额
* 余额结算由 trait alin_recharge_settle() 统一处理
*
* @param array $data 回调数据
* @param int $logId 日志ID
* @return array ['verified' => bool, 'trade_status' => int, 'data' => array]
*/
public function verifyRechargeCallback($data, $logId = 0)
{
// 验签
if (!$this->verifySign($data)) {
addLogToFile('代收回调签名验证失败:' . json_encode($data, 320), 'alin_callback_error', 'alin');
return ['verified' => false, 'trade_status' => 0, 'data' => $data];
}
$orderNo = $data['out_trade_no'] ?? '';
if ($logId && $orderNo) {
Db::name('pay_callback_log')->where('id', $logId)->update(['unique_no' => $orderNo]);
}
$tradeStatus = intval($data['trade_status']);
addLogToFile('代收回调验签通过:order=' . $orderNo . ' status=' . $tradeStatus, 'alin_callback', 'alin');
return ['verified' => true, 'trade_status' => $tradeStatus, 'data' => $data];
}
/**
* 处理代付回调(提现回调)
*
* @param array $data 回调数据
* @param int $logId 日志ID
* @return string|void
*/
public function paymentCallback($data, $logId = 0)
{
// 验签
if (!$this->verifySign($data)) {
addLogToFile('代付回调签名验证失败:' . json_encode($data, 320), 'alin_callback_error', 'alin');
return;
}
$orderNo = $data['out_trade_no'] ?? '';
if (!$orderNo) return;
if ($logId) {
Db::name('pay_callback_log')->where('id', $logId)->update(['unique_no' => $orderNo]);
}
$tradeStatus = intval($data['trade_status']);
$order = Db::name('user_withdraw')->where('order_no', $orderNo)->find();
if (!$order) {
addLogToFile('代付回调订单不存在:' . $orderNo, 'alin_callback', 'alin');
return 'success';
}
// 只处理 AGREE 状态的订单
if ($order['status'] !== 'AGREE') {
addLogToFile('代付回调订单状态非AGREE' . $orderNo . ' status=' . $order['status'], 'alin_callback', 'alin');
return 'success';
}
$payTime = strtotime($data['complete_time'] ?? '') ?: time();
if ($tradeStatus === 1) {
// 成功
$updateData = [
'status' => 'SUCCESS',
'pay_time' => $payTime,
'out_trade_no' => $data['trade_no'] ?? '',
];
Db::name('user_withdraw')->where('id', $order['id'])->update($updateData);
addLogToFile('代付回调成功:' . $orderNo, 'alin_callback', 'alin');
return 'success';
} elseif ($tradeStatus === 2) {
// 失败 — 退回用户余额
Db::startTrans();
try {
$user = Db::name('user')->where('id', $order['user_id'])->lock(true)->find();
$newMoney = $user['money'] + $order['money'] + $order['service_fee_money'];
Db::name('user')->where('id', $order['user_id'])->update([
'money' => $newMoney,
]);
Db::name('user_withdraw')->where('id', $order['id'])->update([
'status' => 'FAIL',
'pay_time' => $payTime,
]);
Db::commit();
addLogToFile('代付回调失败已退款:' . $orderNo . ' refund=' . ($order['money'] + $order['service_fee_money']), 'alin_callback', 'alin');
return 'success';
} catch (\Exception $e) {
Db::rollback();
addLogToFile('代付回调退款异常:' . $e->getMessage(), 'alin_callback_error', 'alin');
return;
}
}
// 处理中(-1),不返回success让网关重试
addLogToFile('代付回调处理中:' . $orderNo . ' status=' . $tradeStatus, 'alin_callback', 'alin');
return;
}
/**
* 获取银行编码列表
*
* @return array
*/
public static function getBankCodes()
{
return self::$bankCodes;
}
/**
* 获取配置信息(外部使用)
*
* @return array
*/
public function getConfigInfo()
{
return $this->config;
}
}
+132
View File
@@ -0,0 +1,132 @@
<?php
namespace pay;
use think\Db;
class Ccpay
{
private $config;
private $apiUrl;
private $mchNo;
private $paySecret;
public function __construct()
{
$this->config = config('pay_list.ccpay') ?: [];
$this->apiUrl = $this->config['api_url'] ?? '';
$this->mchNo = $this->config['mch_no'] ?? '';
$this->paySecret = $this->config['pay_secret'] ?? '';
}
public function getConfigInfo()
{
return $this->config;
}
public function generateSign(array $params)
{
unset($params['sign']);
ksort($params);
$str = '';
foreach ($params as $k => $v) {
if (is_string($v) && strlen($v) > 0) {
$str .= "{$k}={$v}&";
}
}
$str = substr($str, 0, -1) . '&paySecret=' . $this->paySecret;
return strtoupper(md5($str));
}
public function verifySign(array $params)
{
$received = $params['sign'] ?? '';
if (!$received) return false;
$calculated = $this->generateSign($params);
return hash_equals($calculated, $received);
}
public function createOrder($orderNo, $amount, $notifyUrl, $memberId = 'og_user', $callbackUrl = '')
{
$extra = [
'bankType' => 'OFFLINE',
'cardType' => '0',
'orderPeriod' => '30',
'memberId' => $memberId,
'merchantName' => 'OG',
'notifyUrl' => $notifyUrl,
'callbackUrl' => $callbackUrl,
];
$data = [
'tradeType' => 'cs.pay.submit',
'version' => '2.0',
'channel' => 'union_pay',
'mchNo' => $this->mchNo,
'body' => 'online_pay',
'mchOrderNo' => $orderNo,
'amount' => strval(intval($amount)),
'currency' => 'VND',
'timePaid' => date('YmdHis'),
'remark' => 'online-pay',
];
$signParams = array_merge($data, $extra);
$data['sign'] = $this->generateSign($signParams);
$data['extra'] = json_encode($extra);
addLogToFile('ccpay 下单请求: order=' . $orderNo . ' amount=' . $amount . ' params=' . json_encode($data, JSON_UNESCAPED_UNICODE), 'ccpay_request', 'ccpay');
$result = $this->postForm($this->apiUrl, $data);
addLogToFile('ccpay 下单返回: ' . json_encode($result, JSON_UNESCAPED_UNICODE), 'ccpay_response', 'ccpay');
return $result;
}
public function queryOrder($orderNo)
{
$data = [
'tradeType' => 'cs.order.query',
'version' => '2.0',
'mchNo' => $this->mchNo,
'mchOrderNo' => $orderNo,
];
$data['sign'] = $this->generateSign($data);
return $this->postForm($this->apiUrl, $data);
}
private function postForm($url, $params)
{
$ch = curl_init($url);
$body = '';
foreach ($params as $k => $v) {
if (!is_string($v)) continue;
$body .= $k . '=' . urlencode($v) . '&';
}
$body = rtrim($body, '&');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded; charset=UTF-8'],
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$resp = curl_exec($ch);
$err = curl_error($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($resp === false) {
addLogToFile("ccpay curl 失败: code={$code} err={$err}", 'ccpay_error', 'ccpay');
return null;
}
return json_decode($resp, true);
}
}
+213
View File
@@ -0,0 +1,213 @@
<?php
namespace pay;
use think\Db;
/**
* 彩虹易支付(epay)对接类
*
* 对应线上支付平台:https://pay.g7g7.top/
* 官方文档:https://pay.cccyun.cc/
*
* 支付流程:
* 1. buildPayUrl() 构造带签名的 URL,前端 302 跳转到该 URL 发起支付
* 2. 用户在易支付页面完成支付(USDT扫码/银行卡/支付宝 等,取决于通道)
* 3. 易支付异步 POST notify_url,携带 sign;本端 verifyNotifyCallback() 验签
*
* 签名规则(MD5):
* - 去除 sign、sign_type 字段
* - 过滤空值
* - key 字典序排序
* - 拼接 k=v&k=v(不 urlencode,直接原值)
* - 末尾拼接 {商户key}(不是 &key=
* - MD5(str) 32 位小写
*/
class Epay
{
private $config;
private $apiUrl;
public function __construct()
{
$this->getConfig();
}
/**
* 获取配置
* 优先读 pay_channel 表(和 AlinPay 一致的存储位置),
* 回退到 config('pay_list.epay')
*/
private function getConfig()
{
$dbConfig = Db::name('pay_channel')->where('key', 'EPAY')->value('value');
if ($dbConfig) {
$this->config = json_decode($dbConfig, true) ?: [];
} else {
$this->config = config('pay_list.epay') ?: [];
}
$this->apiUrl = $this->config['api_url'] ?? 'https://pay.g7g7.top';
}
public function getConfigInfo()
{
return $this->config;
}
/**
* 生成签名
*
* @param array $params
* @return string
*/
public function generateSign(array $params)
{
unset($params['sign'], $params['sign_type']);
// 过滤空值(易支付官方要求)
$params = array_filter($params, function ($val) {
return $val !== '' && $val !== null;
});
ksort($params);
$parts = [];
foreach ($params as $k => $v) {
$parts[] = $k . '=' . $v;
}
$str = implode('&', $parts) . ($this->config['key'] ?? '');
return md5($str);
}
/**
* 验证回调签名(时间安全比较)
*
* @param array $params
* @return bool
*/
public function verifySign(array $params)
{
$received = $params['sign'] ?? '';
$calculated = $this->generateSign($params);
return hash_equals($calculated, $received);
}
/**
* 构造发起支付的 URL(跳转式 submit.php
* 前端收到该 URL 后直接 window.location 跳转即可
*
* @param string $orderNo 商户订单号
* @param string $type 支付方式:alipay|wxpay|qqpay|bank|jdpay|usdt
* @param string $amount 金额(元)
* @param string $name 商品名称
* @param string $notifyUrl 异步通知地址
* @param string $returnUrl 同步跳转地址
* @param string $param 业务扩展参数(可选,原样回传)
* @return string
*/
public function buildPayUrl($orderNo, $type, $amount, $name, $notifyUrl, $returnUrl = '', $param = '')
{
$params = [
'pid' => strval($this->config['pid'] ?? ''),
'type' => $type,
'out_trade_no' => strval($orderNo),
'notify_url' => $notifyUrl,
'return_url' => $returnUrl,
'name' => $name,
'money' => strval($amount),
'param' => $param,
'sign_type' => 'MD5',
];
$params['sign'] = $this->generateSign($params);
$params = array_filter($params, function ($v) {
return $v !== '' && $v !== null;
});
return rtrim($this->apiUrl, '/') . '/submit.php?' . http_build_query($params);
}
/**
* API 模式下单(mapi.php
*
* @param string $clientIp 下单用户的 IPmapi.php 必填,否则报 "用户IP地址(clientip)不能为空"
* @return array|null
*/
public function createOrderApi($orderNo, $type, $amount, $name, $notifyUrl, $returnUrl = '', $param = '', $clientIp = '')
{
if ($clientIp === '' || $clientIp === null) {
$clientIp = \think\Request::instance()->ip();
}
$params = [
'pid' => strval($this->config['pid'] ?? ''),
'type' => $type,
'out_trade_no' => strval($orderNo),
'notify_url' => $notifyUrl,
'return_url' => $returnUrl,
'name' => $name,
'money' => strval($amount),
'param' => $param,
'clientip' => strval($clientIp),
'sign_type' => 'MD5',
];
$params['sign'] = $this->generateSign($params);
$url = rtrim($this->apiUrl, '/') . '/mapi.php';
addLogToFile('epay API 下单请求:' . $url . ' params=' . json_encode($params, JSON_UNESCAPED_UNICODE), 'epay_request', 'epay');
$result = httpPost($url, $params);
addLogToFile('epay API 下单返回:' . json_encode($result, JSON_UNESCAPED_UNICODE), 'epay_response', 'epay');
if (is_array($result)) return $result;
if (is_string($result)) return json_decode($result, true);
return null;
}
/**
* 订单查询
*/
public function queryOrder($orderNo)
{
$params = [
'act' => 'order',
'pid' => strval($this->config['pid'] ?? ''),
'out_trade_no' => strval($orderNo),
];
$params['sign'] = $this->generateSign($params);
$params['sign_type'] = 'MD5';
$url = rtrim($this->apiUrl, '/') . '/api.php?' . http_build_query($params);
$resp = httpGet($url);
return is_string($resp) ? json_decode($resp, true) : $resp;
}
/**
* 处理异步回调 仅验签+解析状态,不操作余额
* 余额结算由 trait epay_recharge_settle() 统一处理
*
* @param array $data $_POST $_GET
* @param int $logId 日志 ID
* @return array ['verified' => bool, 'success' => bool, 'data' => array]
*/
public function verifyNotifyCallback($data, $logId = 0)
{
if (!$this->verifySign($data)) {
addLogToFile('epay 回调验签失败:' . json_encode($data, 320), 'epay_callback_error', 'epay');
return ['verified' => false, 'success' => false, 'data' => $data];
}
$orderNo = $data['out_trade_no'] ?? '';
if ($logId && $orderNo) {
Db::name('pay_callback_log')->where('id', $logId)->update(['unique_no' => $orderNo]);
}
$success = isset($data['trade_status']) && $data['trade_status'] === 'TRADE_SUCCESS';
addLogToFile('epay 回调验签通过:order=' . $orderNo . ' status=' . ($data['trade_status'] ?? ''), 'epay_callback', 'epay');
return ['verified' => true, 'success' => $success, 'data' => $data];
}
}
+3 -2
View File
@@ -596,7 +596,8 @@ var showCard = function(data){
} }
var showCardNn = function(data){ var showCardNn = function(data){
if(data.round.bet_status == 2){ if(data.round.bet_status == 2){
if (data.card_info.length == 0) { var card_info_arr = data.round.show_card || [];
if (card_info_arr.length == 0) {
$('#show_dice').show(); $('#show_dice').show();
} }
$(".begincard").fadeIn(function(){ $(".begincard").fadeIn(function(){
@@ -606,7 +607,7 @@ var showCardNn = function(data){
$(".begincard .box3").animate({"top":"100%","opacity":"1"}); $(".begincard .box3").animate({"top":"100%","opacity":"1"});
$(".begincard .box4").animate({"top":"100%","opacity":"1"}); $(".begincard .box4").animate({"top":"100%","opacity":"1"});
}); });
card_number_info = data.card_info; card_number_info = card_info_arr;
if(card_number_info.length > 0){ if(card_number_info.length > 0){
for(var i=0;i<card_number_info.length;i++){ for(var i=0;i<card_number_info.length;i++){
if(card_number_info[i]['order_num'] == 0){ if(card_number_info[i]['order_num'] == 0){