微信扫码支付手把手教学

飞一样的编程
飞一样的编程
擅长邻域:Java,MySQL,Linux,nginx,springboot,mongodb,微信小程序,vue

专栏: 220908-小班辅导 标签: 微信支付 扫码支付

2022-10-15 08:31:42 695浏览

微信扫码支付手把手教学

官网api在线文档

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

1.需要提前准备的几个重要参数

微信支付必须是注册商家才行,得有营业执照。下面的参数登陆你的企业微信公众号后台去获取,


2.新建一个WXPayConfig实现类

由于我们要做的是扫码支付,而扫码支付不需要验证证书,所以下面的方法里getCertStream可以直接返回null,但getWXPayDomain必须自定义写哦。

package com.github.wxpay.sdk;

import com.github.wxpay.sdk.config.WXpayConfig;

import java.io.*;

public class WXPayConfigImpl extends WXPayConfig {
    private byte[] certData;
//    public WXPayConfigImpl() throws IOException {
//        String certPath = "D:/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();
//    }

    @Override
    public String getAppID() {

        return WXpayConfig.getProperties("appid");
    }

    @Override
    public String getMchID() {
        return WXpayConfig.getProperties("mch_id");
    }

    @Override
    public String getKey() {
        return WXpayConfig.getProperties("mchKey");

    }

    public String getTradeType(){
        return WXpayConfig.getProperties("trade_type");
    }


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

    @Override
    IWXPayDomain getWXPayDomain() {
        IWXPayDomain iwxPayDomain = new IWXPayDomain() {
            @Override
            public void report(String domain, long elapsedTimeMillis, Exception ex) {

            }

            @Override
            public DomainInfo getDomain(WXPayConfig config) {
                return new IWXPayDomain.DomainInfo(WXPayConstants.DOMAIN_API, true);
            }
        };
        return iwxPayDomain;
    }


}

3. 写一个统一下单接口返回二维码到前端

@WebServlet("/order")
public class OrderServlet extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        try {
            WXPayConfigImpl config = new WXPayConfigImpl();
            WXPay wxpay = new WXPay(config);
            Map<String, String> data = new HashMap<String, String>();
            data.put("appid", config.getAppID());

            data.put("mch_id", config.getMchID());

            data.put("nonce_str", WXPayUtil.generateNonceStr());



            data.put("body", req.getParameter("orderName"));

            data.put("out_trade_no", req.getParameter("orderNo"));

            data.put("total_fee", "1");

            data.put("spbill_create_ip", "123.12.12.123");

            data.put("notify_url",  "http://tf5i8v.natappfree.cc/wxpay_sdk/OrderNotify");

            data.put("trade_type", config.getTradeType());/** wxPay.unifiedOrder 这个方法中调用微信统一下单接口 */

            String sign = WXPayUtil.generateSignature(data, config.getKey(), WXPayConstants.SignType.HMACSHA256); /* 签名*/
            data.put("sign", sign);



            Map<String, String> respData = wxpay.unifiedOrder(data);
            System.out.println("**************wx qr pay***********************************");
            System.out.println(respData);
            if (respData.get("return_code").equals("SUCCESS") && respData.get("return_msg").equals("OK")){

                Map<String,String> codeurlMap = new HashMap<>();
                codeurlMap.put("code_url",respData.get("code_url"));

                res.getWriter().write(JSON.toJSONString(codeurlMap));/*返回二维码的支付参数*/
                res.getWriter().flush();
                res.getWriter().close();
            }else{
                res.getWriter().write("");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.支付回调接口

@WebServlet("/OrderNotify")
public class OrderNotify extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        InputStream in = req.getInputStream();
        BufferedReader br = new BufferedReader( new InputStreamReader( in, "UTF-8" ) );
        StringBuffer result = new StringBuffer();
        String line = "";

        while ( (line = br.readLine())!= null )
        {
            result.append(line);
        }
        in.close();
        br.close();
        try {
            Map<String, String> map = WXPayUtil.xmlToMap( result.toString() );
            System.out.println("===问答=微信扫码支付回调=购买金币=====================================");
            String mch_id=map.get("mch_id");
            String appid=map.get("appid");

            boolean flag = WXPayUtil.isSignatureValid(map, WXpayConfig.getProperties("mchKey"),HMACSHA256);
            if(flag){
                if(map.get("result_code").equals("SUCCESS")) {
                    //修改订单状态啥的。
                    String orderNo = map.get("out_trade_no");//商户订单
                    String transaction_id = map.get("transaction_id");//交易订单号


                    //告诉微信这边已经收到通知了'

                    Map<String,String> returnMap = new HashMap<>();
                    returnMap.put("return_code","SUCCESS");
                    returnMap.put("return_msg","OK");




                    String xml = WXPayUtil.generateSignedXml(returnMap, WXpayConfig.getProperties("mchKey"), HMACSHA256);
                    resp.getWriter().write(xml);

                    resp.getWriter().flush();
                    resp.getWriter().close();
                }
            }



        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.注意事项

  1. 注意这个xml安全机制

微信支付的安全机制:所有请求参数通过ASSIC排序后(abcde的顺序),在末尾添加微信支付秘钥(key),然后把封装好的字符串通过MD5或SHA256方式加密。微信接收到请求信息之后会先把你传递过来的参数重新排序,加密,然后拿2个加密后的字符串做对比,如果匹配证明数据无误,此时的秘钥只有你知,微信知,不能透露给其他无关用户。

  1. 支付回调验签总是失败

原因是:下单的时候默认是用HMACSHA256的加密方式,而验签的时候默认是MD5加密方式,所以我这里的加密方式全部改成了HMACSHA256就可以了。

  1. 支付回调重复调用的问题

已经告诉微信这边进回调了,但微信还是一直发请求过来,原因是给微信返回的必须是xml格式的数据,而且还必须加签加密后再传。

4,主要的参考文档:

https://www.jf3q.com/article/detail/3691

好博客就要一起分享哦!分享海报

此处可发布评论

评论(1展开评论

蓝色妖姬 能力:10

2023-07-20 14:43:48

出去了再学
点击查看更多评论

展开评论

您可能感兴趣的博客

客服QQ 1913284695