@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.
- package/README.md +30 -0
- package/dist/commands/install-current.js +15 -7
- package/dist/commands/install.js +20 -16
- package/dist/commands/uninstall.js +8 -3
- package/dist/commands/update.js +34 -16
- package/dist/index.js +10 -4
- package/dist/utils/channels.js +67 -0
- package/dist/utils/config.js +15 -11
- package/dist/utils/file.js +23 -10
- package/dist/utils/npm.js +19 -33
- package/package.json +8 -3
- package/skill/SKILL.md +2 -0
- package/skill/references/normal/json/release-channel.json +1 -0
- package/skill/references/normal/scripts/self_update.mjs +62 -17
- package/skill/references/normal/self-update.md +3 -1
- package/skill-pre/SKILL.md +65 -0
- package/skill-pre/VERSION +1 -0
- package/skill-pre/references/integration/flow.md +602 -0
- package/skill-pre/references/integration/modules/alipay-sdk-reminder.md +281 -0
- package/skill-pre/references/integration/modules/checklist.md +154 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/skill-pre/references/integration/modules/interface-contract/aipay-interface-contract.md +52 -0
- package/skill-pre/references/integration/modules/interface-contract/apppay-interface-contract.md +45 -0
- package/skill-pre/references/integration/modules/interface-contract/common-trade-contract.md +42 -0
- package/skill-pre/references/integration/modules/interface-contract/notify-url-contract.md +68 -0
- package/skill-pre/references/integration/modules/interface-contract/webpay-interface-contract.md +44 -0
- package/skill-pre/references/integration/modules/interface-guide.md +61 -0
- package/skill-pre/references/integration/modules/product-decision.md +73 -0
- package/skill-pre/references/integration/modules/sandbox/a2m-sandbox-test.md +235 -0
- package/skill-pre/references/integration/modules/sandbox/alipay-sandbox-tool.md +142 -0
- package/skill-pre/references/integration/modules/sandbox/sandbox-setup-guide.md +239 -0
- package/skill-pre/references/integration/modules/scripts/local_402_sandbox_pay.py +900 -0
- package/skill-pre/references/integration/modules/scripts/sandbox_config.sh +347 -0
- package/skill-pre/references/integration/modules/troubleshooting-flow.md +28 -0
- package/skill-pre/references/normal/alipay-cli-env.md +169 -0
- package/skill-pre/references/normal/conversation-telemetry.md +101 -0
- package/skill-pre/references/normal/full-process-routing.md +92 -0
- package/skill-pre/references/normal/integration-worker.md +90 -0
- package/skill-pre/references/normal/json/customer-messages.json +1 -0
- package/skill-pre/references/normal/json/managed-jq-assets.json +1 -0
- package/skill-pre/references/normal/json/policy-rules.json +1 -0
- package/skill-pre/references/normal/json/release-channel.json +1 -0
- package/skill-pre/references/normal/rejection-guide.md +41 -0
- package/skill-pre/references/normal/scripts/agent_platform.mjs +43 -0
- package/skill-pre/references/normal/scripts/alipay_cli_env.mjs +34 -0
- package/skill-pre/references/normal/scripts/alipay_cli_env.sh +55 -0
- package/skill-pre/references/normal/scripts/alipay_cli_refresh.mjs +129 -0
- package/skill-pre/references/normal/scripts/auth_runtime_runner.mjs +60 -0
- package/skill-pre/references/normal/scripts/checklist_sections.mjs +43 -0
- package/skill-pre/references/normal/scripts/common.sh +365 -0
- package/skill-pre/references/normal/scripts/conversation_telemetry.mjs +105 -0
- package/skill-pre/references/normal/scripts/detect_dev_tool.sh +79 -0
- package/skill-pre/references/normal/scripts/flow_loader.mjs +237 -0
- package/skill-pre/references/normal/scripts/integration_context_runner.mjs +151 -0
- package/skill-pre/references/normal/scripts/integration_message_runner.mjs +1456 -0
- package/skill-pre/references/normal/scripts/interaction_reply.mjs +140 -0
- package/skill-pre/references/normal/scripts/managed_jq.mjs +215 -0
- package/skill-pre/references/normal/scripts/onboarding_discovery_runner.mjs +387 -0
- package/skill-pre/references/normal/scripts/onboarding_message_runner.mjs +1425 -0
- package/skill-pre/references/normal/scripts/onboarding_recovery_runner.mjs +100 -0
- package/skill-pre/references/normal/scripts/open_official_url.sh +205 -0
- package/skill-pre/references/normal/scripts/platform_compat.mjs +42 -0
- package/skill-pre/references/normal/scripts/preview_runtime.mjs +151 -0
- package/skill-pre/references/normal/scripts/project_route_inspector.sh +132 -0
- package/skill-pre/references/normal/scripts/python_script_runner.mjs +58 -0
- package/skill-pre/references/normal/scripts/render_customer_message.mjs +1792 -0
- package/skill-pre/references/normal/scripts/runtime.mjs +271 -0
- package/skill-pre/references/normal/scripts/self_update.mjs +376 -0
- package/skill-pre/references/normal/scripts/telemetry.mjs +2102 -0
- package/skill-pre/references/normal/self-update.md +7 -0
- package/skill-pre/references/normal/telemetry.md +70 -0
- package/skill-pre/references/onboarding/assets/keygen.html +927 -0
- package/skill-pre/references/onboarding/flow.md +607 -0
- package/skill-pre/references/onboarding/modules/app-release.md +90 -0
- package/skill-pre/references/onboarding/modules/authorization.md +43 -0
- package/skill-pre/references/onboarding/modules/error-handling.md +62 -0
- package/skill-pre/references/onboarding/modules/product-sign.md +49 -0
- package/skill-pre/references/onboarding/modules/scripts/app.sh +1485 -0
- package/skill-pre/references/onboarding/modules/scripts/ar_sign_apply.sh +331 -0
- package/skill-pre/references/onboarding/modules/scripts/auth.sh +1040 -0
- package/skill-pre/references/onboarding/modules/scripts/download_key_tool.sh +4 -0
- package/skill-pre/references/onboarding/modules/scripts/error_handler.sh +841 -0
- package/skill-pre/references/onboarding/modules/scripts/mcc.sh +1085 -0
- package/skill-pre/references/onboarding/modules/scripts/network_retry.sh +135 -0
- package/skill-pre/references/onboarding/modules/scripts/query_sign_status.sh +105 -0
- package/skill-pre/references/onboarding/modules/scripts/service.sh +528 -0
- package/skill-pre/references/onboarding/modules/scripts/sign_status_parser.sh +58 -0
- package/skill-pre/references/onboarding/modules/scripts/upload_screenshots.sh +208 -0
- package/skill-pre/references/onboarding/modules/scripts/upload_special_license.sh +195 -0
- package/skill-pre/references/onboarding/modules/service-registration.md +40 -0
- package/skill-pre/references/runtime-entry.md +99 -0
- package/dist/commands/install-current.d.ts +0 -4
- package/dist/commands/install-current.d.ts.map +0 -1
- package/dist/commands/install-current.js.map +0 -1
- package/dist/commands/install.d.ts +0 -10
- package/dist/commands/install.d.ts.map +0 -1
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/prepare-tools.d.ts +0 -5
- package/dist/commands/prepare-tools.d.ts.map +0 -1
- package/dist/commands/prepare-tools.js.map +0 -1
- package/dist/commands/uninstall.d.ts +0 -10
- package/dist/commands/uninstall.d.ts.map +0 -1
- package/dist/commands/uninstall.js.map +0 -1
- package/dist/commands/update.d.ts +0 -10
- package/dist/commands/update.d.ts.map +0 -1
- package/dist/commands/update.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/types.d.ts +0 -42
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/alipay-cli.d.ts +0 -20
- package/dist/utils/alipay-cli.d.ts.map +0 -1
- package/dist/utils/alipay-cli.js.map +0 -1
- package/dist/utils/config.d.ts +0 -52
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/file.d.ts +0 -77
- package/dist/utils/file.d.ts.map +0 -1
- package/dist/utils/file.js.map +0 -1
- package/dist/utils/jq.d.ts +0 -17
- package/dist/utils/jq.d.ts.map +0 -1
- package/dist/utils/jq.js.map +0 -1
- package/dist/utils/npm.d.ts +0 -17
- package/dist/utils/npm.d.ts.map +0 -1
- package/dist/utils/npm.js.map +0 -1
- package/dist/utils/shell.d.ts +0 -24
- package/dist/utils/shell.d.ts.map +0 -1
- 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×tamp=2014-07-24+03%3A07%3A50">
|
|
80
|
+
<input type="hidden" name="biz_content" value="{"out_trade_no":"MERCHANT_ORDER_NO_PLACEHOLDER","total_amount":"88.88","subject":"Iphone6 16G","product_code":"FAST_INSTANT_TRADE_PAY"}">
|
|
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×tamp=2014-07-24+03%3A07%3A50&version=1.0
|
|
71
|
+
```
|