- 新增地址选择插件,支持地图位置选择并返回地址和经纬度 - 新增微信订阅消息发送功能,支持审核结果、提现通知等场景 - 新增订单支付状态查询、提现收款人姓名保存等接口 - 新增服务区域管理,支持按省市区划分并同步到信息发布 - 新增资金流水和营收报表导出功能 - 新增可用优惠券查询、订单退款拆分处理等功能 - 优化后台角标显示、首页数据统计、UI配置下发等 - 修复订单支付并发问题、地区管理逻辑等
111 行
4.5 KiB
PHP
111 行
4.5 KiB
PHP
<?php
|
||
|
||
namespace app\api\controller;
|
||
|
||
use think\Db;
|
||
|
||
/**
|
||
* 用户端 · 订单(Module-ORDER)
|
||
* 路由:
|
||
* POST /api/v1/order/recharge 余额充值下单
|
||
*
|
||
* 说明:充值金额一律由客户端传入后**服务端再次校验**(>0 且 ≤100000),并按 round(...,2) 归一;
|
||
* **交易只允许微信支付**:订单落 status=pending,前端调 POST /pay/prepay 调起收银台,
|
||
* 支付成功后由 /pay/notify 复用 creditRecharge() 入账(幂等由回调侧 status=paid 保证)。
|
||
*
|
||
* 【为什么不允许 payType=balance】「用余额充值余额」在本模型里没有任何收款方:余额只会 +amount、
|
||
* 不会扣减,等于给用户凭空增发余额(可用余额去买会员/付费发布/解锁联系方式,直接造成资损)。
|
||
* v1.1.0 初版曾把它当作「余额即时到账」的演示通道,**已移除**;给用户加余额只应来自
|
||
* ① 微信支付回调 creditRecharge(),② 后台「会员管理 → 余额充值」(`fc/userext/recharge`)。
|
||
*/
|
||
class Order extends V1
|
||
{
|
||
/**
|
||
* POST /api/v1/order/recharge {amount,payType}
|
||
* → {orderNo,amount,status:'pending',payType:'wxpay'}
|
||
* 规则:金额 >0 且 ≤100000 → 否则 fail('充值金额不合法');
|
||
* payType=balance → fail('余额充值仅支持微信支付')(资损防护,见类注释);
|
||
* payType 非 wxpay → fail('支付方式不支持')。
|
||
*/
|
||
public function recharge()
|
||
{
|
||
$user = $this->auth();
|
||
|
||
$amount = round((float)$this->input('amount', 0), 2);
|
||
if ($amount <= 0 || $amount > 100000) {
|
||
$this->fail('充值金额不合法');
|
||
}
|
||
|
||
$payType = (string)$this->input('payType', '');
|
||
|
||
// 余额「充值」= 用余额给余额加钱(无收款方、余额不扣减)→ 直接拒绝,防资损
|
||
if ($payType === 'balance') {
|
||
$this->fail('余额充值仅支持微信支付');
|
||
}
|
||
if ($payType !== 'wxpay') {
|
||
$this->fail('支付方式不支持');
|
||
}
|
||
|
||
$now = time();
|
||
$orderNo = $this->orderNo('RC');
|
||
|
||
Db::name('fc_order')->insert([
|
||
'order_no' => $orderNo,
|
||
'user_id' => $user['id'],
|
||
'type' => 'recharge',
|
||
'title' => '余额充值',
|
||
'amount' => $amount,
|
||
'pay_type' => 'wxpay',
|
||
'status' => 'pending',
|
||
'paytime' => null,
|
||
'related_id' => 0,
|
||
'createtime' => $now,
|
||
'updatetime' => $now,
|
||
]);
|
||
|
||
// 入账只在「微信支付回调 /pay/notify」里发生(Order::creditRecharge),本接口不触碰 fa_user.money
|
||
$this->ok([
|
||
'orderNo' => $orderNo,
|
||
'amount' => $amount,
|
||
'status' => 'pending',
|
||
'payType' => 'wxpay',
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 充值入账(**可复用**:微信支付回调 /pay/notify 入账时调用)
|
||
* 动作:fa_user.money 加款 + fc_finance_flow 资金流水 + fc_message 站内信。
|
||
* 幂等:调用方需保证「订单未入账」(回调侧以 fc_order.status=paid 做幂等判定)。
|
||
* 注意:**不要**在充值下单接口里调用它 —— 未真实收款就加余额属于凭空增发(资损)。
|
||
* @param array $order fc_order 行
|
||
* @return array{balance:float,amount:float}
|
||
*/
|
||
public function creditRecharge(array $order)
|
||
{
|
||
$userId = (int)$order['user_id'];
|
||
$amount = round((float)(isset($order['amount']) ? $order['amount'] : 0), 2);
|
||
$orderId = (int)(isset($order['id']) ? $order['id'] : 0);
|
||
$now = time();
|
||
|
||
$row = Db::name('user')->where('id', $userId)->find();
|
||
if (!$row) {
|
||
return ['balance' => 0, 'amount' => $amount];
|
||
}
|
||
|
||
// 原子自增:并发回调/重复入账时不会丢更新(幂等由订单状态保证)
|
||
Db::name('user')->where('id', $userId)->setInc('money', $amount);
|
||
$balance = round((float)Db::name('user')->where('id', $userId)->value('money'), 2);
|
||
Db::name('user')->where('id', $userId)->update(['updatetime' => $now]);
|
||
|
||
$this->flow('income', '余额充值', $amount, $balance, $orderId, '余额充值');
|
||
$this->notify(
|
||
$userId,
|
||
'system',
|
||
'充值成功',
|
||
'您已成功充值 ' . number_format($amount, 2) . ' 元,当前余额 ' . number_format($balance, 2) . ' 元。'
|
||
);
|
||
|
||
return ['balance' => $balance, 'amount' => $amount];
|
||
}
|
||
}
|