@alipay/alipay-aipay 1.7.0 → 1.7.1
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 +926 -0
- package/skill-pre/references/onboarding/flow.md +595 -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 +97 -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,184 @@
|
|
|
1
|
+
# 异步通知处理 - Java 示例
|
|
2
|
+
|
|
3
|
+
适用产品:AI 网页应用收款、AI 移动应用收款。AI 按量付费不使用异步通知。
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
import com.alipay.api.internal.util.AlipaySignature;
|
|
7
|
+
import jakarta.servlet.http.HttpServletRequest;
|
|
8
|
+
import org.springframework.web.bind.annotation.PostMapping;
|
|
9
|
+
import org.springframework.web.bind.annotation.ResponseBody;
|
|
10
|
+
|
|
11
|
+
import java.math.BigDecimal;
|
|
12
|
+
import java.util.HashMap;
|
|
13
|
+
import java.util.Map;
|
|
14
|
+
|
|
15
|
+
public class AlipayNotifyController {
|
|
16
|
+
private static final String CHARSET = "UTF-8";
|
|
17
|
+
private final PaymentConfigRepository paymentConfigRepository;
|
|
18
|
+
private final OrderRepository orderRepository;
|
|
19
|
+
private final NotifyEventRepository notifyEventRepository;
|
|
20
|
+
private final NotifyLogger notifyLogger;
|
|
21
|
+
|
|
22
|
+
public AlipayNotifyController(
|
|
23
|
+
PaymentConfigRepository paymentConfigRepository,
|
|
24
|
+
OrderRepository orderRepository,
|
|
25
|
+
NotifyEventRepository notifyEventRepository,
|
|
26
|
+
NotifyLogger notifyLogger
|
|
27
|
+
) {
|
|
28
|
+
this.paymentConfigRepository = paymentConfigRepository;
|
|
29
|
+
this.orderRepository = orderRepository;
|
|
30
|
+
this.notifyEventRepository = notifyEventRepository;
|
|
31
|
+
this.notifyLogger = notifyLogger;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@PostMapping(value = "/alipay/notify", produces = "text/plain;charset=UTF-8")
|
|
35
|
+
@ResponseBody
|
|
36
|
+
public String handleAlipayNotify(HttpServletRequest request) {
|
|
37
|
+
Map<String, String> params = new HashMap<>();
|
|
38
|
+
try {
|
|
39
|
+
params = collectFormParams(request);
|
|
40
|
+
AlipayNotifyConfig config = paymentConfigRepository.findByAppId(params.get("app_id"));
|
|
41
|
+
|
|
42
|
+
if (config == null || !verifyNotifyWithAlipaySdk(params, config)) {
|
|
43
|
+
return fail("alipay notify signature check failed", params);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
MerchantOrder order = orderRepository.findByOutTradeNo(params.get("out_trade_no"));
|
|
47
|
+
if (order == null || !businessFieldsMatch(order, params, config)) {
|
|
48
|
+
return fail("alipay notify business check failed", params);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
boolean inserted = notifyEventRepository.insertOnce(
|
|
52
|
+
params.get("notify_id"),
|
|
53
|
+
params.get("trade_no"),
|
|
54
|
+
params.get("out_trade_no"),
|
|
55
|
+
params.get("trade_status"),
|
|
56
|
+
params
|
|
57
|
+
);
|
|
58
|
+
if (!inserted) {
|
|
59
|
+
return "success";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (isPaidTradeNotification(params)) {
|
|
63
|
+
orderRepository.markPaidIdempotently(order.outTradeNo(), params.get("trade_no"), params);
|
|
64
|
+
} else {
|
|
65
|
+
orderRepository.recordNonPaidTradeEvent(order.outTradeNo(), params.get("trade_status"), params);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return "success";
|
|
69
|
+
} catch (Exception e) {
|
|
70
|
+
safeLogNotifyError("alipay notify unexpected exception", params);
|
|
71
|
+
return "fail";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private static Map<String, String> collectFormParams(HttpServletRequest request) {
|
|
76
|
+
Map<String, String> params = new HashMap<>();
|
|
77
|
+
request.getParameterMap().forEach((name, values) -> {
|
|
78
|
+
String value = String.join(",", values);
|
|
79
|
+
params.put(name, value);
|
|
80
|
+
});
|
|
81
|
+
return params;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private static boolean verifyNotifyWithAlipaySdk(Map<String, String> params, AlipayNotifyConfig config) throws Exception {
|
|
85
|
+
return AlipaySignature.rsaCheckV1(
|
|
86
|
+
params,
|
|
87
|
+
config.alipayPublicKey(),
|
|
88
|
+
CHARSET,
|
|
89
|
+
params.getOrDefault("sign_type", "RSA2")
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private static boolean businessFieldsMatch(MerchantOrder order, Map<String, String> params, AlipayNotifyConfig config) {
|
|
94
|
+
return config.appId().equals(params.get("app_id"))
|
|
95
|
+
&& order.outTradeNo().equals(params.get("out_trade_no"))
|
|
96
|
+
&& amountEquals(order.totalAmount(), params.get("total_amount"))
|
|
97
|
+
&& expectedSellerMatches(config, params.get("seller_id"), params.get("seller_email"));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private static boolean amountEquals(BigDecimal expected, String actual) {
|
|
101
|
+
if (actual == null) return false;
|
|
102
|
+
try {
|
|
103
|
+
return expected.compareTo(new BigDecimal(actual)) == 0;
|
|
104
|
+
} catch (NumberFormatException e) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private static boolean isPaidTradeNotification(Map<String, String> params) {
|
|
110
|
+
boolean paidStatus = "TRADE_SUCCESS".equals(params.get("trade_status")) || "TRADE_FINISHED".equals(params.get("trade_status"));
|
|
111
|
+
return paidStatus
|
|
112
|
+
&& isBlank(params.get("out_biz_no"))
|
|
113
|
+
&& isBlank(params.get("gmt_refund"))
|
|
114
|
+
&& isBlank(params.get("refund_fee"));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private static boolean expectedSellerMatches(AlipayNotifyConfig config, String sellerId, String sellerEmail) {
|
|
118
|
+
String expectedSellerId = blankToNull(config.sellerId());
|
|
119
|
+
String expectedSellerEmail = blankToNull(config.sellerEmail());
|
|
120
|
+
return (expectedSellerId != null && expectedSellerId.equals(sellerId))
|
|
121
|
+
|| (expectedSellerEmail != null && expectedSellerEmail.equals(sellerEmail));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private static boolean isBlank(String value) {
|
|
125
|
+
return value == null || value.isBlank();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private static String blankToNull(String value) {
|
|
129
|
+
return isBlank(value) ? null : value;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private String fail(String message, Map<String, String> params) {
|
|
133
|
+
safeLogNotifyError(message, params);
|
|
134
|
+
return "fail";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private void safeLogNotifyError(String message, Map<String, String> params) {
|
|
138
|
+
try {
|
|
139
|
+
notifyLogger.warn(message, sanitizeNotifyParams(params));
|
|
140
|
+
} catch (Exception ignored) {
|
|
141
|
+
// 日志失败不能影响支付宝收到纯文本 fail。
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private static Map<String, String> sanitizeNotifyParams(Map<String, String> params) {
|
|
146
|
+
Map<String, String> safeParams = new HashMap<>(params);
|
|
147
|
+
safeParams.remove("sign");
|
|
148
|
+
return safeParams;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 以下接口对接商家项目的真实配置、订单仓储、通知事件表和脱敏日志。
|
|
152
|
+
// 生产环境必须使用持久化订单表和通知事件表;内存 Map 只能用于非生产 demo。
|
|
153
|
+
private interface PaymentConfigRepository {
|
|
154
|
+
AlipayNotifyConfig findByAppId(String appId);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private interface OrderRepository {
|
|
158
|
+
MerchantOrder findByOutTradeNo(String outTradeNo);
|
|
159
|
+
void markPaidIdempotently(String outTradeNo, String tradeNo, Map<String, String> params);
|
|
160
|
+
void recordNonPaidTradeEvent(String outTradeNo, String tradeStatus, Map<String, String> params);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private interface NotifyEventRepository {
|
|
164
|
+
boolean insertOnce(String notifyId, String tradeNo, String outTradeNo, String tradeStatus, Map<String, String> params);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private interface NotifyLogger {
|
|
168
|
+
void warn(String message, Map<String, String> params);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private record AlipayNotifyConfig(String appId, String alipayPublicKey, String sellerId, String sellerEmail) {}
|
|
172
|
+
private record MerchantOrder(String outTradeNo, BigDecimal totalAmount) {}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
要点:
|
|
177
|
+
|
|
178
|
+
- 支付宝通知是 POST 表单,验签前必须收集完整参数 map。
|
|
179
|
+
- `AlipaySignature.rsaCheckV1` 会忽略 `sign` / `sign_type` 完成验签,业务代码不要先删除或改写参数。
|
|
180
|
+
- `app_id`、`seller_id` / `seller_email` 从运行时支付配置校验,不从订单对象默认取值。
|
|
181
|
+
- 金额校验使用 `BigDecimal` 或项目定点数工具,不要用浮点数直接比较。
|
|
182
|
+
- 只有付款成功状态且不是退款、关单、分账等事件时,才认定付款成功。
|
|
183
|
+
- 内存订单或内存幂等只能用于非生产 demo,生产必须使用持久化订单表和通知事件表。
|
|
184
|
+
- 处理成功后返回纯文本 `success`;异常、验签失败或业务校验失败返回 `fail`。
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# 统一收单交易关闭接口 - Java 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
package com.java.sdk.demo;
|
|
7
|
+
|
|
8
|
+
import com.alipay.api.AlipayApiException;
|
|
9
|
+
import com.alipay.api.AlipayClient;
|
|
10
|
+
import com.alipay.api.DefaultAlipayClient;
|
|
11
|
+
import com.alipay.api.AlipayConfig;
|
|
12
|
+
import com.alipay.api.domain.AlipayTradeCloseModel;
|
|
13
|
+
import com.alipay.api.response.AlipayTradeCloseResponse;
|
|
14
|
+
import com.alipay.api.request.AlipayTradeCloseRequest;
|
|
15
|
+
|
|
16
|
+
public class AlipayTradeClose {
|
|
17
|
+
|
|
18
|
+
public static void main(String[] args) throws AlipayApiException {
|
|
19
|
+
// 初始化SDK(Java 使用 PKCS#8 格式私钥,C#/Python 使用 PKCS#1 格式,请勿混用)
|
|
20
|
+
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
|
|
21
|
+
|
|
22
|
+
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
|
|
23
|
+
AlipayTradeCloseModel model = new AlipayTradeCloseModel();
|
|
24
|
+
model.setOutTradeNo("MERCHANT_ORDER_NO_PLACEHOLDER"); // 商户订单号,与 tradeNo 二选一
|
|
25
|
+
// model.setTradeNo("ALIPAY_TRADE_NO_PLACEHOLDER"); // 支付宝交易号,同时传时以 tradeNo 为准
|
|
26
|
+
request.setBizModel(model);
|
|
27
|
+
|
|
28
|
+
AlipayTradeCloseResponse response = alipayClient.execute(request);
|
|
29
|
+
|
|
30
|
+
if (response.isSuccess()) {
|
|
31
|
+
System.out.println("交易关闭成功");
|
|
32
|
+
} else {
|
|
33
|
+
System.out.println("调用失败: " + response.getSubCode() + " - " + response.getSubMsg());
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private static AlipayConfig getAlipayConfig() {
|
|
38
|
+
String privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
|
|
39
|
+
String alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
|
|
40
|
+
AlipayConfig alipayConfig = new AlipayConfig();
|
|
41
|
+
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
|
|
42
|
+
// 沙箱环境: alipayConfig.setServerUrl("https://openapi-sandbox.dl.alipaydev.com/gateway.do");
|
|
43
|
+
alipayConfig.setAppId("<-- 请填写您的AppId,例如:20190xxxxxx -->");
|
|
44
|
+
alipayConfig.setPrivateKey(privateKey);
|
|
45
|
+
alipayConfig.setFormat("json");
|
|
46
|
+
alipayConfig.setAlipayPublicKey(alipayPublicKey);
|
|
47
|
+
alipayConfig.setCharset("UTF-8");
|
|
48
|
+
alipayConfig.setSignType("RSA2");
|
|
49
|
+
return alipayConfig;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 响应示例
|
|
55
|
+
### 正常示例
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"code": "10000",
|
|
59
|
+
"msg": "Success",
|
|
60
|
+
"trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
|
|
61
|
+
"out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
### 异常示例
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"code": "20000",
|
|
68
|
+
"msg": "Service Currently Unavailable",
|
|
69
|
+
"sub_code": "isp.unknow-error",
|
|
70
|
+
"sub_msg": "系统繁忙"
|
|
71
|
+
}
|
|
72
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# 统一收单交易查询接口 - Java 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
package com.java.sdk.demo;
|
|
7
|
+
|
|
8
|
+
import com.alipay.api.AlipayApiException;
|
|
9
|
+
import com.alipay.api.AlipayClient;
|
|
10
|
+
import com.alipay.api.DefaultAlipayClient;
|
|
11
|
+
import com.alipay.api.AlipayConfig;
|
|
12
|
+
import com.alipay.api.response.AlipayTradeQueryResponse;
|
|
13
|
+
import com.alipay.api.request.AlipayTradeQueryRequest;
|
|
14
|
+
import com.alipay.api.domain.AlipayTradeQueryModel;
|
|
15
|
+
|
|
16
|
+
public class AlipayTradeQuery {
|
|
17
|
+
|
|
18
|
+
public static void main(String[] args) throws AlipayApiException {
|
|
19
|
+
// 初始化SDK(Java 使用 PKCS#8 格式私钥,C#/Python 使用 PKCS#1 格式,请勿混用)
|
|
20
|
+
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
|
|
21
|
+
|
|
22
|
+
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
|
|
23
|
+
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
|
|
24
|
+
model.setOutTradeNo("MERCHANT_ORDER_NO_PLACEHOLDER"); // 商户订单号,与 tradeNo 二选一
|
|
25
|
+
// model.setTradeNo("ALIPAY_TRADE_NO_PLACEHOLDER"); // 支付宝交易号,同时传时以 tradeNo 为准
|
|
26
|
+
request.setBizModel(model);
|
|
27
|
+
|
|
28
|
+
AlipayTradeQueryResponse response = alipayClient.execute(request);
|
|
29
|
+
|
|
30
|
+
if (response.isSuccess()) {
|
|
31
|
+
String businessState;
|
|
32
|
+
String tradeStatus = response.getTradeStatus();
|
|
33
|
+
switch (tradeStatus == null ? "" : tradeStatus) {
|
|
34
|
+
case "TRADE_SUCCESS":
|
|
35
|
+
case "TRADE_FINISHED":
|
|
36
|
+
businessState = "PAID";
|
|
37
|
+
break;
|
|
38
|
+
case "WAIT_BUYER_PAY":
|
|
39
|
+
businessState = "PENDING_PAYMENT";
|
|
40
|
+
break;
|
|
41
|
+
case "TRADE_CLOSED":
|
|
42
|
+
businessState = "CLOSED";
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
businessState = "UNKNOWN";
|
|
46
|
+
}
|
|
47
|
+
System.out.println("业务状态: " + businessState + ", 支付宝状态: "
|
|
48
|
+
+ tradeStatus + ", 订单金额: " + response.getTotalAmount());
|
|
49
|
+
} else {
|
|
50
|
+
System.out.println("调用失败: " + response.getSubCode() + " - " + response.getSubMsg());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private static AlipayConfig getAlipayConfig() {
|
|
55
|
+
String privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
|
|
56
|
+
String alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
|
|
57
|
+
AlipayConfig alipayConfig = new AlipayConfig();
|
|
58
|
+
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
|
|
59
|
+
// 沙箱环境: alipayConfig.setServerUrl("https://openapi-sandbox.dl.alipaydev.com/gateway.do");
|
|
60
|
+
alipayConfig.setAppId("<-- 请填写您的AppId,例如:20190xxxxxx -->");
|
|
61
|
+
alipayConfig.setPrivateKey(privateKey);
|
|
62
|
+
alipayConfig.setFormat("json");
|
|
63
|
+
alipayConfig.setAlipayPublicKey(alipayPublicKey);
|
|
64
|
+
alipayConfig.setCharset("UTF-8");
|
|
65
|
+
alipayConfig.setSignType("RSA2");
|
|
66
|
+
return alipayConfig;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 响应示例
|
|
72
|
+
### 正常示例
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"code": "10000",
|
|
76
|
+
"msg": "Success",
|
|
77
|
+
"trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
|
|
78
|
+
"out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
|
|
79
|
+
"trade_status": "TRADE_SUCCESS",
|
|
80
|
+
"total_amount": "88.88",
|
|
81
|
+
"buyer_pay_amount": "8.88",
|
|
82
|
+
"receipt_amount": "15.25",
|
|
83
|
+
"buyer_logon_id": "159****5620",
|
|
84
|
+
"buyer_user_id": "<BUYER_USER_ID>",
|
|
85
|
+
"send_pay_date": "2014-11-27 15:45:57"
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
### 异常示例
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"code": "20000",
|
|
92
|
+
"msg": "Service Currently Unavailable",
|
|
93
|
+
"sub_code": "isp.unknow-error",
|
|
94
|
+
"sub_msg": "系统繁忙"
|
|
95
|
+
}
|
|
96
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# 统一收单交易退款接口 - Java 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
package com.java.sdk.demo;
|
|
7
|
+
|
|
8
|
+
import com.alipay.api.AlipayApiException;
|
|
9
|
+
import com.alipay.api.AlipayClient;
|
|
10
|
+
import com.alipay.api.DefaultAlipayClient;
|
|
11
|
+
import com.alipay.api.AlipayConfig;
|
|
12
|
+
import com.alipay.api.domain.AlipayTradeRefundModel;
|
|
13
|
+
import com.alipay.api.request.AlipayTradeRefundRequest;
|
|
14
|
+
import com.alipay.api.response.AlipayTradeRefundResponse;
|
|
15
|
+
|
|
16
|
+
public class AlipayTradeRefund {
|
|
17
|
+
|
|
18
|
+
public static void main(String[] args) throws AlipayApiException {
|
|
19
|
+
// 初始化SDK(Java 使用 PKCS#8 格式私钥,C#/Python 使用 PKCS#1 格式,请勿混用)
|
|
20
|
+
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
|
|
21
|
+
|
|
22
|
+
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
|
|
23
|
+
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
|
|
24
|
+
model.setOutTradeNo("MERCHANT_ORDER_NO_PLACEHOLDER"); // 商户订单号,与 tradeNo 二选一
|
|
25
|
+
model.setRefundAmount("200.12"); // 使用十进制定点金额;调用前校验累计退款不超过原订单实付金额
|
|
26
|
+
model.setRefundReason("正常退款"); // 退款原因,选填
|
|
27
|
+
model.setOutRequestNo("OUT_REQUEST_NO_PLACEHOLDER"); // 新退款使用新编号;同一退款失败重试必须复用原编号和原参数
|
|
28
|
+
request.setBizModel(model);
|
|
29
|
+
|
|
30
|
+
AlipayTradeRefundResponse response = alipayClient.execute(request);
|
|
31
|
+
|
|
32
|
+
if (response.isSuccess()) {
|
|
33
|
+
if ("Y".equals(response.getFundChange())) {
|
|
34
|
+
System.out.println("退款资金已发生变化,退款金额: " + response.getRefundFee());
|
|
35
|
+
} else {
|
|
36
|
+
System.out.println("退款结果待确认:使用同一 out_request_no 调用 alipay.trade.fastpay.refund.query");
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
System.out.println("调用失败: " + response.getSubCode() + " - " + response.getSubMsg());
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private static AlipayConfig getAlipayConfig() {
|
|
44
|
+
String privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
|
|
45
|
+
String alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
|
|
46
|
+
AlipayConfig alipayConfig = new AlipayConfig();
|
|
47
|
+
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
|
|
48
|
+
// 沙箱环境: alipayConfig.setServerUrl("https://openapi-sandbox.dl.alipaydev.com/gateway.do");
|
|
49
|
+
alipayConfig.setAppId("<-- 请填写您的AppId,例如:20190xxxxxx -->");
|
|
50
|
+
alipayConfig.setPrivateKey(privateKey);
|
|
51
|
+
alipayConfig.setFormat("json");
|
|
52
|
+
alipayConfig.setAlipayPublicKey(alipayPublicKey);
|
|
53
|
+
alipayConfig.setCharset("UTF-8");
|
|
54
|
+
alipayConfig.setSignType("RSA2");
|
|
55
|
+
return alipayConfig;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 响应示例
|
|
61
|
+
### 正常示例
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"code": "10000",
|
|
65
|
+
"msg": "Success",
|
|
66
|
+
"trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
|
|
67
|
+
"out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
|
|
68
|
+
"buyer_logon_id": "159****5620",
|
|
69
|
+
"fund_change": "Y",
|
|
70
|
+
"refund_fee": "88.88"
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
### 异常示例
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"code": "20000",
|
|
77
|
+
"msg": "Service Currently Unavailable",
|
|
78
|
+
"sub_code": "isp.unknow-error",
|
|
79
|
+
"sub_msg": "系统繁忙"
|
|
80
|
+
}
|
|
81
|
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# 统一收单交易退款查询接口 - Java 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
package com.java.sdk.demo;
|
|
7
|
+
|
|
8
|
+
import com.alipay.api.AlipayApiException;
|
|
9
|
+
import com.alipay.api.AlipayClient;
|
|
10
|
+
import com.alipay.api.DefaultAlipayClient;
|
|
11
|
+
import com.alipay.api.AlipayConfig;
|
|
12
|
+
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
|
|
13
|
+
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
|
|
14
|
+
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
|
|
15
|
+
|
|
16
|
+
public class AlipayTradeFastpayRefundQuery {
|
|
17
|
+
|
|
18
|
+
public static void main(String[] args) throws AlipayApiException {
|
|
19
|
+
// 初始化SDK(Java 使用 PKCS#8 格式私钥,C#/Python 使用 PKCS#1 格式,请勿混用)
|
|
20
|
+
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
|
|
21
|
+
|
|
22
|
+
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
|
|
23
|
+
AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
|
|
24
|
+
model.setOutTradeNo("MERCHANT_ORDER_NO_PLACEHOLDER"); // 商户订单号,与 tradeNo 二选一
|
|
25
|
+
model.setOutRequestNo("OUT_REQUEST_NO_PLACEHOLDER"); // 退款请求号,必填,同一笔交易多次部分退款时用于区分
|
|
26
|
+
request.setBizModel(model);
|
|
27
|
+
|
|
28
|
+
AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
|
|
29
|
+
|
|
30
|
+
if (response.isSuccess()) {
|
|
31
|
+
// refund_status: REFUND_SUCCESS 表示退款成功,REFUND_PROCESSING 表示退款处理中
|
|
32
|
+
System.out.println("退款状态: " + response.getRefundStatus() + ", 退款金额: " + response.getRefundAmount());
|
|
33
|
+
} else {
|
|
34
|
+
System.out.println("调用失败: " + response.getSubCode() + " - " + response.getSubMsg());
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private static AlipayConfig getAlipayConfig() {
|
|
39
|
+
String privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
|
|
40
|
+
String alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
|
|
41
|
+
AlipayConfig alipayConfig = new AlipayConfig();
|
|
42
|
+
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
|
|
43
|
+
// 沙箱环境: alipayConfig.setServerUrl("https://openapi-sandbox.dl.alipaydev.com/gateway.do");
|
|
44
|
+
alipayConfig.setAppId("<-- 请填写您的AppId,例如:20190xxxxxx -->");
|
|
45
|
+
alipayConfig.setPrivateKey(privateKey);
|
|
46
|
+
alipayConfig.setFormat("json");
|
|
47
|
+
alipayConfig.setAlipayPublicKey(alipayPublicKey);
|
|
48
|
+
alipayConfig.setCharset("UTF-8");
|
|
49
|
+
alipayConfig.setSignType("RSA2");
|
|
50
|
+
return alipayConfig;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 响应示例
|
|
56
|
+
### 正常示例
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"code": "10000",
|
|
60
|
+
"msg": "Success",
|
|
61
|
+
"trade_no": "ALIPAY_TRADE_NO_PLACEHOLDER",
|
|
62
|
+
"out_trade_no": "MERCHANT_ORDER_NO_PLACEHOLDER",
|
|
63
|
+
"out_request_no": "OUT_REQUEST_NO_PLACEHOLDER",
|
|
64
|
+
"total_amount": "100.20",
|
|
65
|
+
"refund_amount": "12.33",
|
|
66
|
+
"refund_status": "REFUND_SUCCESS"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
### 异常示例
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"code": "20000",
|
|
73
|
+
"msg": "Service Currently Unavailable",
|
|
74
|
+
"sub_code": "isp.unknow-error",
|
|
75
|
+
"sub_msg": "系统繁忙"
|
|
76
|
+
}
|
|
77
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# 统一收单下单并支付页面接口 - Java 示例
|
|
2
|
+
|
|
3
|
+
## 请求示例
|
|
4
|
+
|
|
5
|
+
```java
|
|
6
|
+
package com.java.sdk.demo;
|
|
7
|
+
|
|
8
|
+
import com.alipay.api.AlipayApiException;
|
|
9
|
+
import com.alipay.api.AlipayClient;
|
|
10
|
+
import com.alipay.api.DefaultAlipayClient;
|
|
11
|
+
import com.alipay.api.AlipayConfig;
|
|
12
|
+
import com.alipay.api.domain.AlipayTradePagePayModel;
|
|
13
|
+
import com.alipay.api.response.AlipayTradePagePayResponse;
|
|
14
|
+
import com.alipay.api.request.AlipayTradePagePayRequest;
|
|
15
|
+
|
|
16
|
+
public class AlipayTradePagePay {
|
|
17
|
+
|
|
18
|
+
public static void main(String[] args) throws AlipayApiException {
|
|
19
|
+
// 初始化SDK(Java 使用 PKCS#8 格式私钥,C#/Python 使用 PKCS#1 格式,请勿混用)
|
|
20
|
+
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
|
|
21
|
+
|
|
22
|
+
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
|
|
23
|
+
String notifyUrl = System.getenv("ALIPAY_NOTIFY_URL");
|
|
24
|
+
if (notifyUrl != null && !notifyUrl.isBlank()) {
|
|
25
|
+
request.setNotifyUrl(notifyUrl.trim()); // 真实生产或公网联调时传入;本地没有公网 HTTPS notifyUrl 时不要调用 setNotifyUrl(null/空字符串/占位 URL)
|
|
26
|
+
}
|
|
27
|
+
request.setReturnUrl("https://your-domain.com/return"); // 默认传入并替换为已验证结果页;仅用户明确关闭同步回跳时省略
|
|
28
|
+
|
|
29
|
+
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
|
|
30
|
+
model.setOutTradeNo("MERCHANT_ORDER_NO_PLACEHOLDER"); // 商户订单号,必填
|
|
31
|
+
model.setTotalAmount("88.88"); // 订单总金额,必填,单位为元
|
|
32
|
+
model.setSubject("Iphone6 16G"); // 订单标题,必填
|
|
33
|
+
model.setProductCode("FAST_INSTANT_TRADE_PAY"); // 网站支付固定值,必填
|
|
34
|
+
request.setBizModel(model);
|
|
35
|
+
|
|
36
|
+
// ⚠️ 网站支付必须使用 pageExecute(),不能使用 execute()
|
|
37
|
+
// ⚠️ 必须使用 POST 模式:alipayClient.pageExecute(request, "POST")
|
|
38
|
+
AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "POST");
|
|
39
|
+
String formHtml = response.getBody();
|
|
40
|
+
// pageExecute 返回的是 HTML 表单字符串,前端需要渲染并自动提交
|
|
41
|
+
System.out.println(formHtml);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private static AlipayConfig getAlipayConfig() {
|
|
45
|
+
String privateKey = "<-- 请填写您的应用私钥,例如:MIIE...(脱敏示例) -->";
|
|
46
|
+
String alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIB...(脱敏示例) -->";
|
|
47
|
+
AlipayConfig alipayConfig = new AlipayConfig();
|
|
48
|
+
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
|
|
49
|
+
// 沙箱环境: alipayConfig.setServerUrl("https://openapi-sandbox.dl.alipaydev.com/gateway.do");
|
|
50
|
+
alipayConfig.setAppId("<-- 请填写您的AppId,例如:20190xxxxxx -->");
|
|
51
|
+
alipayConfig.setPrivateKey(privateKey);
|
|
52
|
+
alipayConfig.setFormat("json");
|
|
53
|
+
alipayConfig.setAlipayPublicKey(alipayPublicKey);
|
|
54
|
+
alipayConfig.setCharset("UTF-8");
|
|
55
|
+
alipayConfig.setSignType("RSA2");
|
|
56
|
+
return alipayConfig;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 响应示例
|
|
62
|
+
### 正常示例
|
|
63
|
+
```html
|
|
64
|
+
<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">
|
|
65
|
+
<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"}">
|
|
66
|
+
<input type="submit" value="立即支付" style="display:none" >
|
|
67
|
+
</form>
|
|
68
|
+
<script>document.forms[0].submit();</script>
|
|
69
|
+
```
|