Skip to content

Commit 57eaeff

Browse files
authored
feat: 增加支付宝商品文件上传插件 (#1120)
1 parent 4833b35 commit 57eaeff

File tree

6 files changed

+144
-4
lines changed

6 files changed

+144
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## v3.7.19
2+
3+
### added
4+
5+
- feat: 增加支付宝商品文件上传插件 (#1120)
6+
17
## v3.7.18
28

39
### fixed

src/Plugin/Alipay/V2/AddRadarPlugin.php

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Yansongda\Pay\Plugin\Alipay\V2;
66

77
use Closure;
8+
use GuzzleHttp\Psr7\MultipartStream;
89
use GuzzleHttp\Psr7\Request;
910
use Yansongda\Artful\Contract\PluginInterface;
1011
use Yansongda\Artful\Exception\ContainerException;
@@ -35,21 +36,44 @@ public function assembly(Rocket $rocket, Closure $next): Rocket
3536
// 这里因为支付宝的 payload 里不包含 _method,所以需要取 params 中的
3637
get_radar_method(new Collection($params)) ?? 'POST',
3738
get_alipay_url($config, $payload),
38-
$this->getHeaders(),
39-
// 不能用 packer,支付宝接收的是 x-www-form-urlencoded 返回的又是 json,packer 用的是返回.
40-
$payload?->query() ?? '',
39+
$this->getHeaders($params),
40+
// 不能用 artful 中 get_radar_body 方法
41+
// 来自 AddPayloadBodyPlugin 插件通过 packer 生成的 _body
42+
// 支付宝接收的是 x-www-form-urlencoded 返回的又是 json,packer 用的是返回.
43+
$this->getBody($payload, $params)
4144
));
4245

4346
Logger::info('[Alipay][AddRadarPlugin] 插件装载完毕', ['rocket' => $rocket]);
4447

4548
return $next($rocket);
4649
}
4750

48-
protected function getHeaders(): array
51+
protected function getHeaders(array $params): array
4952
{
53+
if (!empty($params['_multipart'])) {
54+
return [];
55+
}
56+
5057
return [
5158
'Content-Type' => 'application/x-www-form-urlencoded',
5259
'User-Agent' => 'yansongda/pay-v3',
5360
];
5461
}
62+
63+
protected function getBody(?Collection $payload, array $params): MultipartStream|string
64+
{
65+
if (!empty($params['_multipart'])) {
66+
$multipartData = $params['_multipart'];
67+
foreach ($payload as $name => $value) {
68+
$multipartData[] = [
69+
'name' => $name,
70+
'contents' => $value,
71+
];
72+
}
73+
74+
return new MultipartStream($multipartData, uniqid('alipay_', true));
75+
}
76+
77+
return $payload?->query() ?? '';
78+
}
5579
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yansongda\Pay\Plugin\Alipay\V2\Merchant\Item;
6+
7+
use Closure;
8+
use Yansongda\Artful\Contract\PluginInterface;
9+
use Yansongda\Artful\Logger;
10+
use Yansongda\Artful\Rocket;
11+
12+
/**
13+
* 上传商户商品文件.
14+
*
15+
* @see https://opendocs.alipay.com/mini/510d4a72_alipay.merchant.item.file.upload?scene=common&pathHash=c08922b1
16+
*
17+
* @date 2025-10-28
18+
*/
19+
class FileUploadPlugin implements PluginInterface
20+
{
21+
public function assembly(Rocket $rocket, Closure $next): Rocket
22+
{
23+
Logger::debug('[Alipay][Merchant][Item][FileUploadPlugin] 插件开始装载', ['rocket' => $rocket]);
24+
25+
$rocket->mergePayload(
26+
array_merge(
27+
[
28+
'method' => 'alipay.merchant.item.file.upload',
29+
'scene' => 'SYNC_ORDER',
30+
],
31+
$rocket->getParams()
32+
)
33+
);
34+
35+
Logger::info('[Alipay][Merchant][Item][FileUploadPlugin] 插件装载完毕', ['rocket' => $rocket]);
36+
37+
return $next($rocket);
38+
}
39+
}

tests/Plugin/Alipay/V2/AddRadarPluginTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,25 @@ public function testRadarGetNormal()
4040
self::assertEquals('https://openapi.alipay.com/gateway.do?charset=utf-8', (string) $result->getRadar()->getUri());
4141
self::assertEquals('GET', $result->getRadar()->getMethod());
4242
}
43+
44+
public function testRadarHeaders()
45+
{
46+
$rocket = new Rocket();
47+
$rocket->setParams([])->setPayload(new Collection(['name' => 'yansongda']));
48+
49+
$result = $this->plugin->assembly($rocket, function ($rocket) { return $rocket; });
50+
51+
self::assertEquals('application/x-www-form-urlencoded', $result->getRadar()->getHeaderLine('Content-Type'));
52+
self::assertEquals('yansongda/pay-v3', $result->getRadar()->getHeaderLine('User-Agent'));
53+
}
54+
55+
public function testRadarMultipart()
56+
{
57+
$rocket = new Rocket();
58+
$rocket->setParams(['_multipart' => [['name' => 'yansongda', 'contents' => 'yansongda']]])->setPayload(new Collection(['name' => 'yansongda']));
59+
60+
$result = $this->plugin->assembly($rocket, function ($rocket) { return $rocket; });
61+
62+
self::assertEmpty($result->getRadar()->getHeaderLine('Content-Type'));
63+
}
4364
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yansongda\Pay\Tests\Plugin\Alipay\V2\Merchant\Item;
6+
7+
use Yansongda\Artful\Rocket;
8+
use Yansongda\Pay\Plugin\Alipay\V2\Merchant\Item\FileUploadPlugin;
9+
use Yansongda\Pay\Tests\TestCase;
10+
11+
class FileUploadPluginTest extends TestCase
12+
{
13+
protected FileUploadPlugin $plugin;
14+
15+
protected function setUp(): void
16+
{
17+
parent::setUp();
18+
19+
$this->plugin = new FileUploadPlugin();
20+
}
21+
22+
public function testNormal()
23+
{
24+
$picUrl = 'https://cdn.jsdelivr.net/gh/yansongda/pay/web/public/images/pay.jpg';
25+
$fileContent = file_get_contents($picUrl);
26+
$rocket = (new Rocket())
27+
->setParams([
28+
'_multipart' => [
29+
[
30+
'name' => 'file_content',
31+
'contents' => $fileContent,
32+
'filename' => basename($picUrl),
33+
],
34+
],
35+
]);
36+
37+
$result = $this->plugin->assembly($rocket, function ($rocket) { return $rocket; });
38+
39+
$params = $result->getParams();
40+
$this->assertArrayHasKey('_multipart', $params);
41+
$this->assertEquals(basename($picUrl), $params['_multipart'][0]['filename']);
42+
$this->assertEquals($fileContent, $params['_multipart'][0]['contents']);
43+
}
44+
}

web/docs/v3/alipay/all.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,3 +559,9 @@ $result = Pay::alipay()->pay($allPlugins, $params);
559559
- 文字识别OCR
560560

561561
`\Yansongda\Pay\Plugin\Alipay\V2\Member\Ocr\DetectPlugin`
562+
563+
### 文件上传
564+
565+
- 商品文件上传
566+
567+
`\Yansongda\Pay\Plugin\Alipay\V2\Merchant\Item\FileUploadPlugin`

0 commit comments

Comments
 (0)