diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/api/BasePayConfigStorage.java b/pay-java-common/src/main/java/com/egzosn/pay/common/api/BasePayConfigStorage.java index f813936..b559fd5 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/api/BasePayConfigStorage.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/api/BasePayConfigStorage.java @@ -41,7 +41,7 @@ public abstract class BasePayConfigStorage implements PayConfigStorage { /** * 字符类型 */ - private String inputCharset; + private String inputCharset = "utf-8"; /** diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/WxV3PayController.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/WxV3PayController.java index e328f59..c23bf41 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/WxV3PayController.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/WxV3PayController.java @@ -56,14 +56,16 @@ public class WxV3PayController { wxPayConfigStorage.setMchId("1602947765"); //V3密钥 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml wxPayConfigStorage.setV3ApiKey("9bd8f0e7af4841299d782406b7774f57"); + //验签、转账等接口使用,9月份开始不允许获取证书方式了,直接通过公钥字符来做, + wxPayConfigStorage.setKeyPublic("支付平台公钥(原为自动获取的证书)"); wxPayConfigStorage.setNotifyUrl("http://sailinmu.iok.la/wxV3/payBack.json"); wxPayConfigStorage.setReturnUrl("http://sailinmu.iok.la/wxV3/payBack.json"); wxPayConfigStorage.setInputCharset("utf-8"); //使用证书时设置为true // wxPayConfigStorage.setCertSign(true); //商户API证书 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_1.shtml - wxPayConfigStorage.setApiClientKeyP12("yifenli_mall.p12"); - wxPayConfigStorage.setCertStoreType(CertStoreType.PATH); + wxPayConfigStorage.setApiClientKeyP12("http://pay.egzosn.com/yifenli_mall.p12"); + wxPayConfigStorage.setCertStoreType(CertStoreType.URL); service = new WxPayService(wxPayConfigStorage); //微信海外支付:东南亚 // service.setApiServerUrl("https://apihk.mch.weixin.qq.com"); diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/api/WxPayService.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/api/WxPayService.java index 33f0ad6..9984e62 100644 --- a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/api/WxPayService.java +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/api/WxPayService.java @@ -2,7 +2,9 @@ package com.egzosn.pay.wx.v3.api; import java.io.IOException; import java.io.InputStream; +import java.security.GeneralSecurityException; import java.security.PrivateKey; +import java.security.PublicKey; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Collections; @@ -51,6 +53,7 @@ import com.egzosn.pay.common.util.MapGen; import com.egzosn.pay.common.util.Util; import com.egzosn.pay.common.util.sign.SignTextUtils; import com.egzosn.pay.common.util.sign.SignUtils; +import com.egzosn.pay.common.util.sign.encrypt.RSA; import com.egzosn.pay.common.util.sign.encrypt.RSA2; import com.egzosn.pay.common.util.str.StringUtils; import com.egzosn.pay.wx.bean.WxPayError; @@ -130,8 +133,10 @@ public class WxPayService extends BasePayService implements if (null == assistService) { assistService = new DefaultWxPayAssistService(this); } - //在这预先进行初始化 - assistService.refreshCertificate(); + if (StringUtils.isEmpty(payConfigStorage.getKeyPublic())) { + //在这预先进行初始化 + assistService.refreshCertificate(); + } return assistService; } @@ -222,14 +227,15 @@ public class WxPayService extends BasePayService implements //微信平台签名 String signature = noticeParams.getHeader("wechatpay-signature"); - Certificate certificate = getAssistService().getCertificate(serial); - //这里为微信回调时的请求内容体,原值数据 String body = noticeParams.getBodyStr(); //签名信息 String signText = StringUtils.joining("\n", timestamp, nonce, body); - + if (StringUtils.isNotEmpty(payConfigStorage.getKeyPublic())) { + return RSA2.verify(signText, signature, payConfigStorage.getKeyPublic(), payConfigStorage.getInputCharset()); + } + Certificate certificate = getAssistService().getCertificate(serial); return RSA2.verify(signText, signature, certificate, payConfigStorage.getInputCharset()); } @@ -685,19 +691,32 @@ public class WxPayService extends BasePayService implements return null; } - // 商户上送敏感信息时使用`微信支付平台公钥`加密 - String serialNumber = payConfigStorage.getCertEnvironment().getPlatformSerialNumber(); - Certificate certificate = getAssistService().getCertificate(serialNumber); + PublicKey publicKeyTmp = null; + if (StringUtils.isEmpty(payConfigStorage.getKeyPublic())) { + // 商户上送敏感信息时使用`微信支付平台公钥`加密 + String serialNumber = payConfigStorage.getCertEnvironment().getPlatformSerialNumber(); + Certificate certificate = getAssistService().getCertificate(serialNumber); + publicKeyTmp = certificate.getPublicKey(); + } + else { + try { + publicKeyTmp = RSA.getPublicKey(payConfigStorage.getKeyPublic()); + } + catch (IOException | GeneralSecurityException e) { + throw new PayErrorException(new WxPayError("", e.getMessage())); + } + } + PublicKey publicKey = publicKeyTmp; return transferDetails.stream() .peek(transferDetailListItem -> { String userName = transferDetailListItem.getUserName(); if (StringUtils.isNotEmpty(userName)) { - String encryptedUserName = AntCertificationUtil.encryptToString(userName, certificate); + String encryptedUserName = AntCertificationUtil.encryptToString(userName, publicKey); transferDetailListItem.setUserName(encryptedUserName); } String userIdCard = transferDetailListItem.getUserIdCard(); if (StringUtils.isNotEmpty(userIdCard)) { - String encryptedUserIdCard = AntCertificationUtil.encryptToString(userIdCard, certificate); + String encryptedUserIdCard = AntCertificationUtil.encryptToString(userIdCard, publicKey); transferDetailListItem.setUserIdCard(encryptedUserIdCard); } }).collect(Collectors.toList()); diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/utils/AntCertificationUtil.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/utils/AntCertificationUtil.java index e29e163..5e6a58f 100644 --- a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/utils/AntCertificationUtil.java +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/utils/AntCertificationUtil.java @@ -52,7 +52,7 @@ public final class AntCertificationUtil { static { String javaVersion = System.getProperty("java.version"); - if (javaVersion.contains("1.8") || javaVersion.startsWith("8")){ + if (javaVersion.contains("1.8") || javaVersion.startsWith("8")) { Security.setProperty("crypto.policy", "unlimited"); } SignUtils.initBc(); @@ -170,9 +170,20 @@ public final class AntCertificationUtil { * @return 加密后的内容 */ public static String encryptToString(String message, Certificate certificate) { + return encryptToString(message, certificate.getPublicKey()); + } + + /** + * 对请求敏感字段进行加密 + * + * @param message the message + * @param publicKey the certificate + * @return 加密后的内容 + */ + public static String encryptToString(String message, PublicKey publicKey) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", WxConst.BC_PROVIDER); - cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey()); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] data = message.getBytes(StandardCharsets.UTF_8); byte[] cipherData = cipher.doFinal(data);