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();
}
}
