本文給大家講解微信小程式支付全流程,以及相關功能源代碼,專案不開放,帶來不便盡請諒解,小程式支付主要
包含如下幾步驟,1.預下單-呼叫微信統一下單介面進行預下單,2.小程式拿到支付引數喚醒支付,3.支付成功后發起退
款申請,
本文使用okHttpUtil進行介面互動 使用goole的gson與阿里的fastJson進行決議JsonObect,使用封裝的http工具類進行攜
帶證書進行介面互動、使用封裝的工具類實作map轉xml等,
下面是正文:
微信支付檔案: https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
一.獲取微信用戶的openId:
用戶登錄小程式 通過授權得到微信code,然后將微信code、秘鑰、密文傳遞后端,后端進行解密后 得到微信openId
(前端也可以進行解密,但建議放后端)下面是獲取openId的代碼(java)
//獲取微信openId介面url https://api.weixin.qq.com/sns/jscode2session
/** * 決議小程式登錄資料獲取引數 * @param code ---微信code * @param encryptedData --- 加密引數 * @param iv --- 秘鑰 * @return */ public Result<?> getAuthByApplet(String code, String encryptedData, String iv) { Map<String, Object> resultMap = new HashMap<>(); try { log.debug("=========小程式獲取unionId=============: "+ code); //封裝引數 Map<String, String> params = new HashMap<String, String>(); //獲取小程式的openId params.put("appid", appletId); //微信秘鑰 params.put("secret", appletSecret); params.put("js_code", code); params.put("grant_type", "authorization_code"); //呼叫介面進行讀取引數 JsonObject retJson = OkHttpUtils.doGetRetJson(appletOpenIdUrl, params); log.debug(retJson.toString()); //如果獲取到了openId if(retJson.get("openid") != null) { //獲取會話密鑰(session_key) String session_key = retJson.get("session_key").getAsString(); resultMap.put("session_key", session_key); resultMap.put("openId", retJson.get("openid").getAsString()); }else{ throw new Exception("code已失效,請重新獲取"); } return Result.ok(resultMap); } catch (Exception e) { log.error(e.getMessage(), e); throw new RuntimeException(); } }
得到openId后要進行業務保存,因為小程式很多介面都依賴openId,而且同一小程式下,每個微信號的openId是一樣
的,
二:統一下單與小程式支付
通過業務系統的封裝引數,得到支付的商品資訊,價格,業務訂單后,封裝引數,進行加密得到sign簽名,然后
呼叫統一下單介面進行下單,成功后回傳小程式支付引數,
(需要注意的是 微信預下單請求引數要求是xml格式,全String型別)
//微信預下單介面url https://api.mch.weixin.qq.com/pay/unifiedorder
/** * 微信支付-統一下單 * @param body --- 商品描述 * @param outTradeNo --- 業務系統訂單號 * @param totalFee --- 支付金額 * @param spBillCreateIP ---支付人所在 * @param openId --- 支付人的微信openId * @return */ @Override public Map<String, String> toPay(String body, String outTradeNo, String totalFee, String spBillCreateIP, String openId) { try{ Map<String, String> map = new HashMap<>(); //封裝支付必須引數 SortedMap<Object,Object> params = new TreeMap<Object,Object>(); //支付型別 String tradeType = "JSAPI"; //支付后回呼地址 String notifyUrl = ""; String nonceStr = RandomUtil.randomString(16); //小程式id params.put("appid", appletId); //商戶平臺id params.put("mch_id", mchId); //隨機字串 params.put("nonce_str", nonceStr); //商品描述 params.put("body", body); //商品訂單號 params.put("out_trade_no", outTradeNo); //價格的單位為分 params.put("total_fee", totalFee); //支付ip params.put("spbill_create_ip", spBillCreateIP); //異步回呼api params.put("notify_url", notifyUrl); //JSAPI、h5呼叫 params.put("trade_type", tradeType); //支付用戶openid params.put("openid", openId); String sign = WxPaySignatureUtils.createSign(params, key); params.put("sign", sign); String requestXML = WxPaySignatureUtils.getRequestXml(params); log.info("發送給微信的報文:" + requestXML); log.info("加密后的的簽名字串:" + sign); //呼叫微信介面 String result = OkHttpUtils.postXml(unifiedorder, requestXML); log.info("-------------------請求回傳結果------------------"); log.info(result); map = WXPayUtil.xmlToMap(result); //如果回傳有資料 if(map != null){ //并且回傳有sign if(map.get("sign") != null){ return map; } } return map; }catch (Exception e) { log.error(e.getMessage(), e); throw new RuntimeException(); } }
介面請求成功后,微信回傳也是xml格式的報文,需要將xml轉為map或其他,本文使用map接收引數,預下單后,
微信會回傳預付訂單標識,標識用于進支付,
//預付訂單標識 String prepayId = resultMap.get("prepay_id");
然后封裝小程式支付 所需引數
//簽名型別,默認為MD5 String signType = "MD5"; SortedMap<Object,Object> params = new TreeMap<Object,Object>(); params.put("appId", appletId); params.put("timeStamp", timestamp + ""); params.put("timeStamp", timestamp + ""); params.put("nonceStr", nonceStr); params.put("package", "prepay_id=" + prepayId); params.put("signType", signType); //生成簽名 String sign = WxPaySignatureUtils.createSign(params, key); params.put("paySign", sign);
將支付引數回傳給小程式,小程式通過組件 requestPayment 喚醒支付
小程式支付代碼如下:
wx.requestPayment({ timeStamp:param.result.timeStamp, nonceStr: param.result.nonceStr, package: param.result.package, signType:param.result.signType, paySign: param.result.paySign, success: function(res){ console.log(res); wx.showToast({ title: '支付成功', icon: 'success', duration: 2000 }); }, fail: function(res) { wx.showModal({ title:'支付失敗', content:'<text>', showCancel: false }) } })
三: 退款
小程式支付成功后,可以通過支付訂單號進行退款操作,需要注意的是,退款需要http攜帶商戶證書進行支
付,這里圖圖已經封裝好工具類只需要修改下證書的url就可以愉快使用了,
//微信退款使用的url https://api.mch.weixin.qq.com/secapi/pay/refund
/** * 微信支付-退款 * @param transaction_id ---微信支付訂單 * @param out_refund_no --- 系統退款單號 * @param total_fee --- 訂單總金額 * @param refund_fee --- 退款金額 * @return */ @Override public Map<String, String> refundToPay(String transaction_id, String out_refund_no, String out_trade_no, int total_fee, int refund_fee) { //定義回傳引數 Map<String, String> map = new HashMap<>(); try{ SortedMap<Object,Object> params = new TreeMap<Object,Object>(); String notifyUrl = "https://baidu.com"; String nonceStr = RandomUtil.randomString(16); //小程式id params.put("appid", appletId); //商戶平臺id params.put("mch_id", mchId); //隨機字串 params.put("nonce_str", nonceStr); //系統訂單號 params.put("out_trade_no", out_trade_no); //微信訂單號 params.put("transaction_id", transaction_id); //系統退款單號 params.put("out_refund_no", out_refund_no); //訂單金額 params.put("total_fee", total_fee); //退款金額 params.put("refund_fee", refund_fee); //簽名 String sign = WxPaySignatureUtils.createSign(params, key); params.put("sign", sign); //封裝請求報文 String requestXML = WxPaySignatureUtils.getRequestXml(params); log.info("發送給微信的報文:" + requestXML); log.info("加密后的的簽名字串:" + sign); //呼叫微信介面 String result = WXPayUtil.doRefundRequest(mchId, refund, requestXML, certificateUrl); log.info("-------------------請求回傳結果------------------"); log.info(result); if(StrUtil.isNotEmpty(result)){ map = WXPayUtil.xmlToMap(result); //如果回傳有資料 if(map != null){ //并且回傳有sign if(map.get("sign") != null){ return map; } } }else{ log.info("-------------------請求回傳空結果------------------"); } return map; }catch (Exception e) { log.error(e.getMessage(), e); throw new RuntimeException(); } }
本文中所使用到的工具類,圖圖已經幫大家打包好了,在百度網盤,
百度網盤下載鏈接
鏈接:https://pan.baidu.com/s/1YbMrvO3qK1rdmyYyET2xzw 提取碼:ljv6
本文先總結到此,后面繼續更新技術一些文章,大家一起加油鴨!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/271859.html
標籤:其他
上一篇:編程學習篇:用 “ ! = null " 做判空?簡直絕了!
下一篇:OpenCV 之 平面單應性
