微信支付V3-调用API接口(使用Get和Post请求)

本文详细介绍了微信支付V3中如何使用Get和Post请求调用API,包括证书管理、统一下单及订单查询的实现过程。文章强调了使用Post请求的优化,推荐使用cn.hutool.http.HttpUtil工具类进行请求,并讨论了服务端防止订单重复支付的策略。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

收藏好,1套视频搞定,支付宝&微信支付

证书

在这里插入图片描述

Get/Post请求微信API,以及sign加密

public class PayUtils {


    private final static String SERIAL_NO = "xxx";

    private final static String MCHID = "xxx";

    private static final String SCHEMA = "xxx";
// sendGet请求
    public static  String sendGet(String url,String sign) throws URISyntaxException {
        /** 获取连接客户端工具 **/
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String entityStr = null;
        CloseableHttpResponse response = null;
        try {

            /** 由于GET请求的参数都是拼装在URL地址后方,所以我们要构建一个URL,带参数 **/
            URIBuilder uriBuilder = new URIBuilder(url);

            /** 根据带参数的URI对象构建GET请求对象 **/
            HttpGet httpGet = new HttpGet(uriBuilder.build());

            /** 添加请求头信息 **/
            httpGet.addHeader("Accept", "application/json");
            httpGet.addHeader("Authorization", SCHEMA + " " + sign );
            /** 传输的类型 **/
            httpGet.addHeader("Content-Type", "application/json");

            /** 执行请求 **/
            response = httpClient.execute(httpGet);

            /** 获得响应的实体对象 **/
            HttpEntity entity = response.getEntity();
            entityStr = EntityUtils.toString(entity);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return entityStr;
    }
// sendPost请求
    public static String sendPost(String url, String param, String sign) {

        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("Accept", "application/json");
            conn.setRequestProperty("Content-Type", "application/json");

//            conn.setRequestProperty("Charsert", "utf-8");
            conn.setRequestProperty("Authorization", SCHEMA + " " + sign);

            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }
    //HttpUrl httpurl = HttpUrl.parse(url);
//getToken
    public static String getToken(String method, HttpUrl url, String body) throws Exception {
        //32位随机字符串
        String nonceStr = UUID.randomUUID().toString().replace("-", "").toString();
        long timestamp = System.currentTimeMillis() / 1000;
        //生成签名支付串--加密前
        String message = buildMessage(method, url, timestamp, nonceStr, body);

        String signature = sign(message.getBytes("utf-8"));


        return "mchid=\"" + MCHID + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + SERIAL_NO + "\","
                + "signature=\"" + signature + "\"";
    }
//需要sign加密
    public static String sign(byte[] message) throws Exception {
        Signature sign = Signature.getInstance("SHA256withRSA");
        //需要通过密钥加密
        PrivateKey privateKey = PemUtil.loadPrivateKey(new FileInputStream("证书放置的路径/src/main/resources/apiclient_key.pem"));

        sign.initSign(privateKey);  //密钥
        sign.update(message);

        return Base64.getEncoder().encodeToString(sign.sign());
    }

    public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }

        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }
}

统一下单

  • Controller
@RestController
public class WXPayController {
    @Resource
    PayService payService;
    @RequestMapping("/pay")
    public R pay(@RequestBody PayInfo payInfo) throws Exception {
        return payService.pay(payInfo);
    }
}
  • Service
@Service
@PropertySource("classpath:pay.properties")
public class PayServiceImpl implements PayService {

    @Value("${mchId}")
    private String mchId;

    @Value("${appId}")
    private String appId;

    @Value("https://weixin.qq.com/")
    private String notify_url;

    @Value("https://api.mch.weixin.qq.com/v3/pay/transactions/h5")
    private String pay_url;

    private Amount amount;

    private Scene_info scene_info;

    @Override
    public R pay(PayInfo payInfo) throws Exception {

        Map<String, Object> paraMap = new HashMap<String, Object>();
        amount = new Amount(payInfo.getTotal(), "CNY");
        scene_info = new Scene_info(payInfo.getPayer_client_ip(), new H5_info("Wap"));

        paraMap.put("mchid", mchId);
        paraMap.put("out_trade_no", payInfo.getOut_trade_no());
        paraMap.put("appid", appId);
        paraMap.put("description", payInfo.getDescription());
        paraMap.put("notify_url", notify_url);
        paraMap.put("amount", amount);
        paraMap.put("scene_info", scene_info);
        String body = JSON.toJSONString(paraMap);
        HttpUrl httpUrl = HttpUrl.get(pay_url);

        String sign = PayUtils.getToken("POST",httpUrl,body);
        String result = PayUtils.sendPost(pay_url, body, sign);
        String url = null;
        if (result.indexOf("h5_url") != -1) {
           url = (String)JSON.parse(result);
        }else {}
        return R.ok();
    }
}

订单查询

  • Controller
@RestController
@RequestMapping("/pay")
public class PayOrderQueryController {
    @Resource
    OrderQueryPayService orderQueryPayService;

    @RequestMapping(value = "/orderquery")
    public String orderQuery(String outTradeNo) {
        return orderQueryPayService.orderQuery(outTradeNo);
    }
}
  • Service
@Service
@Slf4j
public class OrderQueryPayServiceImpl implements OrderQueryPayService {

    @Override
    public String orderQuery(String outTradeNo) {
        String tradeState = null;
        String body = "";
        String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + outTradeNo + "?mchid=" + "1499322742";
        HttpUrl httpUrl = HttpUrl.get(url);
        try {
            String sign = PayUtils.getToken("GET", httpUrl, body);
            String result = sendGet(url, sign);
            log.info("springboot系统-------微信返回字符串数据:" + result);
            if (null == result || result.equals("") || result.isEmpty()) {
            } else {
                Map<String, Object> parseObject = JSONObject.parseObject(result, Map.class);
                tradeState = String.valueOf(parseObject.get("trade_state"));//交易状态
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tradeState;
    }
}

优化post请求(使用cn.hutool.http.HttpUtil;)

    public static String sendPost(String url, String param, String sign) {

        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
 //       try {
//            URL realUrl = new URL(url);

//            // 打开和URL之间的连接
//            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性

            Map<String, Object> map = new HashMap<>();//存放参数
            map.put("param", param);
            HashMap<String, String> headers = new HashMap<>();//存放请求头,可以存放多个请求头
            headers.put("Accept", "application/json");
            headers.put("Content-Type", "application/json");
            headers.put("Authorization", SCHEMA + " " + sign);


            //发送post请求并接收响应数据
             result= HttpUtil.createPost(url).addHeaders(headers).body(param).execute().body();


//            conn.setRequestProperty("Accept", "application/json");
//            conn.setRequestProperty("Content-Type", "application/json");

//            conn.setRequestProperty("Charsert", "utf-8");
//            conn.setRequestProperty("Authorization", SCHEMA + " " + sign);
//
//            // 发送POST请求必须设置如下两行
//            conn.setDoOutput(true);
//            conn.setDoInput(true);
//            // 获取URLConnection对象对应的输出流
//            out = new PrintWriter(conn.getOutputStream());
//            // 发送请求参数
//            out.print(param);
//            // flush输出流的缓冲
//            out.flush();
//            // 定义BufferedReader输入流来读取URL的响应
//            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
//            String line;
//            while ((line = in.readLine()) != null) {
//                result += line;
//            }
//        } catch (Exception e) {
//            System.out.println("发送 POST 请求出现异常!" + e);
//            e.printStackTrace();
//        }
//        //使用finally块来关闭输出流、输入流
//        finally {
//            try {
//                if (out != null) {
//                    out.close();
//                }
//                if (in != null) {
//                    in.close();
//                }
//            } catch (IOException ex) {
//                ex.printStackTrace();
//            }
//        }
        return result;
    }

推荐使用Post请求

    public static String WXsendPost(String url, String param, String sign) {

        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
 //       try {
//            URL realUrl = new URL(url);

//            // 打开和URL之间的连接
//            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性

            Map<String, Object> map = new HashMap<>();//存放参数
            map.put("param", param);
            HashMap<String, String> headers = new HashMap<>();//存放请求头,可以存放多个请求头
            headers.put("Accept", "application/json");
            headers.put("Content-Type", "application/json");
            headers.put("Authorization", SCHEMA + " " + sign);



            //发送post请求并接收响应数据


             result= HttpUtil.createPost(url).addHeaders(headers).body(param).execute().body();


//            conn.setRequestProperty("Accept", "application/json");
//            conn.setRequestProperty("Content-Type", "application/json");

//            conn.setRequestProperty("Charsert", "utf-8");
//            conn.setRequestProperty("Authorization", SCHEMA + " " + sign);
//
//            // 发送POST请求必须设置如下两行
//            conn.setDoOutput(true);
//            conn.setDoInput(true);
//            // 获取URLConnection对象对应的输出流
//            out = new PrintWriter(conn.getOutputStream());
//            // 发送请求参数
//            out.print(param);
//            // flush输出流的缓冲
//            out.flush();
//            // 定义BufferedReader输入流来读取URL的响应
//            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
//            String line;
//            while ((line = in.readLine()) != null) {
//                result += line;
//            }
//        } catch (Exception e) {
//            System.out.println("发送 POST 请求出现异常!" + e);
//            e.printStackTrace();
//        }
//        //使用finally块来关闭输出流、输入流
//        finally {
//            try {
//                if (out != null) {
//                    out.close();
//                }
//                if (in != null) {
//                    in.close();
//                }
//            } catch (IOException ex) {
//                ex.printStackTrace();
//            }
//        }
        return result;
    }
服务端如何防止订单重复支付!

服务端如何防止订单重复支付!

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值