@alipay/alipay-aipay 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/bin/alipay-aipay.js +6 -0
  2. package/dist/commands/install.d.ts +11 -0
  3. package/dist/commands/install.d.ts.map +1 -0
  4. package/dist/commands/install.js +182 -0
  5. package/dist/commands/install.js.map +1 -0
  6. package/dist/commands/prepare-tools.d.ts +5 -0
  7. package/dist/commands/prepare-tools.d.ts.map +1 -0
  8. package/dist/commands/prepare-tools.js +29 -0
  9. package/dist/commands/prepare-tools.js.map +1 -0
  10. package/dist/commands/uninstall.d.ts +10 -0
  11. package/dist/commands/uninstall.d.ts.map +1 -0
  12. package/dist/commands/uninstall.js +82 -0
  13. package/dist/commands/uninstall.js.map +1 -0
  14. package/dist/commands/update.d.ts +10 -0
  15. package/dist/commands/update.d.ts.map +1 -0
  16. package/dist/commands/update.js +155 -0
  17. package/dist/commands/update.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +65 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/types.d.ts +43 -0
  23. package/dist/types.d.ts.map +1 -0
  24. package/dist/types.js +2 -0
  25. package/dist/types.js.map +1 -0
  26. package/dist/utils/alipay-cli.d.ts +15 -0
  27. package/dist/utils/alipay-cli.d.ts.map +1 -0
  28. package/dist/utils/alipay-cli.js +221 -0
  29. package/dist/utils/alipay-cli.js.map +1 -0
  30. package/dist/utils/config.d.ts +48 -0
  31. package/dist/utils/config.d.ts.map +1 -0
  32. package/dist/utils/config.js +207 -0
  33. package/dist/utils/config.js.map +1 -0
  34. package/dist/utils/file.d.ts +55 -0
  35. package/dist/utils/file.d.ts.map +1 -0
  36. package/dist/utils/file.js +154 -0
  37. package/dist/utils/file.js.map +1 -0
  38. package/dist/utils/gpg.d.ts +14 -0
  39. package/dist/utils/gpg.d.ts.map +1 -0
  40. package/dist/utils/gpg.js +247 -0
  41. package/dist/utils/gpg.js.map +1 -0
  42. package/dist/utils/jq.d.ts +14 -0
  43. package/dist/utils/jq.d.ts.map +1 -0
  44. package/dist/utils/jq.js +221 -0
  45. package/dist/utils/jq.js.map +1 -0
  46. package/dist/utils/npm.d.ts +17 -0
  47. package/dist/utils/npm.d.ts.map +1 -0
  48. package/dist/utils/npm.js +42 -0
  49. package/dist/utils/npm.js.map +1 -0
  50. package/dist/utils/shell.d.ts +11 -0
  51. package/dist/utils/shell.d.ts.map +1 -0
  52. package/dist/utils/shell.js +54 -0
  53. package/dist/utils/shell.js.map +1 -0
  54. package/package.json +48 -7
  55. package/skill/SKILL.md +118 -0
  56. package/skill/references/integration/flow.md +487 -0
  57. package/skill/references/integration/modules/alipay-sdk-reminder.md +256 -0
  58. package/skill/references/integration/modules/checklist.md +122 -0
  59. package/skill/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +68 -0
  60. package/skill/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +77 -0
  61. package/skill/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +74 -0
  62. package/skill/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +73 -0
  63. package/skill/references/integration/modules/code-examples/csharp/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +58 -0
  64. package/skill/references/integration/modules/code-examples/csharp/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +128 -0
  65. package/skill/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.cs +500 -0
  66. package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +72 -0
  67. package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +80 -0
  68. package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +78 -0
  69. package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +77 -0
  70. package/skill/references/integration/modules/code-examples/java/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +66 -0
  71. package/skill/references/integration/modules/code-examples/java/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +135 -0
  72. package/skill/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.java +610 -0
  73. package/skill/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +51 -0
  74. package/skill/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +57 -0
  75. package/skill/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +55 -0
  76. package/skill/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +54 -0
  77. package/skill/references/integration/modules/code-examples/nodejs/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +77 -0
  78. package/skill/references/integration/modules/code-examples/nodejs/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
  79. package/skill/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.js +461 -0
  80. package/skill/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +59 -0
  81. package/skill/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +67 -0
  82. package/skill/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +66 -0
  83. package/skill/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
  84. package/skill/references/integration/modules/code-examples/php/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +56 -0
  85. package/skill/references/integration/modules/code-examples/php/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +107 -0
  86. package/skill/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.php +444 -0
  87. package/skill/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +57 -0
  88. package/skill/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
  89. package/skill/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +63 -0
  90. package/skill/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +62 -0
  91. package/skill/references/integration/modules/code-examples/python/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +48 -0
  92. package/skill/references/integration/modules/code-examples/python/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +43 -0
  93. package/skill/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.py +465 -0
  94. package/skill/references/integration/modules/interface-guide.md +90 -0
  95. package/skill/references/integration/modules/product-decision.md +90 -0
  96. package/skill/references/integration/modules/sandbox/a2m-sandbox-test.md +270 -0
  97. package/skill/references/integration/modules/sandbox/alipay-sandbox-tool.md +133 -0
  98. package/skill/references/integration/modules/sandbox/sandbox-setup-guide.md +218 -0
  99. package/skill/references/integration/modules/scripts/local_402_sandbox_pay.py +659 -0
  100. package/skill/references/normal/alipay-cli-env.md +214 -0
  101. package/skill/references/normal/rejection-guide.md +37 -0
  102. package/skill/references/normal/scripts/common.sh +32 -0
  103. package/skill/references/normal/scripts/detect_dev_tool.sh +46 -0
  104. package/skill/references/onboarding/flow.md +573 -0
  105. package/skill/references/onboarding/modules/app-release.md +415 -0
  106. package/skill/references/onboarding/modules/authorization.md +269 -0
  107. package/skill/references/onboarding/modules/error-handling.md +251 -0
  108. package/skill/references/onboarding/modules/mcc-reference.md +209 -0
  109. package/skill/references/onboarding/modules/product-sign.md +304 -0
  110. package/skill/references/onboarding/modules/scripts/app.sh +705 -0
  111. package/skill/references/onboarding/modules/scripts/ar_sign_apply.sh +248 -0
  112. package/skill/references/onboarding/modules/scripts/auth.sh +505 -0
  113. package/skill/references/onboarding/modules/scripts/error_handler.sh +452 -0
  114. package/skill/references/onboarding/modules/scripts/query_sign_status.sh +146 -0
  115. package/skill/references/onboarding/modules/scripts/service.sh +267 -0
  116. package/skill/references/onboarding/modules/scripts/upload_screenshots.sh +152 -0
  117. package/skill/references/onboarding/modules/service-registration.md +294 -0
