Java微信H5支付实现流程及代码解析

1. 整体流程

Java微信H5支付的实现流程可以简单分为以下几个步骤:

  1. 获取微信支付配置信息:包括商户号、AppID、AppSecret、商户密钥等;
  2. 用户发起支付请求:用户在H5页面选择支付方式,并填写支付金额等信息;
  3. 统一下单:开发者后台通过微信支付接口生成预支付订单,并返回支付参数给H5页面;
  4. 唤起微信支付:H5页面通过调用微信支付JSAPI唤起微信支付界面;
  5. 用户支付完成:用户在微信支付界面中输入密码完成支付;
  6. 支付结果通知:微信服务器将支付结果通知给开发者后台;
  7. 校验支付结果:开发者后台校验支付结果的有效性,并进行相应的业务处理;
  8. 返回支付结果:开发者后台将支付结果返回给H5页面。

下面将逐步解析每一步需要做的事情,并给出相应的代码示例。

2. 获取微信支付配置信息

首先,你需要在微信支付商户平台注册账号,并获取到以下配置信息:

  • 商户号(mchId):商户在微信支付平台的唯一标识;
  • AppID:微信公众号或小程序的唯一标识;
  • AppSecret:用于生成AccessToken的密钥;
  • 商户密钥(key):商户用于生成签名和校验签名的密钥。

3. 用户发起支付请求

用户在H5页面选择支付方式,并填写支付金额等信息。这一步主要由前端实现,后端需要提供接口用于接收支付请求数据。

4. 统一下单

开发者后台通过微信支付接口生成预支付订单,并返回支付参数给H5页面。

// 发起统一下单请求
String url = "
String xmlData = generateXmlData(); // 生成请求参数的XML格式数据
String responseXml = sendPostRequest(url, xmlData); // 发送POST请求,获取响应结果

// 解析响应结果
Map<String, String> resultMap = parseXmlData(responseXml);
String prepayId = resultMap.get("prepay_id"); // 获取预支付订单ID

// 构造支付参数
String timestamp = String.valueOf(System.currentTimeMillis() / 1000); // 时间戳
String nonceStr = generateNonceStr(); // 随机字符串
String packageStr = "prepay_id=" + prepayId; // 预支付订单ID
String signType = "MD5"; // 签名类型
String sign = generateSign(appId, timestamp, nonceStr, packageStr, signType); // 生成签名

// 构造返回给H5页面的支付参数
Map<String, String> payParams = new HashMap<>();
payParams.put("appId", appId);
payParams.put("timeStamp", timestamp);
payParams.put("nonceStr", nonceStr);
payParams.put("package", packageStr);
payParams.put("signType", signType);
payParams.put("paySign", sign);

// 返回支付参数给H5页面
return payParams;

其中,generateXmlData()方法用于生成请求参数的XML格式数据,sendPostRequest()方法用于发送POST请求并获取响应结果,parseXmlData()方法用于解析响应结果的XML数据,generateNonceStr()方法用于生成随机字符串,generateSign()方法用于生成签名。

5. 唤起微信支付

H5页面通过调用微信支付JSAPI唤起微信支付界面。

function onBridgeReady() {
    WeixinJSBridge.invoke('getBrandWCPayRequest', {
        "appId": "${appId}", // 从后台获取的AppID
        "timeStamp": "${timeStamp}", // 从后台获取的时间戳
        "nonceStr": "${nonceStr}", // 从后台获取的随机字符串
        "package": "${package}", // 从后台获取的支付参数
        "signType": "${signType}", // 从后台获取的签名类型
        "paySign": "${paySign}" // 从后台获取的签名
    }, function (res) {
        if (res.err_msg == "get_brand_wcpay_request:ok") {
            // 支付成功后的处理逻辑
        } else {
            // 支付失败后的