@alipay/alipay-aipay 1.7.0 → 1.7.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 (169) hide show
  1. package/README.md +30 -0
  2. package/dist/commands/install-current.js +15 -7
  3. package/dist/commands/install.js +20 -16
  4. package/dist/commands/uninstall.js +8 -3
  5. package/dist/commands/update.js +34 -16
  6. package/dist/index.js +10 -4
  7. package/dist/utils/channels.js +67 -0
  8. package/dist/utils/config.js +15 -11
  9. package/dist/utils/file.js +23 -10
  10. package/dist/utils/npm.js +19 -33
  11. package/package.json +8 -3
  12. package/skill/SKILL.md +2 -0
  13. package/skill/references/normal/json/release-channel.json +1 -0
  14. package/skill/references/normal/scripts/self_update.mjs +62 -17
  15. package/skill/references/normal/self-update.md +3 -1
  16. package/skill-pre/SKILL.md +65 -0
  17. package/skill-pre/VERSION +1 -0
  18. package/skill-pre/references/integration/flow.md +602 -0
  19. package/skill-pre/references/integration/modules/alipay-sdk-reminder.md +281 -0
  20. package/skill-pre/references/integration/modules/checklist.md +154 -0
  21. package/skill-pre/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +199 -0
  22. package/skill-pre/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
  23. package/skill-pre/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 +83 -0
  24. package/skill-pre/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 +80 -0
  25. package/skill-pre/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
  26. package/skill-pre/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 +62 -0
  27. package/skill-pre/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 +132 -0
  28. package/skill-pre/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +640 -0
  29. package/skill-pre/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +184 -0
  30. package/skill-pre/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
  31. package/skill-pre/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 +96 -0
  32. package/skill-pre/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 +81 -0
  33. package/skill-pre/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
  34. package/skill-pre/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 +69 -0
  35. package/skill-pre/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 +138 -0
  36. package/skill-pre/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.md +623 -0
  37. package/skill-pre/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +135 -0
  38. package/skill-pre/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
  39. package/skill-pre/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 +63 -0
  40. package/skill-pre/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 +59 -0
  41. package/skill-pre/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
  42. package/skill-pre/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 +84 -0
  43. package/skill-pre/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 +71 -0
  44. package/skill-pre/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +498 -0
  45. package/skill-pre/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +157 -0
  46. package/skill-pre/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
  47. package/skill-pre/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 +73 -0
  48. package/skill-pre/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 +69 -0
  49. package/skill-pre/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
  50. package/skill-pre/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 +59 -0
  51. package/skill-pre/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 +110 -0
  52. package/skill-pre/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +806 -0
  53. package/skill-pre/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +128 -0
  54. package/skill-pre/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
  55. package/skill-pre/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 +70 -0
  56. package/skill-pre/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 +65 -0
  57. package/skill-pre/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
  58. package/skill-pre/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 +51 -0
  59. package/skill-pre/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 +47 -0
  60. package/skill-pre/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +541 -0
  61. package/skill-pre/references/integration/modules/interface-contract/aipay-interface-contract.md +52 -0
  62. package/skill-pre/references/integration/modules/interface-contract/apppay-interface-contract.md +45 -0
  63. package/skill-pre/references/integration/modules/interface-contract/common-trade-contract.md +42 -0
  64. package/skill-pre/references/integration/modules/interface-contract/notify-url-contract.md +68 -0
  65. package/skill-pre/references/integration/modules/interface-contract/webpay-interface-contract.md +44 -0
  66. package/skill-pre/references/integration/modules/interface-guide.md +61 -0
  67. package/skill-pre/references/integration/modules/product-decision.md +73 -0
  68. package/skill-pre/references/integration/modules/sandbox/a2m-sandbox-test.md +235 -0
  69. package/skill-pre/references/integration/modules/sandbox/alipay-sandbox-tool.md +142 -0
  70. package/skill-pre/references/integration/modules/sandbox/sandbox-setup-guide.md +239 -0
  71. package/skill-pre/references/integration/modules/scripts/local_402_sandbox_pay.py +900 -0
  72. package/skill-pre/references/integration/modules/scripts/sandbox_config.sh +347 -0
  73. package/skill-pre/references/integration/modules/troubleshooting-flow.md +28 -0
  74. package/skill-pre/references/normal/alipay-cli-env.md +169 -0
  75. package/skill-pre/references/normal/conversation-telemetry.md +101 -0
  76. package/skill-pre/references/normal/full-process-routing.md +92 -0
  77. package/skill-pre/references/normal/integration-worker.md +90 -0
  78. package/skill-pre/references/normal/json/customer-messages.json +1 -0
  79. package/skill-pre/references/normal/json/managed-jq-assets.json +1 -0
  80. package/skill-pre/references/normal/json/policy-rules.json +1 -0
  81. package/skill-pre/references/normal/json/release-channel.json +1 -0
  82. package/skill-pre/references/normal/rejection-guide.md +41 -0
  83. package/skill-pre/references/normal/scripts/agent_platform.mjs +43 -0
  84. package/skill-pre/references/normal/scripts/alipay_cli_env.mjs +34 -0
  85. package/skill-pre/references/normal/scripts/alipay_cli_env.sh +55 -0
  86. package/skill-pre/references/normal/scripts/alipay_cli_refresh.mjs +129 -0
  87. package/skill-pre/references/normal/scripts/auth_runtime_runner.mjs +60 -0
  88. package/skill-pre/references/normal/scripts/checklist_sections.mjs +43 -0
  89. package/skill-pre/references/normal/scripts/common.sh +365 -0
  90. package/skill-pre/references/normal/scripts/conversation_telemetry.mjs +105 -0
  91. package/skill-pre/references/normal/scripts/detect_dev_tool.sh +79 -0
  92. package/skill-pre/references/normal/scripts/flow_loader.mjs +237 -0
  93. package/skill-pre/references/normal/scripts/integration_context_runner.mjs +151 -0
  94. package/skill-pre/references/normal/scripts/integration_message_runner.mjs +1456 -0
  95. package/skill-pre/references/normal/scripts/interaction_reply.mjs +140 -0
  96. package/skill-pre/references/normal/scripts/managed_jq.mjs +215 -0
  97. package/skill-pre/references/normal/scripts/onboarding_discovery_runner.mjs +387 -0
  98. package/skill-pre/references/normal/scripts/onboarding_message_runner.mjs +1425 -0
  99. package/skill-pre/references/normal/scripts/onboarding_recovery_runner.mjs +100 -0
  100. package/skill-pre/references/normal/scripts/open_official_url.sh +205 -0
  101. package/skill-pre/references/normal/scripts/platform_compat.mjs +42 -0
  102. package/skill-pre/references/normal/scripts/preview_runtime.mjs +151 -0
  103. package/skill-pre/references/normal/scripts/project_route_inspector.sh +132 -0
  104. package/skill-pre/references/normal/scripts/python_script_runner.mjs +58 -0
  105. package/skill-pre/references/normal/scripts/render_customer_message.mjs +1792 -0
  106. package/skill-pre/references/normal/scripts/runtime.mjs +271 -0
  107. package/skill-pre/references/normal/scripts/self_update.mjs +376 -0
  108. package/skill-pre/references/normal/scripts/telemetry.mjs +2102 -0
  109. package/skill-pre/references/normal/self-update.md +7 -0
  110. package/skill-pre/references/normal/telemetry.md +70 -0
  111. package/skill-pre/references/onboarding/assets/keygen.html +927 -0
  112. package/skill-pre/references/onboarding/flow.md +607 -0
  113. package/skill-pre/references/onboarding/modules/app-release.md +90 -0
  114. package/skill-pre/references/onboarding/modules/authorization.md +43 -0
  115. package/skill-pre/references/onboarding/modules/error-handling.md +62 -0
  116. package/skill-pre/references/onboarding/modules/product-sign.md +49 -0
  117. package/skill-pre/references/onboarding/modules/scripts/app.sh +1485 -0
  118. package/skill-pre/references/onboarding/modules/scripts/ar_sign_apply.sh +331 -0
  119. package/skill-pre/references/onboarding/modules/scripts/auth.sh +1040 -0
  120. package/skill-pre/references/onboarding/modules/scripts/download_key_tool.sh +4 -0
  121. package/skill-pre/references/onboarding/modules/scripts/error_handler.sh +841 -0
  122. package/skill-pre/references/onboarding/modules/scripts/mcc.sh +1085 -0
  123. package/skill-pre/references/onboarding/modules/scripts/network_retry.sh +135 -0
  124. package/skill-pre/references/onboarding/modules/scripts/query_sign_status.sh +105 -0
  125. package/skill-pre/references/onboarding/modules/scripts/service.sh +528 -0
  126. package/skill-pre/references/onboarding/modules/scripts/sign_status_parser.sh +58 -0
  127. package/skill-pre/references/onboarding/modules/scripts/upload_screenshots.sh +208 -0
  128. package/skill-pre/references/onboarding/modules/scripts/upload_special_license.sh +195 -0
  129. package/skill-pre/references/onboarding/modules/service-registration.md +40 -0
  130. package/skill-pre/references/runtime-entry.md +99 -0
  131. package/dist/commands/install-current.d.ts +0 -4
  132. package/dist/commands/install-current.d.ts.map +0 -1
  133. package/dist/commands/install-current.js.map +0 -1
  134. package/dist/commands/install.d.ts +0 -10
  135. package/dist/commands/install.d.ts.map +0 -1
  136. package/dist/commands/install.js.map +0 -1
  137. package/dist/commands/prepare-tools.d.ts +0 -5
  138. package/dist/commands/prepare-tools.d.ts.map +0 -1
  139. package/dist/commands/prepare-tools.js.map +0 -1
  140. package/dist/commands/uninstall.d.ts +0 -10
  141. package/dist/commands/uninstall.d.ts.map +0 -1
  142. package/dist/commands/uninstall.js.map +0 -1
  143. package/dist/commands/update.d.ts +0 -10
  144. package/dist/commands/update.d.ts.map +0 -1
  145. package/dist/commands/update.js.map +0 -1
  146. package/dist/index.d.ts +0 -2
  147. package/dist/index.d.ts.map +0 -1
  148. package/dist/index.js.map +0 -1
  149. package/dist/types.d.ts +0 -42
  150. package/dist/types.d.ts.map +0 -1
  151. package/dist/types.js.map +0 -1
  152. package/dist/utils/alipay-cli.d.ts +0 -20
  153. package/dist/utils/alipay-cli.d.ts.map +0 -1
  154. package/dist/utils/alipay-cli.js.map +0 -1
  155. package/dist/utils/config.d.ts +0 -52
  156. package/dist/utils/config.d.ts.map +0 -1
  157. package/dist/utils/config.js.map +0 -1
  158. package/dist/utils/file.d.ts +0 -77
  159. package/dist/utils/file.d.ts.map +0 -1
  160. package/dist/utils/file.js.map +0 -1
  161. package/dist/utils/jq.d.ts +0 -17
  162. package/dist/utils/jq.d.ts.map +0 -1
  163. package/dist/utils/jq.js.map +0 -1
  164. package/dist/utils/npm.d.ts +0 -17
  165. package/dist/utils/npm.d.ts.map +0 -1
  166. package/dist/utils/npm.js.map +0 -1
  167. package/dist/utils/shell.d.ts +0 -24
  168. package/dist/utils/shell.d.ts.map +0 -1
  169. package/dist/utils/shell.js.map +0 -1
