第三方支付之微信支付(掃碼支付)

来源:http://www.cnblogs.com/gdufs/archive/2017/07/24/7230950.html
-Advertisement-
Play Games

第一步:註冊微信支付賬戶,開通掃碼支付 具體流程請參照官方說明 第二步:創建Maven項目 1. 添加微信支付SDK依賴、二維碼工具依賴(微信支付需要自己通過二維碼工具生成支付二維碼) <!-- 微信支付 --> <dependency> <groupId>com.github.wxpay</gro ...



  第一步:註冊微信支付賬戶,開通掃碼支付 具體流程請參照官方說明   第二步:創建Maven項目   1. 添加微信支付SDK依賴、二維碼工具依賴(微信支付需要自己通過二維碼工具生成支付二維碼)
     <!-- 微信支付 -->
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>
        
        <!-- google二維碼工具 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.1.0</version>
        </dependency>

 

2. 實現SDK微信配置類,創建商戶自己的配置類

public class WxPayConfig implements WXPayConfig{

    private byte[] certData;
    
    //初始化退款、撤銷時的商戶證書
    public WxPayConfig() throws Exception {
        String certPath = "D://第三方開放平臺/wx_apiclient_cert.p12";
        File file = new File(certPath);
        InputStream certStream = new FileInputStream(file);
        this.certData = new byte[(int) file.length()];
        certStream.read(this.certData);
        certStream.close();
    }

    public String getAppID() {
        return "";
    }

    /** 微信支付商戶號 */
    public String getMchID() {
        return "";
    }

    public String getKey() {
        return "";
    }

    public int getHttpConnectTimeoutMs() {
        return 8000;
    }

    public int getHttpReadTimeoutMs() {
        return 10000;
    }

    @Override
    public InputStream getCertStream() {
        ByteArrayInputStream certBis;
        certBis = new ByteArrayInputStream(this.certData);
        return certBis;
    }
}

 

3. 創建微信支付的控制器類        3.1 初始化微信支付的SDK客戶端
private WxPayConfig config;

private WXPay wxpay;

public WxPayController() {
   try {
      //初始化微信支付客戶端
      config = new WxPayConfig();
      wxpay = new WXPay(config);
   } catch (Exception e) {
      e.printStackTrace();
   }
}

 

 3.2 創建預支付介面,生成支付二維碼(可以在頁面添加img標簽,讓它的url指向這裡就能直接在頁面特定區域顯示二維碼了)

