In fact, there have been a lot of cases about wechat payment online. Today, I would like to introduce some easy and easily ignored pits in wechat payment, refund and transfer. As for key, MCID, OPPID and certificate download, there are already comprehensive project dependencies on the web

    <dependency>
        <groupId>com.github.wxpay</groupId>
        <artifactId>wxpay-sdk</artifactId>
        <version>0.03.</version>
     </dependency>
Copy the code

The configuration class:

public class WXConfigUtil implements WXPayConfig {

    private final byte[] certData;

    private String mchId;

    private String key;


    public WXConfigUtil(String certPath, String key, String mchId) throws Exception {
        // The path where the security certificate downloaded from wechat merchant platform is stored
        File file = new File(certPath);
        InputStream certStream = new FileInputStream(file);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int n;
        while((n = certStream.read(b)) ! = -1) {
            bos.write(b, 0, n);
        }
        certStream.close();
        bos.close();
        // Load the read certificate into cerData(this step is almost useless in articles on the web)
        this.certData = bos.toByteArray();
        this.mchId = mchId;
        this.key = key;
    }

    @Override
    public String getAppID(a) {
        return WechatConstant.APP_ID;
    }

    @Override
    public String getMchID(a) {
        return mchId;
    }

    @Override
    public String getKey(a) {
        return key;
    }

    @Override
    public InputStream getCertStream(a) {
        // Get the certificate on request
        return new ByteArrayInputStream(this.certData);
    }

    @Override
    public int getHttpConnectTimeoutMs(a) {
        return 8000;
    }

    @Override
    public int getHttpReadTimeoutMs(a) {
        return 10000; }}Copy the code

