WxJava是一款基于Java语言的微信开发Java SDK,它提供了微信支付,开放平台,小程序,企业微信,公众号等多个平台的API接口,并将其封装为易于调用的Java方法,方便Java开发者快速开发与微信相关的应用。
GitHub地址:
https://github.com/Wechat-Group/WxJava
如果不想使用WxJava,使用官方Api,可以查看,我的另一篇文章:微信支付JAVA V3APP下单整合
- 使用WxJava只需要引入开发相关模块的maven依赖即可
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>4.5.2.B</version>
</dependency>
- 微信配置参数
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
/**
* @author chilei
* @description
* @since 2023/7/20
*/
@Component
@RefreshScope
@Getter
@Setter
public class WxPayProperties {
/**
* 设置微信公众号或者小程序等的appid
*/
@Value("${wx.pay.appid:}")
private String appid;
/**
* 微信支付商户号
*/
@Value("${wx.pay.mchId:}")
private String mchId;
@Value("${wx.pay.privateKeyContent:}")
private String privateKeyContent;
@Value("${wx.pay.privateCertContent:}")
private String privateCertContent;
/**
* 下单回调地址
*/
@Value("${wx.pay.notifyUrl:}")
private String notifyUrl;
/**
* 退款回调地址
*/
@Value("${wx.pay.refundUrl:}")
private String refundUrl;
/**
* apiV3key
*/
@Value("${wx.pay.apiV3key:}")
private String apiV3key;
}
- 微信支付配置类
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
/**
* @author chilei
* @description 微信支付配置类
* @since 2023/7/20
*/
@Configuration
@ConditionalOnClass(WxPayService.class)
public class WxPayConfiguration {
@Resource
private WxPayProperties wxPayProperties;
@Autowired
public WxPayConfiguration(WxPayProperties wxPayProperties) {
this.wxPayProperties = wxPayProperties;
}
@Bean
@ConditionalOnMissingBean
public WxPayService wxService() {
WxPayService wxPayService = new WxPayServiceImpl();
if (StringUtils.isNotBlank(this.wxPayProperties.getAppid())) {
wxPayService.setConfig(wxPayConfig());
}
return wxPayService;
}
@Bean
public WxPayConfig wxPayConfig() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(StringUtils.trimToNull(this.wxPayProperties.getAppid()));
payConfig.setMchId(StringUtils.trimToNull(this.wxPayProperties.getMchId()));
payConfig.setPrivateKeyContent(this.wxPayProperties.getPrivateKeyContent().getBytes(StandardCharsets.UTF_8));
payConfig.setPrivateCertString(this.wxPayProperties.getPrivateCertContent());
payConfig.setApiV3Key(this.wxPayProperties.getApiV3key());
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
return payConfig;
}
}
- 微信支付V3 api
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.shinsson.heeiya.app.config.wx.WxPayProperties;
import com.shinsson.utils.MyDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.security.Signature;
import java.time.OffsetDateTime;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* @author chilei
* @description 微信支付V3 api
* @since 2023/7/20
*/
@Component
@Slf4j
public class WxPayUtil {
@Resource
private WxPayService wxPayService;
@Resource
private WxPayProperties wxPayProperties;
/**
* 统一支付下单接口
*
* @param outTradeNo 商户订单号
* @param totalFee 下单金额(单位:分)
* @param productContent 商品描述
* @param timeExpire 遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE 示例值:2018-06-08T10:34:56+08:00
*/
public Map<String, String> createOrder(String outTradeNo, Integer totalFee, String productContent, OffsetDateTime timeExpire) {
WxPayUnifiedOrderV3Request wxPayUnifiedOrderV3Request = new WxPayUnifiedOrderV3Request();
wxPayUnifiedOrderV3Request.setDescription(productContent);
wxPayUnifiedOrderV3Request.setTimeExpire(timeExpire.format(MyDateUtil.Y_M_D_T_H_M_S_8));
WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
amount.setTotal(totalFee);
wxPayUnifiedOrderV3Request.setAmount(amount);
wxPayUnifiedOrderV3Request.setOutTradeNo(outTradeNo);
wxPayUnifiedOrderV3Request.setNotifyUrl(wxPayProperties.getNotifyUrl());
try {
WxPayUnifiedOrderV3Result.AppResult appResult = wxPayService.createOrderV3(TradeTypeEnum.APP, wxPayUnifiedOrderV3Request);
return this.startWxPay(appResult);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
/**
* 商户订单号查询订单 微信官方文档: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_2.shtml
*
* @param outTradeNo 商户订单号
* @return WxPayOrderQueryV3Result 返回对象
*/
public WxPayOrderQueryV3Result selectOrder(String outTradeNo) {
WxPayOrderQueryV3Request wxPayOrderQueryV3Request = new WxPayOrderQueryV3Request();
wxPayOrderQueryV3Request.setOutTradeNo(outTradeNo);
try {
return wxPayService.queryOrderV3(wxPayOrderQueryV3Request);
} catch (WxPayException e) {
throw new RuntimeException(e.getMessage());
}
}
/**
* 退款调用
*
* @param outTradeNo 商户订单号
* @param outRefundNo 商户退款单号
* @param reason 退款原因
* @param refund 退款金额(单位:分)
* @param total 原订单金额(单位:分)
* @return WxPayRefundV3Result 返回值参考: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_9.shtml
*/
public WxPayRefundV3Result refundOrder(String outTradeNo, String outRefundNo, String reason, Integer refund, Integer total) {
WxPayRefundV3Request wxPayRefundV3Request = new WxPayRefundV3Request();
wxPayRefundV3Request.setOutTradeNo(outTradeNo);
wxPayRefundV3Request.setOutRefundNo(outRefundNo);
wxPayRefundV3Request.setReason(reason);
wxPayRefundV3Request.setNotifyUrl(wxPayProperties.getRefundUrl());
WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
amount.setRefund(refund);
amount.setTotal(total);
amount.setCurrency("CNY");
wxPayRefundV3Request.setAmount(amount);
try {
return wxPayService.refundV3(wxPayRefundV3Request);
} catch (WxPayException e) {
throw new RuntimeException(e.getMessage());
}
}
/**
* 封装二次加签数据 APP调起支付API
*
* @param appResult 预下单数据
* @return Map 返回值
*/
public Map<String, String> startWxPay(WxPayUnifiedOrderV3Result.AppResult appResult) {
Map<String, String> map = new HashMap<>(7);
//时间戳
long timestamp = System.currentTimeMillis() / 1000;
String token = getSign(appResult.getNoncestr(), appResult.getAppid(), appResult.getPrepayId(), timestamp);
map.put("appid", appResult.getAppid());
map.put("partnerId", appResult.getPartnerId());
map.put("prepayId", appResult.getPrepayId());
map.put("package", appResult.getPackageValue());
map.put("nonceStr", appResult.getNoncestr());
map.put("timestamp", String.valueOf(timestamp));
map.put("sign", token);
return map;
}
/**
* 获取签名
*
* @param nonceStr 随机数
* @param appId 微信公众号或者小程序等的appid
* @param prepayId 预支付交易会话ID
* @param timestamp 时间戳 10位
* @return String 新签名
*/
String getSign(String nonceStr, String appId, String prepayId, long timestamp) {
//从下往上依次生成
String message = buildMessage(appId, timestamp, nonceStr, prepayId);
//签名
return sign(message.getBytes(StandardCharsets.UTF_8));
}
String sign(byte[] message) {
try {
//签名方式
Signature sign = Signature.getInstance("SHA256withRSA");
//私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名
sign.initSign(wxPayService.getConfig().getPrivateKey());
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
} catch (Exception e) {
throw new RuntimeException("签名异常,请检查参数或商户私钥");
}
}
/**
* 按照前端签名文档规范进行排序,\n是换行
*
* @param nonceStr 随机数
* @param appId 微信公众号或者小程序等的appid
* @param prepayId 预支付交易会话ID
* @param timestamp 时间戳 10位
* @return String 新签名
*/
String buildMessage(String appId, long timestamp, String nonceStr, String prepayId) {
return appId + "\n"
+ timestamp + "\n"
+ nonceStr + "\n"
+ prepayId + "\n";
}
}
- 简单调用
@Service
public class WxOrderService {
@Resource
private WxPayUtil wxPayUtil;
/**
* 创建微信订单
*
* @param orderNo 订单号
* @param orderRequest 创建订单参数
* @return 换起押金支付的字符串
*/
public String createWxOrder(String orderNo, OrderRequest orderRequest) {
//微信支付,金额 单位为:分
BigDecimal decimal = orderRequest.getAmount().multiply(new BigDecimal(100));
Map<String, String> wxOrder = wxPayUtil.createOrder(orderNo, decimal.intValue(), "描述", OffsetDateTime.now());
String orderStr = JSON.toJSONString(wxOrder);
return orderStr;
}
}
如有错误的地方,请指出,感谢路过的各位大佬。