@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,128 @@
|
|
|
1
|
+
# 异步通知处理 - Python 示例
|
|
2
|
+
|
|
3
|
+
适用产品:AI 网页应用收款、AI 移动应用收款。AI 按量付费不使用异步通知。
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import re
|
|
7
|
+
from flask import Blueprint, Response, request
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def create_alipay_notify_blueprint(deps):
|
|
11
|
+
"""deps 接入项目真实 SDK 验签适配器、支付配置、订单仓储、通知事件仓储和脱敏日志。"""
|
|
12
|
+
blueprint = Blueprint("alipay_notify", __name__)
|
|
13
|
+
|
|
14
|
+
@blueprint.post("/alipay/notify")
|
|
15
|
+
def alipay_notify():
|
|
16
|
+
params = {}
|
|
17
|
+
try:
|
|
18
|
+
params = request.form.to_dict(flat=True)
|
|
19
|
+
config = deps["payment_config_repository"].find_by_app_id(params.get("app_id"))
|
|
20
|
+
if config is None:
|
|
21
|
+
return fail(deps, "alipay notify app config not found", params)
|
|
22
|
+
|
|
23
|
+
if not verify_notify_with_alipay_sdk(params, deps["alipay_notify_verifier"], config):
|
|
24
|
+
return fail(deps, "alipay notify signature check failed", params)
|
|
25
|
+
|
|
26
|
+
order = deps["order_repository"].find_by_out_trade_no(params.get("out_trade_no"))
|
|
27
|
+
if order is None or not business_fields_match(order, params, config):
|
|
28
|
+
return fail(deps, "alipay notify business check failed", params)
|
|
29
|
+
|
|
30
|
+
inserted = deps["notify_event_repository"].insert_once(
|
|
31
|
+
notify_id=params.get("notify_id"),
|
|
32
|
+
trade_no=params.get("trade_no"),
|
|
33
|
+
out_trade_no=params.get("out_trade_no"),
|
|
34
|
+
trade_status=params.get("trade_status"),
|
|
35
|
+
raw_params=params,
|
|
36
|
+
)
|
|
37
|
+
if not inserted:
|
|
38
|
+
return Response("success", mimetype="text/plain")
|
|
39
|
+
|
|
40
|
+
if is_paid_trade_notification(params):
|
|
41
|
+
deps["order_repository"].mark_paid_idempotently(order["out_trade_no"], params.get("trade_no"), params)
|
|
42
|
+
else:
|
|
43
|
+
deps["order_repository"].record_non_paid_trade_event(order["out_trade_no"], params.get("trade_status"), params)
|
|
44
|
+
|
|
45
|
+
return Response("success", mimetype="text/plain")
|
|
46
|
+
except Exception:
|
|
47
|
+
safe_log_notify_error(deps, "alipay notify unexpected exception", params)
|
|
48
|
+
return Response("fail", mimetype="text/plain")
|
|
49
|
+
|
|
50
|
+
return blueprint
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def business_fields_match(order, params, config):
|
|
54
|
+
return (
|
|
55
|
+
params.get("app_id") == config["app_id"]
|
|
56
|
+
and params.get("out_trade_no") == order["out_trade_no"]
|
|
57
|
+
and amount_equals(order["total_amount"], params.get("total_amount"))
|
|
58
|
+
and expected_seller_matches(config, params.get("seller_id"), params.get("seller_email"))
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def is_paid_trade_notification(params):
|
|
63
|
+
paid_status = params.get("trade_status") in ("TRADE_SUCCESS", "TRADE_FINISHED")
|
|
64
|
+
return paid_status and not params.get("out_biz_no") and not params.get("gmt_refund") and not params.get("refund_fee")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def amount_equals(expected, actual):
|
|
68
|
+
expected_amount = normalize_amount_text(expected)
|
|
69
|
+
actual_amount = normalize_amount_text(actual)
|
|
70
|
+
return expected_amount is not None and expected_amount == actual_amount
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def normalize_amount_text(value):
|
|
74
|
+
if value is None:
|
|
75
|
+
return None
|
|
76
|
+
match = re.fullmatch(r"(\d+)(?:\.(\d{1,2}))?", str(value).strip())
|
|
77
|
+
if not match:
|
|
78
|
+
return None
|
|
79
|
+
return f"{int(match.group(1))}.{(match.group(2) or '').ljust(2, '0')}"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def expected_seller_matches(config, seller_id, seller_email):
|
|
83
|
+
expected_seller_id = config.get("seller_id")
|
|
84
|
+
expected_seller_email = config.get("seller_email")
|
|
85
|
+
return (
|
|
86
|
+
bool(expected_seller_id and seller_id == expected_seller_id)
|
|
87
|
+
or bool(expected_seller_email and seller_email == expected_seller_email)
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def verify_notify_with_alipay_sdk(params, verifier, config):
|
|
92
|
+
"""
|
|
93
|
+
使用当前项目已安装的支付宝 SDK 验签能力校验 params["sign"]。
|
|
94
|
+
verifier.verify(params, config) 必须封装目标项目当前 SDK 实际通知验签 API;落地前先查已安装包文档或类型定义,不能手写临时 RSA 验签。
|
|
95
|
+
"""
|
|
96
|
+
return verifier.verify(params, config)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def fail(deps, message, params):
|
|
100
|
+
safe_log_notify_error(deps, message, params)
|
|
101
|
+
return Response("fail", mimetype="text/plain")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def safe_log_notify_error(deps, message, params):
|
|
105
|
+
try:
|
|
106
|
+
logger = deps.get("logger")
|
|
107
|
+
if logger is not None:
|
|
108
|
+
logger.warning(message, extra={"alipay_notify": sanitize_notify_params(params)})
|
|
109
|
+
except Exception:
|
|
110
|
+
# 日志失败不能影响支付宝收到纯文本 fail。
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def sanitize_notify_params(params):
|
|
115
|
+
safe_params = dict(params)
|
|
116
|
+
safe_params.pop("sign", None)
|
|
117
|
+
return safe_params
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
要点:
|
|
121
|
+
|
|
122
|
+
- 支付宝通知是 POST 表单,不能用 JSON body 解析。
|
|
123
|
+
- 验签必须调用当前项目支付宝 SDK 的实际验签 API,验签前不得丢字段或改值。
|
|
124
|
+
- `app_id`、`seller_id` / `seller_email` 从运行时支付配置校验,不从订单对象默认取值。
|
|
125
|
+
- 金额校验使用字符串规范化、`Decimal` 或项目定点数工具,不要用浮点数直接比较。
|
|
126
|
+
- 只有付款成功状态且不是退款、关单、分账等事件时,才认定付款成功。
|
|
127
|
+
- 内存订单或内存幂等只能用于非生产 demo,生产必须使用持久化订单表和通知事件表。
|
|
128
|
+
- 处理成功后返回纯文本 `success`;异常、验签失败或业务校验失败返回 `fail`。
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 统一收单交易关闭接口 - Python 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import json
|
|
7
|
+
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
|
|
8
|
+
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
|
|
9
|
+
from alipay.aop.api.request.AlipayTradeCloseRequest import AlipayTradeCloseRequest
|
|
10
|
+
from alipay.aop.api.domain.AlipayTradeCloseModel import AlipayTradeCloseModel
|
|
11
|
+
|
|
12
|
+
# 初始化SDK(Python 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
|
|
13
|
+
config = AlipayClientConfig()
|
|
14
|
+
config.server_url = "https://openapi.alipay.com/gateway.do"
|
|
15
|
+
# 沙箱环境: config.server_url = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"
|
|
16
|
+
config.app_id = "<-- 请填写您的AppId,例如:20190xxxxxx -->"
|
|
17
|
+
config.app_private_key = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->"
|
|
18
|
+
config.alipay_public_key = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->"
|
|
19
|
+
config.charset = "utf-8"
|
|
20
|
+
config.sign_type = "RSA2"
|
|
21
|
+
client = DefaultAlipayClient(alipay_client_config=config)
|
|
22
|
+
|
|
23
|
+
request = AlipayTradeCloseRequest()
|
|
24
|
+
model = AlipayTradeCloseModel()
|
|
25
|
+
model.out_trade_no = "MERCHANT_ORDER_NO_PLACEHOLDER" # 商户订单号,与 trade_no 二选一
|
|
26
|
+
# model.trade_no = "ALIPAY_TRADE_NO_PLACEHOLDER" # 支付宝交易号,同时传时以 trade_no 为准
|
|
27
|
+
request.biz_model = model
|
|
28
|
+
|
|
29
|
+
response_content = client.execute(request)
|
|
30
|
+
response = json.loads(response_content)
|
|
31
|
+
result = response.get("alipay_trade_close_response", {})
|
|
32
|
+
|
|
33
|
+
if result.get("code") == "10000":
|
|
34
|
+
print("交易关闭成功")
|
|
35
|
+
else:
|
|
36
|
+
print(f"调用失败: {result.get('sub_code')} - {result.get('sub_msg')}")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 响应示例
|
|
40
|
+
### 正常示例
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"code": "10000",
|
|
44
|
+
"msg": "Success",
|
|
45
|
+
"trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
|
|
46
|
+
"out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER"
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
### 异常示例
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"code": "20000",
|
|
53
|
+
"msg": "Service Currently Unavailable",
|
|
54
|
+
"sub_code": "isp.unknow-error",
|
|
55
|
+
"sub_msg": "系统繁忙"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 统一收单交易查询接口 - Python 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import json
|
|
7
|
+
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
|
|
8
|
+
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
|
|
9
|
+
from alipay.aop.api.request.AlipayTradeQueryRequest import AlipayTradeQueryRequest
|
|
10
|
+
from alipay.aop.api.domain.AlipayTradeQueryModel import AlipayTradeQueryModel
|
|
11
|
+
|
|
12
|
+
# 初始化SDK(Python 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
|
|
13
|
+
config = AlipayClientConfig()
|
|
14
|
+
config.server_url = "https://openapi.alipay.com/gateway.do"
|
|
15
|
+
# 沙箱环境: config.server_url = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"
|
|
16
|
+
config.app_id = "<-- 请填写您的AppId,例如:20190xxxxxx -->"
|
|
17
|
+
config.app_private_key = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->"
|
|
18
|
+
config.alipay_public_key = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->"
|
|
19
|
+
config.charset = "utf-8"
|
|
20
|
+
config.sign_type = "RSA2"
|
|
21
|
+
client = DefaultAlipayClient(alipay_client_config=config)
|
|
22
|
+
|
|
23
|
+
request = AlipayTradeQueryRequest()
|
|
24
|
+
model = AlipayTradeQueryModel()
|
|
25
|
+
model.out_trade_no = "MERCHANT_ORDER_NO_PLACEHOLDER" # 商户订单号,与 trade_no 二选一
|
|
26
|
+
# model.trade_no = "ALIPAY_TRADE_NO_PLACEHOLDER" # 支付宝交易号,同时传时以 trade_no 为准
|
|
27
|
+
request.biz_model = model
|
|
28
|
+
|
|
29
|
+
response_content = client.execute(request)
|
|
30
|
+
response = json.loads(response_content)
|
|
31
|
+
result = response.get("alipay_trade_query_response", {})
|
|
32
|
+
|
|
33
|
+
if result.get("code") == "10000":
|
|
34
|
+
business_state = {
|
|
35
|
+
"TRADE_SUCCESS": "PAID",
|
|
36
|
+
"TRADE_FINISHED": "PAID",
|
|
37
|
+
"WAIT_BUYER_PAY": "PENDING_PAYMENT",
|
|
38
|
+
"TRADE_CLOSED": "CLOSED",
|
|
39
|
+
}.get(result.get("trade_status"), "UNKNOWN")
|
|
40
|
+
print(f"业务状态: {business_state}, 支付宝状态: {result.get('trade_status')}, 订单金额: {result.get('total_amount')}")
|
|
41
|
+
else:
|
|
42
|
+
print(f"调用失败: {result.get('sub_code')} - {result.get('sub_msg')}")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 响应示例
|
|
46
|
+
### 正常示例
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"code": "10000",
|
|
50
|
+
"msg": "Success",
|
|
51
|
+
"trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
|
|
52
|
+
"out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
|
|
53
|
+
"trade_status": "TRADE_SUCCESS",
|
|
54
|
+
"total_amount": "88.88",
|
|
55
|
+
"buyer_pay_amount": "8.88",
|
|
56
|
+
"receipt_amount": "15.25",
|
|
57
|
+
"buyer_logon_id": "159****5620",
|
|
58
|
+
"buyer_user_id": "<BUYER_USER_ID>",
|
|
59
|
+
"send_pay_date": "2014-11-27 15:45:57"
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
### 异常示例
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"code": "20000",
|
|
66
|
+
"msg": "Service Currently Unavailable",
|
|
67
|
+
"sub_code": "isp.unknow-error",
|
|
68
|
+
"sub_msg": "系统繁忙"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# 统一收单交易退款接口 - Python 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import json
|
|
7
|
+
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
|
|
8
|
+
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
|
|
9
|
+
from alipay.aop.api.request.AlipayTradeRefundRequest import AlipayTradeRefundRequest
|
|
10
|
+
from alipay.aop.api.domain.AlipayTradeRefundModel import AlipayTradeRefundModel
|
|
11
|
+
|
|
12
|
+
# 初始化SDK(Python 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
|
|
13
|
+
config = AlipayClientConfig()
|
|
14
|
+
config.server_url = "https://openapi.alipay.com/gateway.do"
|
|
15
|
+
# 沙箱环境: config.server_url = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"
|
|
16
|
+
config.app_id = "<-- 请填写您的AppId,例如:20190xxxxxx -->"
|
|
17
|
+
config.app_private_key = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->"
|
|
18
|
+
config.alipay_public_key = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->"
|
|
19
|
+
config.charset = "utf-8"
|
|
20
|
+
config.sign_type = "RSA2"
|
|
21
|
+
client = DefaultAlipayClient(alipay_client_config=config)
|
|
22
|
+
|
|
23
|
+
request = AlipayTradeRefundRequest()
|
|
24
|
+
model = AlipayTradeRefundModel()
|
|
25
|
+
model.out_trade_no = "MERCHANT_ORDER_NO_PLACEHOLDER" # 商户订单号,与 trade_no 二选一
|
|
26
|
+
model.refund_amount = "200.12" # 使用 Decimal 等十进制定点金额;调用前校验累计退款不超过原订单实付金额
|
|
27
|
+
model.refund_reason = "正常退款" # 退款原因,选填
|
|
28
|
+
model.out_request_no = "OUT_REQUEST_NO_PLACEHOLDER" # 新退款使用新编号;同一退款失败重试必须复用原编号和原参数
|
|
29
|
+
request.biz_model = model
|
|
30
|
+
|
|
31
|
+
response_content = client.execute(request)
|
|
32
|
+
response = json.loads(response_content)
|
|
33
|
+
result = response.get("alipay_trade_refund_response", {})
|
|
34
|
+
|
|
35
|
+
if result.get("code") == "10000":
|
|
36
|
+
if result.get("fund_change") == "Y":
|
|
37
|
+
print(f"退款资金已发生变化,退款金额: {result.get('refund_fee')}")
|
|
38
|
+
else:
|
|
39
|
+
print("退款结果待确认:使用同一 out_request_no 调用 alipay.trade.fastpay.refund.query")
|
|
40
|
+
else:
|
|
41
|
+
print(f"调用失败: {result.get('sub_code')} - {result.get('sub_msg')}")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 响应示例
|
|
45
|
+
### 正常示例
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"code": "10000",
|
|
49
|
+
"msg": "Success",
|
|
50
|
+
"trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
|
|
51
|
+
"out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
|
|
52
|
+
"buyer_logon_id": "159****5620",
|
|
53
|
+
"fund_change": "Y",
|
|
54
|
+
"refund_fee": "88.88"
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
### 异常示例
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"code": "20000",
|
|
61
|
+
"msg": "Service Currently Unavailable",
|
|
62
|
+
"sub_code": "isp.unknow-error",
|
|
63
|
+
"sub_msg": "系统繁忙"
|
|
64
|
+
}
|
|
65
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 统一收单交易退款查询接口 - Python 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import json
|
|
7
|
+
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
|
|
8
|
+
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
|
|
9
|
+
from alipay.aop.api.request.AlipayTradeFastpayRefundQueryRequest import AlipayTradeFastpayRefundQueryRequest
|
|
10
|
+
from alipay.aop.api.domain.AlipayTradeFastpayRefundQueryModel import AlipayTradeFastpayRefundQueryModel
|
|
11
|
+
|
|
12
|
+
# 初始化SDK(Python 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
|
|
13
|
+
config = AlipayClientConfig()
|
|
14
|
+
config.server_url = "https://openapi.alipay.com/gateway.do"
|
|
15
|
+
# 沙箱环境: config.server_url = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"
|
|
16
|
+
config.app_id = "<-- 请填写您的AppId,例如:20190xxxxxx -->"
|
|
17
|
+
config.app_private_key = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->"
|
|
18
|
+
config.alipay_public_key = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->"
|
|
19
|
+
config.charset = "utf-8"
|
|
20
|
+
config.sign_type = "RSA2"
|
|
21
|
+
client = DefaultAlipayClient(alipay_client_config=config)
|
|
22
|
+
|
|
23
|
+
request = AlipayTradeFastpayRefundQueryRequest()
|
|
24
|
+
model = AlipayTradeFastpayRefundQueryModel()
|
|
25
|
+
model.out_trade_no = "MERCHANT_ORDER_NO_PLACEHOLDER" # 商户订单号,与 trade_no 二选一
|
|
26
|
+
model.out_request_no = "OUT_REQUEST_NO_PLACEHOLDER" # 退款请求号,必填,同一笔交易多次部分退款时用于区分
|
|
27
|
+
request.biz_model = model
|
|
28
|
+
|
|
29
|
+
response_content = client.execute(request)
|
|
30
|
+
response = json.loads(response_content)
|
|
31
|
+
result = response.get("alipay_trade_fastpay_refund_query_response", {})
|
|
32
|
+
|
|
33
|
+
if result.get("code") == "10000":
|
|
34
|
+
# refund_status: REFUND_SUCCESS 表示退款成功,REFUND_PROCESSING 表示退款处理中
|
|
35
|
+
print(f"退款状态: {result.get('refund_status')}, 退款金额: {result.get('refund_amount')}")
|
|
36
|
+
else:
|
|
37
|
+
print(f"调用失败: {result.get('sub_code')} - {result.get('sub_msg')}")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 响应示例
|
|
41
|
+
### 正常示例
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"code": "10000",
|
|
45
|
+
"msg": "Success",
|
|
46
|
+
"trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
|
|
47
|
+
"out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
|
|
48
|
+
"out_request_no": "OUT_REQUEST_NO_PLACEHOLDER",
|
|
49
|
+
"total_amount": "100.20",
|
|
50
|
+
"refund_amount": "12.33",
|
|
51
|
+
"refund_status": "REFUND_SUCCESS"
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
### 异常示例
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"code": "20000",
|
|
58
|
+
"msg": "Service Currently Unavailable",
|
|
59
|
+
"sub_code": "isp.unknow-error",
|
|
60
|
+
"sub_msg": "系统繁忙"
|
|
61
|
+
}
|
|
62
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# 统一收单下单并支付页面接口 - Python 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import os
|
|
7
|
+
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
|
|
8
|
+
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
|
|
9
|
+
from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest
|
|
10
|
+
from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel
|
|
11
|
+
|
|
12
|
+
# 初始化SDK(Python 使用 PKCS#1 格式私钥,Java 使用 PKCS#8 格式,请勿混用)
|
|
13
|
+
config = AlipayClientConfig()
|
|
14
|
+
config.server_url = "https://openapi.alipay.com/gateway.do"
|
|
15
|
+
# 沙箱环境: config.server_url = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"
|
|
16
|
+
config.app_id = "<-- 请填写您的AppId,例如:20190xxxxxx -->"
|
|
17
|
+
config.app_private_key = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->"
|
|
18
|
+
config.alipay_public_key = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->"
|
|
19
|
+
config.charset = "utf-8"
|
|
20
|
+
config.sign_type = "RSA2"
|
|
21
|
+
client = DefaultAlipayClient(alipay_client_config=config)
|
|
22
|
+
|
|
23
|
+
request = AlipayTradePagePayRequest()
|
|
24
|
+
notify_url = os.getenv("ALIPAY_NOTIFY_URL", "").strip()
|
|
25
|
+
if notify_url:
|
|
26
|
+
request.notify_url = notify_url # 真实生产或公网联调时传入;本地没有公网 HTTPS notify_url 时不要传 None、空字符串或占位 URL
|
|
27
|
+
request.return_url = "https://your-domain.com/return" # 默认传入并替换为已验证结果页;仅用户明确关闭同步回跳时省略
|
|
28
|
+
|
|
29
|
+
model = AlipayTradePagePayModel()
|
|
30
|
+
model.out_trade_no = "MERCHANT_ORDER_NO_PLACEHOLDER" # 商户订单号,必填
|
|
31
|
+
model.total_amount = "88.88" # 订单总金额,必填,单位为元
|
|
32
|
+
model.subject = "Iphone6 16G" # 订单标题,必填
|
|
33
|
+
model.product_code = "FAST_INSTANT_TRADE_PAY" # 网站支付固定值,必填
|
|
34
|
+
request.biz_model = model
|
|
35
|
+
|
|
36
|
+
# ⚠️ 网站支付必须使用 page_execute(),不能使用 execute()
|
|
37
|
+
# ⚠️ 使用 execute() 将无法获取支付表单,是最常见的集成错误
|
|
38
|
+
form_html = client.page_execute(request)
|
|
39
|
+
# page_execute 返回的是 HTML 表单字符串,前端需要渲染并自动提交
|
|
40
|
+
print(form_html)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 响应示例
|
|
44
|
+
### 正常示例
|
|
45
|
+
```html
|
|
46
|
+
<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">
|
|
47
|
+
<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"}">
|
|
48
|
+
<input type="submit" value="立即支付" style="display:none" >
|
|
49
|
+
</form>
|
|
50
|
+
<script>document.forms[0].submit();</script>
|
|
51
|
+
```
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# APP 支付接口 - Python 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
|
|
9
|
+
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
|
|
10
|
+
from alipay.aop.api.request.AlipayTradeAppPayRequest import AlipayTradeAppPayRequest
|
|
11
|
+
from alipay.aop.api.domain.AlipayTradeAppPayModel import AlipayTradeAppPayModel
|
|
12
|
+
|
|
13
|
+
# 初始化SDK
|
|
14
|
+
config = AlipayClientConfig()
|
|
15
|
+
config.server_url = "https://openapi.alipay.com/gateway.do"
|
|
16
|
+
config.app_id = "<-- 请填写您的AppId,例如:20190xxxxxx -->"
|
|
17
|
+
config.app_private_key = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->"
|
|
18
|
+
config.alipay_public_key = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->"
|
|
19
|
+
config.charset = "utf-8"
|
|
20
|
+
config.sign_type = "RSA2"
|
|
21
|
+
client = DefaultAlipayClient(alipay_client_config=config)
|
|
22
|
+
|
|
23
|
+
# 构造请求参数以调用接口
|
|
24
|
+
request = AlipayTradeAppPayRequest()
|
|
25
|
+
notify_url = os.getenv("ALIPAY_NOTIFY_URL", "").strip()
|
|
26
|
+
if notify_url:
|
|
27
|
+
request.notify_url = notify_url # 真实生产或公网联调时传入;本地没有公网 HTTPS notify_url 时不要传 None、空字符串或占位 URL
|
|
28
|
+
model = AlipayTradeAppPayModel()
|
|
29
|
+
|
|
30
|
+
model.out_trade_no = "MERCHANT_ORDER_NO_PLACEHOLDER"
|
|
31
|
+
model.total_amount = "9.00"
|
|
32
|
+
model.subject = "大乐透"
|
|
33
|
+
model.product_code = "QUICK_MSECURITY_PAY"
|
|
34
|
+
|
|
35
|
+
request.biz_model = model
|
|
36
|
+
# 第三方代调用模式下请设置app_auth_token
|
|
37
|
+
# request.add_other_text_param("app_auth_token", "<-- 请填写应用授权令牌 -->")
|
|
38
|
+
|
|
39
|
+
order_str = client.sdk_execute(request)
|
|
40
|
+
print(order_str)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 响应示例
|
|
44
|
+
### 正常示例
|
|
45
|
+
```
|
|
46
|
+
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
|
|
47
|
+
```
|