微信PC扫码支付和微信H5支付

开发前准备工作:先设置微信公众号里的商户ID和微信商家里的商户ID保持一致,申请到公众平台的Appid,设置好回调域名

JAVA后台controller层的代码如下:

    /**
     * 微信PC和H5支付
     *
     * @return
     */
    @PostMapping("/createNative")
    @ApiOperation("微信支付,生成二维码,orderId订单ID,payType(1PC端,2是web端)")
    public DzResult createNative(String orderId, String payType) throws Exception {
        if (StringUtils.isBlank(orderId) || StringUtils.isBlank(payType)) {
            System.out.println("空参数-------------------->");
            return new DzResult().error(OrderCode.ERROR_PARAMS, "参数错误");
        }
        // 获取当前用户
        Claims claims = (Claims) request.getAttribute("authInfo");
        if (claims == null) {
            return new DzResult().error(OrderCode.NOT_LEGAL, "非法操作");
        }
        // 调用业务层查询订单信息
        CyOrder order = weixinPayService.findOrderByOrderId(orderId);
        if (order == null) {
            return new DzResult().error(OrderCode.ORDER_NOT_EXIST, "订单不存在");
        }
        if (!claims.getId().equals(order.getFrontUserId())) {
            return new DzResult().error(OrderCode.NOT_BELONG, "订单不属于当前用户");
        }
        // 商户订单号(用下划线后面数字为标识1:支付定金 2:支付尾款)
        BigDecimal totalAmount;
        // 将数据库价格去分
        BigDecimal mun = BigDecimal.valueOf(100);
        // 名称
        String subject;
        //设置商品详情参数
        HashMap<String, String> attach = new HashMap<>(16);
        // 订单号
        String outTradeNo = orderId;
        //订单号
        attach.put("outTradeNo", outTradeNo);
        //自定义参数
        String attachStr;
        //全款
        //微信是按分为单位,此处*100去分:
        totalAmount = order.getPayMoney().multiply(mun);
        subject = "呈衣全款支付";
        attach.put("subject", subject);
        //去掉小数点后的零
        attach.put("totalAmount", totalAmount.stripTrailingZeros().toPlainString());
        attachStr = JSONUtils.toJSONString(attach);
        Map map = weixinPayService.createNative(outTradeNo, totalAmount.stripTrailingZeros().toPlainString(), attachStr, payType);
        if (map == null) {
            return new DzResult().error(OrderCode.ORDER_WECAT_ERROR, "微信支付异常");
        }
        if ("FAIL".equals(map.get("return_code"))) {
            System.out.println("通讯异常");
            Object errorMsg = map.get("return_msg");
            return new DzResult().error(OrderCode.ORDER_WECAT_ERROR, errorMsg + "");
        }
        if ("FAIL".equals(map.get("result_code"))) {
            System.out.println("支付错误");
            Object errCode = map.get("err_code");
            Object errCodeDes = map.get("err_code_des");
            String errorMsg = errCode + "  :  " + errCodeDes;
            return new DzResult().error(OrderCode.ORDER_WECAT_ERROR, errorMsg + "");
        }
        boolean haveMwebUrl = map.containsKey("mweb_url");
        System.out.println("是否有拉起微信APP的路径:" + haveMwebUrl);
/*        if (haveMwebUrl) {
            String mwebUrl = map.get("mweb_url").toString();
            System.out.println("支付跳转链接:" + mwebUrl);
            //请求该url来拉起微信客户端
            weixinPayService.requestMwebUrl(mwebUrl);
        }*/
        return new DzResult().success(map);
    }

业务层调微信统一下单接口代码如下:

/**
 * 生成二维码
 */
