微信支付—微信H5支付「PC端掃碼支付」


前言

微信支付-微信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(){
                ifthis.codeUrl &&  this.codeUrl!==''){
                    if(this.qrcode !== null){
                        this.qrcode.clear();
                        this.qrcode.makeCode(this.codeUrl);
                    }else{
                        this.qrcode = new QRCode('qrcode', {
                            width200,
                            height200/** 高度 **/
                            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({
                            titlethis.$t('global.prompt'),
                            contentthis.$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年專科畢業后,期間一度迷茫,最近我創建了一個公眾號用來記錄自己的成長。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM