You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
3.5 KiB

<?php
namespace App\Services;
use App\Models\Company;
use App\Models\CompanyQccAccount;
use Illuminate\Support\Facades\DB;
use RuntimeException;
use Throwable;
/**
* 所有企查查(或经元禾穿透)调用的统一状态入口。
* 实际调用由 $operation 传入;调用方必须区分明确成功、明确失败与结果不确定。
*/
class QccCallService
{
public function call(
Company $company,
string $source,
string $requestRef,
callable $operation,
callable $isSuccess,
?callable $isIndeterminate = null
)
{
$account = CompanyQccAccount::query()->where('company_id', $company->id)->first();
if (!$account) {
throw new RuntimeException('企业未纳入企查查企业户候选池');
}
if (!$account->isCallable()) {
throw new RuntimeException('企业户状态待人工确认,暂不能发起调用');
}
try {
$result = $operation();
} catch (Throwable $exception) {
$this->markUnknownWhenSelected($company->id, $exception->getMessage());
throw $exception;
}
try {
if ($isSuccess($result)) {
$this->recordSuccess($company->id, $source, $requestRef);
} elseif ($isIndeterminate) {
$indeterminate = $isIndeterminate($result);
if ($indeterminate) {
$reason = is_string($indeterminate) ? $indeterminate : '调用结果无法确认';
$this->markUnknownWhenSelected($company->id, $reason);
}
}
} catch (Throwable $exception) {
$this->markUnknownWhenSelected($company->id, '调用结果判定异常:' . $exception->getMessage());
throw $exception;
}
return $result;
}
public function recordSuccess(int $companyId, string $source, string $requestRef): CompanyQccAccount
{
return DB::transaction(function () use ($companyId, $source, $requestRef) {
$account = CompanyQccAccount::query()->where('company_id', $companyId)->lockForUpdate()->first();
if (!$account) {
throw new RuntimeException('企业未纳入企查查企业户候选池');
}
if ($account->status === CompanyQccAccount::STATUS_UNKNOWN) {
throw new RuntimeException('企业户状态待人工确认,不能确认调用成功');
}
if ($account->status === CompanyQccAccount::STATUS_SELECTED) {
$account->update([
'status' => CompanyQccAccount::STATUS_OCCUPIED,
'first_success_at' => now(),
'first_success_source' => $source,
'first_success_ref' => $requestRef,
'unknown_note' => null,
]);
}
return $account->fresh();
});
}
public function markUnknownWhenSelected(int $companyId, string $reason): ?CompanyQccAccount
{
return DB::transaction(function () use ($companyId, $reason) {
$account = CompanyQccAccount::query()->where('company_id', $companyId)->lockForUpdate()->first();
if (!$account || $account->status !== CompanyQccAccount::STATUS_SELECTED) {
return $account;
}
$account->update([
'status' => CompanyQccAccount::STATUS_UNKNOWN,
'unknown_note' => mb_substr($reason, 0, 2000),
]);
return $account->fresh();
});
}
}