
java对接微信支付SDK接口
在微信公众平台https://mp.weixin.qq.com/ 注册应用,类型只选择“公众号/小程序/企业微信”,注册完成后需完成”微信认证“(微信收取300元),在基础配置中拿到开发者ID(微信支付 APIv3 使用由 证书授权机构(Certificate Authority,简称CA)签发的证书,商户申请证书时,证书工具会生成。在微信支付商户平台https://pay.weixin.qq.c
1.对接准备
需要的参数包括开发者ID(appid)、商户号、商户api私钥、商户证书序列号、商户APIV3密钥、回调地址。
在微信公众平台https://mp.weixin.qq.com/ 注册应用,类型只选择“公众号/小程序/企业微信”,注册完成后需完成”微信认证“(微信收取300元),在基础配置中拿到开发者ID(APPID)。
在微信支付商户平台https://pay.weixin.qq.com注册商户,在账户中心-api安全中设置APIv3密钥,微信支付 APIv3 使用由 证书授权机构(Certificate Authority,简称CA)签发的证书,商户申请证书时,证书工具会生成商户私钥,并保存在本地证书文件夹的件 apiclient_key.pem
中。开发和部署,需要区分环境,加载 apiclient_key.pem
文件。
在账户中心-商户信息中拿到微信支付商户号,即商户ID (收钱的商家ID);
在产品中心-appid账号管理中,将申请的下来的APPID绑定到商户号下。
Certificate Downloader 是 Java 微信支付 APIv3 平台证书的命令行下载工具。该工具可从https://api.mch.weixin.qq.com/v3/certificates
接口获取商户可用证书。
2.maven引入jar包
<!-- 微信支付SDK --> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>0.2.9</version> </dependency>
3.yml文件配置微信参数,工具类读取
@Component
public class WechatPayConfig {
/**
* 应用ID
*/
public static String appid;
/**
* 商户号
*/
public static String merchantId;
/**
* 商户API私钥路径
*/
public static String privateKeyPath;
/**
* 商户证书序列号
*/
public static String merchantSerialNumber;
/**
* 商户APIV3密钥
*/
public static String apiV3Key;
/**
* 通知地址(有效性:1. HTTPS;2. 不允许携带查询串。)
*/
public static String notifyUrl;
/**
* 微信支付配置
*/
public static Config config;
/**
* 订单支付超时时间/分钟
*/
public static final Integer ORDER_PAY_TIME_OUT = 1440;
private WechatPayConfig() {}
@Value("${wechat.pay.appid}")
public void setAppid(String appid) {
WechatPayConfig.appid = appid;
}
@Value("${wechat.pay.merchantId}")
public void setMerchantId(String merchantId) {
WechatPayConfig.merchantId = merchantId;
}
@Value("${wechat.pay.privateKeyPath}")
public void setPrivateKeyPath(String privateKeyPath) {
String classPath = System.getProperty("java.class.path");
// 是否运行在开发环境
boolean isRunningFromIde = classPath.toLowerCase().contains("eclipse") || classPath.toLowerCase().contains("idea");
// 开发环境与部署jar包环境 不同获取私钥路径
if (isRunningFromIde){
WechatPayConfig.privateKeyPath = getClass().getClassLoader().getResource("apiclient_key.pem").getPath();
}else {
WechatPayConfig.privateKeyPath = privateKeyPath;
}
}
@Value("${wechat.pay.merchantSerialNumber}")
public void setMerchantSerialNumber(String merchantSerialNumber) {
WechatPayConfig.merchantSerialNumber = merchantSerialNumber;
}
@Value("${wechat.pay.apiV3Key}")
public void setApiV3Key(String apiV3Key) {
WechatPayConfig.apiV3Key = apiV3Key;
}
@Value("${wechat.pay.notifyUrl}")
public void setNotifyUrl(String notifyUrl) {
WechatPayConfig.notifyUrl = notifyUrl;
}
@PostConstruct
public void initializeConfig() {
// 初始化微信配置
config = new RSAAutoCertificateConfig.Builder()
.merchantId(merchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3Key)
.build();
}
}
4.对接支付接口
/**
* 微信 Native 支付下单
*
* @param amt 金额
* @param orderNumber 订单号
* @param description 描述
* @return 二维码链接
*/
public static AjaxResult nativePay(BigDecimal amt, String orderNumber, String description) {
// 当前时间
Date currentDate = new Date();
// 将金额转换为分
int total = amt.multiply(new BigDecimal("100")).intValue();
try {
// 构建service
NativePayService service = new NativePayService.Builder().config(WechatPayConfig.config).build();
// 构建请求对象
PrepayRequest request = new PrepayRequest();
request.setAppid(WechatPayConfig.appid);
request.setMchid(WechatPayConfig.merchantId);
request.setNotifyUrl(WechatPayConfig.notifyUrl);
// 设置金额
Amount amount = new Amount();
amount.setTotal(total);
request.setAmount(amount);
request.setDescription(description);
request.setOutTradeNo(orderNumber);
// 计算订单失效时间
Calendar calendar = DateUtils.toCalendar(currentDate);
calendar.add(Calendar.MINUTE, WechatPayConfig.ORDER_PAY_TIME_OUT);
request.setTimeExpire(DateUtils.parseDateToStr("yyyy-MM-dd'T'HH:mm:ss+08:00", calendar.getTime()));
return AjaxResult.success(service.prepay(request).getCodeUrl());
} catch (Exception e){
log.error(e.getMessage(),e);
return AjaxResult.error("支付订单创建失败");
}
}
5.回调地址
/**
* 微信支付回调
*
* @return 回调结果
*/
@PostMapping("/wechat")
public ResponseEntity.BodyBuilder wechat(@RequestBody String body, HttpServletRequest request) {
try {
// 构造 RequestParam
RequestParam requestParam = new RequestParam.Builder()
// 序列号
.serialNumber(request.getHeader("Wechatpay-Serial"))
// 随机数
.nonce(request.getHeader("Wechatpay-Nonce"))
// 签名
.signature(request.getHeader("Wechatpay-Signature"))
// 时间戳
.timestamp(request.getHeader("Wechatpay-Timestamp"))
.body(body)
.build();
// 初始化解析器
NotificationParser parser = new NotificationParser((NotificationConfig) WechatPayConfig.config);
// 验签、解密并转换成 Transaction
Transaction transaction = parser.parse(requestParam, Transaction.class);
// 校验交易状态
if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
// 支付成功,根据订单编号查询订单信息
// 1.查询订单信息
Order orderOld = orderService.selectForUpdateByOrderNumber(transaction.getOutTradeNo());
// 校验金额
if (orderOld != null && orderOld.getPayAmount().equals(transaction.getAmount().getTotal())) {
// 金额相等 完成支付 更新订单状态
WechatPayUtil.success(orderOld,transaction);
} else {
// 金额异常 执行退款
WechatPayUtil.refunded(new WechatPayRedis(transaction.getOutTradeNo(), transaction.getAmount().getTotal(), null));
}
}
} catch (ValidationException e) {
// 签名验证失败,返回 401 UNAUTHORIZED 状态码
return ResponseEntity.status(HttpStatus.UNAUTHORIZED);
}
// 处理成功,返回 200 OK 状态码
return ResponseEntity.status(HttpStatus.OK);
}
/**
* 支付成功
*/
public static void success( Order orderOld,Transaction transaction) {
try {
// 支付完成时间
Date payTime = DateUtils.parseDate(transaction.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ss+08:00");
// 校验订单信息 & 支付结果 & 订单有效期止日期
if (orderOld != null && orderOld.getPayResult() == 0 && payTime.compareTo(orderOld.getExpirationDate()) < 1) {
// 构建修改对象
Order updateOrder = new Order();
updateOrder.setId(orderOld.getId());
updateOrder.setPayMethod(PayMethodEnum.W.name());
updateOrder.setPayChannel(PayChannelEnum.P.name());
updateOrder.setPayDate(payTime);
updateOrder.setPayResult(PayResultEnum.PAID.getCode());
updateOrder.setPayType(PayTypeEnum.U.name());
updateOrder.setSerialNumber(transaction.getTransactionId());
if (orderService.editPayResult(updateOrder,orderOld) == 1) {
// 删除Redis订单支付信息
SpringUtils.getBean(RedisCache.class).deleteObject(WechatPayConfig.ORDER_PAY_REDIS_PREFIX + transaction.getOutTradeNo());
}
} else {
// 订单信息不存在 执行退款
WechatPayUtil.refunded(new WechatPayRedis(transaction.getOutTradeNo(), transaction.getAmount().getTotal(), null));
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* 执行退款
*/
public static void refunded(WechatPayRedis wechatPay) {
try {
// 构建退款Service
RefundService service = new RefundService.Builder().config(WechatPayConfig.config).build();
// 构建请求对象
CreateRequest request = new CreateRequest();
request.setOutTradeNo(wechatPay.getOrderNumber());
request.setOutRefundNo(wechatPay.getOrderNumber());
// 支付总金额(分)
long total = wechatPay.getTotal();
// 设置退款金额
AmountReq amount = new AmountReq();
amount.setRefund(total);
amount.setTotal(total);
amount.setCurrency("CNY");
request.setAmount(amount);
// 请求API申请退款
Refund refund = service.create(request);
// 校验退款结果
if (refund != null && Status.SUCCESS.equals(refund.getStatus())) {
// 退款成功
log.info("微信退款成功:{}", wechatPay);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
更多推荐
所有评论(0)