Java-Web微信網頁支付開發流程以及各種坑
微信網頁支付流程概覽
- 生成Oauth2.0授權連結獲得code
- 使用code獲得使用者資訊(OpenId)
- 向微信統一下單介面提交訂單獲得PrepayID
- 在JS頁面中向用戶發起支付請求
- 使用者輸入支付密碼完成支付
使用weixin-java-tools工具可以快速完成以下開發
1.生成Oauth2.0授權連結
為什麼要生成授權連結:當要為某使用者提交支付訂單時必須要得到該使用者的OpenId(OpenId是加密後的微信帳號,同一個使用者在不同的公眾號內的該值是不同的)
而獲得使用者的OpenId,就需要使用者對你的公眾賬號進行授權(可以不需要關注),使用者授權之後微信將會發送一個code到你提供的頁面(redirect_uri)
你需要提供和關心的內容
引數 | 說明 |
---|---|
appid | 公眾號的唯一標識 |
redirect_uri | 授權後重定向的回撥連結地址,請使用urlencode對連結進行處理 |
scope | 應用授權作用域,snsapi_base (不彈出授權頁面,直接跳轉,只能獲取使用者openid),snsapi_userinfo (彈出授權頁面,可通過openid拿到暱稱、性別、所在地。並且,即使在未關注的情況下,只要使用者授權,也能獲取其資訊) |
使用開源的“weixin-java-tools”可以方便地生成授權連結:
//首先配置你的公眾號資訊
WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
config.setAppId("你的APPID");
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(config);
//輕鬆地拼接一個Oauth2.0授權連結
System.out.println(wxMpService.oauth2buildAuthorizationUrl("你的redirect_uri" ,"snsapi_userinfo","傳遞一個state引數(可為null)"));
例如這裡redirect_uri填寫: http://mytest.com/test/pay
執行後會生成類似如下連結:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx19c7c9777756d0cc&redirect_uri=http%3A%2F%2Fmytest.com%2Ftest%2Fpay&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
上述連結需要你放置在你的微信公眾號或者提交訂單時的H5頁面中,引導使用者點選進行授權。從而可以進行以後的支付操作。
使用者在該連結中選擇授權您的公眾號之後,微信會立即傳送code值和state(你自己設定的欄位)到你的redirect_uri中:
http://mytest.com/test/pay?code=CODE&state=STATE
因此你的redirect_uri應當指向一個服務而不是一個靜態頁面,這裡使用tomcat+Java Servlet實現後續步驟
本章節會遇到的坑:
1.實際測試點選授權頁面時提示redirect_uri引數錯誤
這裡需要在微信公眾號後臺-介面許可權-網頁授權獲取使用者基本資訊-修改 中新增你的redirect_uri的域名,注意是域名哦!此時會獲得一個授權檔案(txt)需要將該檔案放置到你站點的根目錄下。
2.使用code獲得使用者資訊(OpenId)
上一步結束之後我們已經在Servlet中拿到code值,接下來我們需要去請求Access_Token和使用者的OpenId(關鍵是要得到OpenId)(注意此處的Access_Token不同於微信開發中的Access_Token並不混用也不會互相重新整理。code的有效期限為5分鐘,且每申請一次只能使用一次)
//同樣需要先配置公眾號資訊,但本次要求的引數為4個
WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
config.setAppId("你的APPID");
config.setSecret("你的APPSECRET");
config.setPartnerId("你的商戶ID");
config.setPartnerKey("你的商戶SecretKey");
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(config);
//使用已經得到的code獲取AccessToken和OpenId
WxMpOAuth2AccessToken wxMpOAuth2AccessToken= null;
WxMpUser wxMpUser = null;
try {
wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
//下面的方法會獲得使用者的詳細資訊,本例用不到但是如有需要之前的步驟也是這麼進行
wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
} catch (WxErrorException e) {
e.printStackTrace();
}
String Openid=wxMpOAuth2AccessToken.getOpenId();
System.out.println("已經獲得獲得使用者Openid:"+ Openid);
3.向微信統一下單介面提交訂單
在下單之前我們需要組織引數
官方:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
下述例項將只進行關鍵必要引數的設定
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
//由於我們前面的config配置 因此各種ID會被預設配置進去,NonceStr生成方法是System.currentTimeMillis()也已經預設新增。MD5簽名加密問題也無需考慮,其內建的簽名方法已經搞定。
orderRequest.setBody("商品描述");
orderRequest.setOutTradeNo("訂單ID"); //商戶唯一訂單號
orderRequest.setTotalFee(1);//價格單位為‘分’
orderRequest.setOpenid(Openid);
orderRequest.setNotifyURL("http://www.weixin.qq.com/wxpay/pay.php");//微信回撥地址 使用者支付成功後微信會向該介面推送結果
orderRequest.setTradeType("JSAPI");//不要修改
orderRequest.setSpbillCreateIp("172.168.1.1");//當前使用者的IP
WxMpPayService wxMpPayService = wxMpService.getPayService();
String mypackage="";
String nonceStr="";
try { mypackage=""+wxMpPayService.getPayInfo(orderRequest).get("package");
nonceStr=""+wxMpPayService.getPayInfo(orderRequest).get("nonceStr");
System.out.println("prepayID:"+mypackage);
} catch (WxErrorException e) {
e.printStackTrace();
}
我們現在已經在微信上建立了一筆訂單,並且返回我們需要的關鍵資訊為package(包含prepayId),當然nonce_str是之前weixin-java-tools生成的,此時微信也會返回該值直接取得即可。
萬事俱備,只欠從介面向用戶發起支付請求
4.在JS頁面中向用戶發起支付請求
我們需要準備一個JSP請求支付的頁面,並且在Servlet向其轉發剛才獲取的關鍵訂單資訊
<%@ page import="java.sql.Timestamp" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title><link rel="stylesheet" href="js/weui/css/weui.min.css" type="text/css">
<script type="text/javascript" src="js/weui/js/zepto.min.js"></script>
<script type="text/javascript" src="js/weui/js/jweixin.js"></script>
<script type="text/javascript" src="js/weui/js/weui.min.js"></script>
</head>
<body ontouchstart>
<div>
<div class="page">
<a href="javascript:;" class="weui-btn weui-btn_primary" id="btnPay">立即支付</a>
</div>
</div>
<script type="text/javascript">
$("#btnPay").on('click',function(){
console.log("TEST");
});
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : "${APPID}", //公眾號名稱,由商戶傳入
"timeStamp":"${TIMEST}", //時間戳,自1970年以來的秒數
"nonceStr" : "${NOCESTR}", //隨機串
"package" : "${PREPAYID}",
"signType" : "MD5", //微信簽名方式:
"paySign" : "${MYMD5}" //微信簽名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {}
}
);
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
alert('呼叫WeiXin支付');
onBridgeReady();
}
</script>
</body>
</html>
本章節會遇到的坑:
1.實際測試時頁面提示當前URL頁面未註冊
這裡需要在微信公眾號後臺-微信支付-授權測試目錄裡面新增你當前支付JSP頁面的目錄。
比如我的支付頁面是 http://a.com/test/pay/pay.jsp
那麼我就需要填寫 http://a.com/test/pay/
然而這裡有一個坑就是,在實際發起支付的時候他會檢查你發起支付的路徑是什麼,也就是說如果你如果之前使用servler獲取資料後向JSP轉發資料的話,那麼使用者在支付的時候url就不是http://a.com/test/pay/pay.jsp
而可能變成了http://a.com/test/pay?key=value
如此一來你填寫的支付測試路徑就出現了錯誤。因此需要修改測試路徑為 http://a.com/test/ 即可通過。
至此使用者在微信中訪問第一步的授權連結後,會提示授權,然後跳轉到JSP進行支付
歡迎到我的部落格裡坐坐 http://www.xiaomilu.top