商戶已有H5商城網站,用戶通過消息或掃描二維碼在微信內打開網頁時,可以調用微信支付完成下單購買的流程。
正式開發
jsapi統一下單api列表
下面列舉必須字段
Appid,mch_id,nonce_str,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid
注意:total_fee是分爲單位
String total_fee = info.getOrderMoney().multiply(new BigDecimal("100")).intValue()+"";
說下不好獲取的
spbill_create_ip:我當時就是寫了127.0.0.1,我並不清楚怎麼獲取
notify_url:寫公網可以訪問的地址,最好去看下官網的介紹,
out_trade_no:前6位是隨機數,後面是數據庫中實際的訂單編號,這樣是爲了回調的時候獲取訂單編號,當然也可以使用別的方法。
openid:是指一個用戶到一個公衆號,對應的一個key,是唯一的,獲取方法文檔
我的思路是,先獲取code,H5界面裏面,有一個去支付按鈕,而去支付按鈕是一個超鏈接
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx1111111111111111&redirect_uri=http%3A%2F%2Fm.XXXX.com%2FpayList.html%3ForderNumber%3D"+orderNum+"&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
這裏面的redirect_uri需要格式化
import java.net.URLEncoder; String formatUrl = URLEncoder.encode("http://m.XXXX.com/payList.html?orderNumber=XXXXXXX","UTF_8");
跳轉回來的時候是
http://m.XXXX.com/payList.html?orderNumber=XXXXXXX&code=sdhjsdhfjhasjhfhjasdhbavbnb
這個code呢,你開發在電腦端是看不見的,這也就是微信坑的地方,所以你 下載微信開發者工具
獲取code之後,點擊微信支付,發送ajax請求給後臺
@RequestMapping("/payH5") @ResponseBody public Object payH5(@RequestParam("orderNumber") String orderNumber, @RequestParam("type") Integer type, HttpServletRequest request, HttpServletResponse response,@RequestParam(value = "code",defaultValue = "")String code) throws Exception{ try{ OrderInfo info = orderInfoService.selectOne(new EntityWrapper<OrderInfo>() .eq("order_number", orderNumber)); ModelAndView modelAndView = new ModelAndView(); //支付寶支付 if(type.intValue()==1){ response.sendRedirect("http://m.XXXX.com/alipay.html?orderNumber="+orderNumber); //微信支付 }else if(type.intValue()==0){ if("".equals(code)){ return "返回錯誤界面"; } WxpayConfig wxpayConfig = new WxpayConfig(); //此處獲取openid,後臺發請求給,通過code,appId,appsecret String res = HttpUtil.sendGet("https://api.weixin.qq.com/sns/oauth2/access_token", "appid="+wxpayConfig.getApp_id()+"&secret="+wxpayConfig.getApp_secret()+"&code="+code+"&grant_type=authorization_code"); JSONObject json = JSONObject.parseObject(res); String openId = json.getString("openid"); Map<String,String> paraMap = new HashMap<>(); paraMap.put("appid",wxpayConfig.getApp_id()); paraMap.put("body",info.getOrderProject()); paraMap.put("mch_id",wxpayConfig.getMch_id()); paraMap.put("nonce_str", WXPayUtil.generateNonceStr()); paraMap.put("openid",openId); String randomNum = (int)((Math.random()*9+1)*100000)+""; String orderNo =randomNum+orderNumber; paraMap.put("out_trade_no",orderNo); paraMap.put("spbill_create_ip",wxpayConfig.getSpbill_create_ip()); String total_fee = info.getOrderMoney().multiply(new BigDecimal("100")).intValue()+""; paraMap.put("total_fee",total_fee); paraMap.put("trade_type",wxpayConfig.getTrade_type()); paraMap.put("notify_url","http://XXXX.com/XXXX/api/wxnotify?orderNumber="+orderNumber); String apiKey = wxpayConfig.getApi_key(); String sign = WXPayUtil.generateSignature(paraMap,apiKey); paraMap.put("sign",sign); String xml = WXPayUtil.mapToXml(paraMap); //統一下單 https://api.mch.weixin.qq.com/pay/unifiedorder String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; String xmlStr = HttpUtil.sendPost(unifiedorder_url,xml,false); //以下內容是返回前端頁面的json數據 String prepay_id = "";//預支付id if (xmlStr.indexOf("SUCCESS") != -1) { Map<String, String> map = WXPayUtil.xmlToMap(xmlStr); prepay_id = (String) map.get("prepay_id"); } Map<String, String> payMap = new HashMap<String, String>(); payMap.put("appId", wxpayConfig.getApp_id()); payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+""); payMap.put("nonceStr", WXPayUtil.generateNonceStr()); payMap.put("signType", "MD5"); payMap.put("package", "prepay_id=" + prepay_id); String paySign = WXPayUtil.generateSignature(payMap, wxpayConfig.getApi_key()); payMap.put("paySign", paySign); return payMap; } return ""; }catch (Exception e){ e.printStackTrace(); } return "end"; // return new SuccessResponseData(); }
獲取sign
下載後,裏面有一些工具類,WXPayUtil裏面有一個方法可以獲取
返回數據到前臺後,前臺調用js對象,執行
WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId":appId, //公衆號名稱,由商戶傳入 "timeStamp":timeStamp, //時間戳,自1970年以來的秒數 "nonceStr":nonceStr, //隨機串 "package":package, "signType":signType, //微信簽名方式: "paySign":paySign //微信簽名 }, function(res){ console.log(res); window.location.href = "http://m.XXXX.com/orderDetail.html?orderNum="+orderNumber; // if(res.err_msg == "get_brand_wcpay_request:ok" ) { // console.log('支付成功'); // //支付成功後跳轉的頁面 // }else if(res.err_msg == "get_brand_wcpay_request:cancel"){ // console.log('支付取消'); // }else if(res.err_msg == "get_brand_wcpay_request:fail"){ // console.log('支付失敗'); // } //使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功後返回ok,但並不保證它絕對可靠。 }
就會執行微信支付,不管成功沒有,都會跳轉到orderDetail界面,查看order詳情
微信回調
微信會返回結果
我應該處理什麼
@RequestMapping("/wxnotify") public String wxnotify(HttpServletRequest request,HttpServletResponse response){ InputStream is = null; try{ is = request.getInputStream(); String xml = WXPayUtil.inputStream2String(is); Map<String,String> notifyMap = WXPayUtil.xmlToMap(xml); if(notifyMap.get("return_code").equals("SUCCESS")) { String orderNumber = notifyMap.get("out_trade_no").substring(6); OrderInfo info = orderInfoService.selectOne(new EntityWrapper<OrderInfo>() .eq("order_number", orderNumber)); info.setOrderState(1); orderInfoService.updateById(info); String amount = notifyMap.get("total_fee"); System.out.println("實際付款:"+amount); } response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>"); is.close(); } catch (Exception e) { e.printStackTrace(); } return null; }