首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 微信 H5 支付(JSAPI)完整開發指南:獲取 OpenID → 統一下單 → 前端喚起 → 異步回調

     編輯:Java 相關知識

微信公眾號支付(JSAPI)流程分三步:網頁授權獲取 OpenID → 統一下單獲取 prepay_id → JSSDK 喚起支付。本文提供生產級 Java 代碼:HttpClient 封裝授權/下單、XStream 處理 XML 互轉、WxSign 實現簽名算法、前端 WeixinJSBridge 調用全邏輯,並針對 notify_url 異步回調、簽名密鑰區分(商戶 Key ≠ AppSecret)等核心坑點給出避坑方案。

流程時序圖

用戶點擊支付
   ↓
1. 導向授權頁 (scope=snsapi_base) → 獲取 code
   ↓
2. code 換取 access_token + openid
   ↓
3. 統一下單 (trade_type=JSAPI, openid) → 獲得 prepay_id
   ↓
4. 組裝 paySign (appId, timeStamp, nonceStr, package=prepay_id, signType=MD5)
   ↓
5. 前端 WeixinJSBridge.invoke('getBrandWCPayRequest', paySign)
   ↓
6. 用戶輸入密碼 → 微信異步回調 notify_url → 業務系統更新訂單狀態

核心後端代碼

1. 授權獲取 OpenID

String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?"
    + "appid=" + APPID + "&redirect_uri=" + urlEncode(REDIRECT_URI)
    + "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
// 用戶授權後回調 REDIRECT_URI?code=CODE
Map<String, String> params = new HashMap<>();
params.put("appid", APPID); params.put("secret", APPSECRET);
params.put("code", code); params.put("grant_type", "authorization_code");
String resp = HttpClientUtil.post("https://api.weixin.qq.com/sns/oauth2/access_token", params);
AccessToken at = JSON.parseObject(resp, AccessToken.class); // 含 openid

2. 統一下單 (UnifiedorderService)

WxPaySendData data = new WxPaySendData();
data.setAppid(APPID); data.setMch_id(MCHID);
data.setNonce_str(WxSign.getNonceStr());
data.setBody("商品描述"); data.setOut_trade_no(orderNo);
data.setTotal_fee((int)(fee * 100)); // 單位:分
data.setTrade_type("JSAPI"); data.setOpenid(at.getOpenid());
data.setSpbill_create_ip(clientIp); data.setNotify_url(NOTIFY_URL);

// 簽名:參數按 ASCII 升序拼接 + key=商戶Key → MD5 → 大寫
SortedMap<Object,Object> signParams = new TreeMap<>();
// ... put 所有非空非 sign 字段
data.setSign(WxSign.createSign(signParams, MCH_KEY));

// XML 請求
String xml = XStream.toXML(data);
String resultXml = HttpClientUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);
WxPayReturnData ret = XStream.fromXML(resultXml); // 解析 prepay_id

3. 前端喚起參數組裝

SortedMap<Object,Object> paySignMap = new TreeMap<>();
paySignMap.put("appId", ret.getAppid());
paySignMap.put("timeStamp", WxSign.getTimeStamp());
paySignMap.put("nonceStr", ret.getNonce_str());
paySignMap.put("package", "prepay_id=" + ret.getPrepay_id());
paySignMap.put("signType", "MD5");
String paySign = WxSign.createSign(paySignMap, MCH_KEY);
// 返回給頁面:appId, timeStamp, nonceStr, package, signType, paySign

4. 前端調用 (JS)

function onBridgeReady() {
    WeixinJSBridge.invoke('getBrandWCPayRequest', {
        "appId": appId, "timeStamp": timeStamp, "nonceStr": nonceStr,
        "package": pkg, "signType": signType, "paySign": paySign
    }, function(res) {
        if (res.err_msg == "get_brand_wcpay_request:ok") alert("支付成功");
        else if (res.err_msg == "get_brand_wcpay_request:cancel") alert("用戶取消");
        else alert("支付失敗: " + res.err_msg);
    });
}
if (typeof WeixinJSBridge == "undefined") {
    document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else { onBridgeReady(); }

五大避坑指南

  1. 簽名 Key: 統一下單與 paySign 均使用商戶平台設置的 API Key (MCH_KEY),絕非 AppSecret。
  2. 金額單位: 統一下單 total_fee 以分為單位,int(Math.round(fee * 100))。
  3. 授權域名: 微信公眾平台需配置授權回調域名,且必須為一級/二級域名,不可帶端口、IP、localhost。
  4. 異步回調: notify_url 必須為外網可訪問 HTTPS,回應 <xml><return_code><![CDATA[SUCCESS]]></return_code></xml> 否則微信會重試通知。
  5. 預付單有效期: prepay_id 2 小時內有效,前端應即時喚起,超時需重新下單。

完整代碼已模組化,引入 httpclient、xstream、fastjson 即可運行,適合快速接入微信支付業務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved