一、引入微信支付SDK
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
</dependency>
二、支付参数封装
@Data
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayProperties {
/**
* 微信公众号或者小程序等的appid
*/
private String appId;
/**
* 微信支付商户号
*/
private String mchId;
/**
* 微信支付商户密钥
*/
private String mchKey;
/**
* 服务商模式下的子商户公众账号ID
*/
private String subAppId;
/**
* 服务商模式下的子商户号
*/
private String subMchId;
/**
* apiclient_key.pem文件路径
*/
private String keyPath;
/**
* apiclient_cert.pem文件路径
*/
private String certPath;
/**
* 回调通知地址
*/
private String notifyUrl;
/**
* apiV3Key
*/
private String apiV3Key;
}
三、调用微信预下单接口
1、支付业务参数封装
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class PayRequestDTO {
/**
* 订单号
*/
private String orderNo;
/**
* 支付金额
*/
private BigDecimal totalFee;
/**
* 支付描述
*/
private String body;
/**
* 微信支付使用的用户标记
*/
private String openId;
}
2、设置微信支付参数
@Autowired
private WxPayProperties wxPayProperties;
public WxPayConfig getWxConfig() {
WxPayConfig wxPayConfig = new WxPayConfig();
wxPayConfig.setAppId(wxPayProperties.getAppId());
wxPayConfig.setMchId(wxPayProperties.getMchId()));
wxPayConfig.setMchKey(wxPayProperties.getMchKey());
wxPayConfig.setSubAppId(wxPayProperties.getSubAppId();
wxPayConfig.setSubMchId(wxPayProperties.getSubMchId());
wxPayConfig.setKeyPath(wxPayProperties.getKeyPath());
wxPayConfig.setApiV3Key(wxPayProperties.getApiV3Key());
wxPayConfig.setPrivateKeyPath(wxPayProperties.getKeyPath());
wxPayConfig.setPrivateCertPath(wxPayProperties.getCertPath());
wxPayConfig.setNotifyUrl(WX_NOTIFY_URL);
logger.info("微信支付参数wxPayConfig-----{}",wxPayConfig);
return wxPayConfig;
}
3、调用下单接口
public WxPayUnifiedOrderV3Result.JsapiResult wxAppletPay(PayRequestDTO weChatPayRequest) throws Exception {
WxPayConfig wxConfig = this.getWxConfig();
WxPayServiceImpl wxPayServiceApacheHttp = new WxPayServiceImpl();
wxPayServiceApacheHttp.setConfig(wxConfig);
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
amount.setCurrency("CNY").setTotal(weChatPayRequest.getTotalFee().multiply(new BigDecimal(100)).intValue());
WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
payer.setOpenid(weChatPayRequest.getOpenId());
WxPayUnifiedOrderV3Request.SceneInfo sceneInfo = new WxPayUnifiedOrderV3Request.SceneInfo();
sceneInfo.setPayerClientIp("127.0.0.1");
request.setAmount(amount).setPayer(payer).setOutTradeNo(weChatPayRequest.getOutTradeNo())
.setSceneInfo(sceneInfo).setDescription(weChatPayRequest.getBody());
WxPayUnifiedOrderV3Result result = wxPayServiceApacheHttp.unifiedOrderV3(TradeTypeEnum.JSAPI, request);
WxPayConfig wxConfig = this.getWxConfig();
String privateKeyPath = wxConfig.getPrivateKeyPath();
PrivateKey privateKey = CanteenUtils.getPrivateKey(privateKeyPath);
WxPayUnifiedOrderV3Result.JsapiResult payInfo = result.getPayInfo(TradeTypeEnum.JSAPI, wxConfig.getAppId(), wxConfig.getMchId(), privateKey);
return payInfo;
}
生成RSA私钥
public static PrivateKey getPrivateKey(String filename) throws IOException {
String content = new String(Files.readAllBytes(Paths.get(filename)), StandardCharsets.UTF_8);
try {
String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(privateKey)));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("当前Java环境不支持RSA", e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException("无效的密钥格式");
}
}
四、避坑要点
使用v3版本的api接口,jdk8的版本一定要使用最新的,不让会出现各种v3构造异常