微信支付宝支付集成完全指南:Android、Web 与 Go 后端实战
peakchao
2025-12-13 05:45
15 次浏览
0 条评论
支付流程概述
支付时序图
无论是微信支付还是支付宝支付,核心流程都是类似的:
┌─────────────────────────────────────────────────────────────────────────────┐
│ 支付流程时序图 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 客户端 商户后端 支付平台 │
│ │ │ │ │
│ │ ─── 1.创建订单 ───►│ │ │
│ │ │ │ │
│ │ │ ─── 2.预下单请求 ───►│ │
│ │ │ │ │
│ │ │ ◄─── 3.返回预支付 ───│ │
│ │ │ 信息 │ │
│ │ │ │ │
│ │ ◄── 4.返回支付 ────│ │ │
│ │ 参数 │ │ │
│ │ │ │ │
│ │ ─── 5.调起支付 ─────────────────────────►│ │
│ │ SDK/页面 │ │ │
│ │ │ │ │
│ │ ◄── 6.支付结果 ─────────────────────────│ │
│ │ (客户端) │ │ │
│ │ │ │ │
│ │ │ ◄─── 7.异步通知 ────│ │
│ │ │ (服务端) │ │
│ │ │ │ │
│ │ │ ─── 8.返回成功 ─────►│ │
│ │ │ │ │
│ │ ◄── 9.确认结果 ────│ │ │
│ │ │ │ │
└─────────────────────────────────────────────────────────────────────────────┘微信支付 vs 支付宝支付
| 对比项 | 微信支付 | 支付宝支付 |
|---|---|---|
| App支付 | 需要 App ID + 商户号 | 需要 App ID + 私钥 |
| H5支付 | 需要申请 H5 支付权限 | 手机网站支付 |
| 签名算法 | RSA/HMAC-SHA256 | RSA2 (SHA256WithRSA) |
| 异步通知 | XML/JSON 格式 | form 表单格式 |
| 证书管理 | API 证书 + 平台证书 | 应用私钥 + 支付宝公钥 |
准备工作
微信支付准备
-
注册微信商户平台账号
- 访问 微信商户平台
- 完成企业资质认证
-
获取必要参数
| 参数 | 说明 | 获取位置 |
|---|---|---|
appid | 应用/公众号 ID | 微信开放平台/公众平台 |
mchid | 商户号 | 商户平台 - 账户中心 |
apiKey | API 密钥 (V2) | 商户平台 - API安全 |
apiV3Key | API V3 密钥 | 商户平台 - API安全 |
serialNo | 证书序列号 | API 证书详情 |
privateKey | 商户私钥 | 申请 API 证书时生成 |
- 下载 API 证书
- 商户平台 → 账户中心 → API安全 → 申请API证书
- 妥善保管
apiclient_key.pem(私钥)
支付宝支付准备
-
注册支付宝开放平台账号
- 访问 支付宝开放平台
- 创建应用并提交审核
-
获取必要参数
| 参数 | 说明 | 获取位置 |
|---|---|---|
appId | 应用 ID | 开放平台 - 应用详情 |
privateKey | 应用私钥 | 本地生成后上传公钥 |
alipayPublicKey | 支付宝公钥 | 开放平台 - 应用详情 |
signType | 签名类型 | 推荐 RSA2 |
- 生成密钥对
# 生成 RSA2 私钥
# 生成公钥(上传到支付宝开放平台)
# 将私钥转换为 PKCS8 格式(Java/Kotlin 使用)
Go 后端实现
项目结构
payment-server/
├── main.go
├── config/
│ └── config.go
├── handlers/
│ ├── wechat.go
│ └── alipay.go
├── services/
│ ├── wechat_pay.go
│ └── alipay_pay.go
├── models/
│ └── order.go
└── utils/
└── sign.go配置文件
// config/config.go
package config
type PaymentConfig struct
type WechatConfig struct
type AlipayConfig struct 微信支付服务
// services/wechat_pay.go
package services
import (
"context"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
"time"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments/app"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments/h5"
"github.com/wechatpay-apiv3/wechatpay-go/utils"
)
type WechatPayService struct
// NewWechatPayService 创建微信支付服务实例
func NewWechatPayService(cfg *config.WechatConfig) (*WechatPayService, error)
// CreateAppPayOrder 创建 App 支付订单
func (ctx context.Context,
orderNo string, amount int64, description string) (*AppPayResult, error)
// CreateH5PayOrder 创建 H5 支付订单
func (ctx context.Context,
orderNo string, amount int64, description, clientIP string) (string, error)
// AppPayResult App支付结果
type AppPayResult struct 支付宝服务
// services/alipay_pay.go
package services
import (
"context"
"fmt"
"github.com/smartwalle/alipay/v3"
)
type AlipayService struct
// NewAlipayService 创建支付宝支付服务实例
func NewAlipayService(cfg *config.AlipayConfig) (*AlipayService, error)
// CreateAppPayOrder 创建 App 支付订单
func (ctx context.Context,
orderNo string, amount string, subject string) (string, error)
// CreateWapPayOrder 创建手机网站支付订单
func (ctx context.Context,
orderNo string, amount string, subject string) (string, error)
// CreatePagePayOrder 创建电脑网站支付订单
func (ctx context.Context,
orderNo string, amount string, subject string) (string, error)
// VerifyNotify 验证异步通知
func (values map[string][]string) (*alipay.Notification, error)
// QueryOrder 查询订单
func (ctx context.Context, orderNo string) (*alipay.TradeQueryRsp, error) HTTP 处理器
// handlers/payment.go
package handlers
import (
"encoding/json"
"io"
"log"
"net/http"
)
type PaymentHandler struct
// CreateOrderRequest 创建订单请求
type CreateOrderRequest struct
// CreateOrder 统一创建订单接口
func (w http.ResponseWriter, r *http.Request)
// WechatPayNotify 微信支付回调
func (w http.ResponseWriter, r *http.Request)
// AlipayNotify 支付宝回调
func (w http.ResponseWriter, r *http.Request) Android Kotlin 客户端实现
添加依赖
// app/build.gradle.kts
dependencies {
// 微信支付 SDK
implementation("com.tencent.mm.opensdk:wechat-sdk-android:6.8.24")
// 支付宝 SDK - 需要手动下载 aar 放入 libs 目录
implementation(files("libs/alipaysdk.aar"))
// 网络请求
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// 协程
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}支付服务封装
// PaymentService.kt
package com.example.payment
import android.app.Activity
import android.content.Context
import com.alipay.sdk.app.PayTask
import com.tencent.mm.opensdk.modelpay.PayReq
import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class PaymentService(private val context: Context) {
private val wxApi: IWXAPI by lazy {
WXAPIFactory.createWXAPI(context, WX_APP_ID, true).apply {
registerApp(WX_APP_ID)
}
}
companion object {
private const val WX_APP_ID = "your_wechat_app_id"
}
/**
* 微信 App 支付
*/
fun wechatPay(payParams: WechatPayParams): Boolean {
if (!wxApi.isWXAppInstalled) {
throw PaymentException("请先安装微信")
}
val request = PayReq().apply {
appId = payParams.appId
partnerId = payParams.partnerId
prepayId = payParams.prepayId
packageValue = payParams.packageValue
nonceStr = payParams.nonceStr
timeStamp = payParams.timestamp
sign = payParams.sign
}
return wxApi.sendReq(request)
}
/**
* 支付宝 App 支付
*/
suspend fun alipay(activity: Activity, orderStr: String): AlipayResult {
return withContext(Dispatchers.IO) {
val payTask = PayTask(activity)
val result = payTask.payV2(orderStr, true)
parseAlipayResult(result)
}
}
private fun parseAlipayResult(result: Map<String, String>): AlipayResult {
val resultStatus = result["resultStatus"] ?: ""
val memo = result["memo"] ?: ""
return when (resultStatus) {
"9000" -> AlipayResult.Success(memo)
"8000" -> AlipayResult.Processing(memo)
"6001" -> AlipayResult.Cancelled(memo)
"6002" -> AlipayResult.NetworkError(memo)
else -> AlipayResult.Failed(resultStatus, memo)
}
}
}
// 数据类
data class WechatPayParams(
val appId: String,
val partnerId: String,
val prepayId: String,
val packageValue: String,
val nonceStr: String,
val timestamp: String,
val sign: String
)
sealed class AlipayResult {
data class Success(val memo: String) : AlipayResult()
data class Processing(val memo: String) : AlipayResult()
data class Cancelled(val memo: String) : AlipayResult()
data class NetworkError(val memo: String) : AlipayResult()
data class Failed(val code: String, val memo: String) : AlipayResult()
}
class PaymentException(message: String) : Exception(message)微信支付回调
// wxapi/WXPayEntryActivity.kt
package com.example.payment.wxapi
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import com.tencent.mm.opensdk.constants.ConstantsAPI
import com.tencent.mm.opensdk.modelbase.BaseReq
import com.tencent.mm.opensdk.modelbase.BaseResp
import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler
import com.tencent.mm.opensdk.openapi.WXAPIFactory
/**
* 微信支付回调 Activity
* 必须放在 包名.wxapi 目录下,类名必须是 WXPayEntryActivity
*/
class WXPayEntryActivity : Activity(), IWXAPIEventHandler {
private lateinit var api: IWXAPI
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
api = WXAPIFactory.createWXAPI(this, "your_wechat_app_id")
api.handleIntent(intent, this)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
setIntent(intent)
api.handleIntent(intent, this)
}
override fun onReq(req: BaseReq?) {}
override fun onResp(resp: BaseResp?) {
if (resp?.type == ConstantsAPI.COMMAND_PAY_BY_WX) {
val result = when (resp.errCode) {
BaseResp.ErrCode.ERR_OK -> PaymentResult.SUCCESS
BaseResp.ErrCode.ERR_USER_CANCEL -> PaymentResult.CANCELLED
else -> PaymentResult.FAILED
}
// 发送广播或使用 EventBus 通知支付结果
sendPaymentResult(result)
}
finish()
}
private fun sendPaymentResult(result: PaymentResult) {
val intent = Intent("com.example.payment.WECHAT_PAY_RESULT").apply {
putExtra("result", result.name)
}
sendBroadcast(intent)
}
enum class PaymentResult {
SUCCESS, CANCELLED, FAILED
}
}使用示例
// PaymentViewModel.kt
class PaymentViewModel : ViewModel() {
private val paymentApi: PaymentApi = RetrofitClient.create()
private var paymentService: PaymentService? = null
private val _paymentState = MutableStateFlow<PaymentState>(PaymentState.Idle)
val paymentState: StateFlow<PaymentState> = _paymentState
fun initPaymentService(context: Context) {
paymentService = PaymentService(context)
}
/**
* 创建订单并支付
*/
fun pay(orderNo: String, amount: Long, payMethod: String) {
viewModelScope.launch {
_paymentState.value = PaymentState.Loading
try {
// 1. 调用后端创建订单
val response = paymentApi.createOrder(
CreateOrderRequest(
orderNo = orderNo,
amount = amount,
description = "商品购买",
payMethod = payMethod
)
)
if (response.code != 0) {
_paymentState.value = PaymentState.Error("创建订单失败")
return@launch
}
// 2. 调起支付
when (payMethod) {
"wechat_app" -> {
val params = Gson().fromJson(
Gson().toJson(response.data),
WechatPayParams::class.java
)
paymentService?.wechatPay(params)
// 结果通过 WXPayEntryActivity 回调
}
"alipay_app" -> {
val orderStr = response.data as String
// 需要在 Activity 中调用
_paymentState.value = PaymentState.AlipayReady(orderStr)
}
}
} catch (e: Exception) {
_paymentState.value = PaymentState.Error(e.message ?: "支付失败")
}
}
}
}
sealed class PaymentState {
object Idle : PaymentState()
object Loading : PaymentState()
data class AlipayReady(val orderStr: String) : PaymentState()
data class Success(val orderNo: String) : PaymentState()
data class Error(val message: String) : PaymentState()
}Web 前端实现
H5 支付页面
收银台
确认支付
0.00
订单号-
商品-
选择支付方式
支付宝
微信支付
立即支付
正在跳转支付...
安全最佳实践
1. 签名验证
// 始终验证回调通知的签名
func (r *http.Request, body []byte) error 2. 幂等性处理
// 使用 Redis 防止重复处理
func (orderNo string) error 3. 金额校验
// 验证通知中的金额与订单金额是否一致
func verifyAmount(notification *Notification, order *Order) error 常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 签名错误 | 密钥不正确 / 签名算法错误 | 检查密钥配置,确认算法一致 |
| 回调收不到 | 域名未备案 / 防火墙拦截 | 检查域名和服务器配置 |
| 支付宝SDK报错 | 未添加混淆配置 | 添加 ProGuard 规则 |
| 微信未安装提示 | 未注册 AppID | 确保正确调用 registerApp |
请先登录后再发表评论