2021-09-16

微信支付–Native支付(PC网页扫码支付)

一.准备工作
1.申请微信商户号,在微信的开放平台创建一个公众号应用并和商户进行绑定,在这一步你会获得:AppID(公众号的appID),mchid(商户号)
2.配置API key,登录微信商户平台,进入【账户中心 > API安全 > API安全】目录,点击【APIV3密钥】,也可以只配置API密钥。
在这里插入图片描述
在这一步你会获取到到一个新的参数:APi_Key(api密钥)
注意:申请微信材料可以查看微信接入引导:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_1.shtml
进行配置申请。
二.代码开发
1.完成以上步骤可获取到参数:AppID(公众号的appID),mchid(商户号),APi_Key(api密钥)。
2.java服务端代码。
(1).引入依赖

<!--微信的工具依赖-->
<dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>
        
        <!-- 二维码生成依赖 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>2.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>2.1</version>
        </dependency>

微信工具依赖只是将微信订单的参数进行map转成XmL格式,或者将xml转成map,因为微信统一下单需要将订单信息转成xml格式。
二维码依赖是将微信下单成功后微信官方返回的code_url在这里插入图片描述
你可以将这个参数个前端让他们去生成二维码。也可以自己生成给前端访问。
(2).功能代码
支付需要使用的常量配置
WxConfig – (自定以一个类名也行)

/**
     * 微信公众账号
     */
    public final static String APPID = "wxxxxxxxxxxxxx";
    /**
     * 商户号
     */
    public final static String MCH_ID = "xxxxxxxx";
    /**
     * API密钥
     */
    public final static String API_KEY = "xxxxxxxxxxxxxxxxxxxx";
    /**
     *异步回调地址
     * */
    public final  static String notify_url = "http://htk5yt.natappfree.cc/wxpaycontroller/wxPayBynotify";

注:以上参数的异步回调地址不能使用IP去做,需要使用域名可以自己搞一个端口穿孔。

统一下单

一下自己封装的工具类

/**
     * 微信的Pc统一支付(Native)
     * (非证书模式)
     *
     * @param orderId 订单号
     * @param price   金额(分)--格式:0.01
     * @param body    商品描述
     */
    public static JsonResult createNative(
            String orderId,
            String price,
            String body,
            HttpServletRequest request
    ) {
        JsonResult jsonResult = new JsonResult();
        try {
            log.info("微信创建统一支付订单! 订单号:" + orderId + " 支付金额: " + price + " 商品描述: " + body);

            //todo 创建请求参数
            SortedMap<String, String> req = new TreeMap<String, String>();
            req.put("appid", WxPayConfig.APPID);    //公众号appID -- 引入上面的参数
            req.put("mch_id", WxPayConfig.MCH_ID);  // 商户号 
            req.put("nonce_str", WXPayUtil.generateNonceStr()); // 32位随机字符串
            req.put("body", body); // 商品描述
            req.put("out_trade_no", orderId);   // 商户订单号
            req.put("total_fee", df.format(Double.parseDouble(price) * 100));    // 标价金额(分)
            req.put("spbill_create_ip", WxPayHttpUtil.getIp(request));   // 终端IP
            req.put("notify_url", WxPayConfig.notify_url);  // 回调地址
            req.put("trade_type", "NATIVE");    // 交易类型
            req.put("sign", WXPayUtil.generateSignature(req, WxPayConfig.API_KEY, WXPayConstants.SignType.MD5));  // 签名

            //todo 生成要发送的 xml
            String xmlBody = WXPayUtil.generateSignedXml(req, WxPayConfig.API_KEY);
            System.err.println(String.format("微信支付预下单请求 xml 格式:\n%s", xmlBody));

            //todo 发送 POST 请求 统一下单 API 并携带 xmlBody 内容,然后获得返回接口结果
            String result = WxPayHttpUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", xmlBody);
            System.err.println(String.format("%s", result));

            //todo 将返回结果从 xml 格式转换为 map 格式
            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
            Map<String, String> map = new HashMap<>();
            map.put("code_url", resultMap.get("code_url")); // 支付地址
            map.put("total_fee", price); // 总金额
            map.put("out_trade_no", orderId);    // 订单号
            //后台生成二维码,建议给前台生成
            String codeurl = resultMap.get("code_url");
            String destpath = "E:/wximg";

            log.info("微信统一下单成功: codeurl " + codeurl);
            jsonResult.setSuccess(true);
            jsonResult.setObj(map);
            jsonResult.setMsg("微信统一下单成功");
            return jsonResult;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信统一下单失败! 异常:" + e.getMessage());
            jsonResult.setSuccess(false);
            jsonResult.setObj(e.getMessage());
            jsonResult.setMsg("微信统一下单失败");
            return jsonResult;
        }
    }

