微信V3APP支付2022,全网最新+踩坑(已实现)

2年前 (2022) 程序员胖胖胖虎阿
223 0 0

前言

对于controller层 ,如果有几种支付类型,我们可以这样定义。

 //类型3为微信app支付 ,这里我们讲类型3

这里是service层的app支付调用的方法。


 前言

我觉得前两篇我没有把实战代码写上来,并且讲的有点乱,可能小伙伴们还是有点懵逼的,而且我找遍整个csdn,居然全是旧的代码,而且还有很多陷阱居然都不提醒一下萌新,为了大家不再饱受微信支付这个不明不白又麻烦的东西的折磨,我觉得我有必要再出一门,最新,尽量简洁详细的支付说明,并不是只有搞app支付可以看,搞其他的都可以看,比如我的第二篇已有对native支付的介绍,但是讲的有点乱。所以我才决定写此篇文章,如果大家实现了,请在评论区留言点赞收藏。

顺便说一下,最好就先有一点微信支付的基础在来看我的文章,因为这里我不会把所有的知识都讲一遍,可以先看我的第一篇和第二篇文章了解一下。

我也不想讲太多了,因为我相信你们已经看腻了,我直接上代码解释。

我先讲清楚微信支付的大坑

因为有的伙伴可能已经看了无数篇文章,改了无数次代码,其实很有可能你的代码是对的,但是因为某个坑的原因。如果是jdk1.8或者以前版本的,大家先别看代码了,先看这个大坑。

为了让文章看起来更清晰一点,我放到一个专门的文章。    

微信支付调起失败或者llegal key size解密大坑(已解决)

对于controller层 ,如果有几种支付类型,我们可以这样定义。

 /**
     * 支付接口
     */
    @RequestMapping(value = "/alipay/pay.action", method = RequestMethod.GET)
    public @ResponseBody
    MessageBean alipay(String userId, String money, String familyId, String userPhone, String type) throws Exception {
    //定义一个参数的接受类,方便封装参数传递。
        PayVo payVo = new PayVo();
        payVo.setUserId(userId);
        payVo.setUserPhone(userPhone);
        payVo.setMoney(money);
        payVo.setFamilyId(familyId);
        
    //类型1为支付宝

        if (type.equals("1") || type == "1") {
            PayReturnVo returnVo = alipayService.alipay(payVo);
            return MessageUtil.success(returnVo);
        } 

     //类型2为微信native支付
            else if (type.equals("2") || type == "2") {
            PayReturnVo returnVo = wxpayService.wxPay(payVo);
            return MessageUtil.success(returnVo);
        }

 //类型3为微信app支付 ,这里我们讲类型3
        else if (type.equals("3") || type == "3") {
//            WeChatPayAppDatas returnVo = wxpayService.appWxPay(payVo);
            JSONObject object = wxpayService.appWxPay(payVo);
            return MessageUtil.success(object);

        }


        return MessageUtil.failure("失败了");
    }

//类型3为微信app支付 ,这里我们讲类型3

这里是service层的app支付调用的方法。