@@ -0,0 +1,135 @@
1
+ # 异步通知处理 - Node.js 示例
2
+
3
+ 适用产品:AI 网页应用收款、AI 移动应用收款。AI 按量付费不使用异步通知。
4
+
5
+ ```javascript
6
+ const express = require("express");
7
+
8
+ // 支付宝异步通知是 application/x-www-form-urlencoded 表单,不能用 JSON parser 代替。
9
+ // createAlipayNotifyRouter 依赖项目里的真实 SDK 工厂、支付配置、订单仓储和通知事件仓储。
10
+ // 生产环境必须用持久化订单表和通知事件表做幂等;内存 Map 只能用于非生产 demo。
11
+ function createAlipayNotifyRouter(deps) {
12
+ const router = express.Router();
13
+ router.use(express.urlencoded({ extended: false }));
14
+
15
+ router.post("/alipay/notify", async (req, res) => {
16
+ const params = { ...req.body };
17
+
18
+ try {
19
+ const config = await deps.paymentConfigRepository.findByAppId(params.app_id);
20
+ if (!config) {
21
+ return fail(res, deps, "alipay notify app config not found", params);
22
+ }
23
+
24
+ const alipaySdk = deps.alipaySdkFactory.create(config);
25
+ if (!(await verifyNotifyWithAlipaySdk(params, alipaySdk))) {
26
+ return fail(res, deps, "alipay notify signature check failed", params);
27
+ }
28
+
29
+ const order = await deps.orderRepository.findByOutTradeNo(params.out_trade_no);
30
+ if (!order || !businessFieldsMatch(order, params, config)) {
31
+ return fail(res, deps, "alipay notify business check failed", params);
32
+ }
33
+
34
+ const inserted = await deps.notifyEventRepository.insertOnce({
35
+ notifyId: params.notify_id,
36
+ tradeNo: params.trade_no,
37
+ outTradeNo: params.out_trade_no,
38
+ tradeStatus: params.trade_status,
39
+ rawParams: params,
40
+ });
41
+ if (!inserted) {
42
+ return res.type("text/plain").send("success");
43
+ }
44
+
45
+ if (isPaidTradeNotification(params)) {
46
+ await deps.orderRepository.markPaidIdempotently(order.outTradeNo, params.trade_no, params);
47
+ } else {
48
+ await deps.orderRepository.recordNonPaidTradeEvent(order.outTradeNo, params.trade_status, params);
49
+ }
50
+
51
+ return res.type("text/plain").send("success");
52
+ } catch (error) {
53
+ safeLogNotifyError(deps, "alipay notify unexpected exception", params);
54
+ return res.type("text/plain").send("fail");
55
+ }
56
+ });
57
+
58
+ return router;
59
+ }
60
+
61
+ async function verifyNotifyWithAlipaySdk(params, alipaySdk) {
62
+ // 落地前先查看目标项目 node_modules/alipay-sdk 的 package.json 和 .d.ts。
63
+ // 如果当前版本类型定义确认存在 checkNotifySignV2(params),按当前 SDK 实际 API 调用。
64
+ if (typeof alipaySdk.checkNotifySignV2 !== "function") {
65
+ throw new Error("current alipay-sdk does not expose checkNotifySignV2; confirm SDK types before coding");
66
+ }
67
+ return await Promise.resolve(alipaySdk.checkNotifySignV2(params));
68
+ }
69
+
70
+ function businessFieldsMatch(order, params, config) {
71
+ return params.app_id === config.appId
72
+ && params.out_trade_no === order.outTradeNo
73
+ && amountEquals(order.totalAmount, params.total_amount)
74
+ && expectedSellerMatches(config, params.seller_id, params.seller_email);
75
+ }
76
+
77
+ function isPaidTradeNotification(params) {
78
+ const paidStatus = params.trade_status === "TRADE_SUCCESS" || params.trade_status === "TRADE_FINISHED";
79
+ return paidStatus && !params.out_biz_no && !params.gmt_refund && !params.refund_fee;
80
+ }
81
+
82
+ function amountEquals(expected, actual) {
83
+ const expectedAmount = normalizeAmountText(expected);
84
+ const actualAmount = normalizeAmountText(actual);
85
+ return expectedAmount !== null && expectedAmount === actualAmount;
86
+ }
87
+
88
+ // 返回“元”为单位、保留两位小数的金额文本,例如 88.00;不要用浮点数直接比较金额。
89
+ function normalizeAmountText(value) {
90
+ if (value == null) return null;
91
+ const text = String(value).trim();
92
+ const match = text.match(/^(\d+)(?:\.(\d{1,2}))?$/);
93
+ if (!match) return null;
94
+ return `${BigInt(match[1]).toString()}.${(match[2] || "").padEnd(2, "0")}`;
95
+ }
96
+
97
+ function expectedSellerMatches(config, sellerId, sellerEmail) {
98
+ const expectedSellerId = config.sellerId;
99
+ const expectedSellerEmail = config.sellerEmail;
100
+ return Boolean(
101
+ (expectedSellerId && sellerId === expectedSellerId)
102
+ || (expectedSellerEmail && sellerEmail === expectedSellerEmail)
103
+ );
104
+ }
105
+
106
+ function fail(res, deps, message, params) {
107
+ safeLogNotifyError(deps, message, params);
108
+ return res.type("text/plain").send("fail");
109
+ }
110
+
111
+ function safeLogNotifyError(deps, message, params) {
112
+ try {
113
+ deps.logger.warn(message, sanitizeNotifyParams(params));
114
+ } catch (error) {
115
+ // 日志失败不能影响支付宝收到纯文本 fail。
116
+ }
117
+ }
118
+
119
+ function sanitizeNotifyParams(params) {
120
+ const { sign, ...safeParams } = params;
121
+ return safeParams;
122
+ }
123
+
124
+ module.exports = { createAlipayNotifyRouter };
125
+ ```
126
+
127
+ 要点:
128
+
129
+ - `notify_url` 路由必须使用表单解析中间件,不要用 JSON parser 读取支付宝通知。
130
+ - 验签必须调用当前项目支付宝 SDK 的实际验签 API;Node.js 落地前先查目标项目 `alipay-sdk` 类型定义确认 `checkNotifySignV2(params)` 是否存在。
131
+ - `app_id`、`seller_id` / `seller_email` 从运行时支付配置校验,不从订单对象默认取值。
132
+ - 金额校验使用“元”为单位的两位小数字符串或项目定点数工具,不要用浮点数直接比较。
133
+ - 只有付款成功状态且不是退款、关单、分账等事件时,才认定付款成功。
134
+ - 内存订单或内存幂等只能用于非生产 demo,生产必须使用持久化订单表和通知事件表。
135
+ - 处理成功后返回纯文本 `success`;异常、验签失败或业务校验失败返回 `fail`。
@@ -0,0 +1,51 @@
1
+ # 统一收单交易关闭接口 - Node.js 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```javascript
6
+ const { AlipaySdk } = require("alipay-sdk");
7
+
8
+ const alipaySdk = new AlipaySdk({
9
+ appId: "<-- 请填写您的AppId,例如:20190xxxxxx -->",
10
+ privateKey: "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->", // Node.js 使用 PKCS#1 格式私钥
11
+ alipayPublicKey: "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->",
12
+ gateway: "https://openapi.alipay.com/gateway.do",
13
+ signType: "RSA2",
14
+ // 第三方代调用模式下请设置 appAuthToken
15
+ // appAuthToken: "<-- 请填写应用授权令牌 -->",
16
+ });
17
+
18
+ // 交易关闭用于关闭未支付的订单
19
+ // 注意:交易关闭与交易撤销是不同接口 —— 关闭用于未支付订单,撤销用于已支付订单(仅限支付当天)
20
+ const result = await alipaySdk.exec("alipay.trade.close", {
21
+ bizContent: {
22
+ out_trade_no: "MERCHANT_ORDER_NO_PLACEHOLDER", // 商户订单号,与 trade_no 二选一
23
+ },
24
+ });
25
+
26
+ if (result.code === "10000") {
27
+ console.log("调用成功");
28
+ } else {
29
+ console.log("调用失败");
30
+ }
31
+ ```
32
+
33
+ ## 响应示例
34
+ ### 正常示例
35
+ ```json
36
+ {
37
+ "code": "10000",
38
+ "msg": "Success",
39
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
40
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER"
41
+ }
42
+ ```
43
+ ### 异常示例
44
+ ```json
45
+ {
46
+ "code": "20000",
47
+ "msg": "Service Currently Unavailable",
48
+ "sub_code": "isp.unknow-error",
49
+ "sub_msg": "系统繁忙"
50
+ }
51
+ ```
@@ -0,0 +1,63 @@
1
+ # 统一收单交易查询接口 - Node.js 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```javascript
6
+ const { AlipaySdk } = require("alipay-sdk");
7
+
8
+ const alipaySdk = new AlipaySdk({
9
+ appId: "<-- 请填写您的AppId,例如:20190xxxxxx -->",
10
+ privateKey: "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->", // Node.js 使用 PKCS#1 格式私钥
11
+ alipayPublicKey: "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->",
12
+ gateway: "https://openapi.alipay.com/gateway.do",
13
+ signType: "RSA2",
14
+ // 第三方代调用模式下请设置 appAuthToken
15
+ // appAuthToken: "<-- 请填写应用授权令牌 -->",
16
+ });
17
+
18
+ const result = await alipaySdk.exec("alipay.trade.query", {
19
+ bizContent: {
20
+ out_trade_no: "MERCHANT_ORDER_NO_PLACEHOLDER",
21
+ },
22
+ });
23
+
24
+ if (result.code === "10000") {
25
+ const businessState = {
26
+ TRADE_SUCCESS: "PAID",
27
+ TRADE_FINISHED: "PAID",
28
+ WAIT_BUYER_PAY: "PENDING_PAYMENT",
29
+ TRADE_CLOSED: "CLOSED",
30
+ }[result.trade_status] || "UNKNOWN";
31
+ console.log("业务状态:", businessState, "支付宝状态:", result.trade_status);
32
+ } else {
33
+ console.log("调用失败");
34
+ }
35
+ ```
36
+
37
+ ## 响应示例
38
+ ### 正常示例
39
+ ```json
40
+ {
41
+ "code": "10000",
42
+ "msg": "Success",
43
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
44
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
45
+ "buyer_logon_id": "159****5620",
46
+ "trade_status": "TRADE_SUCCESS",
47
+ "total_amount": "88.88",
48
+ "buyer_pay_amount": "8.88",
49
+ "receipt_amount": "15.25",
50
+ "invoice_amount": "12.11",
51
+ "buyer_user_id": "<BUYER_USER_ID>",
52
+ "send_pay_date": "2014-11-27 15:45:57"
53
+ }
54
+ ```
55
+ ### 异常示例
56
+ ```json
57
+ {
58
+ "code": "20000",
59
+ "msg": "Service Currently Unavailable",
60
+ "sub_code": "isp.unknow-error",
61
+ "sub_msg": "系统繁忙"
62
+ }
63
+ ```
@@ -0,0 +1,59 @@
1
+ # 统一收单交易退款接口 - Node.js 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```javascript
6
+ const { AlipaySdk } = require("alipay-sdk");
7
+
8
+ const alipaySdk = new AlipaySdk({
9
+ appId: "<-- 请填写您的AppId,例如:20190xxxxxx -->",
10
+ privateKey: "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->", // Node.js 使用 PKCS#1 格式私钥
11
+ alipayPublicKey: "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->",
12
+ gateway: "https://openapi.alipay.com/gateway.do",
13
+ signType: "RSA2",
14
+ // 第三方代调用模式下请设置 appAuthToken
15
+ // appAuthToken: "<-- 请填写应用授权令牌 -->",
16
+ });
17
+
18
+ const result = await alipaySdk.exec("alipay.trade.refund", {
19
+ bizContent: {
20
+ out_trade_no: "MERCHANT_ORDER_NO_PLACEHOLDER", // 商户订单号,与 trade_no 二选一
21
+ refund_amount: "200.12", // 使用十进制定点金额;调用前校验累计退款不超过原订单实付金额
22
+ refund_reason: "正常退款", // 退款原因,选填
23
+ out_request_no: "OUT_REQUEST_NO_PLACEHOLDER", // 新退款使用新编号;同一退款失败重试必须复用原编号和原参数
24
+ },
25
+ });
26
+
27
+ if (result.code === "10000") {
28
+ if (result.fund_change === "Y") {
29
+ console.log("退款资金已发生变化,退款金额:", result.refund_fee);
30
+ } else {
31
+ console.log("退款结果待确认:使用同一 out_request_no 调用 alipay.trade.fastpay.refund.query");
32
+ }
33
+ } else {
34
+ console.log("调用失败");
35
+ }
36
+ ```
37
+
38
+ ## 响应示例
39
+ ### 正常示例
40
+ ```json
41
+ {
42
+ "code": "10000",
43
+ "msg": "Success",
44
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
45
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
46
+ "buyer_logon_id": "159****5620",
47
+ "fund_change": "Y",
48
+ "refund_fee": "88.88"
49
+ }
50
+ ```
51
+ ### 异常示例
52
+ ```json
53
+ {
54
+ "code": "20000",
55
+ "msg": "Service Currently Unavailable",
56
+ "sub_code": "isp.unknow-error",
57
+ "sub_msg": "系统繁忙"
58
+ }
59
+ ```
@@ -0,0 +1,54 @@
1
+ # 统一收单交易退款查询接口 - Node.js 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```javascript
6
+ const { AlipaySdk } = require("alipay-sdk");
7
+
8
+ const alipaySdk = new AlipaySdk({
9
+ appId: "<-- 请填写您的AppId,例如:20190xxxxxx -->",
10
+ privateKey: "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->", // Node.js 使用 PKCS#1 格式私钥
11
+ alipayPublicKey: "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->",
12
+ gateway: "https://openapi.alipay.com/gateway.do",
13
+ signType: "RSA2",
14
+ // 第三方代调用模式下请设置 appAuthToken
15
+ // appAuthToken: "<-- 请填写应用授权令牌 -->",
16
+ });
17
+
18
+ const result = await alipaySdk.exec("alipay.trade.fastpay.refund.query", {
19
+ bizContent: {
20
+ out_trade_no: "MERCHANT_ORDER_NO_PLACEHOLDER", // 商户订单号,与 trade_no 二选一
21
+ out_request_no: "OUT_REQUEST_NO_PLACEHOLDER", // 退款请求号,必填,同一笔交易多次部分退款时用于区分
22
+ },
23
+ });
24
+
25
+ if (result.code === "10000") {
26
+ console.log("调用成功");
27
+ } else {
28
+ console.log("调用失败");
29
+ }
30
+ ```
31
+
32
+ ## 响应示例
33
+ ### 正常示例
34
+ ```json
35
+ {
36
+ "code": "10000",
37
+ "msg": "Success",
38
+ "trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
39
+ "out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
40
+ "out_request_no": "OUT_REQUEST_NO_PLACEHOLDER",
41
+ "total_amount": "100.20",
42
+ "refund_amount": "12.33",
43
+ "refund_status": "REFUND_SUCCESS"
44
+ }
45
+ ```
46
+ ### 异常示例
47
+ ```json
48
+ {
49
+ "code": "20000",
50
+ "msg": "Service Currently Unavailable",
51
+ "sub_code": "isp.unknow-error",
52
+ "sub_msg": "系统繁忙"
53
+ }
54
+ ```
@@ -0,0 +1,84 @@
1
+ # 统一收单下单并支付页面接口 - Node.js 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```javascript
6
+ const { AlipaySdk } = require("alipay-sdk");
7
+
8
+ const alipaySdk = new AlipaySdk({
9
+ appId: "<-- 请填写您的AppId,例如:20190xxxxxx -->",
10
+ privateKey: "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->", // Node.js 使用 PKCS#1 格式私钥
11
+ alipayPublicKey: "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->",
12
+ gateway: "https://openapi.alipay.com/gateway.do",
13
+ signType: "RSA2",
14
+ // 第三方代调用模式下请设置 appAuthToken
15
+ // appAuthToken: "<-- 请填写应用授权令牌 -->",
16
+ });
17
+
18
+ // ⚠️ 网站支付必须使用 pageExec() 方法,不能使用 exec()
19
+ // ⚠️ pageExec() 第二个参数必须传 'POST'
20
+ // ⚠️ notifyUrl 在真实生产或公网联调时传入;本地生产参数验收模式可临时不传,但仍需实现通知处理代码
21
+ // ⚠️ 本地没有公网 HTTPS notifyUrl 时,直接省略 notifyUrl,不要向 SDK 传 undefined、空字符串或占位 URL
22
+ // ⚠️ returnUrl 默认传入,仅在用户明确关闭同步回跳时省略
23
+ const notifyUrl = (process.env.ALIPAY_NOTIFY_URL || "").trim();
24
+ const requestOptions = {
25
+ returnUrl: "https://your-domain.com/return", // 默认传入并替换为已验证结果页;仅用户明确关闭同步回跳时省略
26
+ bizContent: {
27
+ out_trade_no: "MERCHANT_ORDER_NO_PLACEHOLDER", // 商户订单号,必填
28
+ total_amount: "88.88", // 订单总金额,必填,单位为元,精确到小数点后两位
29
+ subject: "Iphone6 16G", // 订单标题,必填
30
+ product_code: "FAST_INSTANT_TRADE_PAY", // 网站支付固定值,必填
31
+ },
32
+ };
33
+ if (notifyUrl) {
34
+ requestOptions.notifyUrl = notifyUrl;
35
+ }
36
+
37
+ const result = alipaySdk.pageExec(
38
+ "alipay.trade.page.pay",
39
+ "POST",
40
+ requestOptions
41
+ );
42
+
43
+ // pageExec 返回的是 HTML 表单字符串,前端需要渲染并自动提交
44
+ // ⚠️ 禁止用 URL 直接跳转,否则页面只会显示参数而无法跳转支付宝
45
+ console.log(result);
46
+ ```
47
+
48
+ ### 前端渲染支付表单
49
+
50
+ ```javascript
51
+ // pageExec 返回的 result 是包含自动提交脚本的 HTML <form> 字符串
52
+ // 前端必须将此 HTML 渲染到页面并自动提交表单
53
+
54
+ // ✅ 正确写法(以浏览器端 JavaScript 为例)
55
+ if (data.paymentHtml) {
56
+ const container = document.createElement('div');
57
+ container.innerHTML = data.paymentHtml;
58
+ container.style.position = 'fixed';
59
+ container.style.top = '0';
60
+ container.style.left = '0';
61
+ container.style.width = '100%';
62
+ container.style.height = '100%';
63
+ container.style.zIndex = '9999';
64
+ container.style.background = 'white';
65
+ document.body.appendChild(container);
66
+ const form = container.querySelector('form');
67
+ if (form) form.submit();
68
+ }
69
+
70
+ // ❌ 错误写法 — 禁止用 URL 直接跳转
71
+ // window.location.href = data.paymentHtml; // 页面只会显示参数,无法跳转支付宝
72
+ ```
73
+
74
+ ## 响应示例
75
+
76
+ ### 正常示例
77
+
78
+ ```html
79
+ <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">
80
+ <input type="hidden" name="biz_content" value="{&quot;out_trade_no&quot;:&quot;MERCHANT_ORDER_NO_PLACEHOLDER&quot;,&quot;total_amount&quot;:&quot;88.88&quot;,&quot;subject&quot;:&quot;Iphone6 16G&quot;,&quot;product_code&quot;:&quot;FAST_INSTANT_TRADE_PAY&quot;}">
81
+ <input type="submit" value="立即支付" style="display:none" >
82
+ </form>
83
+ <script>document.forms[0].submit();</script>
84
+ ```
@@ -0,0 +1,71 @@
1
+ # APP 支付接口 - Node.js 示例
2
+
3
+ ## 请求示例
4
+
5
+ ```javascript
6
+ const { AlipaySdk } = require("alipay-sdk");
7
+
8
+ const alipaySdk = new AlipaySdk({
9
+ appId: "<-- 请填写您的AppId,例如:20190xxxxxx -->",
10
+ privateKey: "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->",
11
+ alipayPublicKey: "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->",
12
+ gateway: "https://openapi.alipay.com/gateway.do",
13
+ appAuthToken: "<-- 请填写应用授权令牌 -->",
14
+ });
15
+
16
+ // 真实生产或公网联调时传入 notifyUrl;本地没有公网 HTTPS notifyUrl 时直接省略,不要向 SDK 传 undefined、空字符串或占位 URL。
17
+ const notifyUrl = (process.env.ALIPAY_NOTIFY_URL || "").trim();
18
+ const requestOptions = {
19
+ bizContent: {
20
+ out_trade_no: "MERCHANT_ORDER_NO_PLACEHOLDER",
21
+ total_amount: "9.00",
22
+ subject: "大乐透",
23
+ product_code: "QUICK_MSECURITY_PAY",
24
+ goods_detail: [
25
+ {
26
+ goods_name: "ipad",
27
+ alipay_goods_id: "20010001",
28
+ quantity: 1,
29
+ price: "2000",
30
+ goods_id: "apple-01",
31
+ goods_category: "34543238",
32
+ categories_tree: "124868003|126232002|126252004",
33
+ show_url: "http://www.alipay.com/xxx.jpg",
34
+ },
35
+ ],
36
+ time_expire: "2016-12-31+10:05:00",
37
+ extend_params: {
38
+ sys_service_provider_id: "<SYS_SERVICE_PROVIDER_ID>",
39
+ hb_fq_seller_percent: "100",
40
+ hb_fq_num: "3",
41
+ industry_reflux_info:
42
+ '{\\"scene_code\\":\\"metro_tradeorder\\",\\"channel\\":\\"xxxx\\",\\"scene_data\\":{\\"asset_name\\":\\"ALIPAY\\"}}',
43
+ royalty_freeze: "true",
44
+ card_type: "S0JP0000",
45
+ },
46
+ passback_params: "merchantBizType%3d3C%26merchantBizNo%3dMERCHANT_BIZ_NO_PLACEHOLDER",
47
+ merchant_order_no: "MERCHANT_ORDER_NO_PLACEHOLDER",
48
+ ext_user_info: {
49
+ cert_type: "IDENTITY_CARD",
50
+ cert_no: "<CERT_NO>",
51
+ mobile: "<MOBILE>",
52
+ name: "李明",
53
+ min_age: "18",
54
+ need_check_info: "F",
55
+ identity_hash:
56
+ "<IDENTITY_HASH>",
57
+ },
58
+ query_options: ["hyb_amount", "enterprise_pay_info"],
59
+ },
60
+ };
61
+ if (notifyUrl) {
62
+ requestOptions.notifyUrl = notifyUrl;
63
+ }
64
+ const result = await alipaySdk.sdkExec("alipay.trade.app.pay", requestOptions);
65
+ ```
66
+
67
+ ## 响应示例
68
+ ### 正常示例
69
+ ```
70
+ 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
71
+ ```