微信请求加密

This commit is contained in:
gong
2025-12-29 11:42:20 +08:00
parent 2046ad2486
commit 38ea1478cb
4 changed files with 218 additions and 5 deletions

View File

@@ -18,7 +18,7 @@ public class WechatConfig {
* @param dto 微信支付配置
* @return 微信支付配置
*/
public static Config getConfig(WechatPayConfigDto dto) {
public static Config getRsaConfig(WechatPayConfigDto dto) {
return new RSAPublicKeyConfig.Builder()
.merchantId(dto.getMerchantId())
.privateKey(dto.getPrivateKey())
@@ -41,7 +41,7 @@ public class WechatConfig {
* @return 文件上传服务
*/
public static FileUploadService getFileUploadService(WechatPayConfigDto dto) {
return getFileUploadService(getConfig(dto));
return getFileUploadService(getRsaConfig(dto));
}
}

View File

@@ -1,15 +1,45 @@
package com.czg.wechat;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.Base64;
/**
* 微信支付加解密
* @author yjjie
* @date 2025/12/26 10:58
*/
@Slf4j
public class WechatEncrypt {
public static String rsaEncryptOaep(String message, PublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] data = message.getBytes(StandardCharsets.UTF_8);
byte[] cipherData = cipher.doFinal(data);
return Base64.getEncoder().encodeToString(cipherData);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
log.error("当前Java环境不支持RSA v1.5/OAEP");
} catch (InvalidKeyException e) {
log.error("无效的证书");
} catch (IllegalBlockSizeException | BadPaddingException e) {
log.error("加密原串的长度不能超过214字节");
}
return "";
}
public static String getFileBytesSha256(byte[] input) throws NoSuchAlgorithmException {
return bytesToHex(calculateSha256(input));
}

View File

@@ -3,7 +3,15 @@ package com.czg.wechat;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.czg.wechat.dto.config.WechatPayConfigDto;
import com.czg.wechat.dto.req.entry.WechatEntryReqDto;
import com.czg.wechat.dto.req.entry.*;
import com.czg.wechat.dto.req.entry.business.WechatEntryBusinessReqDto;
import com.czg.wechat.dto.req.entry.business.WechatEntryIdentityReqDto;
import com.czg.wechat.dto.req.entry.business.WechatEntryLicenseReqDto;
import com.czg.wechat.dto.req.entry.business.sales.WechatEntrySalesInfoReqDto;
import com.czg.wechat.dto.req.entry.business.sales.WechatEntryStoreInfoReqDto;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
import com.wechat.pay.java.core.cipher.Signer;
import com.wechat.pay.java.service.file.FileUploadService;
import com.wechat.pay.java.service.file.model.FileUploadResponse;
import lombok.extern.slf4j.Slf4j;
@@ -12,6 +20,8 @@ import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Arrays;
import java.util.List;
/**
* 微信支付进件 管理
@@ -22,6 +32,21 @@ import java.net.http.HttpResponse;
@Slf4j
public class WechatEntryManager {
public static void entryMerchant(WechatPayConfigDto configDto, WechatEntryReqDto reqDto) {
String params = JSONObject.toJSONString(reqDto, JSONWriter.Feature.IgnoreEmpty);
// String string = WechatReqUtils.encryptReqParam(configDto, "POST", "/v3/applyment4sub/applyment/", params);
WechatReqUtils.postReq(configDto, "POST", "/v3/applyment4sub/applyment/", params);
}
/**
* 上传图片
*
* @param configDto 配置
* @param url 图片URL
* @return 图片ID
*/
public static String uploadImage(WechatPayConfigDto configDto, String url) {
// 校验入参
if (configDto == null || url == null || url.trim().isEmpty()) {
@@ -156,7 +181,78 @@ public class WechatEntryManager {
// String string = uploadImage(dto, "https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png");
// log.info("图片上传成功:{}", string);
WechatEntryReqDto reqDto = new WechatEntryReqDto();
System.out.println(JSONObject.toJSONString(reqDto, JSONWriter.Feature.IgnoreEmpty));
Config config = WechatConfig.getRsaConfig(dto);
PrivacyEncryptor encryptor = config.createEncryptor();
WechatEntryReqDto reqDto = new WechatEntryReqDto()
.setBusinessCode("MER_20231025110010000010000000000001");
WechatEntryContactReqDto contactInfo = new WechatEntryContactReqDto()
.setContactType("LEGAL")
.setContactName(encryptor.encrypt("张三"))
.setContactIdType("IDCARD")
.setContactIdNumber(encryptor.encrypt("110101199001011234"))
.setContactIdDocCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
.setContactIdDocCopyBack("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
.setContactPeriodBegin("2023-10-25")
.setContactPeriodEnd("2024-10-25")
.setMobilePhone(encryptor.encrypt("13888888888"))
.setContactEmail(encryptor.encrypt("123456@qq.com"));
reqDto.setContactInfo(contactInfo);
WechatEntrySubjectReqDto subjectInfo = new WechatEntrySubjectReqDto()
.setSubjectType("SUBJECT_TYPE_INDIVIDUAL");
WechatEntryLicenseReqDto licenseInfo = new WechatEntryLicenseReqDto()
.setLicenseCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
.setLicenseNumber("110101199001011234")
.setMerchantName("张三商行")
.setLegalPerson(encryptor.encrypt("张三"))
.setLicenseAddress("北京")
.setPeriodBegin("2023-10-25")
.setPeriodEnd("2024-10-25");
subjectInfo.setBusinessLicenseInfo(licenseInfo);
WechatEntryIdentityReqDto identityInfo = new WechatEntryIdentityReqDto()
.setIdHolderType("LEGAL");
subjectInfo.setIdentityInfo(identityInfo);
reqDto.setSubjectInfo(subjectInfo);
WechatEntryBusinessReqDto businessInfo = new WechatEntryBusinessReqDto()
.setMerchantShortname("张三商行")
.setServicePhone("13888888888");
WechatEntrySalesInfoReqDto salesInfo = new WechatEntrySalesInfoReqDto()
.setSalesScenesType(List.of("SALES_SCENES_STORE"));
WechatEntryStoreInfoReqDto storeInfo = new WechatEntryStoreInfoReqDto()
.setBizStoreName("张三商行")
.setBizAddressCode("110101")
.setBizStoreAddress("北京")
.setStoreEntrancePic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"))
.setIndoorPic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"));
salesInfo.setBizStoreInfo(storeInfo);
businessInfo.setSalesInfo(salesInfo);
reqDto.setBusinessInfo(businessInfo);
WechatEntrySettleReqDto settleInfo = new WechatEntrySettleReqDto()
.setSettlementId("719")
.setQualificationType("IDCARD")
.setQualifications(List.of("110101199001011234"))
.setActivitiesId("20191030111cff5b5e");
reqDto.setSettlementInfo(settleInfo);
WechatEntryBankAccountReqDto bankAccountInfo = new WechatEntryBankAccountReqDto()
.setBankAccountType("BANK_ACCOUNT_TYPE_CORPORATE")
.setAccountBank("ICBC")
.setBankName("中国工商银行")
.setAccountName(encryptor.encrypt("张三"))
.setAccountNumber(encryptor.encrypt("110101199001011234"));
reqDto.setBankAccountInfo(bankAccountInfo);
entryMerchant(dto, reqDto);
}
}

View File

@@ -0,0 +1,87 @@
package com.czg.wechat;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.czg.wechat.dto.config.WechatPayConfigDto;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
import com.wechat.pay.java.core.cipher.Signer;
import lombok.extern.slf4j.Slf4j;
import java.util.UUID;
/**
* 微信请求工具类
*
* @author yjjie
* @date 2025/12/29 10:02
*/
@Slf4j
public class WechatReqUtils {
public static String postReq(WechatPayConfigDto configDto, String method, String url, String body) {
long timestamp = getTimestamp();
String nonce = getNonceStr();
String signature = encryptReqParam(configDto, method, url, body, timestamp, nonce);
String authorization = String.format("WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\",timestamp=\"%d\",serial_no=\"%s\"",
configDto.getMerchantId(), nonce, signature, timestamp, "4DE9BAC2EA584C3F274F694C9753CA814C4E9BF4");
log.info("authorization = {}", authorization);
HttpRequest request = HttpUtil.createPost(configDto.getDomain() + url)
.header("Authorization", authorization)
.header("Content-Type", "application/json")
.header("Wechatpay-Serial", configDto.getPublicKeyId())
// .header("Wechatpay-Serial", "4DE9BAC2EA584C3F274F694C9753CA814C4E9BF4")
.body(body);
String s = request.execute().body();
log.info("s = {}", s);
return "";
}
/**
* 加密请求参数
* @param configDto 配置
* @param method 请求方法
* @param url 请求地址
* @param body 请求报文主体
* @return 加密后的报文
*
* 签名方法
* HTTP请求方法\n
* URL\n
* 请求时间戳\n
* 请求随机串\n
* 请求报文主体\n
*/
public static String encryptReqParam(WechatPayConfigDto configDto, String method, String url, String body, long timestamp, String nonce) {
String encryptStr = String.format("%s\n%s\n%d\n%s\n%s\n",
method, url, timestamp, nonce, body);
System.out.println("encryptStr = \n" + encryptStr);
Config config = WechatConfig.getRsaConfig(configDto);
Signer signer = config.createSigner();
String signature = signer.sign(encryptStr).getSign();
System.out.println("signature = " + signature);
return signature;
}
/**
* 获取随机串
*/
private static String getNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
}
/**
* 获取时间戳
*/
private static long getTimestamp() {
return System.currentTimeMillis()/1000;
}
}