我会把里面的方法都在下面一 、一的列举出来,方便你们cv和理解。

 /**
     * Wx-直接App支付
     *
     * @param payVo
     * @return
     */
    @Override
    public JSONObject appWxPay(PayVo payVo) throws Exception {

        //  捐赠的订单流水编号  (在后面我有写把这个工具类代码写上) 
        String orderNumber = GenerateNumUtil.generateOrder();


        // 1:封装请求参数
        Map<String, Object> map = new HashMap();
        map.put("mchid", WechatPayConfig.mchId);
        map.put("appid", WechatPayConfig.appId);
        map.put("out_trade_no", orderNumber);
        map.put("description", "微信支付捐款");
        map.put("notify_url", WechatPayConfig.notifyUrl);


//这个参数微信文档有,是一个对象来的.
        Map<String, Object> amount = new HashMap();

        //订单金额 单位分                (在后面我有写把这个工具类代码写上) 
        amount.put("total", Integer.parseInt(WechatPayUtils.getMoney(payVo.getMoney())));        
        amount.put("currency", "CNY");
        map.put("amount", amount);

        // 附属参数
        Map<String, Object> attachMap = new HashMap();
        attachMap.put("userId", payVo.getUserId());
        attachMap.put("orderNumber", orderNumber);
        attachMap.put("price", payVo.getMoney());
        attachMap.put("userPhone", payVo.getUserPhone());
        map.put("attach", JSONUtils.obj2String(attachMap));
       

        // 2:转换成json字符串,开始微信支付请求
        ObjectMapper objectMapper = new ObjectMapper();
        String body = null;
        try {
            body = objectMapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        //随机字符串,不长于32位。推荐随机数生成算法。(在后面我有写把这个工具类代码写上) 
        String nonce_str = WechatPayUtils.getNonceStr();


        // 3:请求统一微信-拉取app下单接口
        Map<String, Object> stringObjectMap = HttpUtils.doPost(WechatPayConfig.appUnifiedOrderUrl, body);


        // 4:定制前端需要的返回数据
        String prepay_id = stringObjectMap.get("prepay_id").toString();

    
        //拿到prepay_id ,去实现app的调起APP支付,也就是跳转到微信进行支付。
        JSONObject object = WechatPayUtils.WxTuneUp(prepay_id, WechatPayConfig.appId);
        //传入上面生成的订单号
        object.put("orderNumber",orderNumber);

        System.out.println("获取的预支付订单号:" +prepay_id);

        System.out.println("封装的object数据是:"+object.toString());
    //至此,如果你代码没错的话,就可以完成唤醒微信,然后进行支付的。但是支付成功后,是有回调的
//你们看了这么多,或者看了我前面的文章,我就不解释了,后面我们开始讲回调的代码.
        return object;
    }

看不懂方法代表什么没关系,下面会每一个调用的方法。

   //  捐赠的订单流水编号 
        String orderNumber = GenerateNumUtil.generateOrder();

/**
 * 根据时间生成随机订单号
 * 雪花算法
 */
public class GenerateNumUtil {
    // 全局自增数
    private static int count = 0;

    // 每毫秒秒最多生成多少订单(最好是像9999这种准备进位的值)
    private static final int total = 99;

    // 格式化的时间字符串
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

    // 获取当前时间年月日时分秒毫秒字符串
    private static String getNowDateStr() {
        return sdf.format(new Date());
    }

    // 记录上一次的时间,用来判断是否需要递增全局数
    private static String now = null;

    /*
    * 生成一个订单号
    * 雪花算法
    */

    public static String generateOrder() {
        String datastr = getNowDateStr();
        if (datastr.equals(now)) {
            count++;// 自增
        } else {
            count = 1;
            now = datastr;
        }
        int countInteger = String.valueOf(total).length() - String.valueOf(count).length();// 算补位
        String bu = "";// 补字符串
        for (int i = 0; i < countInteger; i++) {
            bu += "0";
        }

        bu += String.valueOf(count);
        if (count >= total) {
            count = 0;
        }
        return datastr + bu;
    }

}

上面出现的方法如果是 WechatPayUtils调用的,那都在下面。需要的工具类里面自己找哈  ctrl+f ,直接查,拿来用就好了。

 我们先来看这一行代码
        // 3:请求统一微信-拉取app下单接口

第一次请求微信支付,生成token签名信息,返回prepay_id

也就是上面的这一行代码
        Map<String, Object> stringObjectMap = HttpUtils.doPost(WechatPayConfig.appUnifiedOrderUrl, body);

public static Map<String, Object> doPost(String url, String body) throws Exception {
    //httpClient 即初始化微信客服端,那么有什么用呢,下面这个代码相信你看中文可以看懂吧
    //意思就是 用这个客服端去执行, 那么执行什么呢,当然是执行我们放入的参数httpPost啦!
      httpClient.execute(httpPost);
      CloseableHttpClient httpClient = HttpClients.createDefault();
    
        //new一个http 的post方法。get为这样  HttpGet httpget = new HttpGet(url);
   // 这些微信V3文档都是有的,链接在下面   //https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay2_0.shtml

        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/json;chartset=utf-8");
        httpPost.addHeader("Accept", "application/json");


        try {
            /* body为我们的参数,url是我们的app下单接口地址,也就 
          是"https://api.mch.weixin.qq.com/v3/pay/transactions/app"

          getToken的目的是为了签名
        签名是什么可以看我第一篇文章.  http://t.csdn.cn/YzeVf

      下面这链接是微信签名的文档,                              
      https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml   */

        //这个方法,下面的WechatPayUtils工具类有。
       String token = WechatPayUtils.getToken("POST", new URL(url), body);

            //设置http头   Authorization: 认证类型 签名信息
       httpPost.setHeader("Authorization", "WECHATPAY2-SHA256-RSA2048 " + token);

            if (body == null) {
                throw new IllegalArgumentException("data参数不能为空");
            }
            StringEntity stringEntity = new StringEntity(body, "utf-8");
            httpPost.setEntity(stringEntity);

            CloseableHttpResponse httpResponse =  httpClient.execute(httpPost);

    //获得请求体信息,也就是返回的参数,特点是调起支付的prepay_id也在里面
            HttpEntity httpEntity = httpResponse.getEntity();

            //响应状态码
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            //响应体
            String jsonResult = EntityUtils.toString(httpEntity);
            if (statusCode == 200) {

                //处理成功
                System.out.println("成功, 返回结果 = " + jsonResult);
                return JSON.readValue(jsonResult, HashMap.class);
            } else if (statusCode == 204) {
                //处理成功,无返回Body
                System.out.println("处理成功,无返回Body");
            } else {
                System.out.println("Native下单失败,响应码 = " + statusCode + ",返回结果 = " + jsonResult);
                System.err.println("微信支付错误信息" + EntityUtils.toString(httpEntity));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;

    }

WechatPayUtils工具类的代码


public class WechatPayUtils {


    /**
     * 元转换成分
     * 微信传输金额以分为单位,需转换 
     *
     * @param money
     * @return
     */          
    //对应上面的代码  
// amount.put("total", Integer.parseInt(WechatPayUtils.getMoney(payVo.getMoney())));


    public static String getMoney(String money) {
        if (money == null || money.equalsIgnoreCase("0")) {
            return "";
        }
        // 金额转化为分为单位
        // 处理包含, ¥ 或者$的金额
        String currency = money.replaceAll("\\$|\\¥|\\,", "");
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0L;
        if (index == -1) {
            amLong = Long.valueOf(currency + "00");
        } else if (length - index >= 3) {
            amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
        } else if (length - index == 2) {
            amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
        } else {
            amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
        }
        return amLong.toString();
    }

   
    /**
     * 获取私钥。(因为私钥需要通过商户证书来获取)
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    //有两种方法。
                        方法一,也是最新版的。推荐用这个。


# 示例:私钥存储在文件
 public static PrivateKey getPrivateKey(String filename) throws IOException {
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
            //如果是把项目放到服务器上,那就是服务器的/为开始(根目录开始)
            //也就是 你输入命令 pwd   显示的目录

        new FileInputStream("存放位置"));

}



                            方法二

    public static PrivateKey getPrivateKey(String filename) throws IOException {
        System.out.println("filename:" + filename);
        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }



    /**
     * 生成token 把请求地址URL和参数进行加密处理
     * 为什么要签名:对请求参数和请求地址进行加密
     *
     * @param method
     * @param url
     * @param body
     * @return
     * @throws Exception
     */
    public static String getToken(String method, URL url, String body) throws Exception {
       //下面有这个方法,生成随机数
        String nonceStr = getNonceStr();
    
        long timestamp = System.currentTimeMillis() / 1000;

//下面有这个buildMessage 构成签名串的方法
        String message = buildMessage(method, url, timestamp, nonceStr, body);

    //下面有这个sign计算签名的方法
        String signature = sign(message.getBytes("utf-8"));

        return  "mchid=\"" + WechatPayConfig.mchId + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + WechatPayConfig.mchSerialNo + "\","
                + "signature=\"" + signature + "\"";
    }



    /**
     * 生成签名
     *
     * @param message
     * @return
     * @throws Exception
     */
    public static String sign(byte[] message) throws Exception {
        Signature sign = Signature.getInstance("SHA256withRSA");
        // 商户私钥
        sign.initSign(WechatPayConfig.privateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    /**
     * 生成签名串
     *
     * @param method
     * @param url
     * @param timestamp
     * @param nonceStr
     * @param body
     * @return
     */
    public static String buildMessage(String method, URL url, long timestamp, String nonceStr, String body) {
//        第二步,获取请求的绝对URL,并去除域名部分得到参与签名的URL。如果请求中有查询参数,URL末尾应附加有'?'和对应的查询字符串。
        String canonicalUrl = url.getPath();
        if (url.getQuery() != null) {
            canonicalUrl += "?" + url.getQuery();
        }
        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

    /**
     * 生成随机数
     *
     * @return
     */
    public static String getNonceStr() {
        return UUID.randomUUID().toString()
                .replaceAll("-", "")
                .substring(0, 32);
    }

    /**
     * 获取平台证书
     *
     * @return
     */
        //推荐使用微信支付提供的SDK。你也可以查看下列编程语言的示例代码。
    public static Map<String, X509Certificate> refreshCertificate() throws Exception {
        Map<String, X509Certificate> certificateMap = new HashMap();
        // 1: 执行get请求
        JsonNode jsonNode = HttpUtils.doGet(WechatPayConfig.certificatesUrl);
        // 2: 获取平台验证的相关参数信息
        JsonNode data = jsonNode.get("data");
        if (data != null) {
            for (int i = 0; i < data.size(); i++) {
                JsonNode encrypt_certificate = data.get(i).get("encrypt_certificate");
                //对关键信息进行解密
                AesUtil aesUtil = new AesUtil(WechatPayConfig.v3Key.getBytes());
                String associated_data = encrypt_certificate.get("associated_data").toString().replaceAll("\"", "");
                String nonce = encrypt_certificate.get("nonce").toString().replaceAll("\"", "");
                String ciphertext = encrypt_certificate.get("ciphertext").toString().replaceAll("\"", "");
                //证书内容
                String certStr = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
                //证书内容转成证书对象
                CertificateFactory cf = CertificateFactory.getInstance("X509");
                X509Certificate x509Cert = (X509Certificate) cf.generateCertificate(
                        new ByteArrayInputStream(certStr.getBytes("utf-8"))
                );
                String serial_no = data.get(i).get("serial_no").toString().replaceAll("\"", "");
                certificateMap.put(serial_no, x509Cert);
            }
        }
        return certificateMap;
    }

  


    /**
     * 构造签名串
     *
     * @param signMessage 待签名的参数
     * @return 构造后带待签名串
     */
    static String buildSignMessage(ArrayList<String> signMessage) {
        if (signMessage == null || signMessage.size() <= 0) {
            return null;
        }
        StringBuilder sbf = new StringBuilder();
        for (String str : signMessage) {
            sbf.append(str).append("\n");
        }
        return sbf.toString();
    }


    /*
    *  获取appid后,调起支付
    */

    public static JSONObject WxTuneUp(String prepay_id, String appId) throws Exception {

        String time = System.currentTimeMillis() / 1000 + "";
        
        String noncestr = UUID.randomUUID().toString().replace("-", "");
//或者   String noncestr = getNonceStr() ;


        ArrayList<String> list = new ArrayList<>();
        list.add(appId);
        list.add(time);
        list.add(noncestr);
        list.add(prepay_id);

        //二次签名,调起支付需要重新签名,注意这个是buildSignMessage()

        String packageSign = sign(buildSignMessage(list).getBytes());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appid", appId);
        jsonObject.put("partnerid", WechatPayConfig.mchId);
        jsonObject.put("prepayid", prepay_id);
        jsonObject.put("package", WechatPayConfig.PACKAGE);
        jsonObject.put("noncestr", noncestr);
        jsonObject.put("timestamp", time);
        jsonObject.put("signtype", "RSA");
        jsonObject.put("sign", packageSign);


        return jsonObject;
    }


    /**
<<<<<<< HEAD
     * 处理返回的回调对象
     *
     * @param request
     * @return
     */
    public static String readData(HttpServletRequest request) {
        BufferedReader br = null;
        try {
            StringBuilder result = new StringBuilder();
            br = request.getReader();
            for (String line; (line = br.readLine()) != null; ) {
                if (result.length() > 0) {
                    result.append("\n");
                }
                result.append(line);
            }
            return result.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static Verifier getVerifier() throws Exception {

// 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();


// 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(WechatPayConfig.mchId, new WechatPay2Credentials(WechatPayConfig.mchId,
                new PrivateKeySigner(WechatPayConfig.mchSerialNo, WechatPayConfig.privateKey)), WechatPayConfig.v3Key.getBytes(StandardCharsets.UTF_8));


// 从证书管理器中获取verifier
        Verifier verifier = certificatesManager.getVerifier(WechatPayConfig.mchId);


        return verifier;
    }


    //这个接口也是最新的,自动签名和验签,也非常方便,不过这篇文章我没用,如果你要用,可以这样。
//  httpClient.execute(httpPost);  ,把这个httpClient 客服端直接换成这个就好了

//比如把 httpClient.execute(httpPost); 换成 WechatPayUtils.getWxPayClient(Verifier verifier).execute(httpPost);  就好了。 

    public static CloseableHttpClient getWxPayClient(Verifier verifier) throws IOException {

        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(WechatPayConfig.mchId, WechatPayConfig.mchSerialNo, WechatPayConfig.privateKey)
                .withValidator(new WechatPay2Validator(verifier));

        // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();

        return httpClient;
    }





}

大家最讨厌的回调来啦 ,里面有  "回调验签和解密超简单代码"

 @ResponseBody
    @RequestMapping(value = "/wxpay/notifyUrl", method = RequestMethod.POST)
    public String wxPayCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {

        Gson gson =new Gson();
        String body =WechatPayUtils.readData(request);
        String serialNumber = request.getHeader("Wechatpay-Serial");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String signature = request.getHeader("Wechatpay-Signature");
        Map<String,String> map =new HashMap<>();

        // 回调验签和解密 ,这个是最新的sdk方法,全网找不到几个用这个方法,所以大家可能有点陌生
//https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient  不信在文档这看
    
//我的微信第二篇文章有解释说明,这里不解释了.
    
        NotificationRequest Nrequest = new NotificationRequest.Builder().withSerialNumber(serialNumber)
                .withNonce(nonce)
                .withTimestamp(timestamp)
                .withSignature(signature)
                .withBody(body)
                .build();

        NotificationHandler handler = new NotificationHandler(WechatPayUtils.getVerifier(), WechatPayConfig.v3Key.getBytes(StandardCharsets.UTF_8));

//JSON.parseObject,是将Json字符串转化为相应的对象;JSON.toJSONString则是将对象转化为Json字符串.用 Gson.toJson也行


        try {
            // 验签和解析请求体
            Notification  notification = handler.parse(Nrequest);

            // 从notification中获取解密报文。
            String plainText = notification.getDecryptData();

              //把密文变成map,方便拿取
           Map resultMap =gson.fromJson(plainText,HashMap.class);
            log.info("验签成功");
            
            //下面就处理业务逻辑,我就不把代码放出来了,你想怎样处理就怎样.
            if (wxpayService.payRecord(resultMap)) {
                response.setStatus(200);
                map.put("code", "SUCCESS");
                map.put("message", "成功");
                log.info("入库成功");

            }
            //成功应答
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return gson.toJson(map);
        } catch (Exception e) {
            log.error("验签失败");

            //应答失败
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "验签失败");
            return gson.toJson(map);
        }

    }

基本配置类

@Data
public class WechatPayConfig {
    /**
     * 微信商户号
     */
    public static String mchId = "";

            /**
             *  微信开放平台的APPID
        * */
    public static String appId = "";
    /**
     * 回调报文解密V3密钥key
     */
    public static String v3Key = "";

    /**
     * 微信获取平台证书列表地址
     */
    public static String certificatesUrl = "https://api.mch.weixin.qq.com/v3/certificates";

    /**
     * 微信Native下单URL
     */
    public static String unifiedOrderUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/native";

    /**
     * 微信App下单URL
     */
    public static String appUnifiedOrderUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/app";

    /**
     * 微信小程序的单URL
     */
    public static String unifiedOrderUrlJS;

    /**
     * 异步接收微信支付结果通知的回调地址
     */


    public static String notifyUrl = "";

    /**
     * 微信证书私钥
     */
    public static PrivateKey privateKey;



    public static String PACKAGE="Sign=WXPay";



    static {
        try {

            privateKey = WechatPayUtils.getPrivateKey("证书放的地址");

    /**
     * logo
     */
    /*    public static String logo;*/

    /**
     * 微信商家api序列号
     */
    public static String mchSerialNo = "";

    // 定义全局容器 保存微信平台证书公钥
    public static Map<String, X509Certificate> certificateMap = new ConcurrentHashMap<>();

HttpUtils的工具类

package com.tuorong.family.common.pay.wx_pay.utils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.net.URL;
import java.util.HashMap;
import java.util.Map;


public class HttpUtils {
    private static final ObjectMapper JSON = new ObjectMapper();

    /**
     * get方法
     *
     * @param url
     * @return
     */
    public static JsonNode doGet(String url) {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpget = new HttpGet(url);
        httpget.addHeader("Content-Type", "application/json;charset=UTF-8");
        httpget.addHeader("Accept", "application/json");
        try {
            String token = WechatPayUtils.getToken("GET", new URL(url), "");
            httpget.addHeader("Authorization", token);
            CloseableHttpResponse httpResponse = httpClient.execute(httpget);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {

                String jsonResult = EntityUtils.toString(httpResponse.getEntity());
                return JSON.readTree(jsonResult);
            } else {
                System.err.println(EntityUtils.toString(httpResponse.getEntity()));
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    /**
     * 封装post
     *
     * @return
     */
    public static Map<String, Object> doPost(String url, String body) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/json;chartset=utf-8");
        httpPost.addHeader("Accept", "application/json");
        try {
            // 1:发起微信支付的真正请求
            String token = WechatPayUtils.getToken("POST", new URL(url), body);
//            httpPost.addHeader("Authorization", token);
            httpPost.setHeader("Authorization",
                    "WECHATPAY2-SHA256-RSA2048 " + token);

            if (body == null) {
                throw new IllegalArgumentException("data参数不能为空");
            }
             构建消息实体
            StringEntity stringEntity = new StringEntity(body, "utf-8");
            httpPost.setEntity(stringEntity);
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();

            //响应状态码
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            //响应体
            String jsonResult = EntityUtils.toString(httpEntity);
            if (statusCode == 200) {

                //处理成功
                System.out.println("成功, 返回结果 = " + jsonResult);
                return JSON.readValue(jsonResult, HashMap.class);
            } else if (statusCode == 204) {
                //处理成功,无返回Body
                System.out.println("处理成功,无返回Body");
            } else {
                System.out.println("Native下单失败,响应码 = " + statusCode + ",返回结果 = " + jsonResult);
                System.err.println("微信支付错误信息" + EntityUtils.toString(httpEntity));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;

    }
 

   
}

好啦,我觉得我应该把所有的东西都列出来了,如果少了什么,请麻烦在评论区告诉我。

相关文章

暂无评论

暂无评论...