From 62804da45a47e364138d0a35befebeeee37600a3 Mon Sep 17 00:00:00 2001 From: limeng <1131177064@qq.com> Date: Fri, 18 Sep 2026 18:31:12 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=94=B6=E6=AC=BE?= =?UTF-8?q?=E8=B4=A6=E6=88=B7=E5=8D=8F=E8=AE=AE=E7=AD=BE=E7=BD=B2=E4=B8=BB?= =?UTF-8?q?=E4=BD=93=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 账户持有人姓名仅用于协议正文,账户类协议始终由快递企业签署,并要求填写匹配 E 签宝账号的实名经办人。 --- .../Business/CourierAgreementSignatures.php | 7 +- .../CourierAgreementSignatureService.php | 16 +--- .../agreement-signing.blade.php | 14 +++- .../Business/AgreementSigningPageTest.php | 2 + .../CourierAgreementSignatureWorkflowTest.php | 76 +++++++++++++++++-- 5 files changed, 91 insertions(+), 24 deletions(-) diff --git a/app/Http/Controllers/Business/CourierAgreementSignatures.php b/app/Http/Controllers/Business/CourierAgreementSignatures.php index b6e27238..0cef1868 100644 --- a/app/Http/Controllers/Business/CourierAgreementSignatures.php +++ b/app/Http/Controllers/Business/CourierAgreementSignatures.php @@ -91,7 +91,7 @@ class CourierAgreementSignatures extends Controller // signing_subject identifies our initiating company. The E-sign // organization must be the counterparty that receives this request. $data['organization_name'] = $this->counterpartyOrganizationName($data); - $data['operator_name'] = $data['operator_name'] ?? $data['courier_name']; + $data['operator_name'] = trim((string) ($data['operator_name'] ?? '')) ?: null; $data['operator_account'] = $data['esign_account']; $data['payload'] = $this->payload($data); @@ -281,7 +281,7 @@ class CourierAgreementSignatures extends Controller 'signing_deadline' => $date, 'esign_account' => ['required', 'string', 'max:255'], 'secondary_esign_account' => ['required_if:document_type,entity-change,cooperation-contract,authorization', 'nullable', 'string', 'max:255'], - 'operator_name' => ['nullable', 'string', 'max:100'], + 'operator_name' => ['required_if:document_type,account-proof,account-change', 'nullable', 'string', 'min:2', 'max:100'], 'archive_mode' => ['required', 'in:auto,manual'], 'account_proof_effective_date' => ['required_if:document_type,account-proof', 'date'], 'account_proof_account_name' => ['required_if:document_type,account-proof', 'string', 'max:255'], @@ -370,8 +370,7 @@ class CourierAgreementSignatures extends Controller private function counterpartyOrganizationName(array $data): string { return match ($data['document_type']) { - 'account-proof' => trim((string) $data['account_proof_account_name']), - 'account-change' => trim((string) $data['new_account_name']), + 'account-proof', 'account-change' => trim((string) $data['courier_name']), 'shared-contract' => trim((string) (($data['shared_courier_names'][0] ?? null) ?: ($data['shared_courier_name'] ?? $data['courier_name']))), 'entity-change' => trim((string) ($data['former_company_name'] ?? $data['courier_name'])), 'authorization' => trim((string) ($data['principal_name'] ?? $data['courier_name'])), diff --git a/app/Support/CourierAgreementSignatureService.php b/app/Support/CourierAgreementSignatureService.php index 49149f11..f17fe566 100644 --- a/app/Support/CourierAgreementSignatureService.php +++ b/app/Support/CourierAgreementSignatureService.php @@ -285,15 +285,10 @@ final class CourierAgreementSignatureService $payload = $signature->payload ?? []; if (in_array($signature->document_type, ['account-proof', 'account-change'], true)) { - $name = $signature->organization_name; - $isOrganization = $this->looksLikeOrganization($name); - return [[ - 'signer_type' => $isOrganization ? 1 : 0, - 'organization_name' => $isOrganization ? $name : null, - 'operator_name' => $isOrganization - ? ($signature->operator_name ?: $signature->courier_name) - : $name, + 'signer_type' => 1, + 'organization_name' => $signature->organization_name, + 'operator_name' => $signature->operator_name, 'operator_account' => $signature->operator_account, ]]; } @@ -352,11 +347,6 @@ final class CourierAgreementSignatureService return [$primary]; } - private function looksLikeOrganization(string $name): bool - { - return preg_match('/公司|有限公司|有限责任|企业|集团|合作社|事务所|中心|厂/u', $name) === 1; - } - private function safeTitle(string $title): string { $title = preg_replace('/[^\p{Han}\p{L}\p{N}_ -]/u', '-', $title) ?: '协议签署'; diff --git a/resources/views/business/pages/courier-payables/agreement-signing.blade.php b/resources/views/business/pages/courier-payables/agreement-signing.blade.php index 8cada51f..2ec4a024 100644 --- a/resources/views/business/pages/courier-payables/agreement-signing.blade.php +++ b/resources/views/business/pages/courier-payables/agreement-signing.blade.php @@ -1400,8 +1400,9 @@

