1.导入依赖
<!-- 微信支付 -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.9</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.0.6</version>
</dependency>
<!--生成二维码-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
2.支付所需参数配置
wx:
# 商户号
mch-id:
# appId
appId:
# 商户证书序列号
mc-serial-no:
# API V3密钥
api-v3-key:
# 回调地址
notify-domain:
# 商户证书地址
keyPath: ../ttlive-server/Common/src/main/java/com/common/cert/apiclient_key.pem
certPath: ../ttlive-server/Common/src/main/java/com/common/cert/apiclient_cert.pem
certP12Path: ../ttlive-server/Common/src/main/java/com/common/cert/apiclient_cert.p12
微信配置类
@Configuration
@Data
@Component
public class WxPayConfig {
private static volatile Config config;
/**
* 商户号
*/
public static String merchantId = "1657.....5";
// 商户API私钥路径 本地路径
// public static String privateKeyPath="../ttliveserver/Common/src/main/java/com/common/cert/apiclient_key.pem";
// 服务器上部署测试路径
public static String privateKeyPath = "../root/cert/apiclient_key.pem";
/**
* 商户证书序列号
*/
public static String merchantSerialNumber = "6E225996B0BE..........B043B6B726";
/**
* 商户APIV3密钥
*/
public static String apiV3Key = "31cc22a............bba9a411";;
//SDK 提供的定时更新平台证书
public static synchronized Config getConfig(WxPayConfig wxPayConfig) {
if (config == null) {
config = new RSAAutoCertificateConfig.Builder()
.merchantId(merchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3Key)
.build();
}
return config;
}
public static Config getConfig() {
return config;
}
public static void setConfig(Config config) {
WxPayConfig.config = config;
}
}
这里我们设置的是 API v3密钥 提前下载并配置商户证书文件,将文件移入项目中
3.生成微信支付二维码
@Autowired
private WxPayConfig wxPayConfig;
Config config = WxPayConfig.getConfig(wxPayConfig);
NativePayService service = new NativePayService.Builder().config(config).build();
// request.setXxx(val)设置所需参数,具体参数可见Request定义
PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(商品价格);
request.setAmount(amount);
request.setAppid("APPID");
request.setMchid("商户号");
request.setDescription("商品名称");
request.setNotifyUrl("回调地址,需绑定域名,否则需要内网穿透工具");
request.setOutTradeNo("你所生成的订单号");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
// 微信二维码失效时间 4 分钟
Date date = new Date(new Date().getTime() + 4 * 60 * 1000);
String expire = format.format(date);
request.setTimeExpire(expire);
// 调用下单方法,得到应答
PrepayResponse response = service.prepay(request);
// 生成二维码链接,扔给前端,或者自己写二维码代码
String codeUrl = response.getCodeUrl();
4.微信回调
public String paymentSuccessNotify(String body, HttpServletRequest request, HttpServletResponse response) {
//时间戳
String timestamp = request.getHeader("wechatPay-Timestamp");
//随机字符串
String nonce = request.getHeader("wechatPay-Nonce");
//签名
String signature = request.getHeader("wechatPay-Signature");
//签名类型
String sigType = request.getHeader("wechatPay-Signature-Type");
//证书序列号
String wechatPayCertificateSerialNumber = request.getHeader("wechatPay-Serial");
// String ciphertext = request.getHeader("ciphertext");
// String associateData = request.getHeader("associated_data");
// //解密方法
// AesUtil aesUtil = new AesUtil("31cc22a17ada73b81ad85832bba9a411".getBytes(StandardCharsets.UTF_8));
// String info = null;
// try {
// info = aesUtil.decryptToString(associateData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);
// } catch (GeneralSecurityException e) {
// throw new RuntimeException(e);
// } catch (IOException e) {
// throw new RuntimeException("解密失败");
// }
// System.out.println(info);
// 构造 RequestParam
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(wechatPayCertificateSerialNumber)
.nonce(nonce)
.signature(signature)
.timestamp(timestamp)
.signType(sigType)
.body(body)
.build();
//获取微信证书,没有的话重新构造一个
Config config = WxPayConfig.getConfig(wxPayConfig);
NotificationParser parser = new NotificationParser((NotificationConfig) config);
// 以支付通知回调为例,验签、解密并转换成 Transaction
Transaction transaction = parser.parse(requestParam, Transaction.class);
Transaction.TradeStateEnum trade_state = transaction.getTradeState();
// 根据transaction的结果进行回调操作
String message = null;
if (trade_state == Transaction.TradeStateEnum.SUCCESS){
message = "200";
}else {
message ="400";
}
// 下面的是业务处理,到这一步,获取到transaction 方法即可
String outTradeNo = transaction.getOutTradeNo();
String transactionId = transaction.getTransactionId();
String poll = outTradeNo+":"+transactionId+"-"+message;
// String poll = JSONObject.toJSONString(transaction);
this.payDao.addOrderNoInfoToQueue(poll);
// 将微信返回的订单号参数信息传到Dao层,进行校验
if (trade_state == Transaction.TradeStateEnum.SUCCESS) {
response.setStatus(200);
JSONObject json = new JSONObject();
json.put("code", "SUCCESS");
return json.toString();
} else {
response.setStatus(400);
JSONObject json = new JSONObject();
json.put("code", "FAIL");
json.put("message", "验签失败");
return json.toString();
}
}