feat: 收益全额直入商城余额、存量结转与奖项名称全局规范化对齐

这个提交包含在:
chen
2026-09-19 11:49:57 +08:00
父节点 85947e43ae
当前提交 aca0d3c671
共有 83 个文件被更改,包括 4146 次插入 和 443 次删除

查看文件

@@ -36,7 +36,7 @@ class Pay extends Common
$payment = $this->request->post('payment');
$openid = $this->request->post('openid', '');
$money = $this->request->post('money', 0);
$money = $money > 0 ? $money : 0;
$money = floatval($money) > 0 ? round(floatval($money), 2) : 0;
$platform = $this->request->header('platform');
list($order, $order_type) = $this->getOrderInstance($order_sn);
@@ -65,30 +65,62 @@ class Pay extends Common
// pay 实例
$payOper = new PayOper();
if ($money && $order_type == 'order') {
// 余额混合支付
$order = Db::transaction(function () use ($payOper, $order, $order_type, $money) {
$mixedPayRecord = null;
if ($money > 0 && $order_type == 'order') {
// 余额混合支付(行锁串行化保障并发资金安全)
$order = Db::transaction(function () use ($order, $order_type, $money, $user, &$mixedPayRecord) {
// 加锁读订单
$order = $order->lock(true)->find($order->id);
if (in_array($order->status, [$order::STATUS_PAID, $order::STATUS_COMPLETED])) {
$this->error('订单已支付');
}
// 余额支付
$order = $payOper->money($order, $money, $order_type);
// 事务内行级排他锁查验用户最新可用余额,杜绝并发快照双花
$lockedUser = \app\admin\model\shopro\user\User::where('id', $user->id)->lock(true)->find();
if (bccomp((string)$money, (string)$lockedUser->money, 2) === 1) {
$this->error('账户可用余额不足以进行本次抵扣');
}
$deductMoney = min($money, floatval($order->remain_pay_fee));
if ($deductMoney <= 0) {
return $order;
}
// 使用锁定的实时用户对象执行余额扣减
$lockedPayOper = new PayOper($lockedUser);
$order = $lockedPayOper->money($order, $deductMoney, $order_type);
return $order;
});
// 获取刚才产生的余额支付记录,用于异常情况冲正
$mixedPayRecord = PayModel::where('order_id', $order->id)
->where('order_type', $order_type)
->where('pay_type', 'money')
->order('id', 'desc')
->find();
if (in_array($order->status, [$order::STATUS_PAID, $order::STATUS_COMPLETED])) {
$this->success('订单支付成功', $order);
}
}
if ($payment == 'money' && $order_type == 'order') {
// 余额支付
$order = Db::transaction(function () use ($payOper, $order, $order_type) {
// 纯余额支付
$order = Db::transaction(function () use ($order, $order_type, $user) {
// 加锁读订单
$order = $order->lock(true)->find($order->id);
if (in_array($order->status, [$order::STATUS_PAID, $order::STATUS_COMPLETED])) {
$this->error('订单已支付');
}
$order = $payOper->money($order, $order->remain_pay_fee, $order_type);
$lockedUser = \app\admin\model\shopro\user\User::where('id', $user->id)->lock(true)->find();
if (bccomp((string)$order->remain_pay_fee, (string)$lockedUser->money, 2) === 1) {
$this->error('账户可用余额不足以付清该订单');
}
$lockedPayOper = new PayOper($lockedUser);
$order = $lockedPayOper->money($order, $order->remain_pay_fee, $order_type);
return $order;
});
@@ -146,7 +178,10 @@ class Pay extends Common
}
if (empty($order_data['payer']['openid'])) {
// 缺少 openid
// 缺少 openid 时,若前面预扣了余额则冲正
if ($mixedPayRecord) {
$this->rollbackMixedMoney($order, $mixedPayRecord, $user, $order_type);
}
$this->error('miss_openid', -1);
}
}
@@ -160,11 +195,18 @@ class Pay extends Common
try {
$result = $payService->pay($order_data);
} catch (\Yansongda\Pay\Exception\Exception $e) {
$this->error('支付失败' . (config('app_debug') ? ":" . $e->getMessage() : ',请重试'));
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
} catch (\Exception $e) {
// 第三方预支付异常,安全冲正本次混合支付预扣款
if ($mixedPayRecord) {
$this->rollbackMixedMoney($order, $mixedPayRecord, $user, $order_type);
}
if ($e instanceof HttpResponseException) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
} else {
$message = $e->getMessage();
}
$this->error('支付失败' . (config('app_debug') ? ":" . $message : ',请重试'));
}
@@ -183,6 +225,39 @@ class Pay extends Common
]);
}
/**
* 混合支付预下单异常时,冲正退回预扣余额
*
* @param \think\Model $order
* @param \think\Model $mixedPayRecord
* @param \think\Model $user
* @param string $order_type
* @return void
*/
protected function rollbackMixedMoney($order, $mixedPayRecord, $user, $order_type)
{
try {
Db::transaction(function () use ($order, $mixedPayRecord, $user, $order_type) {
\addons\shopro\service\Wallet::change($user, 'money', $mixedPayRecord->pay_fee, 'order_refund', [
'order_id' => $order->id,
'order_sn' => $order->order_sn,
'order_type' => $order_type,
'remark' => '混合支付预下单未完成,安全冲正退回'
]);
$mixedPayRecord->status = PayModel::PAY_STATUS_REFUND;
$mixedPayRecord->refund_fee = $mixedPayRecord->pay_fee;
$mixedPayRecord->save();
$order = $order->lock(true)->find($order->id);
$order->remain_pay_fee = bcadd((string)$order->remain_pay_fee, (string)$mixedPayRecord->pay_fee, 2);
$order->save();
});
} catch (\Exception $e) {
Log::write('混合支付预扣款冲正异常: ' . $e->getMessage(), 'error');
}
}
/**