--- title: WeChat Pay Server To Server 集成 permalink: /notes/zh/paymentMethods/WeChatPay/s2s/ createTime: '2025/08/08 15:00:00' description: >- WeChat Pay Server To Server集成文档介绍了如何通过S2S方式实现微信支付。适用于PC、移动端浏览器及Webview内支付场景,覆盖中国大陆地区。关键参数包括`device.orderTerminal`和`shopperIP`。支持直接拉起微信支付或通过中间页处理支付流程,确 --- ## WeChat Pay-Server To Server交互流程 ```mermaid %%{init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#E3F2FD', 'primaryTextColor': '#0D47A1', 'primaryBorderColor': '#1976D2', 'lineColor': '#1565C0', 'secondaryColor': '#BBDEFB', 'tertiaryColor': '#90CAF9', 'background': '#F8FBFF', 'mainBkg': '#E3F2FD', 'secondBkg': '#BBDEFB', 'tertiaryBkg': '#90CAF9', 'actorBkg': '#2196F3', 'actorBorder': '#1976D2', 'actorTextColor': '#FFFFFF', 'actorLineColor': '#1565C0', 'signalColor': '#0D47A1', 'signalTextColor': '#0D47A1', 'c0': '#E8F4FD', 'c1': '#D1E7DD', 'c2': '#B3D9FF', 'c3': '#81C784', 'noteBkgColor': '#E1F5FE', 'noteTextColor': '#01579B', 'noteBorderColor': '#0288D1', 'loopTextColor': '#0D47A1', 'activationBkgColor': '#B3E5FC', 'activationBorderColor': '#0277BD' } }}%% sequenceDiagram participant User as 👤 用户 participant Frontend as 💻 商户前端 participant Merchant as 🏪 商户后端 participant PP as 🔄 PingPong服务端 participant WeChat as 💬 WeChat Pay Note over User, WeChat: 🚀 WeChat Pay Server To Server集成流程 Note over User, Frontend: 📋 准备阶段:• 用户选择支付• 商户自建收银台 User->>Frontend: 1. 用户进入商户收银台页面 User->>Frontend: 2. 选择WeChat Pay支付方式 Frontend->>+Merchant: 3. 提交订单信息 Note right of Merchant: 订单验证
金额计算 Merchant->>+PP: 4. 调用下单并支付API Note right of PP: 创建支付订单
获取微信支付参数 PP-->>-Merchant: 5. 返回支付参数(二维码/调起参数) Merchant->>-Frontend: 6. 返回支付参数到前端 Note over Frontend, WeChat: 💳 微信支付交互 alt 🖥️ [PC端支付] Frontend->>Frontend: 7. 6a️⃣ 显示微信支付二维码 User->>WeChat: 8. 7a️⃣ 用户扫码支付 WeChat->>WeChat: 9. 用户完成支付授权 else 📱 [移动端支付] Frontend->>+WeChat: 10. 6b️⃣ 调起微信客户端 Note right of WeChat: H5跳转微信支付
或微信内直接支付 User->>WeChat: 11. 7b️⃣ 用户完成支付授权 WeChat-->>-Frontend: 12. 支付结果页面跳转 end WeChat->>+PP: 13. 微信支付结果通知 PP->>PP: 14. 处理支付结果 Note right of PP: • 验证支付结果• 更新订单状态• 风控检查 PP->>+Merchant: 15. 🔟 异步通知支付结果 Note right of Merchant: 订单状态更新
业务逻辑处理 Merchant-->>-PP: 16. 确认通知接收 alt ✅ [支付成功] PP-->>WeChat: 17. 支付处理完成 Note over Frontend, Merchant: 🔄 状态轮询(可选) Frontend->>+Merchant: 18. 1️⃣ 轮询支付状态 Merchant-->>-Frontend: 19. 返回最新状态 Frontend->>Frontend: 20. 2️⃣ 显示支付成功页面 Note over Frontend: 商户自定义逻辑
支付完成处理 else ❌ [支付失败] PP-->>WeChat: 21. 支付失败处理 Frontend->>Frontend: 22. 显示支付失败页面 Note right of Frontend: 错误处理
用户提示 end Note over User, PP: 🎯 WeChat Pay Server To Server流程完成 ``` ## 集成导航 ### Step1 调用下单并支付 使用下单并支付接口直接发起微信支付 ### Step2 处理支付响应 根据不同支付场景处理返回的支付参数: **关键参数说明:** 1. `device.orderTerminal` - 02-PC端浏览器(pc) - 04-SDK(ios) - 05-SDK(Android) 2. `shopperIP` - 用户的公网IP地址,微信支付要求必须传递,否则会报错 - 请获取真实的消费者IP地址,不能使用localhost、127.0.0.1等回环地址 ## PC端支付 `device.orderTerminal` = `02` 下单并支付接口返回参数: - `qrCode` : 微信的`qrCode`,需要商户自行处理二维码展示 - `paymentRedirectUrl` : PingPongCheckout包装的二维码页面,只需要重定向到该页面 ## 移动端浏览器支付 `device.orderTerminal` = `04` 或 `05` 下单并支付接口返回参数: - `paymentRedirectUrl` : 对应微信的`mwebUrl`参数 ## Webview内支付 `device.orderTerminal` = `04` 或 `05` 下单并支付接口返回参数: - `paymentRedirectUrl` : 对应微信的`mwebUrl`参数 ### 方案1:Webview直接拉起微信支付 ::: steps 1. **请求下单并支付接口,获取`paymentRedirectUrl`。** 2. **设置 Referer** **Android:在 loadUrl 时添加 Referer** ```kotlin val headers = mutableMapOf() headers["Referer"] = "https://your-domain.com" // 必须与授权域名一致 webView.loadUrl(mwebUrl, headers) ``` **iOS:在 request 头中设置 Referer(WKWebView)** ```swift guard let url = URL(string: mwebUrl) else { return } var request = URLRequest(url: url) request.setValue("https://your-domain.com", forHTTPHeaderField: "Referer") webView.load(request) ``` 3. 拉起微信并支付 ::: ### 方案2:通过中间页拉起为微信支付 ::: steps 1. **请求下单并支付接口,获取`paymentRedirectUrl`。** 2. **创建 pay-proxy 中间页** ```html ``` 3. **创建 back 回调页** ```html ``` 4. **App WebView 加载中间页** ```kotlin webView.loadUrl("https://中间页域名/pay-proxy?orderId=123") ``` 5. **拦截并拉起微信** ```kotlin override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { val url = request?.url?.toString() ?: return false if (url.startsWith("weixin://")) { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) return true } if (url.startsWith("yourapp://")) { handlePayResult(url) return true } return false } ``` 6. **接收回跳并刷新订单** 在 `handlePayResult(url)` 中解析参数,关闭 WebView,查询后端订单状态。 :::