從零玩轉系列之微信支付實戰PC端支付微信取消介面搭建 | 技術創作特訓營第一期

来源:https://www.cnblogs.com/Yangbuyi/archive/2023/08/08/17613962.html
-Advertisement-
Play Games

# 一、前言 [從零玩轉系列之微信支付實戰PC端支付微信取消介面搭建 | 技術創作特訓營第一期 ](​https://cloud.tencent.com/developer/article/2308342) halo各位大佬很久沒更新了最近在搞微信支付,因商戶號審核了我半個月和小程式認證也找了資料並 ...


一、前言

從零玩轉系列之微信支付實戰PC端支付微信取消介面搭建 | 技術創作特訓營第一期

halo各位大佬很久沒更新了最近在搞微信支付,因商戶號審核了我半個月和小程式認證也找了資料並且將商戶號和小程式進行關聯,至此微信支付Native支付完成.此篇文章過長我將分幾個階段的文章發佈(項目源碼都有,小程式和PC端)

在此之前已經更新了微信支付開篇、微信支付安全、微信實戰基礎框架搭建、本次更新為微信支付實戰PC端介面搭建,實戰篇分為幾個章節因為代碼量確實有點多哈.

請在此添加圖片描述

本次項目使用技術棧

後端: SpringBoot3.1.x、Mysql8.0、MybatisPlus

前端: Vue3、Vite、ElementPlus

小程式: Uniapp、Uview

一、取消訂單介面

場景

  1. 用戶下單完畢後未支付 可進行取消訂單
  2. 訂單超時支付系統自動取消訂單

修改 WechatNativeController

    /**
     * 用戶取消訂單
     */
    @PostMapping("/cancel/{orderNo}")
    public R<String> cancel(@PathVariable String orderNo) {
        log.info("取消訂單");
        wxPayService.cancelOrder(orderNo);
        return R.ok("訂單已取消");
    }

修改 wxPayService

    /**
     * 關閉訂單
     */
    @SneakyThrows
    public void cancelOrder(String orderNo) {
        // ...../
    }

邏輯分析

在工作中我們邏輯可能是這樣子的

step 1 查詢該訂單狀態是否需要關閉訂單,如果訂單已經關閉則不需要再次關閉

思考: 我們應該去哪裡查詢訂單的狀態?

輸入圖片說明

假如我們去資料庫查詢記錄的話,如果資料庫因為什麼原因導致狀態可能不對呢?

所以我們直接去微信伺服器查最新的直接更新關閉狀態到資料庫當中

輸入圖片說明

你看微信也要我們這樣子玩那就萬無一失直接乾

================================================================

好既然我們要去調用微信查詢介面我們是不是可以封裝一個通用的 後續肯定有其他地方也會調用查詢支付信息的情況

文檔(商戶): https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_2.shtml

有兩種查詢方式第二種方便就這麼簡單

代碼很好理解傳遞商戶訂單號和直連商戶號mchid

/**
     * 抽出公共獲取微信訂單信息
     */
    private WeChartOrderInfo selectOrderInfo(String orderNo) throws IOException {
        log.info("查詢訂單,直連商戶號:{} , 微信支付訂單號: {}", orderNo, wxPayConfig.getMchId());
        String url = wxPayConfig.getDomain().concat(String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo)).concat("?mchid=").concat(wxPayConfig.getMchId());
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");
        CloseableHttpResponse response = wxPayClient.execute(httpGet);
        WeChartOrderInfo weChartOrderInfo = buildBodyParams(response, WeChartOrderInfo.class);
        log.info("查詢訂單響應, {}", weChartOrderInfo);
        response.close();
        return weChartOrderInfo;
    }

響應結果

{
	"amount": {
		"currency": "CNY",
		"payer_currency": "CNY",
		"payer_total": 1,
		"total": 1
	},
	"appid": "wxdace645e0bc2cXXX",
	"attach": "",
	"bank_type": "OTHERS",
	"mchid": "1900006XXX",
	"out_trade_no": "44_2126281063_5504",
	"payer": {
		"openid": "o4GgauJP_mgWEWictzA15WT15XXX"
	},
	"promotion_detail": [],
	"success_time": "2021-03-22T10:29:05+08:00",
	"trade_state": "SUCCESS",
	"trade_state_desc": "支付成功",
	"trade_type": "JSAPI",
	"transaction_id": "4200000891202103228088184743"
}

完善邏輯

		/**
     * 關閉訂單
     */
    @SneakyThrows
    public void cancelOrder(String orderNo) {
  			// step 1 查詢該訂單狀態是否需要關閉訂單
      	WeChartOrderInfo state = selectOrderInfo(orderNo);
			// 判斷如果訂單已經關閉則不需要再次關閉 更新資料庫
        if (null == state || state.getTrade_state() == null) {
            // 更新本地訂單狀態超時關閉訂單
            orderInfoService.lambdaUpdate().eq(OrderInfo::getOrderNo, orderNo).set(OrderInfo::getOrderStatus, OrderStatus.CLOSED.getType()).update();
            return;
        }
      
        // step 2 還未支付才能取消訂單
        if (state.getTrade_state().equals(OrderStatus.NOTPAY.name())) {
            // step 2 進行調用微信關閉訂單介面
            sendCloseRequest(orderNo);
            // step 2 更新商戶端的訂單狀態用戶取消訂單
            this.orderInfoService.lambdaUpdate().eq(OrderInfo::getOrderNo, orderNo).set(OrderInfo::getOrderStatus, OrderStatus.CANCEL.getType()).update();
        }
    }

抽出通用訂單關閉代碼

