Java对接第三方支付渠道之微信支付APIV3版本
一、接入指引
1.获取商户号
2.获取AppID
3.申请商户证书
步骤:登录商户平台 => 选择 账户中心 => 安全中心 => API安全 => 申请API证书 包括商户证书和商户私钥
可以预先下载,也可以通过编程的方式获取 我这里是直接下载在本地的
步骤:登录商户平台 => 选择 账户中心 => 安全中心 => API安全 => 设置APIv3密钥
二、导入依赖
三、书写配置类
这里导入支付秘钥的时候,我直接选择的是导入秘钥字符串,没有选择导入秘钥文件
四、书写工具类
1.订单状态枚举类
@AllArgsConstructor @Getter public enum OrderStatus { /** * 未支付 */ NOTPAY("未支付"), /** * 支付成功 */ SUCCESS("支付成功"), /** * 已关闭 */ CLOSED("超时已关闭"), /** * 已取消 */ CANCEL("用户已取消"), /** * 类型 */ private final String type; }
2.支付类型枚举类
package com.ruiya.commons.enums.wxpay; import lombok.AllArgsConstructor; import lombok.Getter; @AllArgsConstructor @Getter public enum WxApiType { /** * Native下单 */ NATIVE_PAY("/v3/pay/transactions/native"), /** * 查询订单 */ ORDER_QUERY_BY_NO("/v3/pay/transactions/out-trade-no/%s"), /** * 关闭订单 */ CLOSE_ORDER_BY_NO("/v3/pay/transactions/out-trade-no/%s/close"), /** * 类型 */ private final String type; }
五、调用相关支付接口
1.流程图
2.发起支付
/** * 统一下单 - 生成支付二维码 * @param orderNo 订单编号 * @param uid 用户id * @return */ @Override public String nativePay(String orderNo, String uid) throws Exception{ //根据orderNo获取orderInfo OrderInfo orderInfo = orderInfoService.getOne(new LambdaQueryWrapper<OrderInfo>() .eq(OrderInfo::getOrderNo, orderNo) .eq(OrderInfo::getUid, uid)); if (Objects.isNull(orderInfo)){ throw new ServiceErrorException(ResultCode.ERROR, "发起支付请求失败 - 订单不存在"); } String codeUrl = orderInfo.getCodeUrl(); String orderStatus = orderInfo.getOrderStatus(); //支付二维码不为空 &&订单的支付状态为支付中 if(!StringUtils.isEmpty(codeUrl) && OrderStatus.NOTPAY.getType().equals(orderStatus)){ log.info("订单已存在,二维码已保存"); //返回二维码 return codeUrl; } //更新订单的支付类型 orderInfoService.updatePayTypeByOrderNo(orderInfo.getOrderNo(), PayType.WXPAY); //调用统一下单API HttpPost httpPost=new HttpPost(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType())); // 请求body参数 Gson gson = new Gson(); Map paramsMap = new HashMap(); paramsMap.put("appid", wxPayConfig.getAppid()); paramsMap.put("mchid", wxPayConfig.getMchId()); paramsMap.put("description", orderInfo.getTitle()); paramsMap.put("out_trade_no", orderInfo.getOrderNo()); paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType())); Map amountMap = new HashMap(); BigDecimal payMoney = orderInfo.getTotalFee(); BigDecimal total = payMoney.multiply(new BigDecimal("100")); total = total.setScale(0,BigDecimal.ROUND_UP); //支付金额单位:分 amountMap.put("total", total.intValue()); amountMap.put("currency", "CNY"); paramsMap.put("amount", amountMap); //将参数转换成json字符串 String jsonParams = gson.toJson(paramsMap); log.info("请求参数:" + jsonParams); StringEntity entity = new StringEntity(jsonParams,"utf-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); httpPost.setHeader("Accept", "application/json"); //完成签名并执行请求 CloseableHttpResponse response = (CloseableHttpResponse) httpClientWithSign.execute(httpPost); try { String bodyAsString = EntityUtils.toString(response.getEntity());//响应体 int statusCode = response.getStatusLine().getStatusCode();//响应状态码 if (statusCode == 200) { //处理成功 log.info("成功, 返回结果 = " + bodyAsString); } else if (statusCode == 204) { //处理成功,无返回Body log.info("成功"); } else { log.info("Native下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString); throw new ServiceErrorException(ResultCode.ERROR, "发起支付请求失败 - Native下单失败:" + bodyAsString); } //响应结果 Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class); //获取二维码 codeUrl = resultMap.get("code_url"); //保存支付二维码 orderInfoService.saveCodeUrl(orderNo, codeUrl); return codeUrl; }finally { response.close(); } }