132 lines
5.0 KiB
PHP
132 lines
5.0 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit;
|
|
|
|
use App\Services\Esign\EsignConfiguration;
|
|
use PHPUnit\Framework\TestCase;
|
|
use RuntimeException;
|
|
|
|
class EsignConfigurationTest extends TestCase
|
|
{
|
|
public function test_it_normalizes_private_environment_values_without_exposing_the_secret(): void
|
|
{
|
|
$configuration = new EsignConfiguration(
|
|
environment: 'production',
|
|
baseUrl: 'https://openapi.esign.cn/',
|
|
appId: 'production-app-id',
|
|
appSecret: 'production-app-secret',
|
|
notifyUrl: 'https://example.test/integrations/esign/callback',
|
|
callbackToleranceSeconds: 900,
|
|
timeout: 20,
|
|
);
|
|
|
|
$configuration->assertReadyForApi();
|
|
|
|
$this->assertTrue($configuration->isConfigured());
|
|
$this->assertSame('https://openapi.esign.cn', $configuration->baseUrl());
|
|
$this->assertSame('production-app-id', $configuration->appId());
|
|
}
|
|
|
|
public function test_it_rejects_production_credentials_with_the_sandbox_endpoint(): void
|
|
{
|
|
$configuration = $this->configuration(baseUrl: 'https://smlopenapi.esign.cn');
|
|
|
|
$this->expectException(RuntimeException::class);
|
|
$this->expectExceptionMessage('正式环境不能使用沙箱 API 地址');
|
|
|
|
$configuration->assertReadyForApi();
|
|
}
|
|
|
|
public function test_it_rejects_sandbox_credentials_with_the_production_endpoint(): void
|
|
{
|
|
$configuration = $this->configuration(environment: 'sandbox', baseUrl: 'https://openapi.esign.cn');
|
|
|
|
$this->expectException(RuntimeException::class);
|
|
$this->expectExceptionMessage('沙箱环境不能使用正式 API 地址');
|
|
|
|
$configuration->assertReadyForApi();
|
|
}
|
|
|
|
public function test_it_requires_both_credentials_before_an_api_request(): void
|
|
{
|
|
$configuration = $this->configuration(appSecret: '');
|
|
|
|
$this->assertFalse($configuration->isConfigured());
|
|
$this->expectExceptionMessage('尚未配置 App ID 或 AppSecret');
|
|
$configuration->assertReadyForApi();
|
|
}
|
|
|
|
public function test_selected_company_overrides_the_default_initiator(): void
|
|
{
|
|
$configuration = $this->configuration(
|
|
initiatorAccounts: json_encode([
|
|
'默认企业' => ['org_id' => 'org-default', 'psn_id' => 'person-default'],
|
|
'所选企业' => ['org_id' => 'org-selected', 'psn_id' => 'person-selected'],
|
|
], JSON_THROW_ON_ERROR),
|
|
defaultInitiator: '默认企业',
|
|
);
|
|
|
|
$this->assertSame(['orgInitiator' => [
|
|
'orgId' => 'org-selected', 'transactor' => ['psnId' => 'person-selected'],
|
|
]], $configuration->signFlowInitiator('所选企业'));
|
|
$this->assertSame('org-default', $configuration->signFlowInitiator()['orgInitiator']['orgId']);
|
|
}
|
|
|
|
public function test_unconfigured_installations_keep_the_application_initiator(): void
|
|
{
|
|
$this->assertNull($this->configuration()->signFlowInitiator('旧企业'));
|
|
}
|
|
|
|
public function test_unmapped_company_cannot_silently_use_the_default_initiator(): void
|
|
{
|
|
$configuration = $this->configuration(
|
|
initiatorAccounts: '{"默认企业":{"org_id":"org-default","psn_id":"person-default"}}',
|
|
defaultInitiator: '默认企业',
|
|
);
|
|
$this->expectExceptionMessage('所选签署主体未配置完整');
|
|
$configuration->signFlowInitiator('另一企业');
|
|
}
|
|
|
|
/** @dataProvider invalidInitiatorAccounts */
|
|
public function test_invalid_initiator_configuration_prevents_new_flows(string $accounts): void
|
|
{
|
|
$configuration = $this->configuration(initiatorAccounts: $accounts, defaultInitiator: '企业');
|
|
// Historical reads still use the existing application credentials.
|
|
$configuration->assertReadyForApi();
|
|
$this->expectException(RuntimeException::class);
|
|
$configuration->signFlowInitiator('企业');
|
|
}
|
|
|
|
public static function invalidInitiatorAccounts(): array
|
|
{
|
|
return [
|
|
'invalid json' => ['{'],
|
|
'invalid type' => ['true'],
|
|
'missing transactor' => ['{"企业":{"org_id":"org-a"}}'],
|
|
'blank organization' => ['{"企业":{"org_id":" ","psn_id":"person-a"}}'],
|
|
'invalid account type' => ['{"企业":{"org_id":"org-a","psn_id":123}}'],
|
|
];
|
|
}
|
|
|
|
private function configuration(
|
|
string $environment = 'production',
|
|
string $baseUrl = 'https://openapi.esign.cn',
|
|
string $appId = 'production-app-id',
|
|
string $appSecret = 'production-app-secret',
|
|
string $initiatorAccounts = '{}',
|
|
string $defaultInitiator = '',
|
|
): EsignConfiguration {
|
|
return new EsignConfiguration(
|
|
environment: $environment,
|
|
baseUrl: $baseUrl,
|
|
appId: $appId,
|
|
appSecret: $appSecret,
|
|
notifyUrl: '',
|
|
callbackToleranceSeconds: 900,
|
|
timeout: 20,
|
|
initiatorAccounts: $initiatorAccounts,
|
|
defaultInitiator: $defaultInitiator,
|
|
);
|
|
}
|
|
}
|