In fact, the key configuration above is the configuration of certificate reading. There is no more nonsense, the following is the unified ordering interface processing: Payment :(here has app payment as an example)

  Map<String, String> response;
        try {
            WXConfigUtil wxConfigUtil = new WXConfigUtil(certPath, key, mchid);
            WXPay wxPay = new WXPay(wxConfigUtil);
            Map<String, String> data = new HashMap<>();
            // Randomly generate merchant order numbers

            System.out.println("Merchant Order No. ------------" + orderNo);

            / / merchants
            data.put("mch_id", wxConfigUtil.getMchID());
            // Random string
            data.put("nonce_str", WXPayUtil.generateNonceStr());
            // Product description
            data.put("body"."Description");
            // Order number
            data.put("out_trade_no", orderNo);
            // Total amount (unit cent)
            data.put("total_fee".100);
            / / terminal IP
            data.put("spbill_create_ip"."124.xx.xx.xx");
            // Callback address
            data.put("notify_url", notifyUrl);
            //appid
            data.put("appid", wxConfigUtil.getAppID());
            // Transaction type
            data.put("trade_type"."APP");
            data.put("attach", wechatVo.getUserId().toString());
            // Generate a signature
          String   sign = WXPayUtil.generateSignature(data, wxConfigUtil.getKey(), WXPayConstants.SignType.MD5);
            data.put("sign", sign);
            String str = WXPayUtil.mapToXml(data);
            System.out.println("Turn the map XML" + str);
            System.out.println("The number I gave you is + data);
            System.out.println("First signature ------------------" + sign);
            // Use the official API to request a prepayment order
            response = wxPay.unifiedOrder(data);
            } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        // Return the result, which can be wrapped itself
        return response;
Copy the code

Transfer from business to individual:

  Map<String, String> restmap = null;
        try {
            WXConfigUtil wxConfigUtil = new WXConfigUtil(certPath, key, mchid);
            WXPay wxPay = new WXPay(wxConfigUtil);
            Map<String, String> param = new HashMap<String, String>();
            // Public account appid
            param.put("mch_appid", wxConfigUtil.getAppID());
            / / merchants
            param.put("mchid", wxConfigUtil.getMchID());
            // Random string
            param.put("nonce_str", WXPayUtil.generateNonceStr());
            // Merchant order number
            param.put("partner_trade_no"."");
            / / users openid
            param.put("openid", wechatVo.getOpenId());
            // Check user name option OPTION_CHECK
            param.put("check_name"."NO_CHECK");
            param.put("amount"."");
            // Enterprise payment description
            param.put("desc"."withdraw");
            // Server Ip address
            param.put("spbill_create_ip"."124.xx.xx.xx");
            param.put("sign", WXPayUtil.generateSignature(param, wxConfigUtil.getKey()));
            // Carry the certificate request
            String restxml = wxPay.requestWithCert("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers", param, 15000.15000);
            assertrestxml ! =null;
            restmap = WXPayUtil.xmlToMap(restxml);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        // Return the request result
        return restmap;
Copy the code

Refund:

     HashMap<String, String> data = new HashMap<String, String>();
        String orderNo = "VxRefund_" + System.currentTimeMillis();
        try {
            WXConfigUtil wxConfigUtil = new WXConfigUtil(certPath, key, mchid);
            WXPay wxPay = new WXPay(wxConfigUtil);
            data.put("appid", wxConfigUtil.getAppID());
            data.put("mch_id", wxConfigUtil.getMchID());
            data.put("nonce_str", WXPayUtil.generateNonceStr());
            // wechat order Number serial number ____
            data.put("transaction_id"."Payment serial number");
            // Merchant refund slip No. refund slip no. ___
            data.put("out_refund_no", orderNo);
            // Payment amount. The amount submitted by wechat Pay cannot be numbered with a decimal point and is divided into units. It needs to be converted to a string type, otherwise the signature will fail
            data.put("total_fee"."");
            // Total amount of refund, total amount of order, in minutes, can only be an integer
            data.put("refund_fee"."");
            data.put("op_user_id", wxConfigUtil.getMchID());
            //MD5 generates the signature, here is the first signature, used to call the unified order interface
            String sign = WXPayUtil.generateSignature(data, wxConfigUtil.getKey());
            // Generate a signature
            data.put("sign", sign);
            // Use the carrying certificate request
            String s = wxPay.requestWithCert("https://api.mch.weixin.qq.com/secapi/pay/refund", data, 15000.15000);
            Map<String, String> response = WXPayUtil.xmlToMap(s);
           if ("SUCCESS".equals(returnCode) && returnCode.equals(resultCode)) {
               // Todo's own business logic
            } else {
                return ResultInfo.error("Refund failed"); }}catch (Exception e) {
            e.printStackTrace();
        }
        return ResultInfo.successful("Refund successful");
Copy the code

Unified callback:

 StringBuilder sb = new StringBuilder();
        try {
            // Get the WX callback data
            BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
            String line = null;
            new StringBuilder();
            while((line = br.readLine()) ! =null) {
                sb.append(line);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //sb is the XML returned by wechat
        String notityXml = sb.toString();

        System.out.println("= = = = = = = = = = = = = = = = = = = = = = WeChat pay logic to handle asynchronous results began to = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
        WXConfigUtil config = null;
        try {
            config = new WXConfigUtil(certPath, key, mchid);
        } catch (Exception e) {
            e.printStackTrace();
        }
        WXPay wxpay = new WXPay(config);
        String xmlBack = "";
        Map<String, String> notifyMap = null;
        try {
            // Call the official SDK to convert map data
            notifyMap = WXPayUtil.xmlToMap(notityXml);
            System.out.println("Returned map----------------" + notifyMap);
            // Verify that the signature is valid
            System.out.println("Error code returned --------" + notifyMap.get("err_code") + "Error message returned --------" + notifyMap.get("err_code_des"));
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
                / / state
                String returnCode = notifyMap.get("return_code");
                // Merchant order number
                String outTradeNo = notifyMap.get("out_trade_no");
                String userId = notifyMap.get("attach");
                if ("SUCCESS".equals(returnCode)) {
                    if(outTradeNo ! =null) {
                        // Business data persistence
                        String transactionId = notifyMap.get("transaction_id");
                       // Todo business logic
                      / /...
                        System.err.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- pay success -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
                        xmlBack = "<xml>" + "
      
       
      " + "
      
       
      " + "</xml> ";
                    } else {
                        xmlBack = "<xml>" + "
      
       
      " + "
      
       
      " + "</xml> "; }}}else {
                If there is no sign field in the data, it is considered as a signature error
                // Do you want to store failed data?
                xmlBack = "<xml>" + "
      
       
      " + "
      
       
      " + "</xml> "; }}catch (Exception e) {
            xmlBack = "<xml>" + "
      
       
      " + "
      
       
      " + "</xml> ";
        }
        return ResultInfo.successful(xmlBack);
Copy the code

The above is just some superficial business logic, hope to help you