文檔: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_3.shtml

 /**
     * 發送關閉訂單請求
     *
     * @param orderNo 訂單編號
     */
    @SneakyThrows
    private void sendCloseRequest(String orderNo) {
        log.info("關閉訂單, 訂單號:{}", orderNo);
        String url = String.format(wxPayConfig.getDomain().concat(WxApiType.CLOSE_ORDER_BY_NO.getType()), orderNo);
        HttpPost httpPost = new HttpPost(url);
        Map<String, Object> paramsMap = new HashMap<>(1);
        paramsMap.put("mchid", wxPayConfig.getMchId());
        String jsonParams = JSONUtil.toJsonStr(paramsMap);
        log.info("請求參數 ===> {}", jsonParams);
        StringEntity entity = new StringEntity(jsonParams, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
            log.info("關單響應: {}", response.getEntity());
            log.info("解析body {}", buildBodyParams(response, Map.class));
        }
    }

到這裡訂單取消就完畢了

二、查詢訂單介面

根據上面編寫的查詢訂單方法完善一下

修改 WechatNativeController

/**
 * 查詢訂單
 */
@PostMapping("/query/{orderNo}")
public R<WeChartOrderInfo> query(@PathVariable String orderNo) {
    log.info("查詢訂單");
    return R.ok(wxPayService.queryOrder(orderNo));
}

修改 WxPayService

/**
 * 查詢訂單信息
 *
 * @param orderNo 訂單號
 * @return 訂單信息
 */
@SneakyThrows
public WeChartOrderInfo queryOrder(String orderNo) {
    return this.selectOrderInfo(orderNo);
}

好了查詢介面也寫完了so easy to happy !

我們來測試看看是什麼效果咯~

請在此添加圖片描述

三、測試

下單

我們還沒編寫到前端來所以還是和之前的文章操作一樣使介面調試工具操作這裡我使用之前推薦的IDEA FastRequest插件如下圖

發送請求

發送

發送

生成二維碼

複製codeUrl參數打開草料 https://cli.im/url 不要支付哦我們確保訂單是否成功創建,確保二維碼沒有過期哦

下單

我們也可以先看看訂單啥狀態上面我們不是寫了個查詢訂單詳情的嘛

查詢訂單詳情

調用取消訂單介面

複製 orderNo 訂單編號直接發送取消完成

取消訂單

在查詢一下訂單看看狀態是不是取消成功

over

over

本文章倉庫WeChatPayScaffolding

【寫作提綱】

I. 前言

A. 通過前言表達我每次的文章內容是什麼東西

II. 取消訂單介面實現

A. 集結生活之中的場景來解析他的邏輯

III. 查詢訂單介面實現

A. 完善取消訂單介面當中已經實現了的功能

IV. 測試

A. 通過測試用例一步步排查編寫是否存在BUG

你的壓力來源於無法自律,只是假裝努力,現狀跟不上內心欲望,所以你焦慮又恐慌。——楊不易
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ##### 該切麵功能適用場景 - 下單請求多次提交,導致生成多個相同的訂單 ##### 解決方案 - 前端解決:限制點擊下單按鈕為1次後失效。不足:用戶體驗下降,能繞過前端 - 後端解決:防重提交切麵解決,自定義註釋實現該功能(如下) - 步驟: - 自定義註釋類RepeatSubmit - 創建 ...
  • ## 9.1、環境搭建 ### 9.1.1、創建module ![image](https://img2023.cnblogs.com/blog/2052479/202308/2052479-20230806234218377-617105837.png) ### 9.1.2、選擇maven ![i ...
  • 在Go中,有不同的**變數類型**,例如: - `int` 存儲整數(整數),例如123或-123 - `float32` 存儲浮點數字,帶小數,例如19.99或-19.99 - `string` - 存儲文本,例如“ Hello World”。字元串值用雙引號括起來 - `bool` 存儲具有兩個 ...
  • 本文已收錄至Github,推薦閱讀 👉 [Java隨想錄](https://github.com/ZhengShuHai/JavaRecord) 微信公眾號:[Java隨想錄](https://mmbiz.qpic.cn/mmbiz_jpg/jC8rtGdWScMuzzTENRgicfnr91C5 ...
  • 最近颱風肆虐,已進入我國24小時警戒線!颱風“卡努”到底要去哪兒? 作為一個Python程式員,雖然我幫不上忙,但是時時關註一下還是可以的,順便祈禱一下臺風往東邊某個小日子過得不錯的小島吹。 於是我花了一分鐘,用Python寫了一個獲取天氣數據的代碼,然後進行數據分析,看看到底吹不吹的過去。 首先我 ...
  • 6、安裝插件sublimeREPL 需要安裝插件:sublimeREPL,才能在sublime編譯器中接受鍵盤輸入的信息,才能執行交互結果 插件安裝快捷鍵:ctrl+shift+P,打開插件安裝面板 輸入install後,選擇package control:install package 安裝插件管 ...
  • 在使用python開發一些小工具時,如果其他人電腦中沒有python環境或者沒有安裝相應的第三方庫,是沒辦法運行的,而要求對方安裝又不現實,尤其是對方不是技術人員,因此如何將一個獨立的python程式,使它成為成為一個不用考慮環境,雙擊即可運行的桌面應用呢?使用pyinstaller打包是一個不錯的... ...
  • # 基於python tornado實現的簡易圖床 項目地址 > 因為買了阿裡/騰訊的雲伺服器,但是使用雲存儲還需要收費,又加上家裡正好有一臺`nas`,又加上閑的沒事,所以搞了一個小腳本 > > 這個項目主要功能是為`typora`增加一個自定義圖床 > > 歡迎提出issues和pr,如果閑的沒 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...