/**
     * 微信异步回调处理
     */
    public static JsonResult wxNotify(HttpServletRequest request) {
        JsonResult jsonResult = new JsonResult();

        WXPayConfig mywxpay = new WXPayConfig() {
            @Override
            public String getAppID() {
                return WxPayConfig.APPID;
            }

            @Override
            public String getMchID() {
                return WxPayConfig.MCH_ID;
            }

            @Override
            public String getKey() {
                return WxPayConfig.API_KEY;
            }

            @Override
            public InputStream getCertStream() {
                return null;
            }

            @Override
            public int getHttpConnectTimeoutMs() {
                return 0;
            }

            @Override
            public int getHttpReadTimeoutMs() {
                return 0;
            }
        };

        WXPay wxPay = new WXPay(mywxpay);

        String returnXmlMessage = null;
        String notifyXmlData = null;

        try {
            notifyXmlData = readXmlFromStream(request);

            Map<String, String> notifyMapData = WXPayUtil.xmlToMap(notifyXmlData);
            log.info("解析微信支付回调map成功"+ JSON.toJSONString(notifyMapData));
            // 验证签名
            boolean signatureValid = wxPay.isPayResultNotifySignatureValid(notifyMapData);
            if (signatureValid) {
                log.info("验签成功!");
                // TODO:订单支付成功之后相关业务逻辑...
                // 支付成功
                log.info("微信支付成功回调!");

                //商品订单号
                String out_trade_no = notifyMapData.get("out_trade_no"); // 商品订单号
                log.info("微信商品订单号: " + out_trade_no);
                // 当前交易状态
                String tradeStatus = notifyMapData.get("return_code"); //当前交易状态
                log.info("微信当前交易状态: " + tradeStatus);
                // 支付金额
                String totalAmount = notifyMapData.get("total_fee"); //支付金额
                log.info("微信支付金额: " + totalAmount);
                // 支付时间
                String payDate = notifyMapData.get("time_end"); //支付时间
                log.info("微信支付时间: " + payDate);
                //流水号--支付宝交易号。支付宝交易凭证号。
                String tradeNo = notifyMapData.get("transaction_id"); //流水号
                log.info("微信交易号: " + tradeNo);

                Map<String, String> map = new HashMap<>();
                map.put("tradeNo", tradeNo);
                map.put("out_trade_no", out_trade_no);
                map.put("tradeStatus", tradeStatus);
                map.put("totalAmount", totalAmount);
                map.put("payDate", payDate);

                jsonResult.setSuccess(true);
                jsonResult.setMsg("微信支付成功");
                jsonResult.setObj(map);
                return jsonResult;

            } else {
                //支付其他状态
                log.info("微信支付回调其他状态");
                return jsonResult.setSuccess(false).setMsg("微信支付回调其他状态");
            }

        } catch (IOException e) {
            log.error("微信回调异常:解析网络参数异常:" + e.getMessage());
            return jsonResult.setSuccess(false).setMsg("微信回调异常:解析网络参数异常:" + e.getMessage());
        } catch (Exception e) {
            log.error("微信回调异常:" + e.getMessage());
            return jsonResult.setSuccess(false).setMsg("微信回调异常:" + e.getMessage());
        }

    }