@@ -0,0 +1,65 @@
1
+ # 统一收单交易退款查询接口 - PHP 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```php
6
+ <?php
7
+ require_once __DIR__ . '/aop/AopClient.php';
8
+ require_once __DIR__ . '/aop/request/AlipayTradeFastpayRefundQueryRequest.php';
9
+
10
+ // 初始化 SDK(PHP 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
11
+ $aop = new AopClient();
12
+ $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
13
+ // 沙箱环境: $aop->gatewayUrl = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do';
14
+ $aop->appId = '<-- 请填写您的AppId,例如:20190xxxxxx -->';
15
+ $aop->rsaPrivateKey = '<-- 请填写您的应用私钥(PKCS#1格式),例如:MIIE...(脱敏示例) -->';
16
+ $aop->alipayrsaPublicKey = '<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->';
17
+ $aop->format = 'json';
18
+ $aop->postCharset = 'UTF-8';
19
+ $aop->signType = 'RSA2';
20
+
21
+ // 构造请求参数
22
+ $request = new AlipayTradeFastpayRefundQueryRequest();
23
+ $bizContent = [
24
+ 'out_trade_no' => 'MERCHANT_ORDER_NO_PLACEHOLDER', // 商户订单号
25
+ 'out_request_no' => 'OUT_REQUEST_NO_PLACEHOLDER', // 退款请求号,必填
26
+ ];
27
+ $request->setBizContent(json_encode($bizContent, JSON_UNESCAPED_UNICODE));
28
+
29
+ // 调用接口
30
+ $response = $aop->execute($request);
31
+ $responseApiName = str_replace('.', '_', $request->getApiMethodName()) . '_response';
32
+ $result = $response->$responseApiName;
33
+
34
+ if (!empty($result->code) && $result->code == '10000') {
35
+ // refund_status: REFUND_SUCCESS 表示退款成功
36
+ echo "退款状态: " . $result->refund_status . ", 退款金额: " . $result->refund_amount;
37
+ } else {
38
+ echo "调用失败: " . $result->sub_code . " - " . $result->sub_msg;
39
+ }
40
+ ```
41
+
42
+ ## 响应示例
43
+ ### 正常示例
44
+ ```json
45
+ {
46
+ "code": "10000",
47
+ "msg": "Success",
48
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
49
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
50
+ "out_request_no": "OUT_REQUEST_NO_PLACEHOLDER",
51
+ "total_amount": "0.01",
52
+ "refund_amount": "0.01",
53
+ "refund_status": "REFUND_SUCCESS",
54
+ "gmt_refund_pay": "2014-11-27 15:45:57"
55
+ }
56
+ ```
57
+ ### 异常示例
58
+ ```json
59
+ {
60
+ "code": "20000",
61
+ "msg": "Service Currently Unavailable",
62
+ "sub_code": "isp.unknow-error",
63
+ "sub_msg": "系统繁忙"
64
+ }
65
+ ```
@@ -0,0 +1,56 @@
1
+ # 统一收单下单并支付页面接口 - PHP 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```php
6
+ <?php
7
+ require_once __DIR__ . '/aop/AopClient.php';
8
+ require_once __DIR__ . '/aop/request/AlipayTradePagePayRequest.php';
9
+
10
+ // 初始化 SDK(PHP 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
11
+ $aop = new AopClient();
12
+ $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
13
+ // 沙箱环境: $aop->gatewayUrl = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do';
14
+ $aop->appId = '<-- 请填写您的AppId,例如:20190xxxxxx -->';
15
+ $aop->rsaPrivateKey = '<-- 请填写您的应用私钥(PKCS#1格式),例如:MIIE...(脱敏示例) -->';
16
+ $aop->alipayrsaPublicKey = '<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->';
17
+ $aop->format = 'json';
18
+ $aop->postCharset = 'UTF-8';
19
+ $aop->signType = 'RSA2';
20
+
21
+ // 构造请求参数
22
+ $request = new AlipayTradePagePayRequest();
23
+ $request->setNotifyUrl('https://your-domain.com/notify'); // 异步通知地址
24
+ $request->setReturnUrl('https://your-domain.com/return'); // 同步跳转地址
25
+
26
+ $bizContent = [
27
+ 'out_trade_no' => date('YmdHis') . mt_rand(1000, 9999), // 商户订单号
28
+ 'total_amount' => '0.01', // 订单总金额
29
+ 'subject' => '测试商品', // 订单标题
30
+ 'product_code' => 'FAST_INSTANT_TRADE_PAY', // 网站支付固定值
31
+ ];
32
+ $request->setBizContent(json_encode($bizContent, JSON_UNESCAPED_UNICODE));
33
+
34
+ // ⚠️ 网站支付必须使用 pageExecute(),不能使用 execute()
35
+ // ⚠️ 必须使用 POST 模式:pageExecute($request, 'POST')
36
+ $response = $aop->pageExecute($request, 'POST');
37
+
38
+ // pageExecute 返回的是 HTML 表单字符串,前端需要渲染并自动提交
39
+ echo $response;
40
+ ```
41
+
42
+ > **⚠️ 关键注意事项:**
43
+ > 1. 必须使用 `pageExecute()` 方法,不能使用 `execute()` 方法
44
+ > 2. 必须使用 POST 模式:`$aop->pageExecute($request, 'POST')`
45
+ > 3. 返回的 HTML 需要前端渲染并自动提交,禁止直接在服务端 redirect
46
+ > 4. PHP 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用
47
+
48
+ ## 响应示例
49
+ ### 正常示例
50
+ ```html
51
+ <form name="punchout_form" method="post" action="https://openapi.alipay.com/gateway.do?charset=UTF-8&method=alipay.trade.page.pay&format=json&sign=SIGN_PLACEHOLDER&version=1.0&app_id=20190xxxxxx&sign_type=RSA2&timestamp=2014-07-24+03%3A07%3A50">
52
+ <input type="hidden" name="biz_content" value="{&quot;out_trade_no&quot;:&quot;MERCHANT_ORDER_NO_PLACEHOLDER&quot;,&quot;total_amount&quot;:&quot;0.01&quot;,&quot;subject&quot;:&quot;测试商品&quot;,&quot;product_code&quot;:&quot;FAST_INSTANT_TRADE_PAY&quot;}">
53
+ <input type="submit" value="立即支付" style="display:none" >
54
+ </form>
55
+ <script>document.forms[0].submit();</script>
56
+ ```
@@ -0,0 +1,107 @@
1
+ # APP支付接口 - PHP 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```php
6
+ <?php
7
+ require_once '../aop/AopClient.php';
8
+ require_once '../aop/AopCertClient.php';
9
+ require_once '../aop/AopCertification.php';
10
+ require_once '../aop/AlipayConfig.php';
11
+ require_once '../aop/request/AlipayTradeAppPayRequest.php';
12
+
13
+ // 初始化SDK
14
+ $alipayClient = new AopClient(getAlipayConfig());
15
+ // 构造请求参数以调用接口
16
+ $request = new AlipayTradeAppPayRequest();
17
+ $model = array();
18
+
19
+ // 设置商户订单号
20
+ $model['out_trade_no'] = "MERCHANT_ORDER_NO_PLACEHOLDER";
21
+
22
+ // 设置订单总金额
23
+ $model['total_amount'] = "9.00";
24
+
25
+ // 设置订单标题
26
+ $model['subject'] = "大乐透";
27
+
28
+ // 设置产品码
29
+ $model['product_code'] = "QUICK_MSECURITY_PAY";
30
+
31
+ // 设置订单包含的商品列表信息
32
+ $goodsDetail = array();
33
+ $goodsDetail0 = array();
34
+ $goodsDetail0['goods_name'] = "ipad";
35
+ $goodsDetail0['alipay_goods_id'] = "20010001";
36
+ $goodsDetail0['quantity'] = 1;
37
+ $goodsDetail0['price'] = "2000";
38
+ $goodsDetail0['goods_id'] = "apple-01";
39
+ $goodsDetail0['goods_category'] = "34543238";
40
+ $goodsDetail0['categories_tree'] = "124868003|126232002|126252004";
41
+ $goodsDetail0['show_url'] = "http://www.alipay.com/xxx.jpg";
42
+ $goodsDetail[] = $goodsDetail0;
43
+ $model['goods_detail'] = $goodsDetail;
44
+
45
+ // 设置订单绝对超时时间
46
+ $model['time_expire'] = "2016-12-31 10:05:00";
47
+
48
+ // 设置业务扩展参数
49
+ $extendParams = array();
50
+ $extendParams['sys_service_provider_id'] = "<SYS_SERVICE_PROVIDER_ID>";
51
+ $extendParams['hb_fq_seller_percent'] = "100";
52
+ $extendParams['hb_fq_num'] = "3";
53
+ $extendParams['industry_reflux_info'] = "{\"scene_code\":\"metro_tradeorder\",\"channel\":\"xxxx\",\"scene_data\":{\"asset_name\":\"ALIPAY\"}}";
54
+ $extendParams['royalty_freeze'] = "true";
55
+ $extendParams['card_type'] = "S0JP0000";
56
+ $model['extend_params'] = $extendParams;
57
+
58
+ // 设置公用回传参数
59
+ $model['passback_params'] = "merchantBizType%3d3C%26merchantBizNo%3dMERCHANT_BIZ_NO_PLACEHOLDER";
60
+
61
+ // 设置商户的原始订单号
62
+ $model['merchant_order_no'] = "MERCHANT_ORDER_NO_PLACEHOLDER";
63
+
64
+ // 设置外部指定买家
65
+ $extUserInfo = array();
66
+ $extUserInfo['cert_type'] = "IDENTITY_CARD";
67
+ $extUserInfo['cert_no'] = "<CERT_NO>";
68
+ $extUserInfo['mobile'] = "<MOBILE>";
69
+ $extUserInfo['name'] = "李明";
70
+ $extUserInfo['min_age'] = "18";
71
+ $extUserInfo['need_check_info'] = "F";
72
+ $extUserInfo['identity_hash'] = "<IDENTITY_HASH>";
73
+ $model['ext_user_info'] = $extUserInfo;
74
+
75
+ // 设置通知参数选项
76
+ $queryOptions = array();
77
+ $queryOptions[] = "hyb_amount";
78
+ $queryOptions[] = "enterprise_pay_info";
79
+ $model['query_options'] = $queryOptions;
80
+
81
+ $request->setBizContent(json_encode($model,JSON_UNESCAPED_UNICODE));
82
+ // 如果是第三方代调用模式,请设置app_auth_token(应用授权令牌)
83
+ $orderStr = $alipayClient->sdkExecute($request, "<-- 请填写应用授权令牌 -->");
84
+ echo $orderStr;
85
+
86
+ function getAlipayConfig()
87
+ {
88
+ $privateKey = '<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->';
89
+ $alipayPublicKey = '<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->';
90
+ $alipayConfig = new AlipayConfig();
91
+ $alipayConfig->setServerUrl('https://openapi.alipay.com/gateway.do');
92
+ $alipayConfig->setAppId('<-- 请填写您的AppId,例如:20190xxxxxx -->');
93
+ $alipayConfig->setPrivateKey($privateKey);
94
+ $alipayConfig->setFormat('json');
95
+ $alipayConfig->setAlipayPublicKey($alipayPublicKey);
96
+ $alipayConfig->setCharset('UTF-8');
97
+ $alipayConfig->setSignType('RSA2');
98
+ return $alipayConfig;
99
+ }
100
+ ```
101
+
102
+ ## 响应示例
103
+ ### 正常示例
104
+ ```
105
+ app_id=20190xxxxxx&biz_content=%7B%22time_expire%22%3A%222016-12-31+10%3A05%3A00%22%2C%22extend_params%22%3A%22%22%2C%22query_options%22%3A%22%5B%5C%22hyb_amount%5C%22%2C%5C%22enterprise_pay_info%5C%22%5D%22%2C%22subject%22%3A%22%E5%A4%A7%E4%B9%90%E9%80%8F%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22body%22%3A%22Iphone6+16G%22%2C%22passback_params%22%3A%22merchantBizType%253d3C%2526merchantBizNo%253dMERCHANT_BIZ_NO_PLACEHOLDER%22%2C%22specified_channel%22%3A%22pcredit%22%2C%22goods_detail%22%3A%22%22%2C%22merchant_order_no%22%3A%22MERCHANT_ORDER_NO_PLACEHOLDER%22%2C%22enable_pay_channels%22%3A%22pcredit%2CmoneyFund%2CdebitCardExpress%22%2C%22out_trade_no%22%3A%22MERCHANT_ORDER_NO_PLACEHOLDER%22%2C%22ext_user_info%22%3A%22%22%2C%22total_amount%22%3A%229.00%22%2C%22timeout_express%22%3A%2290m%22%2C%22disable_pay_channels%22%3A%22pcredit%2CmoneyFund%2CdebitCardExpress%22%2C%22agreement_sign_params%22%3A%22%22%7D&charset=UTF-8&format=json&method=alipay.trade.app.pay&sign=SIGN_PLACEHOLDER&sign_type=RSA2&timestamp=2014-07-24+03%3A07%3A50&version=1.0
106
+ ```
107
+
@@ -0,0 +1,444 @@
1
+ <?php
2
+ /**
3
+ * A2M 智能收产品接入示例 - PHP 版本
4
+ *
5
+ * 本文件演示完整的智能收产品接入流程:
6
+ * 1. 返回 402 Payment-Needed Header
7
+ * 2. 验证 Payment-Proof 支付凭证
8
+ * 3. 发送履约回执确认
9
+ * 4. 返回资源内容
10
+ *
11
+ * 依赖安装:
12
+ * composer require alipay/alipay-sdk
13
+ */
14
+
15
+ // ==================== 配置信息(实际使用时请从配置中心读取)====================
16
+ define('ALIPAY_CONFIG', [
17
+ 'appId' => '<APP_ID>',
18
+ 'privateKey' => '<APP_PRIVATE_KEY>', // 请填写您的应用私钥(PKCS#1 格式)
19
+ 'alipayPublicKey' => '<ALIPAY_PUBLIC_KEY>', // 请填写您的支付宝公钥
20
+ 'gateway' => 'https://openapi.alipay.com/gateway.do',
21
+ 'sellerId' => '<SELLER_ID_2088>', // 商户 ID(2088 格式)
22
+ 'serviceId' => '<SERVICE_ID>', // 商户服务 ID
23
+ 'merchantPrivateKey' => '<APP_PRIVATE_KEY>' // 请填写您的应用私钥(用于商家签名)
24
+ ]);
25
+
26
+ define('RESOURCE_CONFIG', [
27
+ 'path' => '/demo/a2m/resource',
28
+ 'goodsName' => 'AI 生成内容服务'
29
+ ]);
30
+
31
+ /**
32
+ * 初始化 SDK
33
+ */
34
+ function initAlipayClient() {
35
+ require_once 'aop/AopClient.php';
36
+ require_once 'aop/AlipayConfig.php';
37
+
38
+ $config = new AlipayConfig();
39
+ $config->setServerUrl(ALIPAY_CONFIG['gateway']);
40
+ $config->setAppId(ALIPAY_CONFIG['appId']);
41
+ $config->setPrivateKey(ALIPAY_CONFIG['privateKey']);
42
+ $config->setFormat('json');
43
+ $config->setAlipayPublicKey(ALIPAY_CONFIG['alipayPublicKey']);
44
+ $config->setCharset('UTF-8');
45
+ $config->setSignType('RSA2');
46
+
47
+ return new AopClient($config);
48
+ }
49
+
50
+ /**
51
+ * 格式化支付宝时间戳:yyyy-MM-dd HH:mm:ss
52
+ */
53
+ function formatAlipayTimestamp($timestamp = null) {
54
+ if ($timestamp === null) {
55
+ $timestamp = time();
56
+ }
57
+ return date('Y-m-d H:i:s', $timestamp);
58
+ }
59
+
60
+ /**
61
+ * 生成商家签名(seller_signature)
62
+ */
63
+ function generateSellerSignature($params, $privateKey) {
64
+ // 1. 按 key 字典序排序
65
+ ksort($params);
66
+
67
+ // 2. 拼接签名内容
68
+ $signContent = [];
69
+ foreach ($params as $key => $value) {
70
+ if ($value !== null && $value !== '') {
71
+ $signContent[] = "{$key}={$value}";
72
+ }
73
+ }
74
+ $signString = implode('&', $signContent);
75
+
76
+ // 3. RSA2 签名
77
+ $privateKeyResource = openssl_pkey_get_private($privateKey);
78
+ openssl_sign($signString, $signature, $privateKeyResource, OPENSSL_ALGO_SHA256);
79
+
80
+ return base64_encode($signature);
81
+ }
82
+
83
+ /**
84
+ * Base64URL 编码
85
+ */
86
+ function base64UrlEncode($data) {
87
+ return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
88
+ }
89
+
90
+ /**
91
+ * Base64URL 解码
92
+ */
93
+ function base64UrlDecode($data) {
94
+ $padding = strlen($data) % 4;
95
+ if ($padding) {
96
+ $data .= str_repeat('=', 4 - $padding);
97
+ }
98
+ return base64_decode(strtr($data, '-_', '+/'));
99
+ }
100
+
101
+ /**
102
+ * 发送 JSON 响应
103
+ */
104
+ function jsonResponse($data, $statusCode = 200, $headers = []) {
105
+ http_response_code($statusCode);
106
+ header('Content-Type: application/json; charset=utf-8');
107
+
108
+ foreach ($headers as $key => $value) {
109
+ header("{$key}: {$value}");
110
+ }
111
+
112
+ echo json_encode($data, JSON_UNESCAPED_UNICODE);
113
+ exit;
114
+ }
115
+
116
+ // ==================== 智能收产品接入示例接口 ====================
117
+
118
+ /**
119
+ * 智能收产品统一接口
120
+ *
121
+ * 完整流程演示:
122
+ * 1. 不带 Payment-Proof Header:返回 HTTP 402 + Payment-Needed Header
123
+ * 2. 带 Payment-Proof Header:验证支付 → 自动履约 → 返回资源
124
+ */
125
+ function handleResourceRequest() {
126
+ // 获取 Payment-Proof Header
127
+ $paymentProof = isset($_SERVER['HTTP_PAYMENT_PROOF']) ? $_SERVER['HTTP_PAYMENT_PROOF'] : null;
128
+
129
+ // 场景 1:用户未支付,返回 402 + Payment-Needed Header
130
+ if (empty($paymentProof) || trim($paymentProof) === '') {
131
+ createPaymentRequiredResponse();
132
+ return;
133
+ }
134
+
135
+ // 场景 2:用户已支付,验证 Payment-Proof 并返回资源
136
+ verifyPaymentAndDeliverResource($paymentProof);
137
+ }
138
+
139
+ /**
140
+ * 创建 402 支付请求响应
141
+ */
142
+ function createPaymentRequiredResponse() {
143
+ try {
144
+ // 1. 构造订单信息
145
+ $outTradeNo = 'ORDER_' . time() . mt_rand(1000, 9999);
146
+ $amount = '0.01'; // 单位:元
147
+ $currency = 'CNY';
148
+ $resourceId = RESOURCE_CONFIG['path'];
149
+ $goodsName = RESOURCE_CONFIG['goodsName'];
150
+
151
+ // 2. 计算支付截止时间(30 分钟后)
152
+ $payBefore = date('c', time() + 30 * 60); // ISO 8601 格式
153
+
154
+ // 3. 生成商家签名
155
+ $sellerSignature = generateSellerSignature([
156
+ 'amount' => $amount,
157
+ 'currency' => $currency,
158
+ 'goods_name' => $goodsName,
159
+ 'out_trade_no' => $outTradeNo,
160
+ 'pay_before' => $payBefore,
161
+ 'resource_id' => $resourceId,
162
+ 'seller_id' => ALIPAY_CONFIG['sellerId'],
163
+ 'service_id' => ALIPAY_CONFIG['serviceId']
164
+ ], ALIPAY_CONFIG['merchantPrivateKey']);
165
+
166
+ // 4. 构造 Payment-Needed Header 内容
167
+ $paymentNeeded = [
168
+ 'protocol' => [
169
+ 'out_trade_no' => $outTradeNo,
170
+ 'amount' => $amount,
171
+ 'currency' => $currency,
172
+ 'resource_id' => $resourceId,
173
+ 'pay_before' => $payBefore,
174
+ 'seller_signature' => $sellerSignature,
175
+ 'seller_sign_type' => 'RSA2',
176
+ 'seller_unique_id' => ALIPAY_CONFIG['sellerId']
177
+ ],
178
+ 'method' => [
179
+ 'seller_name' => '测试商户',
180
+ 'seller_id' => ALIPAY_CONFIG['sellerId'],
181
+ 'seller_app_id' => ALIPAY_CONFIG['appId'],
182
+ 'goods_name' => $goodsName,
183
+ 'seller_unique_id_key' => 'seller_id',
184
+ 'service_id' => ALIPAY_CONFIG['serviceId']
185
+ ]
186
+ ];
187
+
188
+ // 5. Base64URL 编码
189
+ $paymentNeededEncoded = base64UrlEncode(json_encode($paymentNeeded, JSON_UNESCAPED_UNICODE));
190
+
191
+ // 6. 构造 402 响应
192
+ $response = [
193
+ 'code' => 'Payment-Needed',
194
+ 'message' => '需要支付',
195
+ 'out_trade_no' => $outTradeNo,
196
+ 'amount' => $amount,
197
+ 'currency' => $currency,
198
+ 'goods_name' => $goodsName
199
+ ];
200
+
201
+ error_log("创建支付订单成功:outTradeNo={$outTradeNo}, amount={$amount}");
202
+
203
+ jsonResponse($response, 402, ['Payment-Needed' => $paymentNeededEncoded]);
204
+
205
+ } catch (Exception $e) {
206
+ error_log('创建订单失败:' . $e->getMessage());
207
+ jsonResponse([
208
+ 'code' => 'CREATE_ORDER_ERROR',
209
+ 'message' => '创建订单失败:' . $e->getMessage()
210
+ ], 500);
211
+ }
212
+ }
213
+
214
+ /**
215
+ * 验证支付凭证并交付资源
216
+ */
217
+ function verifyPaymentAndDeliverResource($paymentProof) {
218
+ try {
219
+ // 1. 从 Payment-Proof 中解析订单信息
220
+ $decodedProof = base64UrlDecode($paymentProof);
221
+ $proofJson = json_decode($decodedProof, true);
222
+
223
+ if (json_last_error() !== JSON_ERROR_NONE) {
224
+ throw new Exception('Payment-Proof 解析失败:' . json_last_error_msg());
225
+ }
226
+
227
+ // 从 protocol 层获取 payment_proof 和 trade_no
228
+ $paymentProofValue = null;
229
+ $tradeNo = null;
230
+ $clientSession = null;
231
+
232
+ if (isset($proofJson['protocol'])) {
233
+ $paymentProofValue = $proofJson['protocol']['payment_proof'] ?? null;
234
+ $tradeNo = $proofJson['protocol']['trade_no'] ?? null;
235
+ }
236
+
237
+ // 从 method 层获取 client_session
238
+ if (isset($proofJson['method'])) {
239
+ $clientSession = $proofJson['method']['client_session'] ?? null;
240
+ }
241
+
242
+ // 校验必要字段
243
+ if (empty($paymentProofValue)) {
244
+ jsonResponse([
245
+ 'code' => 'INVALID_PAYMENT_PROOF_FORMAT',
246
+ 'message' => 'Payment-Proof 格式错误:缺少 payment_proof'
247
+ ], 400);
248
+ }
249
+
250
+ if (empty($tradeNo)) {
251
+ jsonResponse([
252
+ 'code' => 'INVALID_PAYMENT_PROOF_FORMAT',
253
+ 'message' => 'Payment-Proof 格式错误:缺少 trade_no'
254
+ ], 400);
255
+ }
256
+
257
+ // 2. 调用支付宝 API 验证支付凭证
258
+ $alipayClient = initAlipayClient();
259
+ $request = new \AlipayAipayAgentPaymentVerifyRequest();
260
+
261
+ $model = [
262
+ 'payment_proof' => $paymentProofValue,
263
+ 'trade_no' => $tradeNo,
264
+ 'client_session' => $clientSession
265
+ ];
266
+
267
+ $request->setBizContent(json_encode($model, JSON_UNESCAPED_UNICODE));
268
+ $responseResult = $alipayClient->execute($request);
269
+ $responseApiName = str_replace('.', '_', $request->getApiMethodName()) . '_response';
270
+ $verifyResponse = $responseResult->$responseApiName;
271
+
272
+ // 3. 验证失败,返回错误
273
+ if (empty($verifyResponse->code) || $verifyResponse->code !== '10000') {
274
+ error_log('支付凭证验证失败:' . ($verifyResponse->sub_msg ?? 'Unknown error'));
275
+ jsonResponse([
276
+ 'code' => $verifyResponse->sub_code ?? 'VERIFY_FAILED',
277
+ 'message' => $verifyResponse->sub_msg ?? '支付凭证验证失败'
278
+ ], 400);
279
+ }
280
+
281
+ // 4. 验证成功,获取订单信息
282
+ $verifyTradeNo = $verifyResponse->trade_no ?? null;
283
+ $verifyOutTradeNo = $verifyResponse->out_trade_no ?? null;
284
+ $resourceId = $verifyResponse->resource_id ?? null;
285
+ $active = $verifyResponse->active ?? null;
286
+
287
+ error_log("支付凭证验证成功:tradeNo={$verifyTradeNo}, outTradeNo={$verifyOutTradeNo}");
288
+
289
+ // 5. 校验凭证有效性(active=true 表示凭证有效)
290
+ if ($active !== true) {
291
+ error_log("支付凭证无效或已过期:outTradeNo={$verifyOutTradeNo}");
292
+ jsonResponse([
293
+ 'code' => 'INVALID_PAYMENT_PROOF',
294
+ 'message' => '支付凭证无效或已过期'
295
+ ], 400);
296
+ }
297
+
298
+ // 6. 【TODO】查询订单是否存在(以数据库为准)
299
+ // $order = $orderRepository->findByOutTradeNo($verifyOutTradeNo);
300
+ // if (!$order) {
301
+ // jsonResponse([
302
+ // 'code' => 'ORDER_NOT_FOUND',
303
+ // 'message' => '订单不存在'
304
+ // ], 404);
305
+ // }
306
+
307
+ // 7. 【TODO】资源防串校验
308
+ // if ($resourceId !== $order->getResourceId()) {
309
+ // jsonResponse([
310
+ // 'code' => 'RESOURCE_ID_MISMATCH',
311
+ // 'message' => '资源 ID 不匹配,可能存在资源串改风险'
312
+ // ], 403);
313
+ // }
314
+
315
+ // 8. 【TODO】履约防重放校验(数据库幂等控制)
316
+ // if ($order->getFulfillStatus() === 'FULFILLED') {
317
+ // jsonResponse([
318
+ // 'code' => 'ALREADY_FULFILLED',
319
+ // 'message' => '订单已履约,不重复提供',
320
+ // 'already_fulfilled' => true
321
+ // ], 200);
322
+ // }
323
+
324
+ // 9. 执行业务逻辑,生成资源内容
325
+ $serviceResult = generateServiceResource($resourceId);
326
+
327
+ // 10. 【TODO】履约记录落库(用于审计/售后/对账)
328
+ // $fulfillmentRecordRepository->save([...]);
329
+
330
+ // 11. 【TODO】保存待确认履约状态
331
+ // 实际生产中建议先保存 $serviceResult 和 PENDING_CONFIRM 状态。
332
+ // fulfillment.confirm 成功后再标记 FULFILLED;如果确认失败,
333
+ // 允许同一笔 Payment-Proof 重试确认,避免误返回成功。
334
+ // $orderRepository->update($verifyOutTradeNo, [
335
+ // 'orderStatus' => 'PAID',
336
+ // 'fulfillStatus' => 'PENDING_CONFIRM',
337
+ // 'tradeNo' => $verifyTradeNo,
338
+ // 'serviceResult' => $serviceResult
339
+ // ]);
340
+
341
+ error_log("资源已生成,准备发送履约确认:outTradeNo={$verifyOutTradeNo}, tradeNo={$verifyTradeNo}");
342
+
343
+ // 12. 发送履约确认到支付宝,确认成功后才返回成功交付
344
+ if (!sendFulfillmentConfirm($verifyTradeNo)) {
345
+ jsonResponse([
346
+ 'code' => 'FULFILLMENT_CONFIRM_FAILED',
347
+ 'message' => '资源已生成但履约确认失败,请稍后使用同一 Payment-Proof 重试'
348
+ ], 502);
349
+ }
350
+
351
+ // 12.1 【TODO】履约确认成功后,再标记订单已履约
352
+ // $orderRepository->update($verifyOutTradeNo, [
353
+ // 'fulfillStatus' => 'FULFILLED',
354
+ // 'fulfilledAt' => date('c')
355
+ // ]);
356
+
357
+ error_log("履约确认成功:outTradeNo={$verifyOutTradeNo}, tradeNo={$verifyTradeNo}");
358
+
359
+ // 13. 构造 Payment-Validation Header
360
+ $paymentValidation = [
361
+ 'trade_no' => $verifyTradeNo,
362
+ 'out_trade_no' => $verifyOutTradeNo,
363
+ 'validated' => true,
364
+ 'resource_id' => $resourceId
365
+ ];
366
+
367
+ $paymentValidationEncoded = base64UrlEncode(json_encode($paymentValidation, JSON_UNESCAPED_UNICODE));
368
+
369
+ // 14. 返回资源内容
370
+ jsonResponse([
371
+ 'resource_id' => $resourceId,
372
+ 'content' => $serviceResult,
373
+ 'trade_no' => $verifyTradeNo,
374
+ 'out_trade_no' => $verifyOutTradeNo,
375
+ 'already_fulfilled' => false,
376
+ 'fulfillment_confirmed' => true
377
+ ], 200, ['Payment-Validation' => $paymentValidationEncoded]);
378
+
379
+ } catch (Exception $e) {
380
+ error_log('支付凭证验证异常:' . $e->getMessage());
381
+ jsonResponse([
382
+ 'code' => 'VERIFY_FAILED',
383
+ 'message' => '支付凭证验证失败:' . $e->getMessage()
384
+ ], 500);
385
+ }
386
+ }
387
+
388
+ /**
389
+ * 生成服务资源内容
390
+ */
391
+ function generateServiceResource($resourceId) {
392
+ return json_encode([
393
+ 'status' => 'success',
394
+ 'service_type' => 'AI_CONTENT_GENERATION',
395
+ 'resource_id' => $resourceId,
396
+ 'content' => '这是 AI 生成的内容示例,可根据实际业务替换为任意数字服务内容',
397
+ 'generated_at' => date('c')
398
+ ], JSON_UNESCAPED_UNICODE);
399
+ }
400
+
401
+ /**
402
+ * 发送履约确认
403
+ */
404
+ function sendFulfillmentConfirm($tradeNo) {
405
+ try {
406
+ error_log("开始发送履约确认:tradeNo={$tradeNo}");
407
+
408
+ $alipayClient = initAlipayClient();
409
+ $request = new \AlipayAipayAgentFulfillmentConfirmRequest();
410
+
411
+ $request->setBizContent(json_encode([
412
+ 'trade_no' => $tradeNo
413
+ ], JSON_UNESCAPED_UNICODE));
414
+
415
+ $responseResult = $alipayClient->execute($request);
416
+ $responseApiName = str_replace('.', '_', $request->getApiMethodName()) . '_response';
417
+ $response = $responseResult->$responseApiName;
418
+
419
+ if (!empty($response->code) && $response->code === '10000') {
420
+ error_log("履约确认成功:tradeNo={$tradeNo}");
421
+ return true;
422
+ } else {
423
+ error_log("履约确认失败:tradeNo={$tradeNo}, errorCode=" .
424
+ ($response->sub_code ?? 'Unknown') . ", errorMsg=" .
425
+ ($response->sub_msg ?? 'Unknown'));
426
+ return false;
427
+ }
428
+
429
+ } catch (Exception $e) {
430
+ error_log("履约确认异常:tradeNo={$tradeNo}, error=" . $e->getMessage());
431
+ return false;
432
+ }
433
+ }
434
+
435
+ // ==================== 路由处理 ====================
436
+
437
+ // 简单路由
438
+ $requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
439
+ if ($requestUri === RESOURCE_CONFIG['path'] && $_SERVER['REQUEST_METHOD'] === 'GET') {
440
+ handleResourceRequest();
441
+ } else {
442
+ http_response_code(404);
443
+ echo json_encode(['code' => 'NOT_FOUND', 'message' => '接口不存在'], JSON_UNESCAPED_UNICODE);
444
+ }