微信支付jsapi

微信支付jsapi

訂單表
訂單列表
支付界面
商戶已有H5商城網站,用戶通過消息或掃描二維碼在微信內打開網頁時,可以調用微信支付完成下單購買的流程。

開發步驟

技術博客

jspi支付,是指微信公衆號裏面的打開網站,支付

大致流程

  1. 獲取所需參數
  2. 發送給統一下單的接口
  3. 根據返回的參數,進行解析,如果成功,將部分參數發送給前臺。注意前臺的瀏覽器是微信內置瀏覽器,有一個內置的js對象,可以通過js對象,調起支付
  4. 最後跳轉到結果頁面

正式開發

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

獲取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詳情

微信回調

微信會返回結果

我應該處理什麼

  1. 告訴微信,我收到了,返回success
  2. 對訂單信息,獲取orderNum,對訂單狀態進行更新
@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;
}