@Override
public Map createNative(String outTradeNo, String totalFee, String attachStr, String payType) {
    System.out.println("进入生成二维码方法");

    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();

    //设置失效时间5分钟
    String expireTime = getOrderExpireTime(300 * 1000L);
    //1.创建参数
    HashMap<String, String> param = new HashMap<>(16);
    //公账号
    param.put("appid", WeChatPayConfig.app_id);
    //自定义参数(attach)
    param.put("attach", attachStr);
    //商品描述:商品名字
    param.put("body", "呈衣定制");
    //商户号
    param.put("mch_id", WeChatPayConfig.partner);
    //随机字符串
    param.put("nonce_str", WXPayUtil.generateNonceStr());
    //回调地址
    param.put("notify_url", WeChatPayConfig.notify_url);
    //订单号
    param.put("out_trade_no", outTradeNo);
    //ip,
    param.put("spbill_create_ip", getIpAddr(request));
    //设置失效时间5分钟
    param.put("time_expire", expireTime);
    //总金额(分)
    param.put("total_fee", totalFee);
    //1是PC  2 是webApp
    if ("1".equals(payType)) {
        //交易类型
        param.put("trade_type", "NATIVE");
    }
    if ("2".equals(payType)) {
        //交易类型
        param.put("trade_type", "MWEB");
        //支付场景,H5必填
        param.put("scene_info", "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"https://www.cyclothes.cn\",\"wap_name\": \"呈衣服装定制\"}}");
    }
    try {
        //2.生成要发送的xml,方法中传入签名
        String xmlParam = WXPayUtil.generateSignedXml(param, WeChatPayConfig.partner_key);
        System.out.println("调用微信的请求方法,请求的参数" + xmlParam);
        //请求的url地址
        HttpClient httpclient = new HttpClient(WeChatPayConfig.request_url);
        //是否是https协议
        httpclient.setHttps(true);
        //发送的xml数据
        httpclient.setXmlParam(xmlParam);
        //执行的请求方法
        httpclient.post();
        Map<String, String> returnMap = WXPayUtil.xmlToMap(httpclient.getContent());
        returnMap.put("out_trade_no", outTradeNo);
        returnMap.put("attach", attachStr);
        System.out.println("调用统一下单接口正常");
        return returnMap;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

微信异步通知代码如下:

  /**
     * 微信回调方法,被拦截器放行
     * 注意该回调方法要和微信配置中心中的回调方法保持一致
     *
     * @throws Exception
     */
    @PostMapping("/WeChatPayNotify")
    @ApiOperation("微信回调方法")
    public void weChatPayNotify() throws Exception {
        System.out.println("进入回调方法,核对订单信息");
        //读取参数
        InputStream inputStream;
        StringBuffer sbs = new StringBuffer();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sbs.append(s);
        }
        in.close();
        inputStream.close();
        //解析xml成map
        Map<String, String> map = WXPayUtil.xmlToMap(sbs.toString());
        if (map == null) {
            logger.info("支付异常");
            System.out.println("支付异常");
        }
        System.out.println("支付数据正常");
        String resXml = "";
        if (!"SUCCESS".equals(map.get("return_code"))) {
            Object errorMsg = map.get("return_msg");
            System.out.println("微信通信异常: " + errorMsg);
            logger.info("微信通信异常: " + errorMsg);
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[" + errorMsg + "]]></return_msg>" + "</xml>";
        }
        System.out.println("通讯正常");
        //自定义参数
        JSONObject attach = JSON.parseObject(map.get("attach"));
        String outTradeNo = (String) attach.get("outTradeNo");
        String subject = (String) attach.get("subject");
        String totalAmount = (String) attach.get("totalAmount");
        System.out.println("attach中获取的总金额" + totalAmount);
        String appid = map.get("appid");
        String tradeNo = map.get("out_trade_no");
        // 获取订单号以及交易类型(如果有)
        Map<String, String> checkMap = new HashMap<>(16);
        checkMap.put("out_trade_no", outTradeNo);
        // 创建参数校验载体Map
        checkMap.put("total_amount", totalAmount);
        checkMap.put("app_id", appid);
        String orderId = checkMap.get("out_trade_no");
        //获取验签参数
        SortedMap<Object, Object> packageParams = WeixinPayCommonUtil.isTrue(map);
        //验证签名是否成功
        boolean tenpaySign = WeixinPayCommonUtil.isTenpaySign("UTF-8", packageParams, WeChatPayConfig.partner_key);
        if (!tenpaySign) {
            // 校验参数
            System.out.println("验证签名失败");
            logger.info("验证签名失败");
        } else {
            // 校验参数
            weixinPayService.checkRequest(checkMap);
            if ("FAIL".equals(map.get("result_code"))) {
                Object errorMsg = map.get("return_msg");
                System.out.println("微信支付异常: " + errorMsg);
                logger.info("微信支付失败: " + errorMsg);
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[" + errorMsg + "]]></return_msg>" + "</xml> ";
            } else {
                System.out.println("通信成功");
                String mch_id = (String) packageParams.get("mch_id");
                String openid = (String) packageParams.get("openid");
                String is_subscribe = (String) packageParams.get("is_subscribe");
                String outTradeNo1 = (String) packageParams.get("out_trade_no");
                String totalFee = (String) packageParams.get("total_fee");
                //判断当前的订单是否已经处理
                boolean isHandle = weixinPayService.isHandle(orderId);
                String message;
                if (!isHandle) {
                    // 未处理,处理业务,修改状态
                    weixinPayService.updateStatus(orderId, tradeNo, totalAmount);
                    System.out.println("已处理支付业务...");
                    message = subject + ":支付成功,处理业务";
                    logger.info("message" + message);
                } else {
                    System.out.println("SUCCESS: 已处理支付业务,无需再次处理...");
                    message = subject + ":支付成功,已处理支付业务,无需再次处理";
//                    logger.info("mch_id:" + mch_id);//商户id
//                    logger.info("openid:" + openid);//用户标识
//                    logger.info("is_subscribe:" + is_subscribe);//是否关注公众号
                    logger.info("out_trade_no:" + outTradeNo1);
                    logger.info("total_fee:" + totalFee);
                    logger.info("message" + message);
                }
                logger.info("支付成功");
                //通知微信.异步确认成功.必写.不然会一直通知后台.10次之后就认为交易失败了.
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                System.out.println("支付成功结束");
            }
        }
        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }

注意:微信调用异步通知签名验证失败很有可能是partner_key(商户key)在商户品台中没设置,或者和代码中的没有保持一致导致的

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值