```
feat(commission): 添加分账成功后佣金处理功能 添加了新的方法来处理分账成功后的佣金结算: - 新增 runCommissionRewardByOrderWithoutWallet 方法用于分账成功时标记已结算 - 新增 runCommissionRewardWithoutWallet 方法处理不入余额的佣金奖励 - 避免在分账成功时重复将佣金计入用户余额 feat(regional_agent): 添加区域代理分账处理逻辑 - 新增 settleByRegionalOrderWithoutWallet 方法处理区域代理分账 - 新增 settleRewardWithoutWallet 方法处理不入钱包的奖励结算 - 完善区域代理佣金处理流程 refactor(split): 优化分账执行器逻辑 - 修改 SplitExecutor 类以支持延迟钱包结算 - 添加异常处理和事务管理 - 支持根据支付网关类型决定是否延迟钱包结算 feat(split): 实现分账完成后钱包结算机制 - 添加 SplitWalletSettlement 类来管理分账与钱包结算的协调 - 支持在分账成功后延迟钱包入账,失败时回退到钱包 - 修复汇付分账与佣金结算的时间冲突问题 refactor(hook): 调整分账钩子事件处理 - 修改 SplitHook 类的事件参数传递 - 更新各个订单状态变更事件的分账触发逻辑 - 确保分账执行时能正确获取事件类型 docs(tests): 更新分账佣金验证说明 - 更新测试文件中的注释说明 - 明确汇付/微信分账成功后的佣金处理方式 ```
这个提交包含在:
@@ -22,93 +22,106 @@ class SplitExecutor
|
||||
|
||||
public function executeByOrderId($orderId, $event = 'payed')
|
||||
{
|
||||
if (!$this->config->isEnable()) {
|
||||
return false;
|
||||
}
|
||||
$order = Order::get($orderId);
|
||||
$deferWallet = $order && SplitWalletSettlement::shouldDeferForGatewaySplit($order, $event);
|
||||
$ok = false;
|
||||
|
||||
if (class_exists('\\addons\\shopro_huifu\\library\\Bridge')) {
|
||||
$hookParams = [
|
||||
'order_id' => $orderId,
|
||||
'event' => $event,
|
||||
];
|
||||
$handled = \think\Hook::listen('shopro_split_execute', $hookParams, null, true);
|
||||
if ($handled === true) {
|
||||
try {
|
||||
if (!$this->config->isEnable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (class_exists('\\addons\\shopro_huifu\\library\\Bridge')) {
|
||||
$hookParams = [
|
||||
'order_id' => $orderId,
|
||||
'event' => $event,
|
||||
];
|
||||
$handled = \think\Hook::listen('shopro_split_execute', $hookParams, null, true);
|
||||
if ($handled === true) {
|
||||
$ok = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$orderCheck = Order::get($orderId);
|
||||
if ($orderCheck && $orderCheck['pay_type'] === 'huifu_wechat') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$exists = SplitOrder::where('order_id', $orderId)->where('status', 'in', [1, 2])->find();
|
||||
if ($exists) {
|
||||
$ok = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$orderCheck = Order::get($orderId);
|
||||
if ($orderCheck && $orderCheck['pay_type'] === 'huifu_wechat') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$exists = SplitOrder::where('order_id', $orderId)->where('status', 'in', [1, 2])->find();
|
||||
if ($exists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$order = Order::get($orderId);
|
||||
if (!$order || empty($order['transaction_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$items = $this->calculator->calculate($orderId);
|
||||
if (empty($items)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$outOrderNo = 'PS' . date('YmdHis') . $orderId;
|
||||
$splitAmount = array_sum(array_column($items, 'amount'));
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$splitOrder = SplitOrder::create([
|
||||
'order_id' => $orderId,
|
||||
'order_sn' => $order['order_sn'],
|
||||
'transaction_id' => $order['transaction_id'],
|
||||
'out_order_no' => $outOrderNo,
|
||||
'total_amount' => $order['pay_fee'],
|
||||
'split_amount' => $splitAmount,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
$receivers = [];
|
||||
foreach ($items as $item) {
|
||||
SplitOrderReceiver::create([
|
||||
'split_order_id' => $splitOrder->id,
|
||||
'receiver_id' => $item['receiver_id'],
|
||||
'role_type' => $item['role_type'],
|
||||
'amount' => $item['amount'],
|
||||
'description' => $item['description'],
|
||||
'status' => 0,
|
||||
]);
|
||||
$receivers[] = [
|
||||
'type' => $item['receiver_type'],
|
||||
'account' => $item['receiver_account'],
|
||||
'name' => $item['receiver_name'] ?? '',
|
||||
'amount' => intval(round($item['amount'] * 100)),
|
||||
'description' => $item['description'],
|
||||
];
|
||||
$order = Order::get($orderId);
|
||||
if (!$order || empty($order['transaction_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $this->service->createOrder([
|
||||
'transaction_id' => $order['transaction_id'],
|
||||
'out_order_no' => $outOrderNo,
|
||||
'receivers' => $receivers,
|
||||
'unfreeze_unsplit' => true,
|
||||
]);
|
||||
$items = $this->calculator->calculate($orderId);
|
||||
if (empty($items)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$splitOrder->wx_result = is_array($result) ? json_encode($result, JSON_UNESCAPED_UNICODE) : json_encode($result);
|
||||
$splitOrder->status = 2;
|
||||
$splitOrder->save();
|
||||
$outOrderNo = 'PS' . date('YmdHis') . $orderId;
|
||||
$splitAmount = array_sum(array_column($items, 'amount'));
|
||||
|
||||
SplitOrderReceiver::where('split_order_id', $splitOrder->id)->update(['status' => 1]);
|
||||
Db::commit();
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
$this->markFailed($orderId, $outOrderNo ?? ('PS' . $orderId), $order, $items ?? [], $e->getMessage());
|
||||
return false;
|
||||
Db::startTrans();
|
||||
try {
|
||||
$splitOrder = SplitOrder::create([
|
||||
'order_id' => $orderId,
|
||||
'order_sn' => $order['order_sn'],
|
||||
'transaction_id' => $order['transaction_id'],
|
||||
'out_order_no' => $outOrderNo,
|
||||
'total_amount' => $order['pay_fee'],
|
||||
'split_amount' => $splitAmount,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
$receivers = [];
|
||||
foreach ($items as $item) {
|
||||
SplitOrderReceiver::create([
|
||||
'split_order_id' => $splitOrder->id,
|
||||
'receiver_id' => $item['receiver_id'],
|
||||
'role_type' => $item['role_type'],
|
||||
'amount' => $item['amount'],
|
||||
'description' => $item['description'],
|
||||
'status' => 0,
|
||||
]);
|
||||
$receivers[] = [
|
||||
'type' => $item['receiver_type'],
|
||||
'account' => $item['receiver_account'],
|
||||
'name' => $item['receiver_name'] ?? '',
|
||||
'amount' => intval(round($item['amount'] * 100)),
|
||||
'description' => $item['description'],
|
||||
];
|
||||
}
|
||||
|
||||
$result = $this->service->createOrder([
|
||||
'transaction_id' => $order['transaction_id'],
|
||||
'out_order_no' => $outOrderNo,
|
||||
'receivers' => $receivers,
|
||||
'unfreeze_unsplit' => true,
|
||||
]);
|
||||
|
||||
$splitOrder->wx_result = is_array($result) ? json_encode($result, JSON_UNESCAPED_UNICODE) : json_encode($result);
|
||||
$splitOrder->status = 2;
|
||||
$splitOrder->save();
|
||||
|
||||
SplitOrderReceiver::where('split_order_id', $splitOrder->id)->update(['status' => 1]);
|
||||
Db::commit();
|
||||
$ok = true;
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
$this->markFailed($orderId, $outOrderNo ?? ('PS' . $orderId), $order, $items ?? [], $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
if ($deferWallet) {
|
||||
SplitWalletSettlement::finalizeAfterSplitAttempt($orderId, $event, $ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户