@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,256 @@
1
+ # Alipay-SDK Reminder
2
+
3
+ 以下各项为接入支付宝 SDK 的相关规则,**严禁在未阅读全部内容的情况下编写任何 SDK 相关代码**。每条规则均来自真实集成踩坑,请逐条阅读并确认后再继续,编写代码遵守规则。
4
+
5
+ ---
6
+
7
+ ## SDK 引入方式
8
+
9
+ SDK 的引入方式取决于对应语言的包管理方式和实际导出方式,**绝不能凭猜测选择**,必须通过查阅 SDK 文档或类型定义确定。
10
+
11
+ **各语言 SDK 引入方式参考:**
12
+
13
+ | 语言 | 包管理 | 引入方式 | 备注 |
14
+ |------|--------|---------|------|
15
+ | Java | Maven | `import com.alipay.api.*;` | 通过 Maven 依赖引入,包结构固定 |
16
+ | .NET | NuGet | `using Aop.Api;` 等 | 通过 NuGet 安装 `AlipaySDKNet.Standard`,命名空间固定 |
17
+ | PHP | Composer | `require_once '../aop/AopClient.php';` 等 | 通过 GitHub 仓库或 Composer 引入,类文件路径以实际目录为准 |
18
+ | Python | pip | `from alipay.aop.api.AlipayClientConfig import AlipayClientConfig`<br>`from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient` | 通过 pip 安装 `alipay-sdk-python`,模块路径以实际版本为准 |
19
+ | Node.js | npm | 需查阅类型定义确认 | 导入方式可能随版本变化,**必须验证**,详见下方「Node.js 导入格式判断」 |
20
+
21
+ ### Node.js 导入格式判断
22
+
23
+ `alipay-sdk`(Node.js)的导入方式取决于包的实际导出方式,**绝不能凭猜测选择**。
24
+
25
+ **判断流程:**
26
+
27
+ 1. **查看 package.json**:确认模块类型(ESM/CJS)和入口路径
28
+ ```bash
29
+ cat node_modules/alipay-sdk/package.json
30
+ ```
31
+ 重点看 `type`、`exports`、`main`、`types` 字段。
32
+
33
+ 2. **查看类型定义文件**:确认导出方式
34
+ ```bash
35
+ cat node_modules/alipay-sdk/dist/types/index.d.ts
36
+ ```
37
+ 注意:类型定义文件路径以 package.json 中 `types` 字段为准。
38
+
39
+ 3. **选择导入语法**:
40
+ - 命名导出(`export class AlipaySdk`)→ `import { AlipaySdk } from 'alipay-sdk'`
41
+ - 默认导出(`export default`)→ `import AlipaySdk from 'alipay-sdk'`
42
+ - 混合导出 → `import AlipaySdk, { AlipaySdkConfig } from 'alipay-sdk'`
43
+
44
+ **优先级**:类型定义(.d.ts)> 官方文档 > 源码
45
+
46
+ **注意:**
47
+ - package.json 的 `exports` 字段是入口路径配置,不是导出方式
48
+ - 包的导出方式可能随版本更新而改变,务必验证
49
+
50
+ ---
51
+
52
+ ## 页面跳转类 API 方法选择
53
+
54
+ `alipay.trade.page.pay` 是页面跳转类 API,**严禁使用 `exec()` 方法**,必须使用页面跳转方法。各语言 SDK 的方法名不同,请按下表选择:
55
+
56
+ | 语言 | 页面跳转方法 | SDK 执行方法 | 页面跳转类 API 举例 |
57
+ |------|-------------|-------------|-------------------|
58
+ | Java | `alipayClient.pageExecute(request, "POST")` | `alipayClient.execute(request)` | `alipay.trade.page.pay` |
59
+ | .NET | `alipayClient.PageExecute(request, null, "POST")` | `alipayClient.Execute(request)` | 同上 |
60
+ | PHP | `$alipayClient->pageExecute($request, "POST")` | `$alipayClient->execute($request)` | 同上 |
61
+ | Node.js | `alipaySdk.pageExec('alipay.trade.page.pay', 'POST', {...})` | `alipaySdk.exec('alipay.trade.query', {...})` | 同上 |
62
+ | Python | `alipay_client.page_execute(request)` | `alipay_client.execute(request)` | 同上 |
63
+
64
+ **此外,APP支付(`alipay.trade.app.pay`)属于客户端 SDK 调用类 API,需使用 `sdkExecute`/`sdkExec` 方法:**
65
+
66
+ | 语言 | 客户端 SDK 方法 |
67
+ |------|---------------|
68
+ | Java | `alipayClient.sdkExecute(request)` |
69
+ | .NET | `alipayClient.SdkExecute(request)` |
70
+ | PHP | `$alipayClient->sdkExecute($request)` |
71
+ | Node.js | `alipaySdk.sdkExecute('alipay.trade.app.pay', {...})` |
72
+
73
+ **Node.js 对比示例:**
74
+ ```javascript
75
+ // ✅ 正确 - 页面跳转类 API 使用 pageExec()
76
+ const htmlForm = alipaySdk.pageExec('alipay.trade.page.pay', 'POST', {
77
+ bizContent: { out_trade_no: '123', total_amount: '10.00', ... }
78
+ });
79
+ // 返回:<form action="...">...</form> HTML 字符串
80
+
81
+ // ❌ 错误 - 对页面跳转类 API 使用 exec()
82
+ const result = await alipaySdk.exec('alipay.trade.page.pay', {
83
+ bizContent: { out_trade_no: '123', total_amount: '10.00', ... }
84
+ });
85
+ // 返回:JSON 对象,无法用于页面跳转,这是最常见的集成错误!
86
+ ```
87
+
88
+ | 方法类型 | 用途 | 返回值 | 示例 |
89
+ | --- | --- | --- | --- |
90
+ | 页面跳转方法(`pageExec()`/`pageExecute()` 等) | 页面跳转类 API(如:支付) | HTML 表单字符串 | 网站支付 |
91
+ | `exec()` | 服务端 API(查询 / 退款) | 结构化数据(JSON 等) | 交易查询、退款 |
92
+
93
+ **对支付接口调用 exec() 将不会得到可用的支付表单,是最常见的集成错误之一。**
94
+
95
+ ### 前端支付表单处理
96
+
97
+ 页面跳转类 API 返回的是包含自动提交脚本的 HTML `<form>` 字符串,前端**必须将此 HTML 渲染到页面并自动提交表单**,禁止直接用 URL 跳转。
98
+
99
+ **❌ 错误写法(以浏览器端 JavaScript 为例)**:
100
+ ```javascript
101
+ // paymentHtml 是 HTML 表单字符串,不是 URL
102
+ if (data.paymentHtml) {
103
+ window.location.href = data.paymentHtml; // 页面只显示 ?method=alipay.trade.page.pay... 参数,无法跳转
104
+ }
105
+ ```
106
+
107
+ **✅ 正确写法**:
108
+ ```javascript
109
+ if (data.paymentHtml) {
110
+ const container = document.createElement('div');
111
+ container.innerHTML = data.paymentHtml;
112
+ container.style.position = 'fixed';
113
+ container.style.top = '0';
114
+ container.style.left = '0';
115
+ container.style.width = '100%';
116
+ container.style.height = '100%';
117
+ container.style.zIndex = '9999';
118
+ container.style.background = 'white';
119
+ document.body.appendChild(container);
120
+ const form = container.querySelector('form');
121
+ if (form) form.submit();
122
+ }
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 私钥格式
128
+
129
+ **沙箱返回两个私钥字段,必须按语言选对:**
130
+
131
+ | 字段 | 格式 | 使用场景 |
132
+ |------|------|---------|
133
+ | `appPrivateKey` | PKCS#8 格式 | ✅ Java 语言必须使用 |
134
+ | `appPrivatePkcsKey` | PKCS#1 格式 | ✅ 非 Java 语言(Python、Node.js、PHP、.NET 等)必须使用 |
135
+
136
+ **严禁以下误判行为:**
137
+
138
+ | 误判行为 | 为什么错 | 正确做法 |
139
+ |---------|---------|---------|
140
+ | 看到 `ERR_OSSL_UNSUPPORTED` 就推断私钥格式有问题 | 该错误通常是 SDK 配置参数错误(如私钥字段选错、字符编码问题),**不是**私钥格式本身有问题 | 先确认使用了正确的私钥字段(Java 用 `appPrivateKey`,非 Java 用 `appPrivatePkcsKey`),再检查其他配置参数 |
141
+ | 手动添加 PEM 头尾、其他前后缀、包装行或说明文字 | 支付宝 SDK 会按配置自行处理密钥包装,手动添加会导致格式错误 | 直接使用沙箱或生产配置中的原始私钥值,不做任何格式处理 |
142
+ | 将沙箱返回的 `appPrivatePkcsKey` 转换为 PKCS#8 格式 | 沙箱已同时返回两种格式,转换会引入不必要风险 | 非 Java 语言使用原始 `appPrivatePkcsKey` 值,不做转换 |
143
+ | 将沙箱返回的 `appPrivateKey` 转换为 PKCS#1 格式 | 沙箱已同时返回两种格式,转换会引入不必要风险 | Java 语言使用原始 `appPrivateKey` 值,不做转换 |
144
+ | 对私钥内容做 Base64 解码/重新编码 | 无需任何编码处理 | 直接使用沙箱返回的原始字符串 |
145
+ | 因为字段名含 "Pkcs" 就认为是 PKCS#8 格式 | `appPrivatePkcsKey` 是 **PKCS#1** 格式,"Pkcs" 仅表示这是 PKCS 系列标准之一,不代表 PKCS#8 | 非 Java 语言使用 `appPrivatePkcsKey`(PKCS#1),Java 语言使用 `appPrivateKey`(PKCS#8) |
146
+
147
+ **核心原则:沙箱配置直接使用沙箱返回的对应私钥字段,不做格式转换;生产配置必须确认应用私钥格式与项目语言匹配。所有写入 SDK 配置的私钥值都使用不带 PEM 头尾或其他前后缀的原始密钥字符串,禁止手动添加 PEM 头尾、添加其他前后缀、编码处理或换行符调整。Java 语言使用 PKCS#8,非 Java 语言(Node.js、Python、PHP、.NET 等)使用 PKCS#1。**
148
+
149
+ ### 生产密钥替换与生产支付测试提醒
150
+
151
+ 当用户要求 Agent 直接替换生产环境密钥配置,或用户声称已经替换完成并要求启动生产环境支付测试时,必须先提醒并核对以下事项:
152
+
153
+ 1. `appId`、应用公钥、应用私钥必须属于同一套生产应用密钥,不得混用沙箱应用、其他生产应用或另一套重新生成的密钥。
154
+ 2. 基于项目编程语言确认应用私钥格式:Java 使用 PKCS#8;非 Java(Node.js、Python、PHP、.NET 等)使用 PKCS#1。
155
+ 3. 如果生产应用私钥格式与当前语言 SDK 要求不一致,请使用支付宝开放平台密钥工具进行私钥格式转换,再将转换后的原始私钥字符串写入项目配置。
156
+ 4. 不得把私钥输出到日志、对话总结、测试结果或完整支付表单中。
157
+
158
+ ### 连环误判链
159
+
160
+ 遇到 `ERR_OSSL_UNSUPPORTED` 时,agent 容易陷入以下**越错越远**的连环推理,**每一步都是错的**,必须识别并阻断:
161
+
162
+ ```
163
+ ❌ 连环误判链(严禁陷入):
164
+
165
+ 第 1 步(误判起点):看到 ERR_OSSL_UNSUPPORTED → 推断"私钥格式有问题"
166
+ ↓
167
+ 第 2 步(错误修复):认为"PKCS#1 私钥应该手动添加 PEM 头尾或其他前后缀"
168
+ → 手动添加 PEM 头尾或其他前后缀 → 错误仍在
169
+ ↓
170
+ 第 3 步(错误归因):认为"Node.js 18+ 用了 OpenSSL 3.0,旧格式不被支持"
171
+ ↓
172
+ 第 4 步(越错越远):认为"应该把原始私钥改成另一种格式"
173
+ → 将私钥转换为 PKCS#8 格式 → 错误更严重(注:Java 语言应直接使用沙箱返回的 `appPrivateKey` 字段,而非手动转换格式)
174
+ ```
175
+
176
+ **正确做法**:看到 `ERR_OSSL_UNSUPPORTED`,**立即停止所有格式操作**,按下方「验签失败排查原则」中的正确排查顺序逐项检查。
177
+
178
+ ---
179
+
180
+ ## 验签失败排查原则
181
+
182
+ 遇到 `invalid-signature`(验签出错)时,**严禁凭猜测归因到私钥格式或环境兼容性**,必须按以下顺序逐项排查:
183
+
184
+ ### 正确排查顺序
185
+
186
+ **原则:先验证实际请求内容,再怀疑密钥配置。**
187
+
188
+ 1. **检查请求参数完整性**(最常见原因)
189
+ - 支付宝验签时校验所有请求参数是否匹配。如果 `return_url`、`notify_url` 等参数在配置中定义但未传入支付请求,或传入但未参与签名,将导致验签失败。
190
+ - **排查方法**:打印或检查实际发送给支付宝的请求参数,确认 `return_url`、`notify_url` 等参数是否正确包含在请求中。
191
+ ```bash
192
+ # 检查实际请求中是否包含 return_url
193
+ # 在服务端日志中打印请求参数,确认 return_url 存在
194
+ ```
195
+
196
+ 2. **检查私钥来源**
197
+ - 确认使用的是沙箱返回的正确私钥字段:Java 使用 `appPrivateKey`,非 Java 使用 `appPrivatePkcsKey`,而非自行生成或其他来源。
198
+
199
+ 3. **检查 signType 是否一致**
200
+ - 请求中的 `sign_type` 必须为 `RSA2`,与配置保持一致。
201
+
202
+ 4. **检查私钥格式完整性**
203
+ - 私钥内容无多余空格、换行符。
204
+
205
+ 5. **检查网关地址**
206
+ - 沙箱环境必须使用沙箱网关 `https://openapi-sandbox.dl.alipaydev.com/gateway.do`,生产环境使用 `https://openapi.alipay.com/gateway.do`。
207
+
208
+ > **核心教训**:验签失败 ≠ 私钥问题。应先通过日志/输出验证实际请求行为(参数是否完整传入),而非基于技术传言做假设。
209
+
210
+ ---
211
+
212
+ ## 时间戳格式化
213
+
214
+ 支付宝要求时间戳格式为 `yyyy-MM-dd HH:mm:ss`(空格分隔,非 ISO 格式)。
215
+
216
+ ### Java
217
+ ```java
218
+ import java.text.SimpleDateFormat;
219
+ // ✅ 正确
220
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
221
+ // ❌ 错误:Instant.now().toString() → "2026-04-29T14:30:00.000Z"
222
+ ```
223
+
224
+ ### .NET (C#)
225
+ ```csharp
226
+ // ✅ 正确
227
+ DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
228
+ // ❌ 错误:DateTime.Now.ToString("o") → "2026-04-29T14:30:00.0000000+08:00"
229
+ ```
230
+
231
+ ### PHP
232
+ ```php
233
+ // ✅ 正确
234
+ date("Y-m-d H:i:s");
235
+ // ❌ 错误:date("c") → "2026-04-29T14:30:00+08:00"
236
+ ```
237
+
238
+ ### Node.js
239
+ ```javascript
240
+ function formatAlipayTimestamp(date) {
241
+ const pad = (n) => n.toString().padStart(2, '0');
242
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
243
+ }
244
+
245
+ // ❌ 错误:new Date().toISOString() → "2026-04-29T14:30:00.000Z"
246
+ ```
247
+
248
+ ### Python
249
+ ```python
250
+ from datetime import datetime
251
+
252
+ def format_alipay_timestamp(dt: datetime) -> str:
253
+ return dt.strftime("%Y-%m-%d %H:%M:%S")
254
+
255
+ # ❌ 错误:datetime.isoformat() → "2026-04-29T14:30:00"
256
+ ```
@@ -0,0 +1,122 @@
1
+ # 支付宝支付集成校验清单
2
+
3
+ 本文档整理了支付宝支付集成过程中的通用校验项,仅包含必须校验和高危项目。集成完成后,请逐项核对并通过校验模板输出结果。校验结果供参考,开发者务必按照支付宝最新开放平台文档进行检查。
4
+
5
+ ---
6
+
7
+ ## 一、密钥与安全校验
8
+
9
+ | 校验项 | 校验要求 | 说明 |
10
+ |----------|----------|----------|
11
+ | 私钥存储位置 | 私钥不得保存在客户端代码中 | 构造交易数据并签名必须在商家服务端完成,私钥绝对不能保存在商家APP客户端中,也不能从服务端下发。商户需妥善保存私钥,不建议在代码或配置中明文写入私钥,应当通过加密配置文件或秘钥管理平台进行管理 |
12
+ | 私钥日志安全 | 私钥不得出现在日志中 | 私钥的保密等级比源码高,出现在日志中将增加私钥泄露的风险 |
13
+ | 私钥仓库安全 | 私钥不得上传公共仓库 | 私钥泄露将导致应用和支付宝交互的安全性完全丧失 |
14
+ | 沙箱配置后置校验 | 沙箱 appId、应用私钥、支付宝公钥写入项目后必须完成配置准确性校验 | 必须确认写入配置来自同一份沙箱返回配置、与沙箱返回配置一致、字段选择正确、SDK 配置匹配,私钥不是占位符、示例值或其他来源的密钥 |
15
+
16
+ ---
17
+
18
+ ## 二、异步通知校验
19
+
20
+ | 校验项 | 校验要求 | 说明 |
21
+ |----------|----------|----------|
22
+ | 验签必须执行 | 收到异步通知后必须先验签 | 确保通知来自支付宝 |
23
+ | 关键信息校验 | 检验 out_trade_no、total_amount、app_id、seller_id 等商户请求关键参数| 防止伪造订单、金额篡改等 |
24
+ | 交易状态判断 | 仅 `TRADE_SUCCESS` 或 `TRADE_FINISHED` 才算支付成功 | 其他状态不算支付成功 |
25
+ | 幂等处理 | 必须进行幂等处理,过滤重复的通知 | 同一笔订单可能收到多次异步通知 |
26
+ | 响应值 | 商户侧处理成功后需返回字符串 `success` | 否则支付宝会重试通知 |
27
+ | URL 格式 | notify_url 不能包含空格和 HTML 标签 | 否则可能导致通知失败 |
28
+ | 重定向 | notify_url 不能重定向 | 重定向会导致支付宝收不到 success |
29
+ | 外网可访问 | notify_url 必须外网可访问 | 需确保支付宝服务器可访问 |
30
+
31
+ ---
32
+
33
+ ## 三、支付结果处理校验
34
+
35
+ | 校验项 | 校验要求 | 说明 |
36
+ |----------|----------|----------|
37
+ | 前台同步结果防范 | 前台同步跳转结果仅作通知,**不能作为支付成功的依据** | 必须以异步通知或查询接口结果为准 |
38
+ | 支付成功判断 | 仅 `trade_status` 为 `TRADE_SUCCESS` 或 `TRADE_FINISHED` 时才认定付款成功 | 其他状态不算支付成功 |
39
+ | 主动查询兜底 | 主动查询订单状态必须作为支付结果确认的兜底逻辑 | 无论异步通知是否到达,都应具备主动查询订单状态的能力,防止因网络抖动、通知延迟或丢失导致的状态不一致 |
40
+ | 未知异常处理 | 网络超时或未知异常时,必须调用查询接口确认 | 不能简单推断为成功或失败 |
41
+ | 商家资损防范 | 不依赖前台同步结果,以异步通知或查询为准 | 防止用户未付款但商家判定成功 |
42
+ | 用户资损防范 | 未确认支付结果前不要求用户再次付款 | 防止用户已付款但商家判定失败导致重复扣款 |
43
+
44
+ > 按量付费不使用前台同步跳转结果和异步通知作为支付成功依据,需按下一节专项校验。
45
+
46
+ ---
47
+
48
+ ## 四、按量付费专项校验
49
+
50
+ | 校验项 | 校验要求 | 说明 |
51
+ |----------|----------|----------|
52
+ | 订单持久化 | 返回 `Payment-Needed` 前必须持久化 `out_trade_no`、`resource_id`、金额、状态、过期时间 | 付款后携带 `Payment-Proof` 回来时必须能映射回商户本地订单 |
53
+ | Payment-Proof 验证 | 收到 `Payment-Proof` 后必须调用 `alipay.aipay.agent.payment.verify` | 验证成功只代表支付宝凭证有效,不代表本地订单已完成校验 |
54
+ | 本地订单匹配 | 验付成功后必须查询本地订单并校验状态 | 防止凭证有效但商户订单不存在、过期或状态异常 |
55
+ | 资源防串 | 必须校验本地订单的 `resource_id` 与验付结果/请求资源一致 | 防止用户通过篡改资源标识获取其他资源 |
56
+ | 金额一致性 | 必须校验本地订单金额与 `Payment-Needed` 账单金额和服务定价一致;若验付接口返回金额字段,再校验实际支付金额 | 防止金额篡改或错误定价 |
57
+ | 幂等履约 | 同一订单重复携带 `Payment-Proof` 时不得重复发放资源 | 应返回历史履约结果或可重试确认结果 |
58
+ | 履约确认 | 资源生成后必须调用 `alipay.aipay.agent.fulfillment.confirm` | 确认成功后再标记订单 `FULFILLED` 并返回成功交付 |
59
+ | 沙箱空字段边界 | 沙箱联调中字段为空可用于排查定位,生产环境关键字段为空必须按异常处理 | 不得把沙箱容错逻辑直接迁移成生产跳过校验 |
60
+
61
+ ---
62
+
63
+ ## 五、退款校验
64
+
65
+ | 校验项 | 校验要求 | 说明 |
66
+ |----------|----------|----------|
67
+ | 退款使用场景 | 所有退款业务都必须调用退款接口 | 撤销接口不能用于退款业务,撤销接口仅用于在不确定支付结果情况下对交易发起撤销 |
68
+ | 退款是否成功判断 | 退款接口返回 `fund_change=Y` 或退款查询返回 `refund_status=REFUND_SUCCESS` 才算退款成功 | 其他状态不算退款成功 |
69
+ | 退款幂等保障 | 接口未退款成功且不明确交易情况时,重试请务必保证退款请求号 out_request_no 以及请求参数一致,避免发生多次退款 | 防止多次退款 |
70
+
71
+ ---
72
+
73
+ ## 六、上线前校验
74
+
75
+ | 校验项 | 校验要求 | 说明 |
76
+ |----------|----------|----------|
77
+ | 网关地址切换 | 切换为生产网关 `https://openapi.alipay.com/gateway.do`| 上线前必须修改 |
78
+ | APPID 切换 | 使用生产环境的 APPID | 与沙箱 APPID 不同 |
79
+ | 密钥切换 | 使用生产环境的应用私钥和支付宝公钥 | 与沙箱密钥不同 |
80
+ | 生产密钥对应关系 | `appId`、应用公钥、应用私钥属于同一套生产应用密钥 | 不得混用沙箱应用、其他生产应用或另一套重新生成的密钥 |
81
+ | 生产私钥格式 | 应用私钥格式与项目语言 SDK 匹配 | Java 使用 PKCS#8;非 Java 使用 PKCS#1。格式不匹配时使用支付宝开放平台密钥工具转换 |
82
+ | 证书切换 | 公钥证书模式需切换为生产环境证书 | 应用公钥证书、支付宝公钥证书、支付宝根证书 |
83
+ | 产品开通状态 | 确认产品已在生产环境开通 | 沙箱无需开通,生产环境需要申请开通 |
84
+ | 私钥安全 | 私钥不在代码、日志、公共仓库中明文存储 | 使用安全的方式管理私钥 |
85
+ | 日志安全 | 日志中不打印敏感信息(私钥、用户信息等) | 防止信息泄露 |
86
+ | HTTPS 通信 | 生产环境必须使用 HTTPS | 保证传输安全 |
87
+
88
+ ---
89
+
90
+ ## 七、集成结果校验模板
91
+
92
+ > 复制以下模板,逐项填写校验结果并输出。校验结果说明:
93
+ > - ✅ 通过:已实现且符合规范
94
+ > - ❌ 不通过:未实现或不符合规范,需整改
95
+ > - ⚠️ 部分通过:部分实现,需补充完善
96
+ > - ➖ 不适用:当前集成场景不涉及此项
97
+
98
+ ### 一、校验结论
99
+ [校验结果整体结论,输出校验结果和风险情况]
100
+ ---
101
+
102
+ ### 二、校验清单
103
+
104
+ | 校验类别 | 校验项 | 校验结果 | 问题描述 |
105
+ |------|------|------|------|
106
+ | 密钥与安全校验 | | | |
107
+ | 异步通知校验 | | | |
108
+ | 支付结果处理校验 | | | |
109
+ | 按量付费专项校验 | | | |
110
+ | 退款校验 | | | |
111
+ | 上线前校验 | | | |
112
+ | **合计** | | | |
113
+
114
+ ---
115
+
116
+ ### 三、风险说明
117
+
118
+ [未通过校验项(❌不通过、⚠️部分通过)的风险说明,需要提醒用户发布前完成整改或确认风险可接受。]
119
+
120
+ ---
121
+
122
+ > 📖 本文档内容整理自支付宝开放平台官方文档,如有更新请以官方文档为准。
@@ -0,0 +1,68 @@
1
+ # 统一收单交易关闭接口 - C# 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```csharp
6
+ using Aop.Api;
7
+ using Aop.Api.Request;
8
+ using Aop.Api.Response;
9
+ using Aop.Api.Domain;
10
+
11
+ // 初始化SDK(C#/.NET 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
12
+ IAopClient alipayClient = new DefaultAopClient(GetAlipayConfig());
13
+
14
+ var request = new AlipayTradeCloseRequest();
15
+ var model = new AlipayTradeCloseModel
16
+ {
17
+ OutTradeNo = "MERCHANT_ORDER_NO_PLACEHOLDER", // 商户订单号,与 TradeNo 二选一
18
+ // TradeNo = "ALIPAY_TRADE_NO_PLACEHOLDER", // 支付宝交易号,同时传时以 TradeNo 为准
19
+ };
20
+ request.SetBizModel(model);
21
+
22
+ AlipayTradeCloseResponse response = alipayClient.Execute(request);
23
+
24
+ if (!response.IsError)
25
+ {
26
+ Console.WriteLine("交易关闭成功");
27
+ }
28
+ else
29
+ {
30
+ Console.WriteLine($"调用失败: {response.SubCode} - {response.SubMsg}");
31
+ }
32
+
33
+ private static AlipayConfig GetAlipayConfig()
34
+ {
35
+ string privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
36
+ string alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
37
+ AlipayConfig alipayConfig = new AlipayConfig();
38
+ alipayConfig.ServerUrl = "https://openapi.alipay.com/gateway.do";
39
+ // 沙箱环境: alipayConfig.ServerUrl = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
40
+ alipayConfig.AppId = "<-- 请填写您的AppId,例如:20190xxxxxx -->";
41
+ alipayConfig.PrivateKey = privateKey;
42
+ alipayConfig.Format = "json";
43
+ alipayConfig.AlipayPublicKey = alipayPublicKey;
44
+ alipayConfig.Charset = "UTF-8";
45
+ alipayConfig.SignType = "RSA2";
46
+ return alipayConfig;
47
+ }
48
+ ```
49
+
50
+ ## 响应示例
51
+ ### 正常示例
52
+ ```json
53
+ {
54
+ "code": "10000",
55
+ "msg": "Success",
56
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
57
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER"
58
+ }
59
+ ```
60
+ ### 异常示例
61
+ ```json
62
+ {
63
+ "code": "20000",
64
+ "msg": "Service Currently Unavailable",
65
+ "sub_code": "isp.unknow-error",
66
+ "sub_msg": "系统繁忙"
67
+ }
68
+ ```
@@ -0,0 +1,77 @@
1
+ # 统一收单交易查询接口 - C# 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```csharp
6
+ using Aop.Api;
7
+ using Aop.Api.Request;
8
+ using Aop.Api.Response;
9
+ using Aop.Api.Domain;
10
+
11
+ // 初始化SDK(C#/.NET 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
12
+ IAopClient alipayClient = new DefaultAopClient(GetAlipayConfig());
13
+
14
+ var request = new AlipayTradeQueryRequest();
15
+ var model = new AlipayTradeQueryModel
16
+ {
17
+ OutTradeNo = "MERCHANT_ORDER_NO_PLACEHOLDER", // 商户订单号,与 TradeNo 二选一
18
+ // TradeNo = "ALIPAY_TRADE_NO_PLACEHOLDER", // 支付宝交易号,同时传时以 TradeNo 为准
19
+ };
20
+ request.SetBizModel(model);
21
+
22
+ AlipayTradeQueryResponse response = alipayClient.Execute(request);
23
+
24
+ if (!response.IsError)
25
+ {
26
+ // trade_status: TRADE_SUCCESS/TRADE_FINISHED 表示支付成功,TRADE_CLOSED 表示已关闭
27
+ Console.WriteLine($"交易状态: {response.TradeStatus}");
28
+ Console.WriteLine($"订单金额: {response.TotalAmount}");
29
+ }
30
+ else
31
+ {
32
+ Console.WriteLine($"调用失败: {response.SubCode} - {response.SubMsg}");
33
+ }
34
+
35
+ private static AlipayConfig GetAlipayConfig()
36
+ {
37
+ string privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
38
+ string alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
39
+ AlipayConfig alipayConfig = new AlipayConfig();
40
+ alipayConfig.ServerUrl = "https://openapi.alipay.com/gateway.do";
41
+ // 沙箱环境: alipayConfig.ServerUrl = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
42
+ alipayConfig.AppId = "<-- 请填写您的AppId,例如:20190xxxxxx -->";
43
+ alipayConfig.PrivateKey = privateKey;
44
+ alipayConfig.Format = "json";
45
+ alipayConfig.AlipayPublicKey = alipayPublicKey;
46
+ alipayConfig.Charset = "UTF-8";
47
+ alipayConfig.SignType = "RSA2";
48
+ return alipayConfig;
49
+ }
50
+ ```
51
+
52
+ ## 响应示例
53
+ ### 正常示例
54
+ ```json
55
+ {
56
+ "code": "10000",
57
+ "msg": "Success",
58
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
59
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
60
+ "trade_status": "TRADE_SUCCESS",
61
+ "total_amount": "88.88",
62
+ "buyer_pay_amount": "8.88",
63
+ "receipt_amount": "15.25",
64
+ "buyer_logon_id": "159****5620",
65
+ "buyer_user_id": "<BUYER_USER_ID>",
66
+ "send_pay_date": "2014-11-27 15:45:57"
67
+ }
68
+ ```
69
+ ### 异常示例
70
+ ```json
71
+ {
72
+ "code": "20000",
73
+ "msg": "Service Currently Unavailable",
74
+ "sub_code": "isp.unknow-error",
75
+ "sub_msg": "系统繁忙"
76
+ }
77
+ ```
@@ -0,0 +1,74 @@
1
+ # 统一收单交易退款接口 - C# 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```csharp
6
+ using Aop.Api;
7
+ using Aop.Api.Request;
8
+ using Aop.Api.Response;
9
+ using Aop.Api.Domain;
10
+
11
+ // 初始化SDK(C#/.NET 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
12
+ IAopClient alipayClient = new DefaultAopClient(GetAlipayConfig());
13
+
14
+ var request = new AlipayTradeRefundRequest();
15
+ var model = new AlipayTradeRefundModel
16
+ {
17
+ OutTradeNo = "MERCHANT_ORDER_NO_PLACEHOLDER", // 商户订单号,与 TradeNo 二选一
18
+ RefundAmount = "200.12", // 退款金额,必填,单位为元
19
+ RefundReason = "正常退款", // 退款原因,选填
20
+ OutRequestNo = "OUT_REQUEST_NO_PLACEHOLDER", // 退款请求号,同一笔交易多次部分退款时必填且必须不同
21
+ };
22
+ request.SetBizModel(model);
23
+
24
+ AlipayTradeRefundResponse response = alipayClient.Execute(request);
25
+
26
+ if (!response.IsError)
27
+ {
28
+ // fund_change: Y=发生了资金变化(退款成功),N=未发生资金变化
29
+ Console.WriteLine($"资金变化: {response.FundChange}, 退款金额: {response.RefundFee}");
30
+ }
31
+ else
32
+ {
33
+ Console.WriteLine($"调用失败: {response.SubCode} - {response.SubMsg}");
34
+ }
35
+
36
+ private static AlipayConfig GetAlipayConfig()
37
+ {
38
+ string privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
39
+ string alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
40
+ AlipayConfig alipayConfig = new AlipayConfig();
41
+ alipayConfig.ServerUrl = "https://openapi.alipay.com/gateway.do";
42
+ // 沙箱环境: alipayConfig.ServerUrl = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
43
+ alipayConfig.AppId = "<-- 请填写您的AppId,例如:20190xxxxxx -->";
44
+ alipayConfig.PrivateKey = privateKey;
45
+ alipayConfig.Format = "json";
46
+ alipayConfig.AlipayPublicKey = alipayPublicKey;
47
+ alipayConfig.Charset = "UTF-8";
48
+ alipayConfig.SignType = "RSA2";
49
+ return alipayConfig;
50
+ }
51
+ ```
52
+
53
+ ## 响应示例
54
+ ### 正常示例
55
+ ```json
56
+ {
57
+ "code": "10000",
58
+ "msg": "Success",
59
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
60
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
61
+ "buyer_logon_id": "159****5620",
62
+ "fund_change": "Y",
63
+ "refund_fee": "88.88"
64
+ }
65
+ ```
66
+ ### 异常示例
67
+ ```json
68
+ {
69
+ "code": "20000",
70
+ "msg": "Service Currently Unavailable",
71
+ "sub_code": "isp.unknow-error",
72
+ "sub_msg": "系统繁忙"
73
+ }
74
+ ```
@@ -0,0 +1,73 @@
1
+ # 统一收单交易退款查询接口 - C# 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```csharp
6
+ using Aop.Api;
7
+ using Aop.Api.Request;
8
+ using Aop.Api.Response;
9
+ using Aop.Api.Domain;
10
+
11
+ // 初始化SDK(C#/.NET 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
12
+ IAopClient alipayClient = new DefaultAopClient(GetAlipayConfig());
13
+
14
+ var request = new AlipayTradeFastpayRefundQueryRequest();
15
+ var model = new AlipayTradeFastpayRefundQueryModel
16
+ {
17
+ OutTradeNo = "MERCHANT_ORDER_NO_PLACEHOLDER", // 商户订单号,与 TradeNo 二选一
18
+ OutRequestNo = "OUT_REQUEST_NO_PLACEHOLDER", // 退款请求号,必填,同一笔交易多次部分退款时用于区分
19
+ };
20
+ request.SetBizModel(model);
21
+
22
+ AlipayTradeFastpayRefundQueryResponse response = alipayClient.Execute(request);
23
+
24
+ if (!response.IsError)
25
+ {
26
+ // refund_status: REFUND_SUCCESS 表示退款成功,REFUND_PROCESSING 表示退款处理中
27
+ Console.WriteLine($"退款状态: {response.RefundStatus}, 退款金额: {response.RefundAmount}");
28
+ }
29
+ else
30
+ {
31
+ Console.WriteLine($"调用失败: {response.SubCode} - {response.SubMsg}");
32
+ }
33
+
34
+ private static AlipayConfig GetAlipayConfig()
35
+ {
36
+ string privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
37
+ string alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
38
+ AlipayConfig alipayConfig = new AlipayConfig();
39
+ alipayConfig.ServerUrl = "https://openapi.alipay.com/gateway.do";
40
+ // 沙箱环境: alipayConfig.ServerUrl = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
41
+ alipayConfig.AppId = "<-- 请填写您的AppId,例如:20190xxxxxx -->";
42
+ alipayConfig.PrivateKey = privateKey;
43
+ alipayConfig.Format = "json";
44
+ alipayConfig.AlipayPublicKey = alipayPublicKey;
45
+ alipayConfig.Charset = "UTF-8";
46
+ alipayConfig.SignType = "RSA2";
47
+ return alipayConfig;
48
+ }
49
+ ```
50
+
51
+ ## 响应示例
52
+ ### 正常示例
53
+ ```json
54
+ {
55
+ "code": "10000",
56
+ "msg": "Success",
57
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
58
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
59
+ "out_request_no": "OUT_REQUEST_NO_PLACEHOLDER",
60
+ "total_amount": "100.20",
61
+ "refund_amount": "12.33",
62
+ "refund_status": "REFUND_SUCCESS"
63
+ }
64
+ ```
65
+ ### 异常示例
66
+ ```json
67
+ {
68
+ "code": "20000",
69
+ "msg": "Service Currently Unavailable",
70
+ "sub_code": "isp.unknow-error",
71
+ "sub_msg": "系统繁忙"
72
+ }
73
+ ```