/**
     * 預支付介面,生成支付二維碼
     * @param order
     * @return
     * @throws Exception
     */
    @RequestMapping("/wxpay/pay")
    public void pay(HttpServletResponse response) throws Exception {
        //TODO:這裡執行商戶系統創建新的訂單操作
        WxPayOrder order = new WxPayOrder();
        order.setOut_trade_no(System.currentTimeMillis() + "");
        wxPayService.createOrder(order);
        
        //設置請求參數
        Map<String, String> data = new HashMap<String, String>();
        data.put("body", "微信支付測試");
        data.put("out_trade_no", order.getOut_trade_no());
        data.put("device_info", "");
        data.put("fee_type", "CNY");
        data.put("total_fee", "1");
        data.put("spbill_create_ip", "192.168.0.119");
        data.put("notify_url", notify_url);
        data.put("trade_type", "NATIVE");  // 此處指定為掃碼支付
        data.put("product_id", "12");

        try {
            //發起支付
            Map<String, String> resp = wxpay.unifiedOrder(data);
            //獲取二維碼URL
            String code_url = resp.get("code_url");
            //根據url生成二維碼
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            // 設置二維碼參數
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            BitMatrix bitMatrix = multiFormatWriter.encode(code_url, BarcodeFormat.QR_CODE, 300, 300, hints);
            //返回二維碼
            MatrixToImageWriter.writeToStream(bitMatrix, "jpg", response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

 3.3 創建支付結果回調介面(回調的URL必須公網可以訪問,測試時可以使用花生殼等工具映射一個公網地址

/**
     * 支付結果回調
     * @return
     * @throws Exception 
     */
    @PostMapping("/wxpay/notify_url")
    public void notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 讀取回調內容
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        
        // 支付結果通知的xml格式數據
        String notifyData = sb.toString(); 

        // 轉換成map
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);

        //支付確認內容
        String resXml = "";
        //驗證簽名
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {        // 簽名正確
            WxPayOrder order = wxPayService.getOrder(notifyMap.get("out_trade_no"));
            if(order != null) {
                if("SUCCESS".equals(notifyMap.get("result_code"))) {    //交易成功
                    // TODO:更新訂單
                    System.out.println("訂單" + notifyMap.get("out_trade_no") + "微信支付成功");
                } else {    //交易失敗
                    System.out.println("訂單" + notifyMap.get("out_trade_no") + "微信支付失敗");
                }
            }
            // 註意特殊情況:訂單已經退款,但收到了支付結果成功的通知,不應把商戶側訂單狀態從退款改成支付成功
            
            //設置成功確認內容
            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
        }
        else {  // 簽名錯誤,如果數據里沒有sign欄位,也認為是簽名錯誤
            //設置失敗確認內容
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg></return_msg>" + "</xml> ";
            System.out.println("訂單" + notifyMap.get("out_trade_no") + "微信支付失敗");
        }
        
        //發送通知
        response.getWriter().println(resXml);
    }

 

 3.4 創建申請退款介面(這裡一定要註意先要下載並配置證書,否則會報錯;證書下載請參考官方文檔,證書配置見商戶微信配置類)

/**
     * 微信申請退款介面
     * @param out_trade_no        訂單號
     * @throws Exception
     */
    @RequestMapping("/wxpay/refund")
    public void refund(String out_trade_no) throws Exception {
        //設置請求參數
        HashMap<String, String> data = new HashMap<String, String>();
        data.put("out_trade_no", out_trade_no);
        data.put("out_refund_no", out_trade_no);
        data.put("total_fee", "1");
        data.put("refund_fee", "1");
        data.put("refund_fee_type", "CNY");
        data.put("op_user_id", config.getMchID());

        try {
            //調用sdk發起退款
            Map<String, String> result = wxpay.refund(data);
            if("SUCCESS".equals(result.get("result_code"))) {
                //TODO:更新訂單
                System.out.println("訂單" + out_trade_no + "微信退款成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

第三步:測試支付、退款   1. 運行項目 mvn jetty:run   2. 測試支付介面:http://localhost:8080/wxpay/pay   3. 測試退款介面:http://localhost:8080/wxpay/refund     說明:當前項目僅實現了簡單的支付和退款功能,代碼大部分搬自官方示例,並不包括完整的支付流程,有什麼不明白的地方,歡迎留言 項目源碼:https://github.com/13babybear/bounter-pay
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 消息保證送達是指消息發送方保證在任何情況下都會至少一次確定的消息送達。AtleastOnceDelivery是一個獨立的trait,主要作用是對不確定已送達的消息進行補發,這是一種自動的操作,無需用戶干預。既然涉及到消息的補發,就不可避免地影響發送方和接收方之間消息傳遞的順序、接收方重覆收到相同的消 ...
  • 1、函數嵌套 1.1函數的嵌套調用 在調用一個函數的過程中,又調用了其他函數 1.2函數的嵌套定義 在一個函數的內部,又定義另外一個函數 2、名稱空間 2.1名稱空間 名稱空間:存放名字的地方,準確的說名稱空間是存放名字與變數值綁定關係的地方 內置名稱空間:在python解釋器啟動時產生,存放一些p ...
  • 一 概述 1.整合目的 有了Spring以後,所有對象的創建任務都應該交給Spring容器來完成,這樣做不僅是為了降低代碼的耦合度,而且可以利用Spring容器作為代理工廠實現代理。 2.整合目標 將Spring容器中的bean註入Action中,將Action的創建與管理工作交給Spring容器。 ...
  • 一 概述 1.整合目的 將所有對象的創建與管理任務交給Spring容器,降低程式的耦合度。 2.整合途徑 將Spring容器註入到Web容器中。 3.具體實現 使用ServletContextListener監聽ServletContext,當ServletContexxt創建時同時創建Spring ...
  • 經典數據集CIFAR-10,60000張32x32彩色圖像,訓練集50000張,測試集10000張。標註10類,每類圖片6000張。airplance、automobile、bird、cat、deer、dog、frog、horse、ship、truck。沒有任何重疊。CIFAR-100,100類標註 ...
  • 載入MNIST數據集。創建預設Interactive Session。 初始化函數,權重製造隨機雜訊打破完全對稱。截斷正態分佈雜訊,標準差設0.1。ReLU,偏置加小正值(0.1),避免死亡節點(dead neurons)。 捲積層函數,tf.nn.conv2d,TensorFlow 2 維捲積函數 ...
  • 題目原文: An inversion in an array a[] is a pair of entries a[i] and a[j] such that i<j but a[i]>a[j]. Given an array, design a linearithmic algorithm to ...
  • 一 概述 1.整合目的 在Hibernate中,SessionFactory是一個重量級對象,創建與初始化會耗費大量的資源,應該減少對象的創建次數,並且SessionFactory線程安全,可以採用單例模式,如果將對象的創建任務交給Spring容器就解決了這個問題。 二 實現 1.配置Session ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...