155 lines
7.0 KiB
PHP
155 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Business;
|
|
|
|
use App\Jobs\Business\ArchiveCourierAgreementSignature;
|
|
use App\Models\Auth\Permission;
|
|
use App\Models\Business\CourierAgreementSignature;
|
|
use Illuminate\Http\Client\Request as ClientRequest;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Queue;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Tests\Feature\FeatureTestCase;
|
|
|
|
class CourierAgreementSignatureWorkflowTest extends FeatureTestCase
|
|
{
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
Storage::fake('uploads');
|
|
config([
|
|
'services.esign.environment' => 'sandbox',
|
|
'services.esign.base_url' => 'https://smlopenapi.esign.test',
|
|
'services.esign.app_id' => 'sandbox-app-id',
|
|
'services.esign.app_secret' => 'sandbox-app-secret',
|
|
'services.esign.notify_url' => null,
|
|
]);
|
|
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
|
|
}
|
|
|
|
public function test_account_proof_uses_its_own_document_mapping_and_pushes_once(): void
|
|
{
|
|
$this->fakeEsign();
|
|
$payload = $this->accountProofPayload('request-001');
|
|
|
|
$this->loginAs()
|
|
->post(route('business.courier-agreement-signatures.store'), $payload)
|
|
->assertRedirect(route('business.pages.show', [
|
|
'section' => 'courier-payables',
|
|
'page' => 'agreement-signing',
|
|
'agreement_view' => 'tasks',
|
|
]));
|
|
|
|
$signature = CourierAgreementSignature::query()->firstOrFail();
|
|
$this->assertSame('TPL-ACCOUNT-CERT-V2', $signature->template_code);
|
|
$this->assertSame(CourierAgreementSignature::STATUS_SIGNING, $signature->status);
|
|
$this->assertSame('flow-agreement-001', $signature->esign_sign_flow_id);
|
|
Storage::disk('uploads')->assertExists($signature->source_pdf_path);
|
|
$this->assertSame('新北中通快递有限公司', $signature->payload['account_proof_account_name']);
|
|
|
|
$this->loginAs()->post(route('business.courier-agreement-signatures.store'), $payload)->assertRedirect();
|
|
Http::assertSentCount(4);
|
|
$this->assertSame(1, CourierAgreementSignature::query()->count());
|
|
}
|
|
|
|
public function test_verified_agreement_callback_is_idempotent_and_queues_archive(): void
|
|
{
|
|
Queue::fake();
|
|
$signature = CourierAgreementSignature::create([
|
|
'company_id' => $this->company->id,
|
|
'business_no' => 'AGR-CALLBACK-001',
|
|
'idempotency_key' => 'callback-001',
|
|
'document_type' => 'account-proof',
|
|
'template_code' => 'TPL-ACCOUNT-CERT-V2',
|
|
'template_version' => '2',
|
|
'source_file_name' => '收款账户证明文件.doc',
|
|
'status' => CourierAgreementSignature::STATUS_SIGNING,
|
|
'courier_name' => '新北中通',
|
|
'company_full_name' => $this->company->name,
|
|
'organization_name' => '新北中通快递有限公司',
|
|
'operator_name' => '张经理',
|
|
'operator_account' => '13800138000',
|
|
'payload' => ['company_full_name' => $this->company->name, 'courier_name' => '新北中通'],
|
|
'environment' => 'sandbox',
|
|
'source_pdf_path' => 'courier-agreements/test/source.pdf',
|
|
'source_pdf_sha256' => hash('sha256', '%PDF-source'),
|
|
'esign_file_id' => 'file-agreement-001',
|
|
'esign_sign_flow_id' => 'flow-agreement-callback',
|
|
'remote_status' => '1',
|
|
'created_by' => $this->user->id,
|
|
'updated_by' => $this->user->id,
|
|
]);
|
|
$payload = json_encode([
|
|
'action' => 'SIGN_FLOW_COMPLETE',
|
|
'signFlowId' => 'flow-agreement-callback',
|
|
'signFlowStatus' => '2',
|
|
], JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
|
|
$timestamp = (string) now()->getTimestampMs();
|
|
$callbackSignature = hash_hmac('sha256', $timestamp . '12' . $payload, 'sandbox-app-secret');
|
|
|
|
$server = [
|
|
'HTTP_X_TSIGN_OPEN_TIMESTAMP' => $timestamp,
|
|
'HTTP_X_TSIGN_OPEN_SIGNATURE_ALGORITHM' => 'HmacSHA256',
|
|
'HTTP_X_TSIGN_OPEN_APP_ID' => 'sandbox-app-id',
|
|
'HTTP_X_TSIGN_OPEN_SIGNATURE' => $callbackSignature,
|
|
'CONTENT_TYPE' => 'application/json',
|
|
];
|
|
$this->call('POST', route('integrations.esign.callback') . '?zeta=2&alpha=1', [], [], [], $server, $payload)
|
|
->assertOk();
|
|
|
|
$signature->refresh();
|
|
$this->assertSame(CourierAgreementSignature::STATUS_COMPLETED, $signature->status);
|
|
$this->assertSame(hash('sha256', $payload), $signature->callback_payload_hash);
|
|
Queue::assertPushed(ArchiveCourierAgreementSignature::class, 1);
|
|
$this->assertNull(app(\App\Support\CourierAgreementSignatureService::class)->acceptCallback(
|
|
'flow-agreement-callback', '2', hash('sha256', $payload),
|
|
));
|
|
|
|
$this->call('POST', route('integrations.esign.callback') . '?zeta=2&alpha=1', [], [], [], $server, $payload)
|
|
->assertOk();
|
|
Queue::assertPushed(ArchiveCourierAgreementSignature::class, 1);
|
|
}
|
|
|
|
private function fakeEsign(): void
|
|
{
|
|
Http::fake(function (ClientRequest $request) {
|
|
return match (true) {
|
|
$request->url() === 'https://smlopenapi.esign.test/v3/files/file-upload-url' => Http::response([
|
|
'code' => 0,
|
|
'data' => ['fileId' => 'file-agreement-001', 'fileUploadUrl' => 'https://upload.esign.test/agreement-001'],
|
|
]),
|
|
$request->url() === 'https://upload.esign.test/agreement-001' => Http::response(['ok' => true]),
|
|
$request->url() === 'https://smlopenapi.esign.test/v3/files/file-agreement-001' => Http::response([
|
|
'code' => 0,
|
|
'data' => ['status' => 2],
|
|
]),
|
|
$request->url() === 'https://smlopenapi.esign.test/v3/sign-flow/create-by-file' => Http::response([
|
|
'code' => 0,
|
|
'data' => ['signFlowId' => 'flow-agreement-001'],
|
|
]),
|
|
default => Http::response(['code' => 404], 404),
|
|
};
|
|
});
|
|
}
|
|
|
|
private function accountProofPayload(string $idempotencyKey): array
|
|
{
|
|
return [
|
|
'idempotency_key' => $idempotencyKey,
|
|
'courier_name' => '新北中通',
|
|
'document_type' => 'account-proof',
|
|
'signing_subject' => $this->company->name,
|
|
'company_full_name' => $this->company->name,
|
|
'signing_deadline' => now()->addDays(7)->toDateString(),
|
|
'esign_account' => '13800138000',
|
|
'operator_name' => '张经理',
|
|
'archive_mode' => 'auto',
|
|
'account_proof_effective_date' => now()->toDateString(),
|
|
'account_proof_account_name' => '新北中通快递有限公司',
|
|
'account_proof_bank_name' => '中国工商银行',
|
|
'account_proof_bank_account' => '6222000012345678',
|
|
];
|
|
}
|
|
}
|