188 lines
7.1 KiB
PHP
188 lines
7.1 KiB
PHP
<?php
|
||
|
||
namespace Tests\Feature\Console;
|
||
|
||
use App\Models\Business\CourierAgreementSignature;
|
||
use App\Models\Business\CourierQuoteSignature;
|
||
use Illuminate\Support\Facades\Http;
|
||
use Tests\Feature\FeatureTestCase;
|
||
|
||
class PollEsignSignaturesTest extends FeatureTestCase
|
||
{
|
||
protected function setUp(): void
|
||
{
|
||
parent::setUp();
|
||
|
||
config([
|
||
'services.esign.environment' => 'production',
|
||
'services.esign.base_url' => 'https://openapi.esign.test',
|
||
'services.esign.app_id' => 'production-app-id',
|
||
'services.esign.app_secret' => 'production-app-secret',
|
||
'services.esign.notify_url' => null,
|
||
'services.esign.polling_enabled' => true,
|
||
]);
|
||
}
|
||
|
||
public function test_it_polls_only_due_non_terminal_flows_without_a_callback(): void
|
||
{
|
||
$quote = $this->quoteSignature([
|
||
'status' => CourierQuoteSignature::STATUS_SIGNING,
|
||
'esign_sign_flow_id' => 'quote-flow-due',
|
||
'last_synced_at' => now()->subMinutes(5),
|
||
]);
|
||
$this->quoteSignature([
|
||
'status' => CourierQuoteSignature::STATUS_ARCHIVED,
|
||
'esign_sign_flow_id' => 'quote-flow-archived',
|
||
'last_synced_at' => now()->subMinutes(5),
|
||
]);
|
||
$agreement = $this->agreementSignature([
|
||
'status' => CourierAgreementSignature::STATUS_UNKNOWN,
|
||
'esign_sign_flow_id' => 'agreement-flow-due',
|
||
'last_synced_at' => null,
|
||
]);
|
||
$this->agreementSignature([
|
||
'status' => CourierAgreementSignature::STATUS_SIGNING,
|
||
'esign_sign_flow_id' => 'agreement-flow-recent',
|
||
'last_synced_at' => now(),
|
||
]);
|
||
|
||
Http::fake([
|
||
'https://openapi.esign.test/v3/sign-flow/*/detail' => Http::response([
|
||
'code' => 0,
|
||
'data' => ['signFlowStatus' => 1],
|
||
]),
|
||
]);
|
||
|
||
$this->artisan('esign:poll-signatures', ['--limit' => 10, '--min-age' => 120])
|
||
->expectsOutputToContain('候选 2,成功 2,失败 0')
|
||
->assertSuccessful();
|
||
|
||
Http::assertSentCount(2);
|
||
$this->assertNotNull($quote->fresh()->last_synced_at);
|
||
$this->assertNotNull($agreement->fresh()->last_synced_at);
|
||
}
|
||
|
||
public function test_it_skips_polling_until_the_private_switch_is_enabled(): void
|
||
{
|
||
config(['services.esign.polling_enabled' => false]);
|
||
Http::preventStrayRequests();
|
||
|
||
$this->artisan('esign:poll-signatures')
|
||
->expectsOutputToContain('定时轮询未启用')
|
||
->assertSuccessful();
|
||
|
||
Http::assertNothingSent();
|
||
}
|
||
|
||
public function test_it_does_not_poll_flows_created_in_another_environment(): void
|
||
{
|
||
$this->quoteSignature([
|
||
'environment' => 'sandbox',
|
||
'esign_sign_flow_id' => 'sandbox-quote-flow',
|
||
'last_synced_at' => now()->subMinutes(5),
|
||
]);
|
||
$this->agreementSignature([
|
||
'environment' => 'sandbox',
|
||
'esign_sign_flow_id' => 'sandbox-agreement-flow',
|
||
'last_synced_at' => now()->subMinutes(5),
|
||
]);
|
||
Http::preventStrayRequests();
|
||
|
||
$this->artisan('esign:poll-signatures', ['--limit' => 10, '--min-age' => 0])
|
||
->expectsOutputToContain('候选 0,成功 0,失败 0')
|
||
->assertSuccessful();
|
||
|
||
Http::assertNothingSent();
|
||
}
|
||
|
||
public function test_it_limits_the_total_number_of_remote_queries_per_run(): void
|
||
{
|
||
$this->agreementSignature([
|
||
'esign_sign_flow_id' => 'agreement-flow-first',
|
||
'last_synced_at' => now()->subMinutes(10),
|
||
]);
|
||
$this->agreementSignature([
|
||
'esign_sign_flow_id' => 'agreement-flow-second',
|
||
'last_synced_at' => now()->subMinutes(5),
|
||
]);
|
||
Http::fake([
|
||
'https://openapi.esign.test/v3/sign-flow/*/detail' => Http::response([
|
||
'code' => 0,
|
||
'data' => ['signFlowStatus' => 1],
|
||
]),
|
||
]);
|
||
|
||
$this->artisan('esign:poll-signatures', ['--limit' => 1, '--min-age' => 0])
|
||
->expectsOutputToContain('候选 1,成功 1,失败 0')
|
||
->assertSuccessful();
|
||
|
||
Http::assertSentCount(1);
|
||
}
|
||
|
||
public function test_it_continues_after_one_remote_query_fails(): void
|
||
{
|
||
$failed = $this->agreementSignature([
|
||
'esign_sign_flow_id' => 'agreement-flow-failed',
|
||
'last_synced_at' => now()->subMinutes(10),
|
||
]);
|
||
$succeeded = $this->agreementSignature([
|
||
'esign_sign_flow_id' => 'agreement-flow-succeeded',
|
||
'last_synced_at' => now()->subMinutes(5),
|
||
]);
|
||
Http::fake(fn ($request) => str_contains($request->url(), 'agreement-flow-failed')
|
||
? Http::response(['code' => 500, 'message' => 'temporary failure'], 503)
|
||
: Http::response(['code' => 0, 'data' => ['signFlowStatus' => 1]]));
|
||
|
||
$this->artisan('esign:poll-signatures', ['--limit' => 10, '--min-age' => 0])
|
||
->expectsOutputToContain('候选 2,成功 1,失败 1')
|
||
->assertFailed();
|
||
|
||
Http::assertSentCount(2);
|
||
$this->assertNotNull($failed->fresh()->last_error);
|
||
$this->assertNotNull($succeeded->fresh()->last_synced_at);
|
||
}
|
||
|
||
private function quoteSignature(array $overrides = []): CourierQuoteSignature
|
||
{
|
||
return CourierQuoteSignature::create(array_merge([
|
||
'company_id' => $this->company->id,
|
||
'quote_version_id' => random_int(1000, 999999),
|
||
'provider' => 'esign',
|
||
'environment' => 'production',
|
||
'status' => CourierQuoteSignature::STATUS_SIGNING,
|
||
'organization_name' => '测试快递公司',
|
||
'source_pdf_path' => 'quotes/source.pdf',
|
||
'source_pdf_sha256' => str_repeat('a', 64),
|
||
'source_pdf_generated_at' => now(),
|
||
'created_by' => $this->user->id,
|
||
'updated_by' => $this->user->id,
|
||
], $overrides));
|
||
}
|
||
|
||
private function agreementSignature(array $overrides = []): CourierAgreementSignature
|
||
{
|
||
$sequence = CourierAgreementSignature::count() + 1;
|
||
|
||
return CourierAgreementSignature::create(array_merge([
|
||
'company_id' => $this->company->id,
|
||
'business_no' => 'ESIGN-POLL-' . $sequence,
|
||
'idempotency_key' => 'esign-poll-' . $sequence,
|
||
'document_type' => 'account-proof',
|
||
'template_code' => 'TPL-ACCOUNT-CERT-V2',
|
||
'template_version' => '2',
|
||
'source_file_name' => 'account-proof.doc',
|
||
'status' => CourierAgreementSignature::STATUS_SIGNING,
|
||
'courier_name' => '测试快递',
|
||
'company_full_name' => '测试公司',
|
||
'organization_name' => '测试快递公司',
|
||
'operator_account' => '13800138000',
|
||
'payload' => ['archive_mode' => 'auto'],
|
||
'environment' => 'production',
|
||
'source_pdf_path' => 'agreements/source.pdf',
|
||
'source_pdf_sha256' => str_repeat('b', 64),
|
||
'created_by' => $this->user->id,
|
||
'updated_by' => $this->user->id,
|
||
], $overrides));
|
||
}
|
||
}
|