微信支付—微信H5支付「非微信内部浏览器-QQ/UC浏览器等」
前言
微信支付-微信H5外部瀏覽器支付「本文」
微信H5內部瀏覽器支付「待寫」
PC端掃碼支付「待寫」
一直計劃著寫一寫微信支付相關的文章,希望能加深一下自己的印象,拖了一天又一天…
最近終于空出時間來填坑了,我將文章分為微信H5外部瀏覽器支付、微信H5內部瀏覽器支付、PC端掃碼支付三篇來寫。
本篇是微信H5外部瀏覽器支付:支付時會喚起微信APP進行支付。
掃盲補充:關于微信H5支付,分為內部瀏覽器支付 + 外部瀏覽器支付,兩者還是稍微有點點區別的,內部瀏覽器即在微信內打開網頁,進行支付,支付調用由前端發起「JSSDK」;而外部瀏覽器「比如QQ瀏覽器等」則通過后臺返回的 mweb_url 交由前端喚起微信APP發起支付操作,微信官方提供了個測試網頁 https://wxpay.wxutil.com/mch/pay/h5.v2.php,可以在手機瀏覽器打開體驗一番。
本文開發環境: Java + SpringBoot + IDEA + WxJava(開源SDK)
再多啰嗦幾句,最開始并沒有選擇 WxJava 開源SDK,因為沒有仔細閱讀官方文檔,反正各種報錯,比如:支付驗證簽名失敗 等等~,最后妥協不重復造輪子了,如下為正文。
1、 引入依賴包
pom.xml文件中引入 WxJava 依賴「本文使用的是3.3.0版本」
<dependency>????<groupId>com.github.binarywang</groupId>
????<artifactId>weixin-java-pay</artifactId>
????<version>3.3.0</version>
</dependency>
2、基礎配置
WxJava 提供了微信支付的Demo,可以參考 https://github.com/binarywang/weixin-java-pay-demo
2.1、增加支付配置信息
下面提供 application.yml 、application.properties 兩種格式,具體如下:
wx.pay.appId=#微信公眾號或者小程序等的appidwx.pay.mchId=#微信支付商戶號
wx.pay.mchKey=#微信支付商戶密鑰
wx.pay.notifyUrl=#支付成功回調URL
wx.pay.keyPath=#?p12證書的位置,可以指定絕對路徑,也可以指定類路徑(以classpath:開頭)
#?-----------------------------------------
wx:
??pay:
????appId:?#微信公眾號或者小程序等的appid
????mchId:?#微信支付商戶號
????mchKey:?#微信支付商戶密鑰
????notifyUrl:?#支付成功回調URL
????keyPath:?#?p12證書的位置,可以指定絕對路徑,也可以指定類路徑(以classpath:開頭)
補充:keyPath 用來指定證書路徑,關于證書的用途:發紅包/企業付款/退款等操作,本文不涉及,留空。
2.2、代碼中的配置
一個是用來讀取配置信息的實體類,一個是用來初始化支付SDK的Configuration
讀取配置類:WxProperties.java
@Data@Configuration
@ConfigurationProperties(prefix?=?"wx.pay")
public?class?WxProperties?{
????/**
?????*?設置微信公眾號或者小程序等的appid
?????*/
????private?String?appId;
????/**
?????*?微信支付商戶號
?????*/
????private?String?mchId;
????/**
?????*?微信支付商戶密鑰
?????*/
????private?String?mchKey;
????/**
?????*?apiclient_cert.p12文件的絕對路徑,或者如果放在項目中,請以classpath:開頭指定
?????*/
????private?String?keyPath;
????/**
?????*?微信回調接口地址
?????*/
????private?String?notifyUrl;
}
初始化支付SDK類:WxConfig.java
@Configurationpublic?class?WxConfig?{
????@Autowired
????private?WxProperties?properties;
????@Bean
????@ConditionalOnMissingBean
????public?WxPayService?wxService()?{
????????WxPayConfig?payConfig?=?new?WxPayConfig();
????????payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
????????payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
????????payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
????????payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
????????payConfig.setNotifyUrl(StringUtils.trimToNull(this.properties.getNotifyUrl()));
????????//?可以指定是否使用沙箱環境
????????payConfig.setUseSandboxEnv(false);
????????WxPayService?wxPayService?=?new?WxPayServiceImpl();
????????wxPayService.setConfig(payConfig);
????????return?wxPayService;
????}
}
2.3、微信支付接口
微信非內部瀏覽器支付,比如在手機QQ瀏覽器中發起支付,會喚起微信APP進行支付操作,此時調用微信接口返回的是一個 URL,返回結果如下:
weixin://wxpay/bizpayurl?pr=IzX8nS下方是獲取支付URL的后端接口方法:
@RequestMapping(value?=?"createOrder",?method?=?{RequestMethod.POST})public?Result<Object>?createQRCode(UserModel?user,?HttpServletResponse?response,@RequestBody?WechatOrderRequest?obj)?{
????Orders?orders?=?null;
????if?(StringUtils.isNotBlank(obj.getOrderId()))?{
????????orders?=?ordersService.searchOrder(user,?obj.getOrderId());
????}?else?{
????????orders?=?ordersService.createOrder(user,?obj);
????}
????WechatOrderResponse?wechatOrderResponse?=?new?WechatOrderResponse();
????wechatOrderResponse.setCodeUrl(wechatService.createOrderInfo(orders,user.getPayType()));
????wechatOrderResponse.setOrderId(orders.getOrderId());
????return?ResultUtil.success(wechatOrderResponse);
}
該方法僅供參考,上方方法中對訂單id進行了一個判空操作,因為我這邊有可能是用戶未支付訂單,繼續支付的操作,代碼主要是 wechatService.createOrderInfo 方法,實現如下:
public?String?createOrderInfo(Orders?orders,String?payType)?{????WxPayMwebOrderResult?result?=?null;
????try?{
????????WxPayUnifiedOrderRequest?orderRequest?=?new?WxPayUnifiedOrderRequest();
????????orderRequest.setOutTradeNo(orders.getOrderId());
????????orderRequest.setBody("我是商品描述");
????????orderRequest.setTotalFee(orders.getAmount().multiply(new?BigDecimal("100")).intValue());//金額需要擴大100倍:1代表支付時是0.01
????????orderRequest.setSpbillCreateIp(DispatchParams.getInstance().getWechatSpbillCreateIp());
????????orderRequest.setProductId(orders.getOrderId());
????????orderRequest.setTradeType(WxPayConstants.TradeType.MWEB);//?h5網頁支付
????????result?=?wxPayService.createOrder(orderRequest);
????????return?result.getMwebUrl();
????}?catch?(WxPayException?e)?{
????????logger.error("[微信支付異常]?異常",?e);
????????//?拋出一個自定義全局異常「自己定義」
????????throw?new?CommonException(微信支付異常提示信息?,?狀態碼?);
????}
}
具體參數就不啰嗦了,詳細請看官方支付文檔。
綜上,當前端調用 createOrder 方法,將 weixin://wxpay/bizpayurl?pr=IzX8nS 返回給前端,那么前端怎么調用呢?
下面是我的一個測試例子,其中 res.codeUrl 為后端返回的 URL:
window.open(res.codeUrl,?'_blank’);是的,就是這么簡單,新窗口打開就可以了,看一下運行調起微信的截圖「我手機裝了兩個微信」:
支付成功后會回調后端接口,具體由后端參數配置的 return_url 控制。
2.4、微信回調接口
當支付完成后,微信會自動回調該接口,我們可以根據返回的信息修改訂單狀態,看一下方法,代碼僅供參考:
@RequestMapping(value?=?"/notify")@ResponseBody
public?String?notify(String?body)?throws?Exception?{
????????WxPayOrderNotifyResult?result?=?null;
????????try?{
????????????result?=?wxPayService.parseOrderNotifyResult(body);
????????}?catch?(WxPayException?e)?{
????????????logger.error("[微信解析回調請求]?異常",?e);
????????????return?WxPayNotifyResponse.fail(e.getMessage());
????????}
????????logger.info("處理微信支付平臺的訂單支付");
????????logger.info(JSONObject.toJSONString(result));
????????String?appid?=?result.getAppid();//應用ID
????????String?attach?=?result.getAttach();//商家數據包
????????String?bank_type?=result.getBankType();//付款銀行
????????Integer?cash_fee?=?result.getCashFee();//現金支付金額
????????String?fee_type?=?result.getFeeType();//貨幣種類
????????String?is_subscribe?=?result.getIsSubscribe();//是否關注公眾賬號
????????String?mch_id?=?result.getMchId();//商戶號
????????String?nonce_str?=?result.getNonceStr();//隨機字符串
????????String?openid?=?result.getOpenid();//用戶標識
????????String?out_trade_no?=?result.getOutTradeNo();//?獲取商戶訂單號
????????String?result_code?=?result.getResultCode();//?業務結果
????????String?return_code?=?result.getReturnCode();//?SUCCESS/FAIL
????????String?sign?=?result.getSign();//?獲取簽名
????????String?time_end?=?result.getTimeEnd();//支付完成時間
????????Integer?total_fee?=?result.getTotalFee();//?獲取訂單金額
????????String?trade_type?=?result.getTradeType();//交易類型
????????String?transaction_id?=?result.getTransactionId();//微信支付訂單號
????????//如果成功寫入數據庫
????????if("SUCCESS".equals(return_code))?{//?如果微信返回的結果是success,則修改訂單狀態
????????????Orders?orders?=?ordersDao.selectByOrderId(out_trade_no);
????????????//?驗證簽名
????????????if(orders?!=?null){
????????????????if(!"1".equals(orders.getOrderStatus())){//判斷是否訂單已經完成了
????????????????????//?判斷金額是否跟數據庫訂單金額一致,放置人為修改
????????????????????if(orders.getAmount().multiply(new?BigDecimal("100")).compareTo(new?BigDecimal(total_fee))?==?0){
????????????????????????//更新訂單狀態
????????????????????????業務邏輯處理部分...
????????????????????????return?WxPayNotifyResponse.success("訂單已經處理成功!");
????????????????????}else{
????????????????????????logger.error("微信:金額不一致!");
????????????????????????return?WxPayNotifyResponse.fail("訂單金額不一致");
????????????????????}
????????????????}else?{
????????????????????return?WxPayNotifyResponse.success("訂單已經處理成功!");
????????????????}
????????????}else{
????????????????return?WxPayNotifyResponse.fail("商戶訂單號不匹配");
????????????}
????????}
????????System.out.println("回調成功");
????????System.out.println("----返回給微信的xml:"?+?result);
????????return?WxPayNotifyResponse.success("支付成功!");
}
如上代碼,微信返回的是 XML ,經過 wxPayService.parseOrderNotifyResult() 方法轉換后得到 WxPayOrderNotifyResult 實體,具體參數我上邊羅列出來了「盡管沒用到」,然后就是修改數據庫訂單狀態等操作。
最后
博客地址:https://www.cgblog.com/niceyoo
如果覺得這篇文章有丶東西,不放關注一下我,關注是對我最大的鼓勵~
18年專科畢業后,期間一度迷茫,最近我創建了一個公眾號用來記錄自己的成長。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的微信支付—微信H5支付「非微信内部浏览器-QQ/UC浏览器等」的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Flash Builder4.7 破解方
 - 下一篇: 判断listview是上滑还是下滑的方法