feat(shopro_huifu): 添加汇付进件自动提交功能 - 新增自动提交开关配置项,支持定时自动提交汇付进件 - 添加失败重提间隔配置,支持失败后指定时间自动重试 - 创建OnboardAutoSubmit命令类,实现自动提交逻辑 - 在进件页面更新提示信息,说明自动提交流程 - 同步更新数据库配置表结构和升级脚本 ```
147 行
4.5 KiB
PHP
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);
|
|
}
|
|
}
|