文件
xionggeshop/addons/shopro_huifu/library/onboard/HuifuOnboardAutoSubmit.php
可乐加冰 fa8d57693b ```
feat(shopro_huifu): 添加汇付进件自动提交功能

- 新增自动提交开关配置项,支持定时自动提交汇付进件
- 添加失败重提间隔配置,支持失败后指定时间自动重试
- 创建OnboardAutoSubmit命令类,实现自动提交逻辑
- 在进件页面更新提示信息,说明自动提交流程
- 同步更新数据库配置表结构和升级脚本
```
2026-10-08 13:40:52 +08:00

147 行
4.5 KiB
PHP

<?php
namespace addons\shopro_huifu\library\onboard;
use addons\shopro_huifu\library\HuifuConfig;
use addons\shopro_huifu\model\Onboard;
use think\Log;
/**
* 汇付进件后台自动提交:业务已通过且从未提交汇付的立即提交;失败/驳回满冷却期后重提。
*/
class HuifuOnboardAutoSubmit
{
public function run($limit = 30, $dryRun = false)
{
$stats = [
'scanned' => 0,
'submit_now' => 0,
'retry' => 0,
'skipped' => 0,
'failed' => 0,
'details' => [],
];
if (!HuifuOnboardGate::isOnboardRequired()) {
$stats['details'][] = 'skip: 汇付进件未启用';
return $stats;
}
if (!$this->isAutoSubmitEnabled()) {
$stats['details'][] = 'skip: onboard_auto_submit=0';
return $stats;
}
$limit = max(1, min(100, (int) $limit));
$retryAfter = $this->getRetryAfterSeconds();
$service = new HuifuOnboardService();
$now = time();
$rows = Onboard::where('onboard_status', 'in', [
Onboard::STATUS_DRAFT,
Onboard::STATUS_FAILED,
Onboard::STATUS_REJECTED,
])->order('id asc')->limit($limit * 3)->select();
foreach ($rows as $row) {
if ($stats['submit_now'] + $stats['retry'] >= $limit) {
break;
}
$stats['scanned']++;
$data = $row->toArray();
$action = $this->resolveAction($data, $now, $retryAfter);
if ($action === null) {
$stats['skipped']++;
continue;
}
$payload = json_decode($row['payload'] ?? '', true);
if (!$payload || !is_array($payload)) {
$stats['skipped']++;
$stats['details'][] = 'id=' . $row['id'] . ' skip: 无进件资料 payload';
continue;
}
$line = 'id=' . $row['id'] . ' uid=' . $row['user_id'] . ' ' . $row['role_type']
. ' action=' . $action;
if ($dryRun) {
$stats[$action === 'submit_now' ? 'submit_now' : 'retry']++;
$stats['details'][] = $line . ' (dry-run)';
continue;
}
try {
if ($action === 'submit_now') {
$service->submitFromDraft($row['user_id'], $row['role_type'], $row['role_ref_id']);
$stats['submit_now']++;
} else {
$service->resubmit($row['user_id'], $row['role_type'], $row['role_ref_id'], $payload);
$stats['retry']++;
}
$stats['details'][] = $line . ' ok';
} catch (\Throwable $e) {
$stats['failed']++;
$msg = HuifuOnboardError::translate($e->getMessage());
Log::error('[shopro_huifu] onboard auto-submit fail ' . $line . ' ' . $e->getMessage());
$stats['details'][] = $line . ' fail: ' . $msg;
}
}
return $stats;
}
/**
* @return string|null submit_now|retry
*/
protected function resolveAction(array $data, $now, $retryAfter)
{
if (!HuifuOnboardAdminView::isBusinessApproved($data)) {
return null;
}
$status = (string) ($data['onboard_status'] ?? '');
$updatedAt = intval($data['updatetime'] ?? 0);
if ($status === Onboard::STATUS_DRAFT) {
if ($this->hasSubmittedToHuifu($data)) {
return null;
}
return 'submit_now';
}
if (in_array($status, [Onboard::STATUS_FAILED, Onboard::STATUS_REJECTED], true)) {
if ($updatedAt <= 0 || ($now - $updatedAt) < $retryAfter) {
return null;
}
return 'retry';
}
return null;
}
protected function hasSubmittedToHuifu(array $data)
{
if (!empty($data['basic_req_seq_id']) || !empty($data['busi_req_seq_id'])) {
return true;
}
if (!empty($data['huifu_id'])) {
return true;
}
return false;
}
protected function isAutoSubmitEnabled()
{
return HuifuConfig::getInstance()->get('onboard_auto_submit', '1') !== '0';
}
protected function getRetryAfterSeconds()
{
$hours = (float) HuifuConfig::getInstance()->get('onboard_auto_retry_hours', '24');
if ($hours <= 0) {
$hours = 24;
}
return (int) round($hours * 3600);
}
}