CaiWuXiTong/tests/Unit/EsignConfigurationTest.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,
);
}
}