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


 
第一步:註冊微信支付帳戶,開通掃碼支付
具體流程請參照官方說明
 
第二步:建立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微信配置類,建立商戶本身的配置類java

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指向這裏就能直接在頁面特定區域顯示二維碼了)git

/**
     * 預支付接口,生成支付二維碼
     * @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必須公網能夠訪問,測試時能夠使用花生殼等工具映射一個公網地址github

/**
     * 支付結果回調
     * @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 建立申請退款接口(這裏必定要注意先要下載並配置證書,不然會報錯;證書下載請參考官方文檔,證書配置見商戶微信配置類)api

/**
     * 微信申請退款接口
     * @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
 
 
說明:當前項目僅實現了簡單的支付和退款功能,代碼大部分搬自官方示例,並不包括完整的支付流程,有什麼不明白的地方,歡迎留言
相關文章
相關標籤/搜索