4
4
5
5
use Mockery as m ;
6
6
use Overtrue \Socialite \Exceptions \AuthorizeFailedException ;
7
+ use Overtrue \Socialite \Exceptions \BadRequestException ;
8
+ use Overtrue \Socialite \Exceptions \InvalidArgumentException ;
7
9
use Overtrue \Socialite \Providers \Alipay ;
8
10
use PHPUnit \Framework \TestCase ;
11
+ use ReflectionMethod ;
9
12
10
13
class AlipayTest extends TestCase
11
14
{
12
- public function testThrowsExceptionWhenTokenResponseMissing ()
15
+ public function testAlipayProviderHasCorrectRedirectResponse ()
13
16
{
14
17
$ provider = new Alipay ([
15
18
'client_id ' => 'client_id ' ,
16
- 'private_key ' => 'private_key ' ,
19
+ 'rsa_private_key ' => 'private_key ' ,
20
+ 'redirect_url ' => 'http://localhost/callback ' ,
21
+ ]);
22
+
23
+ $ response = $ provider ->redirect ();
24
+
25
+ $ this ->assertStringStartsWith ('https://openauth.alipay.com/oauth2/publicAppAuthorize.htm ' , $ response );
26
+ $ this ->assertStringContains ('redirect_uri=http%3A%2F%2Flocalhost%2Fcallback ' , $ response );
27
+ $ this ->assertStringContains ('app_id=client_id ' , $ response );
28
+ $ this ->assertStringContains ('scope=auth_user ' , $ response );
29
+ }
30
+
31
+ public function testAlipayProviderSandboxMode ()
32
+ {
33
+ $ provider = new Alipay ([
34
+ 'client_id ' => 'client_id ' ,
35
+ 'rsa_private_key ' => 'private_key ' ,
36
+ 'redirect_url ' => 'http://localhost/callback ' ,
37
+ 'sandbox ' => true ,
38
+ ]);
39
+
40
+ $ response = $ provider ->redirect ();
41
+
42
+ $ this ->assertStringStartsWith ('https://openauth.alipaydev.com/oauth2/publicAppAuthorize.htm ' , $ response );
43
+ }
44
+
45
+ public function testAlipayProviderUrlsAndFields ()
46
+ {
47
+ $ provider = new Alipay ([
48
+ 'client_id ' => 'client_id ' ,
49
+ 'rsa_private_key ' => 'private_key ' ,
50
+ 'redirect_url ' => 'http://localhost/callback ' ,
51
+ ]);
52
+
53
+ $ getTokenUrl = new ReflectionMethod (Alipay::class, 'getTokenUrl ' );
54
+ $ getTokenUrl ->setAccessible (true );
55
+
56
+ $ this ->assertSame ('https://openapi.alipay.com/gateway.do ' , $ getTokenUrl ->invoke ($ provider ));
57
+ }
58
+
59
+ public function testGetPublicFields ()
60
+ {
61
+ $ provider = new Alipay ([
62
+ 'client_id ' => 'test_app_id ' ,
63
+ 'rsa_private_key ' => 'private_key ' ,
17
64
'redirect_url ' => 'http://localhost/callback ' ,
18
65
]);
19
66
20
- // Mock the getHttpClient method to return response without token response
67
+ $ fields = $ provider ->getPublicFields ('test.method ' );
68
+
69
+ $ this ->assertArrayHasKey ('app_id ' , $ fields );
70
+ $ this ->assertSame ('test_app_id ' , $ fields ['app_id ' ]);
71
+ $ this ->assertArrayHasKey ('method ' , $ fields );
72
+ $ this ->assertSame ('test.method ' , $ fields ['method ' ]);
73
+ $ this ->assertArrayHasKey ('format ' , $ fields );
74
+ $ this ->assertSame ('json ' , $ fields ['format ' ]);
75
+ $ this ->assertArrayHasKey ('charset ' , $ fields );
76
+ $ this ->assertSame ('UTF-8 ' , $ fields ['charset ' ]);
77
+ $ this ->assertArrayHasKey ('sign_type ' , $ fields );
78
+ $ this ->assertSame ('RSA2 ' , $ fields ['sign_type ' ]);
79
+ $ this ->assertArrayHasKey ('timestamp ' , $ fields );
80
+ $ this ->assertArrayHasKey ('version ' , $ fields );
81
+ $ this ->assertSame ('1.0 ' , $ fields ['version ' ]);
82
+ }
83
+
84
+ public function testGetCodeFieldsThrowsExceptionWhenNoRedirectUrl ()
85
+ {
86
+ $ provider = new Alipay ([
87
+ 'client_id ' => 'client_id ' ,
88
+ 'rsa_private_key ' => 'private_key ' ,
89
+ ]);
90
+
91
+ $ this ->expectException (InvalidArgumentException::class);
92
+ $ this ->expectExceptionMessage ('Please set the correct redirect URL refer which was on the Alipay Official Admin pannel. ' );
93
+
94
+ $ getCodeFields = new ReflectionMethod (Alipay::class, 'getCodeFields ' );
95
+ $ getCodeFields ->setAccessible (true );
96
+ $ getCodeFields ->invoke ($ provider );
97
+ }
98
+
99
+ public function testGetCodeFields ()
100
+ {
101
+ $ provider = new Alipay ([
102
+ 'app_id ' => 'test_app_id ' ,
103
+ 'rsa_private_key ' => 'private_key ' ,
104
+ 'redirect_url ' => 'http://localhost/callback ' ,
105
+ ]);
106
+
107
+ $ getCodeFields = new ReflectionMethod (Alipay::class, 'getCodeFields ' );
108
+ $ getCodeFields ->setAccessible (true );
109
+ $ fields = $ getCodeFields ->invoke ($ provider );
110
+
111
+ $ this ->assertArrayHasKey ('app_id ' , $ fields );
112
+ $ this ->assertSame ('test_app_id ' , $ fields ['app_id ' ]);
113
+ $ this ->assertArrayHasKey ('scope ' , $ fields );
114
+ $ this ->assertSame ('auth_user ' , $ fields ['scope ' ]);
115
+ $ this ->assertArrayHasKey ('redirect_uri ' , $ fields );
116
+ $ this ->assertSame ('http://localhost/callback ' , $ fields ['redirect_uri ' ]);
117
+ }
118
+
119
+ public function testSignWithSHA256RSAThrowsExceptionWhenNoPrivateKey ()
120
+ {
121
+ $ provider = new Alipay ([
122
+ 'client_id ' => 'client_id ' ,
123
+ 'redirect_url ' => 'http://localhost/callback ' ,
124
+ ]);
125
+
126
+ $ this ->expectException (InvalidArgumentException::class);
127
+ $ this ->expectExceptionMessage ('no RSA private key set. ' );
128
+
129
+ $ signWithSHA256RSA = new ReflectionMethod (Alipay::class, 'signWithSHA256RSA ' );
130
+ $ signWithSHA256RSA ->setAccessible (true );
131
+ $ signWithSHA256RSA ->invoke ($ provider , 'test_content ' , '' );
132
+ }
133
+
134
+ public function testBuildParams ()
135
+ {
136
+ $ params = [
137
+ 'app_id ' => 'test_app_id ' ,
138
+ 'method ' => 'test.method ' ,
139
+ 'sign ' => 'signature ' ,
140
+ 'timestamp ' => '2024-01-01 12:00:00 ' ,
141
+ ];
142
+
143
+ $ result = Alipay::buildParams ($ params );
144
+ $ this ->assertSame ('app_id=test_app_id&method=test.method×tamp=2024-01-01 12:00:00 ' , $ result );
145
+
146
+ $ resultWithUrlencode = Alipay::buildParams ($ params , true );
147
+ $ this ->assertStringContains ('timestamp=2024-01-01%2012%3A00%3A00 ' , $ resultWithUrlencode );
148
+ }
149
+
150
+ public function testTokenFromCodeSuccess ()
151
+ {
152
+ $ mockProvider = $ this ->getMockBuilder (Alipay::class)
153
+ ->setConstructorArgs ([[
154
+ 'client_id ' => 'client_id ' ,
155
+ 'rsa_private_key ' => 'private_key ' ,
156
+ 'redirect_url ' => 'http://localhost/callback ' ,
157
+ ]])
158
+ ->onlyMethods (['getHttpClient ' , 'generateSign ' ])
159
+ ->getMock ();
160
+
161
+ $ mockHttpClient = m::mock ();
162
+ $ mockResponse = m::mock ();
163
+
164
+ $ mockHttpClient ->shouldReceive ('post ' )
165
+ ->once ()
166
+ ->andReturn ($ mockResponse );
167
+
168
+ $ mockResponse ->shouldReceive ('getBody ' )
169
+ ->once ()
170
+ ->andReturn ('{"alipay_system_oauth_token_response": {"access_token": "token123", "user_id": "user123"}} ' );
171
+
172
+ $ mockProvider ->method ('getHttpClient ' )->willReturn ($ mockHttpClient );
173
+ $ mockProvider ->method ('generateSign ' )->willReturn ('test_signature ' );
174
+
175
+ $ token = $ mockProvider ->tokenFromCode ('test_code ' );
176
+
177
+ $ this ->assertArrayHasKey ('access_token ' , $ token );
178
+ $ this ->assertSame ('token123 ' , $ token ['access_token ' ]);
179
+ }
180
+
181
+ public function testThrowsExceptionWhenTokenResponseMissing ()
182
+ {
21
183
$ mockProvider = $ this ->getMockBuilder (Alipay::class)
22
184
->setConstructorArgs ([[
23
185
'client_id ' => 'client_id ' ,
24
- 'private_key ' => 'private_key ' ,
186
+ 'rsa_private_key ' => 'private_key ' ,
25
187
'redirect_url ' => 'http://localhost/callback ' ,
26
188
]])
27
- ->onlyMethods (['getHttpClient ' ])
189
+ ->onlyMethods (['getHttpClient ' , ' generateSign ' ])
28
190
->getMock ();
29
191
30
192
$ mockHttpClient = m::mock ();
@@ -39,13 +201,137 @@ public function testThrowsExceptionWhenTokenResponseMissing()
39
201
->andReturn ('{"success": true} ' ); // Missing alipay_system_oauth_token_response
40
202
41
203
$ mockProvider ->method ('getHttpClient ' )->willReturn ($ mockHttpClient );
204
+ $ mockProvider ->method ('generateSign ' )->willReturn ('test_signature ' );
42
205
43
206
$ this ->expectException (AuthorizeFailedException::class);
44
207
$ this ->expectExceptionMessage ('Authorization failed: missing alipay_system_oauth_token_response in response ' );
45
208
46
209
$ mockProvider ->tokenFromCode ('test_code ' );
47
210
}
48
211
212
+ public function testThrowsExceptionWhenErrorResponse ()
213
+ {
214
+ $ mockProvider = $ this ->getMockBuilder (Alipay::class)
215
+ ->setConstructorArgs ([[
216
+ 'client_id ' => 'client_id ' ,
217
+ 'rsa_private_key ' => 'private_key ' ,
218
+ 'redirect_url ' => 'http://localhost/callback ' ,
219
+ ]])
220
+ ->onlyMethods (['getHttpClient ' , 'generateSign ' ])
221
+ ->getMock ();
222
+
223
+ $ mockHttpClient = m::mock ();
224
+ $ mockResponse = m::mock ();
225
+
226
+ $ mockHttpClient ->shouldReceive ('post ' )
227
+ ->once ()
228
+ ->andReturn ($ mockResponse );
229
+
230
+ $ mockResponse ->shouldReceive ('getBody ' )
231
+ ->once ()
232
+ ->andReturn ('{"error_response": {"code": "40002", "msg": "Invalid parameter"}} ' );
233
+
234
+ $ mockProvider ->method ('getHttpClient ' )->willReturn ($ mockHttpClient );
235
+ $ mockProvider ->method ('generateSign ' )->willReturn ('test_signature ' );
236
+
237
+ $ this ->expectException (BadRequestException::class);
238
+
239
+ $ mockProvider ->tokenFromCode ('test_code ' );
240
+ }
241
+
242
+ public function testGetUserByTokenSuccess ()
243
+ {
244
+ $ mockProvider = $ this ->getMockBuilder (Alipay::class)
245
+ ->setConstructorArgs ([[
246
+ 'client_id ' => 'client_id ' ,
247
+ 'rsa_private_key ' => 'private_key ' ,
248
+ 'redirect_url ' => 'http://localhost/callback ' ,
249
+ ]])
250
+ ->onlyMethods (['getHttpClient ' , 'generateSign ' ])
251
+ ->getMock ();
252
+
253
+ $ mockHttpClient = m::mock ();
254
+ $ mockResponse = m::mock ();
255
+
256
+ $ mockHttpClient ->shouldReceive ('post ' )
257
+ ->once ()
258
+ ->andReturn ($ mockResponse );
259
+
260
+ $ mockResponse ->shouldReceive ('getBody ' )
261
+ ->once ()
262
+ ->andReturn ('{"alipay_user_info_share_response": {"user_id": "user123", "nick_name": "Test User", "avatar": "http://avatar.url"}} ' );
263
+
264
+ $ mockProvider ->method ('getHttpClient ' )->willReturn ($ mockHttpClient );
265
+ $ mockProvider ->method ('generateSign ' )->willReturn ('test_signature ' );
266
+
267
+ $ getUserByToken = new ReflectionMethod (Alipay::class, 'getUserByToken ' );
268
+ $ getUserByToken ->setAccessible (true );
269
+ $ result = $ getUserByToken ->invoke ($ mockProvider , 'test_token ' );
270
+
271
+ $ this ->assertArrayHasKey ('user_id ' , $ result );
272
+ $ this ->assertSame ('user123 ' , $ result ['user_id ' ]);
273
+ $ this ->assertArrayHasKey ('nick_name ' , $ result );
274
+ $ this ->assertSame ('Test User ' , $ result ['nick_name ' ]);
275
+ }
276
+
277
+ public function testGetUserByTokenThrowsExceptionWhenErrorResponse ()
278
+ {
279
+ $ mockProvider = $ this ->getMockBuilder (Alipay::class)
280
+ ->setConstructorArgs ([[
281
+ 'client_id ' => 'client_id ' ,
282
+ 'rsa_private_key ' => 'private_key ' ,
283
+ 'redirect_url ' => 'http://localhost/callback ' ,
284
+ ]])
285
+ ->onlyMethods (['getHttpClient ' , 'generateSign ' ])
286
+ ->getMock ();
287
+
288
+ $ mockHttpClient = m::mock ();
289
+ $ mockResponse = m::mock ();
290
+
291
+ $ mockHttpClient ->shouldReceive ('post ' )
292
+ ->once ()
293
+ ->andReturn ($ mockResponse );
294
+
295
+ $ mockResponse ->shouldReceive ('getBody ' )
296
+ ->once ()
297
+ ->andReturn ('{"error_response": {"code": "40002", "msg": "Invalid parameter"}} ' );
298
+
299
+ $ mockProvider ->method ('getHttpClient ' )->willReturn ($ mockHttpClient );
300
+ $ mockProvider ->method ('generateSign ' )->willReturn ('test_signature ' );
301
+
302
+ $ this ->expectException (BadRequestException::class);
303
+
304
+ $ getUserByToken = new ReflectionMethod (Alipay::class, 'getUserByToken ' );
305
+ $ getUserByToken ->setAccessible (true );
306
+ $ getUserByToken ->invoke ($ mockProvider , 'test_token ' );
307
+ }
308
+
309
+ public function testMapUserToObject ()
310
+ {
311
+ $ provider = new Alipay ([
312
+ 'client_id ' => 'client_id ' ,
313
+ 'rsa_private_key ' => 'private_key ' ,
314
+ 'redirect_url ' => 'http://localhost/callback ' ,
315
+ ]);
316
+
317
+ $ mapUserToObject = new ReflectionMethod (Alipay::class, 'mapUserToObject ' );
318
+ $ mapUserToObject ->setAccessible (true );
319
+
320
+ $ user = [
321
+ 'user_id ' => 'user123 ' ,
322
+ 'nick_name ' => 'Test User ' ,
323
+ 'avatar ' => 'http://avatar.url ' ,
324
+
325
+ ];
326
+
327
+ $ result = $ mapUserToObject ->invoke ($ provider , $ user );
328
+
329
+ $ this ->assertSame ('user123 ' , $ result ->getId ());
330
+ $ this ->assertSame ('Test User ' , $ result ->getName ());
331
+ $ this ->assertSame ('http://avatar.url ' , $ result ->getAvatar ());
332
+ $ this ->
assertSame (
'[email protected] ' ,
$ result->
getEmail ());
333
+ }
334
+
49
335
protected function tearDown (): void
50
336
{
51
337
m::close ();
0 commit comments