fix: 缺少发起身份时拒绝按错误主体推送易签宝 (#1145)

This commit is contained in:
limeng 2026-11-13 09:57:51 +08:00
parent 8fb8d9487b
commit b4783ae528
5 changed files with 34 additions and 8 deletions

View File

@ -123,11 +123,11 @@ final class EsignConfiguration
if (! is_array($accounts)) {
throw new RuntimeException('E 签宝发起身份配置格式无效,请联系管理员。');
}
if ($accounts === [] && $this->defaultInitiator === '') {
$name = trim((string) $organizationName) ?: $this->defaultInitiator;
if ($accounts === [] && $name === '') {
return null;
}
$name = trim((string) $organizationName) ?: $this->defaultInitiator;
$account = $accounts[$name] ?? null;
if (! is_array($account) || ! is_string($account['org_id'] ?? null) || ! is_string($account['psn_id'] ?? null)
|| trim($account['org_id']) === '' || trim($account['psn_id']) === '') {

View File

@ -44,7 +44,7 @@ ESIGN_INITIATOR_ACCOUNTS='{"示例发起企业":{"org_id":"企业实名账号ID"
协议和报价确认单按页面选择的 `signing_subject` 查找对应身份;旧报价推送入口未选择主体时使用配置中的默认企业。每个企业必须单独核对认证、有效的 `org_initiate_sign` 授权及经办人的 `psn_initiate_sign` 授权,不能使用对方快递经办人的账号。真实企业和经办人 ID 只保存在私有配置中。
启用对应关系后,缺少所选企业或经办人配置时会在上传前拒绝推送,不再静默使用应用所属企业。未启用时保持应用自身发起的接入方式。配置只用于新建流程,不切换 App ID/AppSecret,历史流程的查询、回调和归档继续使用原应用。
只要页面选择了签署主体,缺少该企业或经办人配置时就会在上传前拒绝推送;即使全部发起身份配置为空,也不能静默使用应用所属企业。仅未选择主体、且未配置默认发起企业的旧接入方式继续由应用自身发起。配置只用于新建流程,不切换 App ID/AppSecret,历史流程的查询、回调和归档继续使用原应用。
e签宝要求高级版通过“关联企业”开通,生态伙伴版通过企业和经办人授权;套餐能力以e签宝实际开通结果为准。参考[指定合同发起方](https://open.esign.cn/doc/opendoc/pdf-sign3/su5g42)。

View File

@ -85,9 +85,13 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase
$this->assertSame(1, CourierAgreementSignature::query()->count());
}
public function test_missing_selected_initiator_fails_before_upload_without_unknown_status(): void
/** @dataProvider missingInitiatorConfigurations */
public function test_missing_selected_initiator_fails_before_upload_without_unknown_status(string $defaultInitiator): void
{
config(['services.esign.initiator_accounts' => '{}']);
config([
'services.esign.initiator_accounts' => '{}',
'services.esign.default_initiator' => $defaultInitiator,
]);
Http::fake();
$this->withExceptionHandling()->loginAs()
@ -102,6 +106,11 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase
$this->assertStringContainsString('所选签署主体未配置完整', $signature->last_error);
}
public static function missingInitiatorConfigurations(): array
{
return ['default configured' => ['默认企业'], 'all settings absent' => ['']];
}
public function test_authorized_business_user_can_push_without_becoming_an_administrator(): void
{
$this->user->syncRoles([Role::where('name', 'user')->firstOrFail()->id]);

View File

@ -134,8 +134,13 @@ class CourierQuoteSignatureWorkflowTest extends FeatureTestCase
});
}
public function test_unmapped_quote_initiator_stops_before_upload(): void
/** @dataProvider missingInitiatorConfigurations */
public function test_unmapped_quote_initiator_stops_before_upload(string $defaultInitiator): void
{
config([
'services.esign.initiator_accounts' => '{}',
'services.esign.default_initiator' => $defaultInitiator,
]);
$signature = $this->createPreparedSignature();
Http::fake();
@ -158,6 +163,11 @@ class CourierQuoteSignatureWorkflowTest extends FeatureTestCase
$this->assertNull($signature->fresh()->esign_sign_flow_id);
}
public static function missingInitiatorConfigurations(): array
{
return ['default configured' => ['默认企业'], 'all settings absent' => ['']];
}
public function test_tampered_source_pdf_is_not_sent(): void
{
$signature = $this->createPreparedSignature();

View File

@ -72,9 +72,16 @@ class EsignConfigurationTest extends TestCase
$this->assertSame('org-default', $configuration->signFlowInitiator()['orgInitiator']['orgId']);
}
public function test_unconfigured_installations_keep_the_application_initiator(): void
public function test_unconfigured_legacy_requests_without_a_selected_company_keep_the_application_initiator(): void
{
$this->assertNull($this->configuration()->signFlowInitiator('旧企业'));
$this->assertNull($this->configuration()->signFlowInitiator());
}
public function test_selected_company_requires_its_identity_even_without_any_initiator_configuration(): void
{
$this->expectExceptionMessage('所选签署主体未配置完整');
$this->configuration()->signFlowInitiator('所选企业');
}
public function test_unmapped_company_cannot_silently_use_the_default_initiator(): void