微信公众号支付开发全过程
微信公眾號(hào)支付開發(fā)全過程
需求:把游戲里的商城轉(zhuǎn)移到微信公眾號(hào)上
微信公眾號(hào)支付開發(fā)的準(zhǔn)備過程:
需要注冊(cè)一個(gè)公眾號(hào),然后開通微信支付功能(需要5個(gè)工作日左右),然后就可以得到APPID,APP_SECRET,商戶號(hào),商戶key等參數(shù)。
開始開發(fā):
1. 調(diào)用統(tǒng)一下單接口,獲取預(yù)支付ID
/*** 用戶提交支付,獲取微信支付訂單接口*/ @RequestMapping(value="/pay") public ModelAndView pay(HttpServletRequest request,HttpServletResponse response){ModelAndView mv = new ModelAndView();String GZHID = "wxfd7c065eee11112222";// 微信公眾號(hào)idString GZHSecret = "b5b3a627f5d1f8888888888888";// 微信公眾號(hào)密鑰idString SHHID = "111111111";// 財(cái)付通商戶號(hào)String SHHKEY = "mmmmmmmmmmmmmmm";// 商戶號(hào)對(duì)應(yīng)的密鑰/*------1.獲取參數(shù)信息------- *///商戶訂單號(hào)String out_trade_no= request.getParameter("state"); //價(jià)格String money = request.getParameter("money");//金額轉(zhuǎn)化為分為單位String finalmoney = WeChat.getMoney(money);//獲取用戶的codeString code = request.getParameter("code");/*------2.根據(jù)code獲取微信用戶的openId和access_token------- *///注: 如果后臺(tái)程序之前已經(jīng)得到了用戶的openId 可以不需要這一步,直接從存放openId的位置或session中獲取就可以。//toPay.jsp頁面中提交的url路徑也就不需要再經(jīng)過微信重定向。寫成:http://localhost:8080/項(xiàng)目名/wechat/pay?money=${sumPrice}&state=${orderId}String openid=null;try {List<Object> list = accessToken(code);openid=list.get(1).toString();} catch (IOException e) {logger.error("根據(jù)code獲取微信用戶的openId出現(xiàn)錯(cuò)誤", e);mv.setViewName("error");return mv;}/*------3.生成預(yù)支付訂單需要的的package數(shù)據(jù)------- *///隨機(jī)數(shù) String nonce_str= MD5.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());//訂單生成的機(jī)器 IPString spbill_create_ip = request.getRemoteAddr();//交易類型 :jsapi代表微信公眾號(hào)支付String trade_type = "JSAPI";//這里notify_url是 微信處理完支付后的回調(diào)的應(yīng)用系統(tǒng)接口url。String notify_url ="http://69a6a38e.ngrok.natapp.cn/heyi-console/wechat/weixinNotify";SortedMap<String, String> packageParams = new TreeMap<String, String>();packageParams.put("appid", GZHID); packageParams.put("mch_id", SHHID); packageParams.put("nonce_str", nonce_str); packageParams.put("body", "費(fèi)用"); packageParams.put("out_trade_no", out_trade_no); packageParams.put("total_fee", finalmoney); packageParams.put("spbill_create_ip", spbill_create_ip); packageParams.put("notify_url", notify_url); packageParams.put("trade_type", trade_type); packageParams.put("openid", openid); /*------4.根據(jù)package數(shù)據(jù)生成預(yù)支付訂單號(hào)的簽名sign------- */RequestHandler reqHandler = new RequestHandler(request, response);reqHandler.init( GZHID, GZHSecret, SHHKEY);String sign = reqHandler.createSign(packageParams);/*------5.生成需要提交給統(tǒng)一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder 的xml數(shù)據(jù)-------*/String xml="<xml>"+"<appid>"+ GZHID+"</appid>"+"<mch_id>"+ SHHID+"</mch_id>"+"<nonce_str>"+nonce_str+"</nonce_str>"+"<sign>"+sign+"</sign>"+"<body><![CDATA["+"費(fèi)用"+"]]></body>"+"<out_trade_no>"+out_trade_no+"</out_trade_no>"+"<total_fee>"+finalmoney+"</total_fee>"+"<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+"<notify_url>"+notify_url+"</notify_url>"+"<trade_type>"+trade_type+"</trade_type>"+"<openid>"+openid+"</openid>"+"</xml>";/*------6.調(diào)用統(tǒng)一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder 生產(chǎn)預(yù)支付訂單----------*/String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";String prepay_id="";try {prepay_id = GetWxOrderno.getPayNo(createOrderURL, xml);if(prepay_id.equals("")){mv.addObject("ErrorMsg", "支付錯(cuò)誤");mv.setViewName("error");return mv;}} catch (Exception e) {logger.error("統(tǒng)一支付接口獲取預(yù)支付訂單出錯(cuò)", e);mv.setViewName("error");return mv;}/*將prepay_id存到庫中*/PageData p = new PageData();p.put("shopId", out_trade_no);p.put("prePayId", prepay_id);activityService.updatePrePayId(p);/*------7.將預(yù)支付訂單的id和其他信息生成簽名并一起返回到j(luò)sp頁面 ------- */nonce_str= MD5.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());SortedMap<String, String> finalpackage = new TreeMap<String, String>();String timestamp = String.valueOf(System.currentTimeMillis() / 1000);String packages = "prepay_id="+prepay_id;finalpackage.put("appId", GZHID); finalpackage.put("timeStamp", timestamp); finalpackage.put("nonceStr", nonce_str); finalpackage.put("package", packages); finalpackage.put("signType", "MD5");String finalsign = reqHandler.createSign(finalpackage);mv.addObject("appid", GZHID);mv.addObject("timeStamp", timestamp);mv.addObject("nonceStr", nonce_str);mv.addObject("packageValue", packages);mv.addObject("paySign", finalsign);mv.addObject("success","ok");mv.setViewName("wechat/pay");return mv; }2.?H5調(diào)起微信支付的內(nèi)置JS
<script type="text/javascript">function onBridgeReady(){WeixinJSBridge.invoke('getBrandWCPayRequest', {"appId" : "<%=paramsMap.get("appId") %>", //公眾號(hào)名稱,由商戶傳入 "timeStamp":"<%=paramsMap.get("timeStamp") %>", //時(shí)間戳,自1970年以來的秒數(shù) "nonceStr" : "<%=paramsMap.get("nonceStr")%>", //隨機(jī)串 "package" : "<%=paramsMap.get("package")%>", "signType" : "<%=paramsMap.get("signType")%>", //微信簽名方式: "paySign" : "<%=paramsMap.get("paySign")%>" //微信簽名 },function(res){ // 使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示:res.err_msg將在用戶支付成功后返回 ok,但并不保證它絕對(duì)可靠。 if(res.err_msg == "get_brand_wcpay_request:ok" ) {//成功$("#tip_icon").addClass("weui_icon_success");$("#tip").text("購買成功");$("#amount").text("恭喜你,獲得"+"<%=goodContent%>");}else if(res.err_msg == "get_brand_wcpay_request:cancel" ) {//取消$("#tip_icon").addClass("weui_icon_warn");$("#tip").text("用戶取消支付");}else if(res.err_msg == "get_brand_wcpay_request:fail" ) {//失敗$("#tip_icon").addClass("weui_icon_warn");$("#tip").text("支付失敗");}else{$("#tip").text(res.err_msg);}$(".confirm_container").show();$("#chargeBtn").show();}); }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{onBridgeReady();}</script>3.支付成功之后跳轉(zhuǎn)回自己的系統(tǒng)的某個(gè)頁面
遇到的問題:
1.在微信商戶平臺(tái)里面需要設(shè)置api秘鑰(paternerKey),所謂paternerKey意思就是伙伴的秘鑰,也就是合作商的秘鑰。
需要自定義一個(gè)字符串,然后用MD5加密成32位的字符串,然后設(shè)置。
2.統(tǒng)一下單接口的容易出錯(cuò)的參數(shù):
1)trade_type==交易類型==取值如下:JSAPI,NATIVE,APP。我們這里使用的JSAPI。標(biāo)題已經(jīng)說了,是微信公眾號(hào)支付。他們的區(qū)別,請(qǐng)參考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2。
ps:JSAPI--公眾號(hào)支付、NATIVE--原生掃碼支付、APP--app支付,統(tǒng)一下單接口trade_type的傳參可參考這里。MICROPAY--刷卡支付,刷卡支付有單獨(dú)的支付接口,不調(diào)用統(tǒng)一下單接口。
2)notify_url==通知地址==接收微信支付異步通知回調(diào)地址,通知url必須為直接可訪問的url,不能攜帶參數(shù)。
3)sign==簽名==官方給的簽名算法。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3。獲取預(yù)支付ID時(shí),如果返回值是【簽名錯(cuò)誤】。那真是的你的簽名錯(cuò)了,請(qǐng)仔細(xì)核對(duì)生成sign的參數(shù)名稱、參數(shù)值和調(diào)用統(tǒng)一下單接口的參數(shù)名稱和參數(shù)值
3.要想支付成功,需要在商戶號(hào)設(shè)置支付授權(quán)目錄。路徑應(yīng)為支付頁面的上一級(jí)路徑。
======================================大功告成=============================================
?
?
總結(jié)
以上是生活随笔為你收集整理的微信公众号支付开发全过程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django之序列化
- 下一篇: Jmeter(四十二)_控制器下遍历一组