/**
     * 微信订单状态查询
     * @param orderId
     **/
    public static Map<String,String> wxOrderStart(String orderId){

        try {
            //todo 创建请求参数
            SortedMap<String, String> req = new TreeMap<String, String>();
            req.put("appid", WxPayConfig.APPID); // 公众号ID
            req.put("mch_id", WxPayConfig.MCH_ID);   // 商户号
            req.put("out_trade_no", orderId);    // 订单号
            req.put("nonce_str", WXPayUtil.generateNonceStr()); // 随机字符串
            req.put("sign", WXPayUtil.generateSignature(req, WxPayConfig.API_KEY, WXPayConstants.SignType.MD5));

            //todo 生成要发送的 xml
            String xmlBody = WXPayUtil.generateSignedXml(req, WxPayConfig.API_KEY);
            System.err.println(String.format("查询订单支付状态 xml 格式:\n%s", xmlBody));

            //todo 调用查询订单支付状态 API
            String result = WxPayHttpUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/orderquery", "POST", xmlBody);

            //todo 返回解析后的 map 数据
            Map<String, String> map = WXPayUtil.xmlToMap(result);
            System.out.println(String.format("%s", map));
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

注:以上用的WxPayConfig是上面代码自己定义的微信支付参数

自己在也一个Controller接口去调用就行

异步回调:service层

 @Override
    public void wxPayBynNotify(HttpServletRequest request) {
        //微信异步回调
        JsonResult jsonResult = new JsonResult();
        jsonResult = WxPayUtil.wxNotify(request);
        boolean orderstart = jsonResult.getSuccess();
        if (orderstart) {
            Map<String, String> map = (Map) jsonResult.getObj();
            //商品订单号
            String out_trade_no = map.get("out_trade_no"); // 商品订单号
            // 当前交易状态
            String tradeStatus = map.get("tradeStatus"); //当前交易状态
            // 支付金额
            String totalAmount = map.get("totalAmount"); //支付金额
            // 支付时间
            String payDate = map.get("payDate"); //支付时间
            //流水号--微信交易号。微信交易凭证号。
            String tradeNo = map.get("tradeNo"); //流水号
            log.info("微信参数取出: out_trade_no: " + out_trade_no + " tradeStatus: " + tradeStatus + " totalAmount: " + totalAmount + " payDate: " + payDate + " tradeNo: " + tradeNo);
			
			//自己处理业务

            } else {
                log.error("订单不存在");
            }
        } else {
            log.info("微信回调处理异常待处理");
        }


    }

因为PC端是生成二维码,要写一个获取订单状态的接口去查订单状态
状态查询:service层

	@Override
    public JsonResult wxPayByOrderStart(String orderId) {
        JsonResult jsonResult = new JsonResult();
        int x = 0;
        // 调用查询微信支付订单状态方法
        Map<String, String> map = WxPayUtil.wxOrderStart(orderId);
        Map<String,Integer> startmap = new HashMap<>();
        // startmap的状态说明:1不要刷新二维码等待支付,2刷新二维码就是重新调用下单,3,订单支付成功前端跳转页面

        try {
            log.info("微信状态查询:" + JSON.toJSONString(map));
            if (map.isEmpty()) {
                //支付出错
                return jsonResult.setSuccess(false).setMsg("支付出错,重新调用统一下单,刷新二维密码。");
            }
            if (map.get("trade_state").equals("SUCCESS")) {
                //支付成功
                startmap.put("start",3);
                return jsonResult.setSuccess(true).setMsg("订单支付成功!").setObj(startmap);
            }else if(map.get("trade_state").equals("NOTPAY")){
                //订单未支付
                startmap.put("start",1);
                return jsonResult.setSuccess(true).setMsg("订单等待支付中!").setObj(startmap);
            }
        } catch (Exception e) {
            //进入其中的话就说明账号没有问题,是订单有问题,处理map里面返回的错误码
            String err_code = map.get("err_code");
            String err_msg = map.get("err_code_des");
            if(err_code.equals("USERPAYING")){
                //	USERPAYING--用户支付中,需要输入密码
                startmap.put("start",1);
                return jsonResult.setSuccess(true).setMsg(err_msg).setObj(startmap);
            }else if(err_code.equals("TRADE_ERROR")){
                // TRADE_ERROR--交易错误
                startmap.put("start",2);
                return jsonResult.setSuccess(true).setMsg(err_msg).setObj(startmap);
            }else if(err_code.equals("SYSTEMERROR")){
                // SYSTEMERROR--系统错误
                startmap.put("start",2);
                return jsonResult.setSuccess(true).setMsg(err_msg).setObj(startmap);

            }else if(err_code.equals("OUT_TRADE_NO_USED")){
                // OUT_TRADE_NO_USED--订单号重复
                startmap.put("start",2);
                return jsonResult.setSuccess(true).setMsg(err_msg).setObj(startmap);

            }else if(err_code.equals("ORDERNOTEXIST")){
                // ORDERNOTEXIST--订单不存在
                startmap.put("start",2);
                return jsonResult.setSuccess(true).setMsg(err_msg).setObj(startmap);

            }else if(err_code.equals("ORDER_CLOSED")){
                // ORDER_CLOSED--订单已关闭,当前订单已关闭,请重新下单
                startmap.put("start",2);
                return jsonResult.setSuccess(true).setMsg(err_msg).setObj(startmap);
            }else{
                startmap.put("start",2);
                return jsonResult.setSuccess(true).setMsg(err_msg).setObj(startmap);
            }
        }
        return jsonResult.setSuccess(false).setMsg("重新");
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值