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(); }); } }