AuthenticatorTest.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <?php
  2. declare(strict_types=1);
  3. namespace SixShop\Wangdian\Tests\Unit\Auth;
  4. use PHPUnit\Framework\TestCase;
  5. use SixShop\Wangdian\Auth\Authenticator;
  6. use SixShop\Wangdian\Config\Config;
  7. class AuthenticatorTest extends TestCase
  8. {
  9. private Authenticator $authenticator;
  10. private Config $config;
  11. protected function setUp(): void
  12. {
  13. $this->config = new Config(
  14. sid: 'test_sid',
  15. appKey: 'test_app_key',
  16. appSecret: 'test_app_secret'
  17. );
  18. $this->authenticator = new Authenticator($this->config);
  19. }
  20. public function testGenerateSignature(): void
  21. {
  22. $params = [
  23. 'shop_no' => 'test_shop',
  24. 'trade_list' => '[{"trade_no":"123"}]'
  25. ];
  26. $signature = $this->authenticator->generateSignature($params);
  27. $this->assertIsString($signature);
  28. $this->assertEquals(32, strlen($signature)); // MD5 hash length
  29. $this->assertMatchesRegularExpression('/^[a-f0-9]{32}$/', $signature);
  30. }
  31. public function testGenerateSignatureRemovesExistingSign(): void
  32. {
  33. $params = [
  34. 'shop_no' => 'test_shop',
  35. 'sign' => 'old_signature'
  36. ];
  37. $signature1 = $this->authenticator->generateSignature($params);
  38. unset($params['sign']);
  39. $signature2 = $this->authenticator->generateSignature($params);
  40. $this->assertEquals($signature1, $signature2);
  41. }
  42. public function testGenerateSignatureConsistency(): void
  43. {
  44. $params = [
  45. 'shop_no' => 'test_shop',
  46. 'trade_list' => '[{"trade_no":"123"}]'
  47. ];
  48. $signature1 = $this->authenticator->generateSignature($params);
  49. $signature2 = $this->authenticator->generateSignature($params);
  50. // Note: signatures will be different due to timestamp, but structure should be consistent
  51. $this->assertIsString($signature1);
  52. $this->assertIsString($signature2);
  53. $this->assertEquals(32, strlen($signature1));
  54. $this->assertEquals(32, strlen($signature2));
  55. }
  56. public function testAddAuthParams(): void
  57. {
  58. $params = ['shop_no' => 'test_shop'];
  59. $authenticatedParams = $this->authenticator->addAuthParams($params);
  60. $this->assertArrayHasKey('sid', $authenticatedParams);
  61. $this->assertArrayHasKey('appkey', $authenticatedParams);
  62. $this->assertArrayHasKey('timestamp', $authenticatedParams);
  63. $this->assertArrayHasKey('sign', $authenticatedParams);
  64. $this->assertArrayHasKey('shop_no', $authenticatedParams);
  65. $this->assertEquals('test_sid', $authenticatedParams['sid']);
  66. $this->assertEquals('test_app_key', $authenticatedParams['appkey']);
  67. $this->assertEquals('test_shop', $authenticatedParams['shop_no']);
  68. $this->assertIsInt($authenticatedParams['timestamp']);
  69. $this->assertIsString($authenticatedParams['sign']);
  70. $this->assertEquals(32, strlen($authenticatedParams['sign']));
  71. }
  72. public function testAddAuthParamsOverwritesExisting(): void
  73. {
  74. $params = [
  75. 'shop_no' => 'test_shop',
  76. 'sid' => 'old_sid',
  77. 'appkey' => 'old_appkey',
  78. 'timestamp' => 123456,
  79. 'sign' => 'old_sign'
  80. ];
  81. $authenticatedParams = $this->authenticator->addAuthParams($params);
  82. $this->assertEquals('test_sid', $authenticatedParams['sid']);
  83. $this->assertEquals('test_app_key', $authenticatedParams['appkey']);
  84. $this->assertNotEquals(123456, $authenticatedParams['timestamp']);
  85. $this->assertNotEquals('old_sign', $authenticatedParams['sign']);
  86. }
  87. public function testValidateParamsSuccess(): void
  88. {
  89. $params = [
  90. 'sid' => 'test_sid',
  91. 'appkey' => 'test_app_key',
  92. 'timestamp' => time()
  93. ];
  94. // Should not throw exception
  95. $this->authenticator->validateParams($params);
  96. $this->assertTrue(true); // Assert that we reach this point
  97. }
  98. public function testValidateParamsMissingSid(): void
  99. {
  100. $params = [
  101. 'appkey' => 'test_app_key',
  102. 'timestamp' => time()
  103. ];
  104. $this->expectException(\InvalidArgumentException::class);
  105. $this->expectExceptionMessage('Missing required parameter: sid');
  106. $this->authenticator->validateParams($params);
  107. }
  108. public function testValidateParamsMissingAppkey(): void
  109. {
  110. $params = [
  111. 'sid' => 'test_sid',
  112. 'timestamp' => time()
  113. ];
  114. $this->expectException(\InvalidArgumentException::class);
  115. $this->expectExceptionMessage('Missing required parameter: appkey');
  116. $this->authenticator->validateParams($params);
  117. }
  118. public function testValidateParamsMissingTimestamp(): void
  119. {
  120. $params = [
  121. 'sid' => 'test_sid',
  122. 'appkey' => 'test_app_key'
  123. ];
  124. $this->expectException(\InvalidArgumentException::class);
  125. $this->expectExceptionMessage('Missing required parameter: timestamp');
  126. $this->authenticator->validateParams($params);
  127. }
  128. public function testValidateParamsEmptyValues(): void
  129. {
  130. $params = [
  131. 'sid' => '',
  132. 'appkey' => 'test_app_key',
  133. 'timestamp' => time()
  134. ];
  135. $this->expectException(\InvalidArgumentException::class);
  136. $this->expectExceptionMessage('Missing required parameter: sid');
  137. $this->authenticator->validateParams($params);
  138. }
  139. public function testPackDataFormat(): void
  140. {
  141. // Test the pack data format by using reflection to access private method
  142. $reflection = new \ReflectionClass($this->authenticator);
  143. $packDataMethod = $reflection->getMethod('packData');
  144. $packDataMethod->setAccessible(true);
  145. $params = [
  146. 'b' => 'second',
  147. 'a' => 'first'
  148. ];
  149. $packed = $packDataMethod->invoke($this->authenticator, $params);
  150. // Should be sorted by key: a first, then b
  151. // Format: length-key:length-value;length-key:length-value
  152. $expected = '01-a:0005-first;01-b:0006-second';
  153. $this->assertEquals($expected, $packed);
  154. }
  155. public function testPackDataWithUtf8(): void
  156. {
  157. $reflection = new \ReflectionClass($this->authenticator);
  158. $packDataMethod = $reflection->getMethod('packData');
  159. $packDataMethod->setAccessible(true);
  160. $params = [
  161. 'name' => '测试'
  162. ];
  163. $packed = $packDataMethod->invoke($this->authenticator, $params);
  164. // UTF-8 characters should be properly counted
  165. $expected = '04-name:0002-测试';
  166. $this->assertEquals($expected, $packed);
  167. }
  168. public function testPackDataSkipsSignParameter(): void
  169. {
  170. $reflection = new \ReflectionClass($this->authenticator);
  171. $packDataMethod = $reflection->getMethod('packData');
  172. $packDataMethod->setAccessible(true);
  173. $params = [
  174. 'a' => 'value',
  175. 'sign' => 'should_be_ignored'
  176. ];
  177. $packed = $packDataMethod->invoke($this->authenticator, $params);
  178. $expected = '01-a:0005-value';
  179. $this->assertEquals($expected, $packed);
  180. }
  181. }