微信app支付-java后端(从注册到調微信app生成预支付订单号,使用的是微信V2版本接口文档)

由于公司自己的app,需要接入微信app支付,我使用的是微信支付V2版本,有V3版本

一丶在微信开放平台认证开发者资质认证(以公司的身份)。 交300元,有专门的给审核,第一次审核没过,补交资料申请公函,打款凭证(验证公司对公账户)

 

二、审核通过后,创建移动应用,(也要审核,人工审核、检查你的官网,应用类目(这里自己新增就是)) 得到 appId,

注意:应用签名(32位的MD5)和包名,只有正确才能拉起微信app的收银台,之前调试调起微信支付接口时 一直报-1

 

 

 

三、在商户平台成为商家得到商户号,在开放平台的app管理管理自己的商户号。同时设置商户平台api验签的秘钥

 

四。下载微信sdk

配置 appId,商户号,api验签密钥, 

五。后台创建微信预付订单后将预付订单再次加密给前段。就可以了

  1.调用微信sdk生成预付订单

       
        Map<String, String> data = new HashMap<>();
        WXPay wxPay = new WXPay(this, true);   // 微信sdk this里面配置了appId,商户号,api密钥 
         // this 继承了微信提供了 WXPayConfig
        data.put("appid", this.appId);
        data.put("mch_id", this.mchId);
        String firstNonce = WXPayUtil.generateNonceStr();

        data.put("nonce_str", firstNonce);
        data.put("body", body);
        data.put("out_trade_no", String.valueOf(orderId));
        String total_fee = String.valueOf(price.multiply(new BigDecimal(100)).intValue());
        data.put("total_fee", total_fee); // 金额分
        data.put("attach", num.toString()); // 附加数据
        data.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress()); // 调用微信支付API的机器IP
        data.put("notify_url", notifyUrl); // 回调地址
        data.put("trade_type", "APP"); // 支付方式
        data.put("sign", WXPayUtil.generateSignature(data, key)); // 签名微信的sdk,签名有问题,会多次覆盖这个sign,我将sdk的签名注释了
        Map<String, String> response = wxPay.unifiedOrder(data);


// 自己的订单记录
   /*
          处理的自己的业务逻辑,生成自己的业务订单
         */


        ConsumeHistoryEntity consumeHistoryEntity = new ConsumeHistoryEntity();
        consumeHistoryEntity.setPrice(price);  // 总价
        consumeHistoryEntity.setStatus(0);  // 未支付
        consumeHistoryEntity.setTitle(body); // 标题
        consumeHistoryEntity.setOrderId(orderId); // 订单号
        consumeHistoryEntity.setId(orderId);
        if (Objects.nonNull(userEntity))
            consumeHistoryEntity.setUserId(userEntity.getId());
//        consumeHistoryEntity.setUserId(64L); // 测试写死
        consumeHistory.save(consumeHistoryEntity);  // 插入数据库

微信的sdk会重新再次签名了。我将sdk注释了。

 

 

 

2.将微信生成的预支付订单,再次签名返回给前段

 

       
        // 统一下单生成的预支付订单
        Map<String, String> response = wxPay.unifiedOrder(data);

        String appid = response.get("appid"); //appId
        String partnerid = getMchID();  // 商户号
        String prepayid = response.get("prepay_id"); // 预支付单号
        String packageValue = "Sign=WXPay";
        String noncestr = WXPayUtil.generateNonceStr();  // 随机字符串
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000); // 10的时间戳
        Map<String, String> returnApp = new TreeMap<>();
        returnApp.put("appid", appid);
        returnApp.put("partnerid", partnerid);
        returnApp.put("prepayid", prepayid);
        returnApp.put("package", packageValue);
        returnApp.put("noncestr", noncestr);
        returnApp.put("timestamp", timestamp);
        returnApp.put("sign", WXPayUtil.generateSignature(returnApp, this.key)); // 签名
        // 查询业务支付订单,不参与签名,orderId 是前段实际查询支付状态
        returnApp.put("oderId", String.valueOf(orderId));
        return ResponseEntity.success(returnApp);

 

 

3.前端接收参数,调用sdk就能拉取微信收银台

4.拉取微信收银台

 

六丶 支付结果通知(在微信创建预付订单配置了回调地址。我用的ngrok将内网映射出去),由于微信返回来的是xml

 

 

    @RequestMapping("weixinCallback")
    public String weixinCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {

        try {
            //读取参数
            int len = request.getContentLength();
            ServletInputStream in = request.getInputStream();
            byte[] buffer = new byte[len];
            in.read(buffer, 0, len);
            String data = new String(buffer, "utf-8");
            in.close();
            HashMap<String, String> map = new HashMap<>();
            //解析xml成map
            Map<String, String> result = WXPayUtil.xmlToMap(data);
            if (!result.get("return_code").equals(WXPayConstants.SUCCESS)){
                map.put("return_code","FAIL");
                map.put("return_msg","");
                return wxService.mapToXml(map);
            }
            if(wxService.isPayResultNotifySignatureValid(result)){
                ///----------------------/ 修改订单支付状态
                String out_trade_no = result.get("out_trade_no"); // 商户订单编号
                String attach = result.get("attach"); // 商户订单编号
                String appId = result.get("appid"); // 商户订单编号
                String transaction_id = result.get("transaction_id"); // 微信支付订单号
                String total_fee = result.get("total_fee");   // 实际支付金额
                ConsumeHistoryEntity consumeHistoryById = consumeHistory.getById(out_trade_no);
                if(Objects.nonNull(consumeHistoryById)){
                    BigDecimal price = consumeHistoryById.getPrice();
                    BigDecimal wxPrice = new BigDecimal(total_fee).divide(new BigDecimal(100));

                    /**  支付宝验签
                     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
                     * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
                     * 3、校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
                     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
                     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
                     * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
                     *
                     */
                  // 我的判断逻辑是,该订单的支付状态为0,价格与数据相等, appId相等
                    if(consumeHistoryById.getStatus() == 0 && wxPrice.equals(price) && wxService.getAppID().equals(appId) ){
                        //订单支付成功
                      // 实际的业务逻辑
                      // TODO
                    
                    }
                    map.put("return_code","SUCCESS");
                    map.put("return_msg","OK");
                    return wxService.mapToXml(map);
                }
                //-----/
            }else {
                log.error("非法回调,验签失败:"+ result);
                map.put("return_code","FAIL");
                map.put("return_msg","");
                return wxService.mapToXml(map);
            }
            map.put("return_code","FAIL");
            map.put("return_msg","");
            return wxService.mapToXml(map);
        } catch (Exception ex) {
            HashMap<String, String> map = new HashMap<>();
            map.put("return_code", "FAIL");
            map.put("return_msg", ex.getMessage());
            return wxService.mapToXml(map);
        }

    }

支付成功验签:

/**  支付宝验签
 * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
 * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
 * 3、校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
 * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
 * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
 * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
 *
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值