1.解析的字段
/**
* v3 支付异步通知验证解析签名
*
* @param body 异步通知密文
* @param key api 密钥
* @return 异步通知明文
* @throws Exception 异常信息
*/
protected static String analysisNotify(String body, String key) throws Exception {
// 获取平台证书序列号
JSONObject resultObject = JSONObject.parseObject(body);
JSONObject resource = resultObject.getJSONObject("resource");
String cipherText = resource.getString("ciphertext");
String nonceStr = resource.getString("nonce");
String associatedData = resource.getString("associated_data");
AesUtil aesUtil = new AesUtil(key.getBytes(StandardCharsets.UTF_8));
// 密文解密
return aesUtil.decryptToString(
associatedData.getBytes(StandardCharsets.UTF_8),
nonceStr.getBytes(StandardCharsets.UTF_8),
cipherText
);
}
2解析的工具类
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
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 != KEY_LENGTH_BYTE) {
throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
}
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(aesKey, "AES");
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
cipher.updateAAD(associatedData);
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new IllegalStateException(e);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalArgumentException(e);
}
}
}
3 调用
public WxPayOrderNotifyResult parseJsApiNew(String result) throws WxPayException, Exception {
String privateKey = weixinPayConfig.getApiV3key();
// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
String plainText = analysisNotify(result, privateKey);
WxPayOrderNotifyResult refundOrderNotifyVo = new WxPayOrderNotifyResult();
try {
/* ObjectMapper mapper = new ObjectMapper();
JSONObject json = JSONObject.parseObject(plainText, JSONObject.class);*/
refundOrderNotifyVo = JSONObject.parseObject(plainText, WxPayOrderNotifyResult.class);
JSONObject json = JSONObject.parseObject(plainText, JSONObject.class);
Map<String, Object> objMap = (Map<String, Object>) json.get("amount");
refundOrderNotifyVo.setTotalFee((Integer) objMap.get("payer_total"));
} catch (Exception e) {
}
return refundOrderNotifyVo;
}
微信支付回调解析
于 2024-10-27 08:38:14 首次发布