选择快递公司后自动带出工作平台的“电子签章经办人”(dzqzjbr);如资料未维护,可手工填写对方在 E 签宝实名绑定的手机号或邮箱。

- - + + +

仅用于 E 签宝身份核验,不是收款人姓名;收款人姓名请填写在下方账户资料中。

+
+ + +

必须与对方 E 签宝企业认证名称一致;这是签署主体,不要求与银行卡持卡人姓名一致。

+
@@ -1882,6 +1887,8 @@ var subjectCodeInput = root.querySelector('[data-subject-code]'); var courierSelect = root.querySelector('[data-courier-select]'); var esignAccountInput = root.querySelector('input[name="esign_account"]'); + var accountOrganizationField = root.querySelector('[data-account-organization-field]'); + var accountOrganizationInput = root.querySelector('[data-account-organization-name]'); var operatorNameInput = root.querySelector('[data-account-operator-name]'); var operatorRequiredMark = root.querySelector('[data-account-operator-required]'); var sharedCourierList = root.querySelector('[data-shared-courier-list]'); @@ -2392,12 +2399,19 @@ var templateType = documentOption.value; var courier = fieldValue('[name="courier_name"]', '快递公司'); var companyName = fieldValue('[name="company_full_name"]', '待填写公司全称'); - var accountOperatorRequired = templateType === 'account-proof' || templateType === 'account-change'; + var accountAgreement = templateType === 'account-proof' || templateType === 'account-change'; + if (accountOrganizationField) { + accountOrganizationField.hidden = !accountAgreement; + } + if (accountOrganizationInput) { + accountOrganizationInput.disabled = !accountAgreement; + accountOrganizationInput.required = accountAgreement; + } if (operatorNameInput) { - operatorNameInput.required = accountOperatorRequired; + operatorNameInput.required = accountAgreement; } if (operatorRequiredMark) { - operatorRequiredMark.hidden = !accountOperatorRequired; + operatorRequiredMark.hidden = !accountAgreement; } activateTemplate(templateType); refreshSignerAccountLabels(templateType); @@ -2439,8 +2453,7 @@ setPreviewValue('proofAccountName', fieldValue('[name="account_proof_account_name"]', '待填写')); setPreviewValue('proofBankName', fieldValue('[name="account_proof_bank_name"]', '待填写')); setPreviewValue('proofBankAccount', fieldValue('[name="account_proof_bank_account"]', '待填写')); - var proofName = fieldValue('[name="account_proof_account_name"]', '待填写'); - setPreviewValue('proofSigner', proofName + (/(公司|有限公司|有限责任|企业|集团|合作社|事务所|中心|厂)/.test(proofName) ? ' 公司盖章' : ' 签字')); + setPreviewValue('proofSigner', '公司盖章'); } if (templateType === 'account-change') { @@ -2452,8 +2465,7 @@ setPreviewValue('newAccountName', fieldValue('[name="new_account_name"]', '待填写')); setPreviewValue('newBankName', fieldValue('[name="new_bank_name"]', '待填写')); setPreviewValue('newBankAccount', fieldValue('[name="new_bank_account"]', '待填写')); - var changeName = fieldValue('[name="new_account_name"]', '待填写'); - setPreviewValue('changeSigner', changeName + (/(公司|有限公司|有限责任|企业|集团|合作社|事务所|中心|厂)/.test(changeName) ? ' 公司盖章' : ' 签字')); + setPreviewValue('changeSigner', '公司盖章'); } if (templateType === 'entity-change') { diff --git a/tests/Feature/Business/AgreementSigningPageTest.php b/tests/Feature/Business/AgreementSigningPageTest.php index cf5778fc..0e7cb92a 100644 --- a/tests/Feature/Business/AgreementSigningPageTest.php +++ b/tests/Feature/Business/AgreementSigningPageTest.php @@ -74,8 +74,12 @@ class AgreementSigningPageTest extends FeatureTestCase ->assertSee("labels.secondary = '我方 E 签宝账号'", false) ->assertSee("labels.primary = '委托方 E 签宝账号'", false) ->assertSee("labels.secondary = '受托方 E 签宝账号'", false) + ->assertSeeText('对方签署企业全称') + ->assertSeeText('必须与对方 E 签宝企业认证名称一致') ->assertSeeText('对方 E 签宝实名认证姓名') ->assertSeeText('仅用于 E 签宝身份核验,不是收款人姓名') + ->assertSee("setPreviewValue('proofSigner', '公司盖章')", false) + ->assertSee("setPreviewValue('changeSigner', '公司盖章')", false) ->assertSeeText('合作合同统一使用我方账号 18052733960') ->assertSeeText('填写变量') ->assertSeeText('签署完成后自动归档') diff --git a/tests/Feature/Business/CourierAgreementSignatureWorkflowTest.php b/tests/Feature/Business/CourierAgreementSignatureWorkflowTest.php index 69ffeb1c..76e5d939 100644 --- a/tests/Feature/Business/CourierAgreementSignatureWorkflowTest.php +++ b/tests/Feature/Business/CourierAgreementSignatureWorkflowTest.php @@ -48,7 +48,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase $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); - $this->assertSame('新北中通', $signature->organization_name); + $this->assertSame('新北中通快递有限公司', $signature->organization_name); $this->assertSame('2026-09-21', $signature->payload['signature_date']); Storage::disk('uploads')->assertExists($signature->source_pdf_path); $this->assertSame('新北中通快递有限公司', $signature->payload['account_proof_account_name']); @@ -59,7 +59,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase } return data_get($request->data(), 'signers.0.signerType') === 1 - && data_get($request->data(), 'signers.0.orgSignerInfo.orgName') === '新北中通' + && data_get($request->data(), 'signers.0.orgSignerInfo.orgName') === '新北中通快递有限公司' && data_get($request->data(), 'signers.0.orgSignerInfo.transactorInfo.psnInfo.psnName') === '张经理'; }); @@ -88,7 +88,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase } return data_get($request->data(), 'signers.0.signerType') === 1 - && data_get($request->data(), 'signers.0.orgSignerInfo.orgName') === '新北中通' + && data_get($request->data(), 'signers.0.orgSignerInfo.orgName') === '新北中通快递有限公司' && data_get($request->data(), 'signers.0.orgSignerInfo.transactorInfo.psnInfo.psnName') === '张经理' && data_get($request->data(), 'signers.0.psnSignerInfo') === null; }); @@ -105,7 +105,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase ->assertRedirect(); $signature = CourierAgreementSignature::query()->firstOrFail(); - $this->assertSame('新北中通', $signature->organization_name); + $this->assertSame('新北中通快递有限公司', $signature->organization_name); $this->assertSame('李四', $signature->payload['new_account_name']); $this->assertSame('张经理', $signature->operator_name); @@ -115,7 +115,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase } return data_get($request->data(), 'signers.0.signerType') === 1 - && data_get($request->data(), 'signers.0.orgSignerInfo.orgName') === '新北中通' + && data_get($request->data(), 'signers.0.orgSignerInfo.orgName') === '新北中通快递有限公司' && data_get($request->data(), 'signers.0.orgSignerInfo.transactorInfo.psnInfo.psnName') === '张经理' && data_get($request->data(), 'signers.0.psnSignerInfo') === null; }); @@ -136,6 +136,21 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase Http::assertNothingSent(); } + public function test_account_change_requires_counterparty_esign_organization_name(): void + { + $this->fakeEsign(); + $payload = $this->accountChangePayload('request-missing-counterparty-organization'); + unset($payload['counterparty_organization_name']); + + $this->withExceptionHandling() + ->loginAs() + ->post(route('business.courier-agreement-signatures.store'), $payload) + ->assertSessionHasErrors('counterparty_organization_name'); + + $this->assertDatabaseCount('business_courier_agreement_signatures', 0); + Http::assertNothingSent(); + } + public function test_cooperation_contract_maps_party_variables_and_creates_two_signers(): void { $this->fakeEsign(); @@ -665,6 +680,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase 'signing_deadline' => now()->addDays(7)->toDateString(), 'esign_account' => '13800138000', 'operator_name' => '张经理', + 'counterparty_organization_name' => '新北中通快递有限公司', 'archive_mode' => 'auto', 'account_proof_effective_date' => now()->toDateString(), 'account_proof_account_name' => '新北中通快递有限公司', @@ -681,9 +697,11 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase 'document_type' => 'account-change', 'signing_subject' => $this->company->name, 'company_full_name' => $this->company->name, + 'signature_date' => '2026-09-21', 'signing_deadline' => now()->addDays(7)->toDateString(), 'esign_account' => '13800138000', 'operator_name' => '张经理', + 'counterparty_organization_name' => '新北中通快递有限公司', 'archive_mode' => 'auto', 'account_change_date' => now()->toDateString(), 'old_account_name' => '新北中通快递有限公司', -- 2.47.2