private static String privateApiV3Key="cn5HxRmmbTDTUYgw3nGHU1YyFe72222";
/**
* 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url
*
* @return
*/
@PostMapping("/get/result")
@ApiOperationSupport(order = 5)
@ApiOperation(value = " 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url", notes = " 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url")
public void notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception{
String requestString = WXUtil.getStreamString(request.getInputStream());
logger.info("微信结果通知加密字符串"+requestString);
NotifyResutlVo obj = JSON.parseObject(requestString, NotifyResutlVo.class);
String associated_data = obj.getResource().getAssociated_data();
String nonce = obj.getResource().getNonce();
String ciphertext = obj.getResource().getCiphertext();
AesUtil aesUtil = new AesUtil(privateApiV3Key.getBytes());
try {
String s = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
logger.info("微信结果通知解密字符串"+s);
JSONObject jsonObject = JSONObject.fromObject(s);
//订单号
String out_trade_no = jsonObject.getString("out_trade_no");
//微信支付订单号
String transaction_id = jsonObject.getString("transaction_id");
/**
* 交易状态
*
* 1.SUCCESS:支付成功
* 2.REFUND:转入退款
* 3.NOTPAY:未支付
* 4.CLOSED:已关闭
* 5.REVOKED:已撤销(付款码支付)
* 6.USERPAYING:用户支付中(付款码支付)
* 7.PAYERROR:支付失败(其他原因,如银行返回失败)
*
*
*/
QueryWrapper<BladeWechat> queryWrapperNew = new QueryWrapper<>();
queryWrapperNew.lambda().eq(BladeWechat::getOutTradeNumber, out_trade_no);
BladeWechat bw = new BladeWechat();
bw.setVehicleWechatOrder(transaction_id);
String trade_state=jsonObject.getString("trade_state");
if("SUCCESS".equals(trade_state)){
bw.setStatus(StatusEnum.success.getIndex());
}else if("PAYERROR".equals(trade_state)) {
bw.setStatus(StatusEnum.fail.getIndex());
}else{
logger.info(String.format("其它未完成支付原因,当前的订单号:%s,通知的支付状态是:%s",out_trade_no,trade_state));
bw.setStatus(StatusEnum.other.getIndex());
}
bladeWechatService.update(bw, queryWrapperNew);
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
数据模型:
package com.hdd.tms.modules.payment.vo;
import lombok.Data;
/**
* @ProjectName: BladeX-Boot
* @Package: com.hdd.tms.modules.payment.vo
* @ClassName: NotifyResutlVo
* @Author: szk
* @Description:
* @Date: 2021/9/13 10:55
*/
@Data
public class NotifyResutlVo {
private String id;
private String create_time;
private String resource_type;
private String event_type;
private String summary;
private ResouceVo resource;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCreate_time() {
return create_time;
}
public void setCreate_time(String create_time) {
this.create_time = create_time;
}
public String getResource_type() {
return resource_type;
}
public void setResource_type(String resource_type) {
this.resource_type = resource_type;
}
public String getEvent_type() {
return event_type;
}
public void setEvent_type(String event_type) {
this.event_type = event_type;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public ResouceVo getResource() {
return resource;
}
public void setResource(ResouceVo resource) {
this.resource = resource;
}
@Override
public String toString() {
return "NotifyResutlVo{" +
"id='" + id + '\'' +
", create_time='" + create_time + '\'' +
", resource_type='" + resource_type + '\'' +
", event_type='" + event_type + '\'' +
", summary='" + summary + '\'' +
", resource=" + resource +
'}';
}
}
package com.hdd.tms.modules.payment.vo;
import lombok.Data;
/**
* @ProjectName: BladeX-Boot
* @Package: com.hdd.tms.modules.payment.vo
* @ClassName: ResouceVo
* @Author: szk
* @Description:
* @Date: 2021/9/13 11:11
*/
@Data
public class ResouceVo {
private String original_type;
private String algorithm;
private String ciphertext;
private String associated_data;
private String nonce;
public String getOriginal_type() {
return original_type;
}
public void setOriginal_type(String original_type) {
this.original_type = original_type;
}
public String getAlgorithm() {
return algorithm;
}
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
public String getCiphertext() {
return ciphertext;
}
public void setCiphertext(String ciphertext) {
this.ciphertext = ciphertext;
}
public String getAssociated_data() {
return associated_data;
}
public void setAssociated_data(String associated_data) {
this.associated_data = associated_data;
}
public String getNonce() {
return nonce;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
@Override
public String toString() {
return "ResouceVo{" +
"original_type='" + original_type + '\'' +
", algorithm='" + algorithm + '\'' +
", ciphertext='" + ciphertext + '\'' +
", associated_data='" + associated_data + '\'' +
", nonce='" + nonce + '\'' +
'}';
}
}
解密工具
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.wechat.pay.contrib.apache.httpclient.util;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AesUtil {
static final int KEY_LENGTH_BYTE = 32;
static final int TAG_LENGTH_BIT = 128;
private final byte[] aesKey;
public AesUtil(byte[] key) {
if (key.length != 32) {
throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
} else {
this.aesKey = key;
}
}
public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException {
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec key = new SecretKeySpec(this.aesKey, "AES");
GCMParameterSpec spec = new GCMParameterSpec(128, nonce);
cipher.init(2, key, spec);
cipher.updateAAD(associatedData);
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
} catch (NoSuchPaddingException | NoSuchAlgorithmException var7) {
throw new IllegalStateException(var7);
} catch (InvalidAlgorithmParameterException | InvalidKeyException var8) {
throw new IllegalArgumentException(var8);
}
}
}
pom依赖
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.2.1</version>
</dependency>