fix(funds): 加固转账冲正、结算收付幂等与坏账核销
- 转入 main_site_timeout 等不可冲正场景直接拒绝,避免假结案 - payment_records / settlement_adjustments 增加 partial unique 索引 - 坏账核销行锁 + meta 幂等回放;补差单记录 result_bill_id - 新增 FundOperationsHardeningTest 覆盖关键路径
This commit is contained in:
@@ -384,6 +384,14 @@ final class LotteryTransferService
|
||||
);
|
||||
}
|
||||
|
||||
if (! $this->isEligibleForReverse($locked)) {
|
||||
throw new WalletOperationException(
|
||||
'reverse_not_eligible',
|
||||
ErrorCode::WalletExternalRejected->value,
|
||||
422,
|
||||
);
|
||||
}
|
||||
|
||||
if ($locked->direction === self::DIR_OUT) {
|
||||
$idempotentKey = 'reversal:'.$locked->transfer_no;
|
||||
$alreadyCredited = WalletTxn::query()
|
||||
@@ -566,6 +574,20 @@ final class LotteryTransferService
|
||||
&& $this->isEligibleForCompleteCredit($order);
|
||||
}
|
||||
|
||||
/** 后台冲正:转出 pending_reconcile 或转入 lottery_credit_failed 且主站已扣款。 */
|
||||
public function isEligibleForReverse(TransferOrder $order): bool
|
||||
{
|
||||
if ($order->status !== self::ST_PENDING_RECONCILE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($order->direction === self::DIR_OUT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->isEligibleForTransferInReverse($order);
|
||||
}
|
||||
|
||||
public function isEligibleForManualProcess(TransferOrder $order): bool
|
||||
{
|
||||
if (! in_array($order->status, [self::ST_PROCESSING, self::ST_FAILED, self::ST_PENDING_RECONCILE], true)) {
|
||||
|
||||
Reference in New Issue
Block a user