最近在搞微信支付,V3版本文档对于新手理解起来相对比较绕,最终还是搞起来了。此代码片段只写了下单支付接口,其他接口相对简单就不一一列举出来了。
话不多说直接上代码。
一、下单
1、支付相关参数配置,根据自己相关参数配置
/**
* 商户号
*/
private String mchId;
/**
* 商户证书序列号
*/
private String mchSerialNo;
/**
* apiV3密钥
*/
private String apiV3key;
/**
* APP ID
*/
private String appId;
/**
* 回调通知路径
*/
private String notifyUrl;
/**
* 支付url
*/
private String payUrl;
/**
* 查询支付Url
*/
private String queryPayUrl;
2、支付方法(获取支付连接可以封装成工具类)
AutoUpdateCertificatesVerifier verifier =null;
CloseableHttpClient httpClient =null;
PrivateKey merchantPrivateKey =null;
try{
merchantPrivateKey =
PemUtil.loadPrivateKey(
new ByteArrayInputStream(emsWeChatPayConfig.getPrivateKey().getBytes("utf-8")));
// 使用自动更新的签名验证器,不需要传入证书
verifier =
new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(
emsWeChatPayConfig.getMchId(),
new PrivateKeySigner(emsWeChatPayConfig.getMchSerialNo(), merchantPrivateKey)),
emsWeChatPayConfig.getApiV3key().getBytes("utf-8"));
httpClient =
WechatPayHttpClientBuilder.create()
.withMerchant(emsWeChatPayConfig.getMchId(), emsWeChatPayConfig.getMchSerialNo(), merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier))
.build();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
log.error("【微信下单支付】----初始化连接异常--{}--",e.getMessage());
}
HttpPost httpPost = new HttpPost(emsWeChatPayConfig.getPayUrl());
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode rootNode = objectMapper.createObjectNode();
rootNode
.put("mchid", emsWeChatPayConfig.getMchId())
.put("appid", emsWeChatPayConfig.getAppId())
.put("description", payInfoVo.getTitle())
.put("notify_url", emsWeChatPayConfig.getNotifyUrl())
.put("out_trade_no", payInfoVo.getOutTradeNo());
rootNode.putObject("amount").put("total", payInfoVo.getPayFree());
try {
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
int statusCode = response.getStatusLine().getStatusCode();
log.info("【微信下单返回参数】:状态码:{} 返回内容:{}",statusCode,bodyAsString);
//微信成功响应
if (statusCode==200){
String timestamp = System.currentTimeMillis()/1000+"";
String nonce = RandomUtil.randomString(32);
StringBuilder builder = new StringBuilder();
// Appid
builder.append(emsWeChatPayConfig.getAppId()).append("\n");
// 时间戳
builder.append(timestamp).append("\n");
// 随机字符串
builder.append(nonce).append("\n");
JsonNode jsonNode = objectMapper.readTree(bodyAsString);
// 预支付会话ID
builder.append(jsonNode.get("prepay_id").textValue()).append("\n");
// 获取签名
//String ciphertext = RsaCryptoUtil.encryptOAEP(builder.toString(),verifier.getValidCertificate());
String sign = this.sign(builder.toString().getBytes("utf-8"), merchantPrivateKey);
JSONObject jsonMap = new JSONObject();
jsonMap.put("noncestr", nonce);
jsonMap.put("timestamp", timestamp);
jsonMap.put("prepayid", jsonNode.get("prepay_id").textValue());
jsonMap.put("sign", sign);
jsonMap.put("package", emsWeChatPayConfig.getPackageStr());
jsonMap.put("appid", emsWeChatPayConfig.getAppId());
jsonMap.put("partnerid", emsWeChatPayConfig.getMchId());
return jsonMap.toJSONString();
2、计算签名方法
/**
* 计算签名
* @param message
* @param yourPrivateKey
* @return
*/
private String sign(byte[] message, PrivateKey yourPrivateKey) {
try{
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(yourPrivateKey);
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return "";
}
3、支付回调通知
public String callback(HttpServletRequest request) throws IOException {
log.info("【微信支付结果回调】:回调成功");
String wechatpayTimestamp = request.getHeader("Wechatpay-Timestamp");
String wechatpayNonce = request.getHeader("Wechatpay-Nonce");
String wechatpaySignature = request.getHeader("Wechatpay-Signature");
String wechatpaySerial = request.getHeader("Wechatpay-Serial");
BufferedReader reader = request.getReader();
String str = null;
StringBuilder builder = new StringBuilder();
while ((str = reader.readLine()) != null) {
builder.append(str);
}
StringBuilder signStr = new StringBuilder();
signStr.append(wechatpayTimestamp).append("\n");
signStr.append(wechatpayNonce).append("\n");
signStr.append(builder.toString()).append("\n");
//验证签名
if (!signVerify(wechatpaySerial, signStr.toString(), wechatpaySignature)) {
log.error("【微信支付回调】:签名延签错误");
return this.resultCallbackJson(Constants.FAIL_CODE,"签名延签错误");
}
//解密密文
String decryptOrder = this.decryptOrder(builder.toString());
log.info("【微信支付回调】:解密密文:{}",decryptOrder);
if (StringUtils.isEmpty(decryptOrder)){
log.error("【微信支付回调】:解密为空");
return this.resultCallbackJson(Constants.FAIL_CODE,"解密为空");
}
JSONObject resultJson = JSONObject.parseObject(decryptOrder);
//微信订单号
String transactionId = resultJson.getString("transaction_id");
//商户订单号
String outTradeNo = resultJson.getString("out_trade_no");
//支付状态
String tradeState = resultJson.getString("trade_state");
JSONObject amount = resultJson.getJSONObject("amount");
//用户支付金额
int payerTotal = amount.getInteger("payer_total");
//总金额
int total = amount.getInteger("total");
//附加数据
String attach = amount.getString("attach");
}
4、验证签名
/**
* 验证签名
*
* @param serial
* @param message
* @param signture
* @return
* @throws UnsupportedEncodingException
*/
public boolean signVerify(String serial, String message, String signture) throws UnsupportedEncodingException {
AutoUpdateCertificatesVerifier verifier =null;
PrivateKey merchantPrivateKey =null;
try{
merchantPrivateKey =
PemUtil.loadPrivateKey(
new ByteArrayInputStream(emsWeChatPayConfig.getPrivateKey().getBytes("utf-8")));
// 使用自动更新的签名验证器,不需要传入证书
verifier =
new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(
emsWeChatPayConfig.getMchId(),
new PrivateKeySigner(emsWeChatPayConfig.getMchSerialNo(), merchantPrivateKey)),
emsWeChatPayConfig.getApiV3key().getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
log.error("【微信下单支付】----初始化连接异常--{}--",e.getMessage());
}
return verifier.verify(serial, message.getBytes("utf-8"), signture);
}
5、解密回调通知密文
/**
* 解密回调通知密文
* @param body
* @return
*/
private String decryptOrder(String body){
try {
AesUtil aesUtil = new AesUtil(emsWeChatPayConfig.getApiV3key().getBytes("utf-8"));
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(body);
JsonNode resource = jsonNode.get("resource");
//数据密文
String ciphertext = resource.get("ciphertext").textValue();
String associatedData = resource.get("associated_data").textValue();
String nonce = resource.get("nonce").textValue();
return aesUtil.decryptToString(associatedData.getBytes("utf-8"),nonce.getBytes("utf-8"),ciphertext);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
return "";
}
|