diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/SignatureProvider.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/SignatureProvider.java index 7611470..900ec7c 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/SignatureProvider.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/SignatureProvider.java @@ -70,7 +70,7 @@ public class SignatureProvider { /** * The constant ID_GENERATOR. */ - private static final IdGenerator ID_GENERATOR = new AlternativeJdkIdGenerator(); + private final IdGenerator nonceStrGenerator = new AlternativeJdkIdGenerator(); /** * The constant SCHEMA. */ @@ -114,18 +114,14 @@ public class SignatureProvider { */ @SneakyThrows public String requestSign(String tenantId, String method, String canonicalUrl, String body) { - Signature signer = Signature.getInstance("SHA256withRSA"); - WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId); - signer.initSign(wechatMetaBean.getKeyPair().getPrivate()); long timestamp = System.currentTimeMillis() / 1000; - String nonceStr = ID_GENERATOR.generateId() + String nonceStr = nonceStrGenerator.generateId() .toString() .replaceAll("-", ""); - final String signatureStr = createSign(method, canonicalUrl, String.valueOf(timestamp), nonceStr, body); - signer.update(signatureStr.getBytes(StandardCharsets.UTF_8)); - String encode = Base64Utils.encodeToString(signer.sign()); - + WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId); + PrivateKey privateKey = wechatMetaBean.getKeyPair().getPrivate(); + String encode = this.doRequestSign(privateKey, method, canonicalUrl, String.valueOf(timestamp), nonceStr, body); // 序列号 String serialNo = wechatMetaBean.getSerialNumber(); // 生成token @@ -135,6 +131,24 @@ public class SignatureProvider { return SCHEMA.concat(token); } + + /** + * Do request sign. + * + * @param privateKey the private key + * @param orderedComponents the orderedComponents + * @return the string + * @since 1.0.4.RELEASE + */ + @SneakyThrows + public String doRequestSign(PrivateKey privateKey, String... orderedComponents) { + Signature signer = Signature.getInstance("SHA256withRSA"); + signer.initSign(privateKey); + final String signatureStr = createSign(orderedComponents); + signer.update(signatureStr.getBytes(StandardCharsets.UTF_8)); + return Base64Utils.encodeToString(signer.sign()); + } + /** * 我方对响应验签,和应答签名做比较,使用微信平台证书. * @@ -257,6 +271,16 @@ public class SignatureProvider { return wechatMetaContainer; } + /** + * Nonce generator. + * + * @return the id generator + * @since 1.0.4.RELEASE + */ + public IdGenerator nonceStrGenerator() { + return nonceStrGenerator; + } + /** * 请求时设置签名 组件 * diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatDirectPayApi.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatDirectPayApi.java index 101264c..64cb11d 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatDirectPayApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatDirectPayApi.java @@ -18,18 +18,22 @@ */ package cn.felord.payment.wechat.v3; -import cn.felord.payment.wechat.enumeration.WeChatServer; +import cn.felord.payment.PayException; import cn.felord.payment.wechat.WechatPayProperties; +import cn.felord.payment.wechat.enumeration.WeChatServer; import cn.felord.payment.wechat.enumeration.WechatPayV3Type; import cn.felord.payment.wechat.v3.model.PayParams; import cn.felord.payment.wechat.v3.model.TransactionQueryParams; import com.fasterxml.jackson.databind.node.ObjectNode; +import org.springframework.http.HttpStatus; import org.springframework.http.RequestEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; +import java.security.PrivateKey; +import java.util.Objects; /** * 普通支付-直连模式. @@ -59,7 +63,43 @@ public class WechatDirectPayApi extends AbstractApi { WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>(); this.client().withType(WechatPayV3Type.APP, payParams) .function(this::payFunction) - .consumer(wechatResponseEntity::convert) + .consumer(responseEntity -> { + int httpStatus = HttpStatus.BAD_REQUEST.value(); + ObjectNode body = null; + if (Objects.nonNull(responseEntity)) { + httpStatus = responseEntity.getStatusCodeValue(); + body = responseEntity.getBody(); + if (Objects.isNull(body)) { + throw new PayException("response body cannot be resolved"); + } + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + + SignatureProvider signatureProvider = this.client().signatureProvider(); + String nonceStr = signatureProvider.nonceStrGenerator() + .generateId() + .toString() + .replaceAll("-", ""); + + WechatMetaContainer wechatMetaContainer = signatureProvider.wechatMetaContainer(); + + WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId()); + PrivateKey privateKey = wechatMetaBean.getKeyPair().getPrivate(); + String appId = wechatMetaBean.getV3().getAppId(); + String prepayId = body.get("prepay_id").asText(); + String paySign = signatureProvider.doRequestSign(privateKey, appId, timestamp, nonceStr, prepayId); + body.put("appid", appId); + String mchId = wechatMetaBean.getV3().getMchId(); + body.put("partnerid", mchId); + body.put("prepayid", prepayId); + body.put("package", "Sign=WXPay"); + body.put("nonceStr", nonceStr); + body.put("timeStamp", timestamp); + body.put("signType", "RSA"); + body.put("paySign", paySign); + } + wechatResponseEntity.setHttpStatus(httpStatus); + wechatResponseEntity.setBody(body); + }) .request(); return wechatResponseEntity; } @@ -74,7 +114,40 @@ public class WechatDirectPayApi extends AbstractApi { WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>(); this.client().withType(WechatPayV3Type.JSAPI, payParams) .function(this::payFunction) - .consumer(wechatResponseEntity::convert) + .consumer(responseEntity -> { + int httpStatus = HttpStatus.BAD_REQUEST.value(); + ObjectNode body = null; + if (Objects.nonNull(responseEntity)) { + httpStatus = responseEntity.getStatusCodeValue(); + body = responseEntity.getBody(); + if (Objects.isNull(body)) { + throw new PayException("response body cannot be resolved"); + } + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + + SignatureProvider signatureProvider = this.client().signatureProvider(); + String nonceStr = signatureProvider.nonceStrGenerator() + .generateId() + .toString() + .replaceAll("-", ""); + + String packageStr = "prepay_id=" + body.get("prepay_id").asText(); + WechatMetaContainer wechatMetaContainer = signatureProvider.wechatMetaContainer(); + + WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId()); + PrivateKey privateKey = wechatMetaBean.getKeyPair().getPrivate(); + String appId = wechatMetaBean.getV3().getAppId(); + String paySign = signatureProvider.doRequestSign(privateKey, appId, timestamp, nonceStr, packageStr); + body.put("appId", appId); + body.put("timeStamp", timestamp); + body.put("nonceStr", nonceStr); + body.put("package", packageStr); + body.put("signType", "RSA"); + body.put("paySign", paySign); + } + wechatResponseEntity.setHttpStatus(httpStatus); + wechatResponseEntity.setBody(body); + }) .request(); return wechatResponseEntity; }