前言
微信支付-微信H5外部瀏覽器支付
微信支付-微信H5內部瀏覽器支付
微信支付-PC端掃碼支付「本文」
本篇是微信支付系列的第三篇,PC端掃碼支付。
開發環境:Java + SpringBoot + Vue +WxJava(開源SDK)
流程補充:關於微信PC端掃碼支付,首先前端傳遞商品金額給后端生成支付二維碼內容「本案例二維碼由前端生成」,獲得后端返回的內容后,前端根據內容生成二維碼然后展示給用戶,用戶掃碼支付成功后,微信官方推送給后端接口用戶支付信結果,再根據結果更新數據庫訂單信息。
如下是正文部分。
Java支付項目實戰教程,包括支付寶,微信等支付方式,不看虧!1、獲取二維碼內容
需要后端創建二維碼接口,具體代碼如下:
/**
* 創建二維碼
*/
@RequestMapping(value = "createQRCode", method = {RequestMethod.POST})
@ApiOperation(value = "創建二維碼")
public Result<Object> createQRCode(@RequestBody WechatOrderRequest obj) {
Orders orders = null;
if (StringUtils.isNotBlank(obj.getOrderId())) {
orders = ordersService.searchOrder(obj.getUserId, obj.getOrderId());
} else {
orders = ordersService.createOrder(obj.getUserId, obj.getTotal_fee(), "new");
}
WechatOrderResponse wechatOrderResponse = new WechatOrderResponse();
wechatOrderResponse.setCodeUrl(wechatService.createOrderInfo(orders);
wechatOrderResponse.setOrderId(orders.getOrderId());
return ResultUtil.success(wechatOrderResponse);
}
關於上方方法,WechatOrderRequest實體,包含前端商品金額,以及用戶信息、創建訂單方式「是新建訂單,還是未支付訂單再次支付」等,總之,主要作用就是創建訂單實體,之所以判斷一下 OrderId,是因為未支付訂單再次支付調用的接口共用了。
關於 createOrder() 創建訂單的方法,大致如下:
public Orders createOrder(String userId,String total_fee){
String orderId=ToolUtils.makeUUID();
Orders orders=new Orders();
orders.setOrderId(orderId);
orders.setOrderStatus("0");
orders.setAmount(new BigDecimal(total_fee));
orders.setCreateTime(new Date());
orders.setUserId(userId);
orders.setInvoice("0");
orders.setAppType(appType);
orders.setNonceStr(ToolUtils.makeUUID().toUpperCase());
ordersDao.insertOrders(orders);
return orders;
}
searchOrder() 訂單實體查詢的接口就不貼出來了,就是簡單的查詢數據庫。
我們接着來看主要的方法,wechatService.createOrderInfo() :
@Transactional
public String createOrderInfo(Orders orders) {
WxPayNativeOrderResult result = null;
try {
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setOutTradeNo(orders.getOrderId());
orderRequest.setBody("我是商品描述");
orderRequest.setTotalFee(orders.getAmount().multiply(new BigDecimal("100")).intValue());
orderRequest.setSpbillCreateIp(DispatchParams.getInstance().getWechatSpbillCreateIp());
orderRequest.setProductId(orders.getOrderId());
orderRequest.setTradeType(WxPayConstants.TradeType.NATIVE);
result = wxPayService.createOrder(orderRequest);
return result.getCodeUrl();
} catch (WxPayException e) {
logger.error("[微信支付異常] 異常", e);
throw 自定義異常;
}
}
補充:由於使用了 WxJava,所以接口相對是非常簡潔的,賦予 WxPayUnifiedOrderRequest 對象必須的參數,比如支付金額,商品描述,ip,支付類型等,然后調動 createOrder() 方法就能得到二維碼內容了,具體請求過程可以自己進入源碼查看。
返回的內容格式:weixin://wxpay/bizpayurl?pr=1RhYbXa
ok,我們再回到最開始的方法,我們將獲得的二維碼內容、訂單id,返回給前端,二維碼內容供前端生成二維碼,而訂單id的作用則是,在當前支付界面,前端根據訂單id不停地請求后端訂單查詢接口,如果后端返回結果,給出響應的提示,比如支付成功,支付失敗等。
2、前端生成二維碼
前端生成二維碼有許多方式,本文采用 qrcodejs2 生成,package.json 加入以下依賴:
"dependencies": {
"qrcodejs2": "0.0.2"
}
代碼中使用,如下代碼精簡過了,就兩個主要方法,看個熱鬧就行哈,具體的自行實現:
<template>
<div>
<div id="qrcode" class="wechat_code"></div>
</div>
</template>
<script>
import QRCode from 'qrcodejs2'
export default {
methods:{
qrCode(){
if( this.codeUrl && this.codeUrl!==''){
if(this.qrcode !== null){
this.qrcode.clear();
this.qrcode.makeCode(this.codeUrl);
}else{
this.qrcode = new QRCode('qrcode', {
width: 200,
height: 200, /** 高度 **/
text: this.codeUrl /** 二維碼內容 **/
})
}
this.setTimeout=setTimeout(this.queryOrder,3000)
}
},
queryOrder(){
if(this.orderId !== null && this.orderId !== ""){
/** 定時查詢后端,請自行修改接口 **/
this.getRequest("請求路徑", this.orderId).then(res => {
this.loading = false;
if (res.success) {
clearTimeout(this.setTimeout);
this.visible = false;
this.$Modal.success({
title: this.$t('global.prompt'),
content: this.$t('recharge.paySuccess',{ amount:this.money })
});
this.$emit('search-orders');
}else{
this.setTimeout=setTimeout(this.queryOrder,1500)
}
});
}
}
},
</script>
簡單說一下這兩個方法,qrCode() 用於根據后端返回的內容 codeUrl 創建二維碼;
queryOrder() 方法永不不停地請求后端接口查詢訂單信息,如果返回數據,就不再繼續調用自身,這塊這樣做就是為了給用戶有好的提示,比如下方是一個支付二維碼的彈窗,用戶支付成功了,不但沒有提示,窗口還一直打開着,想想用戶體驗是多么的不好。

3、微信推送支付結果
用戶掃碼支付后,微信會自動回調后端 notify 接口,具體如下「代碼僅供參考」:
@RequestMapping(value = "/notify")
@ResponseBody
public String notify(@RequestBody 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("支付成功!");
}
最后
博客地址:https://www.cnblogs.com/niceyoo
如果覺得這篇文章有丶東西,不放關注一下我,關注是對我最大的鼓勵~
18年專科畢業后,期間一度迷茫,最近我創建了一個公眾號用來記錄自己的成長。
