diff --git a/framework/pom.xml b/framework/pom.xml index bfcd88a3..2b359058 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -468,6 +468,11 @@ runtime osx-aarch_64 + + com.github.wechatpay-apiv3 + wechatpay-java + 0.2.15 + diff --git a/framework/src/main/java/cn/lili/common/utils/CurrencyUtil.java b/framework/src/main/java/cn/lili/common/utils/CurrencyUtil.java index aa030d6e..1b731c61 100644 --- a/framework/src/main/java/cn/lili/common/utils/CurrencyUtil.java +++ b/framework/src/main/java/cn/lili/common/utils/CurrencyUtil.java @@ -125,13 +125,21 @@ public final class CurrencyUtil { return (int) price; } + public static Long getFenLong(Double money) { + BigDecimal bigDecimalValue = BigDecimal.valueOf(money); + // 乘以 100 并四舍五入到最接近的整数 + BigDecimal fenValue = bigDecimalValue.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP); + + return fenValue.longValue(); + } + /** * 金额转分 * * @param money 金额 * @return double类型分 */ - public static double reversalFen(Double money) { + public static double reversalFen(Integer money) { return div(money, 100); } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/PayKit.java b/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/PayKit.java index 3b2d9d09..626a1b2f 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/PayKit.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/PayKit.java @@ -327,6 +327,24 @@ public class PayKit { return RsaKit.encryptByPrivateKey(signMessage, privateKey); } + /** + * v3 接口创建签名 + * + * @param signMessage 待签名的参数 + * @param key key.pem 证书 + * @return 生成 v3 签名 + * @throws Exception 异常信息 + */ + public static String createPublicSign(String signMessage, String key) throws Exception { + if (StrUtil.isEmpty(signMessage)) { + return null; + } + //获取商户私钥 + PrivateKey privateKey = PayKit.getPublicKey(key); + //生成签名 + return RsaKit.encryptByPrivateKey(signMessage, privateKey); + } + /** * v3 接口创建签名 * @@ -392,6 +410,23 @@ public class PayKit { return RsaKit.loadPrivateKey(privateKey); } + /** + * 获取商户公钥 + * + * @param key 商户私钥证书 + * @return {@link PrivateKey} 商户私钥 + * @throws Exception 异常信息 + */ + public static PrivateKey getPublicKey(String key) throws Exception { +// String originalKey = FileUtil.readUtf8String(keyPath); + String privateKey = key + .replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replaceAll("\\s+", ""); + + return RsaKit.loadPrivateKey(privateKey); + } + /** * 获取证书 * diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/RsaKit.java b/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/RsaKit.java index e045ea41..e9c10595 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/RsaKit.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/RsaKit.java @@ -312,13 +312,18 @@ public class RsaKit { */ public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception { try { + + byte[] buffer = Base64.decode(privateKeyStr); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); return keyFactory.generatePrivate(keySpec); + + } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { + e.printStackTrace(); throw new Exception("私钥非法"); } catch (NullPointerException e) { throw new Exception("私钥数据为空"); diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/WxPayKit.java b/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/WxPayKit.java index c9ec5e53..da918bad 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/WxPayKit.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/core/kit/WxPayKit.java @@ -450,6 +450,7 @@ public class WxPayKit { * @param mchId 商户Id * @param serialNo 商户 API 证书序列号 * @param key key.pem 证书 + * @param publicKey 公钥证书 * @param body 接口请求参数 * @param nonceStr 随机字符库 * @param timestamp 时间戳 @@ -458,11 +459,12 @@ public class WxPayKit { * @throws Exception 异常信息 */ public static String buildAuthorization(RequestMethodEnums method, String urlSuffix, String mchId, - String serialNo, String key, String body, String nonceStr, + String serialNo, String key, String publicKey ,String body, String nonceStr, long timestamp, String authType) throws Exception { //构建签名参数 String buildSignMessage = PayKit.buildSignMessage(method, urlSuffix, timestamp, nonceStr, body); - String signature = PayKit.createSign(buildSignMessage, key); + String publicKeySignature = PayKit.createPublicSign(buildSignMessage, publicKey); + String signature = PayKit.createSign(publicKeySignature, key); //根据平台规则生成请求头 authorization return PayKit.getAuthorization(mchId, serialNo, nonceStr, String.valueOf(timestamp), signature, authType); } @@ -492,27 +494,27 @@ public class WxPayKit { return PayKit.getAuthorization(mchId, serialNo, nonceStr, String.valueOf(timestamp), signature, authType); } - /** - * 构建 v3 接口所需的 Authorization - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlSuffix 可通过 WxApiType 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param keyPath key.pem 证书路径 - * @param body 接口请求参数 - * @return {@link String} 返回 v3 所需的 Authorization - * @throws Exception 异常信息 - */ - public static String buildAuthorization(RequestMethodEnums method, String urlSuffix, String mchId, - String serialNo, String keyPath, String body) throws Exception { - - long timestamp = System.currentTimeMillis() / 1000; - String authType = "WECHATPAY2-SHA256-RSA2048"; - String nonceStr = IdUtil.fastSimpleUUID(); - - return buildAuthorization(method, urlSuffix, mchId, serialNo, keyPath, body, nonceStr, timestamp, authType); - } +// /** +// * 构建 v3 接口所需的 Authorization +// * +// * @param method {@link RequestMethodEnums} 请求方法 +// * @param urlSuffix 可通过 WxApiType 来获取,URL挂载参数需要自行拼接 +// * @param mchId 商户Id +// * @param serialNo 商户 API 证书序列号 +// * @param keyPath key.pem 证书路径 +// * @param body 接口请求参数 +// * @return {@link String} 返回 v3 所需的 Authorization +// * @throws Exception 异常信息 +// */ +// public static String buildAuthorization(RequestMethodEnums method, String urlSuffix, String mchId, +// String serialNo, String keyPath, String body) throws Exception { +// +// long timestamp = System.currentTimeMillis() / 1000; +// String authType = "WECHATPAY2-SHA256-RSA2048"; +// String nonceStr = IdUtil.fastSimpleUUID(); +// +// return buildAuthorization(method, urlSuffix, mchId, serialNo, keyPath, body, nonceStr, timestamp, authType); +// } /** * 构建 v3 接口所需的 Authorization diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatApi.java b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatApi.java index 240a658a..e2752820 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatApi.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatApi.java @@ -1,859 +1,862 @@ -package cn.lili.modules.payment.kit.plugin.wechat; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.http.ContentType; -import cn.lili.modules.payment.kit.core.PaymentHttpResponse; -import cn.lili.modules.payment.kit.core.enums.RequestMethodEnums; -import cn.lili.modules.payment.kit.core.kit.HttpKit; -import cn.lili.modules.payment.kit.core.kit.PayKit; -import cn.lili.modules.payment.kit.core.kit.WxPayKit; -import cn.lili.modules.payment.kit.plugin.wechat.enums.WechatApiEnum; -import cn.lili.modules.payment.kit.plugin.wechat.enums.WechatDomain; - -import java.io.File; -import java.io.InputStream; -import java.security.PrivateKey; -import java.util.HashMap; -import java.util.Map; - -/** - * 微信支付相关接口 - * - * @author Chopper - * @since 2021/1/26 15:25 - */ - -public class WechatApi { - - private WechatApi() { - } - - /** - * 获取接口请求的 URL - * - * @param wechatApiEnum {@link WechatApiEnum} 支付 API 接口枚举 - * @return {@link String} 返回完整的接口请求URL - */ - public static String getReqUrl(WechatApiEnum wechatApiEnum) { - return getReqUrl(wechatApiEnum, null, false); - } - - /** - * 获取接口请求的 URL - * - * @param wechatApiEnum {@link WechatApiEnum} 支付 API 接口枚举 - * @param isSandBox 是否是沙箱环境 - * @return {@link String} 返回完整的接口请求URL - */ - public static String getReqUrl(WechatApiEnum wechatApiEnum, boolean isSandBox) { - return getReqUrl(wechatApiEnum, null, isSandBox); - } - - /** - * 获取接口请求的 URL - * - * @param wechatApiEnum {@link WechatApiEnum} 支付 API 接口枚举 - * @param wechatDomain {@link WechatDomain} 支付 API 接口域名枚举 - * @param isSandBox 是否是沙箱环境 - * @return {@link String} 返回完整的接口请求URL - */ - public static String getReqUrl(WechatApiEnum wechatApiEnum, WechatDomain wechatDomain, boolean isSandBox) { - if (wechatDomain == null) { - wechatDomain = WechatDomain.CHINA; - } - return wechatDomain.getType() - .concat(isSandBox ? WechatApiEnum.SAND_BOX_NEW.getUrl() : "") - .concat(wechatApiEnum.getUrl()); - } - - /** - * 发起请求 - * - * @param apiUrl 接口 URL - * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} - * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 - * @param params 接口请求参数 - * @return {@link String} 请求返回的结果 - */ - public static String execution(String apiUrl, Map params) { - return doPost(apiUrl, params); - } - - /** - * 发起请求 - * - * @param apiUrl 接口 URL - * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} - * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 - * @param params 接口请求参数 - * @return {@link String} 请求返回的结果 - */ - public static String executionByGet(String apiUrl, Map params) { - return doGet(apiUrl, params); - } - - /** - * 发起请求 - * - * @param apiUrl 接口 URL - * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} - * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 - * @param params 接口请求参数 - * @param certPath 证书文件路径 - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String execution(String apiUrl, Map params, String certPath, String certPass) { - return doPostSsl(apiUrl, params, certPath, certPass); - } - - /** - * 发起请求 - * - * @param apiUrl 接口 URL - * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} - * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 - * @param params 接口请求参数 - * @param certPath 证书文件路径 - * @return {@link String} 请求返回的结果 - */ - public static String execution(String apiUrl, Map params, String certPath) { - return doPostSsl(apiUrl, params, certPath); - } - - /** - * 发起请求 - * - * @param apiUrl 接口 URL - * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} - * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 - * @param params 接口请求参数 - * @param certFile 证书文件输入流 - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String execution(String apiUrl, Map params, InputStream certFile, String certPass) { - return doPostSsl(apiUrl, params, certFile, certPass); - } - - /** - * 发起请求 - * - * @param apiUrl 接口 URL - * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} - * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 - * @param params 接口请求参数 - * @param certFile 证书文件输入流 - * @return {@link String} 请求返回的结果 - */ - public static String execution(String apiUrl, Map params, InputStream certFile) { - return doPostSsl(apiUrl, params, certFile); - } - - public static String execution(String apiUrl, Map params, - String certPath, String certPass, String filePath) { - return doUploadSsl(apiUrl, params, certPath, certPass, filePath); - } - - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号,接口中包含敏感信息时必传 - * @param keyPath apiclient_key.pem 证书 - * @param body 接口请求参数 - * @param nonceStr 随机字符库 - * @param timestamp 时间戳 - * @param authType 认证类型 - * @param file 文件 - * @return {@link PaymentHttpResponse} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, - String mchId, String serialNo, String platSerialNo, String key, - String body, String nonceStr, long timestamp, String authType, - File file) throws Exception { - //构建 Authorization - String authorization = WxPayKit.buildAuthorization(method, urlSuffix, mchId, serialNo, - key, body, nonceStr, timestamp, authType); - - if (StrUtil.isEmpty(platSerialNo)) { - platSerialNo = serialNo; - } - if (method == RequestMethodEnums.GET) { - return get(urlPrefix.concat(urlSuffix), authorization, platSerialNo, null); - } else if (method == RequestMethodEnums.POST) { - return post(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); - } else if (method == RequestMethodEnums.DELETE) { - return delete(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); - } else if (method == RequestMethodEnums.UPLOAD) { - return upload(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body, file); - } else if (method == RequestMethodEnums.PUT) { - return put(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); - } - return null; - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号,接口中包含敏感信息时必传 - * @param privateKey 商户私钥 - * @param body 接口请求参数 - * @param nonceStr 随机字符库 - * @param timestamp 时间戳 - * @param authType 认证类型 - * @param file 文件 - * @return {@link PaymentHttpResponse} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, - String mchId, String serialNo, String platSerialNo, PrivateKey privateKey, - String body, String nonceStr, long timestamp, String authType, - File file) throws Exception { - //构建 Authorization - String authorization = WxPayKit.buildAuthorization(method, urlSuffix, mchId, serialNo, - privateKey, body, nonceStr, timestamp, authType); - - if (StrUtil.isEmpty(platSerialNo)) { - platSerialNo = serialNo; - } - - if (method == RequestMethodEnums.GET) { - return get(urlPrefix.concat(urlSuffix), authorization, platSerialNo, null); - } else if (method == RequestMethodEnums.POST) { - return post(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); - } else if (method == RequestMethodEnums.DELETE) { - return delete(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); - } else if (method == RequestMethodEnums.UPLOAD) { - return upload(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body, file); - } else if (method == RequestMethodEnums.PUT) { - return put(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); - } - return null; - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param key apiclient_key.pem 证书 - * @param body 接口请求参数 - * @return {@link PaymentHttpResponse} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, String mchId, - String serialNo, String platSerialNo, String key, String body) throws Exception { - long timestamp = System.currentTimeMillis() / 1000; - String authType = "WECHATPAY2-SHA256-RSA2048"; - String nonceStr = WxPayKit.generateStr(); - return v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, key, body, nonceStr, timestamp, authType, null); - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param privateKey 商户私钥 - * @param body 接口请求参数 - * @return {@link PaymentHttpResponse} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, String mchId, - String serialNo, String platSerialNo, PrivateKey privateKey, String body) throws Exception { - long timestamp = System.currentTimeMillis() / 1000; - String authType = "WECHATPAY2-SHA256-RSA2048"; - String nonceStr = WxPayKit.generateStr(); - return v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, privateKey, body, nonceStr, timestamp, authType, null); - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param keyPath apiclient_key.pem 证书路径 - * @param params Get 接口请求参数 - * @return {@link PaymentHttpResponse} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, - String mchId, String serialNo, String platSerialNo, String keyPath, - Map params) throws Exception { - long timestamp = System.currentTimeMillis() / 1000; - String authType = "WECHATPAY2-SHA256-RSA2048"; - String nonceStr = WxPayKit.generateStr(); - if (null != params && !params.keySet().isEmpty()) { - urlSuffix = urlSuffix.concat("?").concat(PayKit.createLinkString(params, true)); - } - return v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, "", nonceStr, timestamp, authType, null); - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param privateKey 商户私钥 - * @param params Get 接口请求参数 - * @return {@link PaymentHttpResponse} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, - String mchId, String serialNo, String platSerialNo, PrivateKey privateKey, - Map params) throws Exception { - long timestamp = System.currentTimeMillis() / 1000; - String authType = "WECHATPAY2-SHA256-RSA2048"; - String nonceStr = WxPayKit.generateStr(); - if (null != params && !params.keySet().isEmpty()) { - urlSuffix = urlSuffix.concat("?").concat(PayKit.createLinkString(params, true)); - } - return v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, privateKey, "", nonceStr, timestamp, authType, null); - } - - /** - * V3 接口统一执行入口 - * - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param keyPath apiclient_key.pem 证书路径 - * @param body 接口请求参数 - * @param file 文件 - * @return {@link PaymentHttpResponse} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - public static PaymentHttpResponse v3(String urlPrefix, String urlSuffix, String mchId, String serialNo, String platSerialNo, String keyPath, String body, File file) throws Exception { - long timestamp = System.currentTimeMillis() / 1000; - String authType = "WECHATPAY2-SHA256-RSA2048"; - String nonceStr = WxPayKit.generateStr(); - return v3(RequestMethodEnums.UPLOAD, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, body, nonceStr, timestamp, authType, file); - } - - /** - * V3 接口统一执行入口 - * - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param privateKey 商户私钥 - * @param body 接口请求参数 - * @param file 文件 - * @return {@link PaymentHttpResponse} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - public static PaymentHttpResponse v3(String urlPrefix, String urlSuffix, String mchId, String serialNo, - String platSerialNo, PrivateKey privateKey, String body, File file) throws Exception { - long timestamp = System.currentTimeMillis() / 1000; - String authType = "WECHATPAY2-SHA256-RSA2048"; - String nonceStr = WxPayKit.generateStr(); - return v3(RequestMethodEnums.UPLOAD, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, privateKey, body, nonceStr, timestamp, authType, file); - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号,接口中包含敏感信息时必传 - * @param keyPath apiclient_key.pem 证书路径 - * @param body 接口请求参数 - * @param nonceStr 随机字符库 - * @param timestamp 时间戳 - * @param authType 认证类型 - * @param file 文件 - * @return {@link Map} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - @Deprecated - public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, - String mchId, String serialNo, String platSerialNo, String keyPath, - String body, String nonceStr, long timestamp, String authType, - File file) throws Exception { - PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, body, nonceStr, timestamp, authType, file); - return buildResMap(response); - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param keyPath apiclient_key.pem 证书路径 - * @param body 接口请求参数 - * @return {@link Map} 请求返回的结果 - */ - @Deprecated - public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, String mchId, - String serialNo, String keyPath, String body) throws Exception { - PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, null, keyPath, body); - return buildResMap(response); - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param keyPath apiclient_key.pem 证书路径 - * @param body 接口请求参数 - * @return {@link Map} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - @Deprecated - public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, String mchId, - String serialNo, String platSerialNo, String keyPath, String body) throws Exception { - PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, body); - return buildResMap(response); - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param keyPath apiclient_key.pem 证书路径 - * @param params Get 接口请求参数 - * @return {@link Map} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - @Deprecated - public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, - String mchId, String serialNo, String platSerialNo, String keyPath, - Map params) throws Exception { - PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, params); - return buildResMap(response); - } - - /** - * V3 接口统一执行入口 - * - * @param method {@link RequestMethodEnums} 请求方法 - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param keyPath apiclient_key.pem 证书路径 - * @param params Get 接口请求参数 - * @return {@link Map} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - @Deprecated - public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, - String mchId, String serialNo, String keyPath, - Map params) throws Exception { - PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, null, keyPath, params); - return buildResMap(response); - } - - /** - * V3 接口统一执行入口 - * - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param platSerialNo 平台序列号 - * @param keyPath apiclient_key.pem 证书路径 - * @param body 接口请求参数 - * @param file 文件 - * @return {@link Map} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - @Deprecated - public static Map v3Upload(String urlPrefix, String urlSuffix, String mchId, String serialNo, String platSerialNo, String keyPath, String body, File file) throws Exception { - PaymentHttpResponse response = v3(urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, body, file); - return buildResMap(response); - } - - /** - * V3 接口统一执行入口 - * - * @param urlPrefix 可通过 {@link WechatDomain}来获取 - * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 - * @param mchId 商户Id - * @param serialNo 商户 API 证书序列号 - * @param keyPath apiclient_key.pem 证书路径 - * @param body 接口请求参数 - * @param file 文件 - * @return {@link Map} 请求返回的结果 - * @throws Exception 接口执行异常 - */ - @Deprecated - public static Map v3Upload(String urlPrefix, String urlSuffix, String mchId, String serialNo, String keyPath, String body, File file) throws Exception { - return v3Upload(urlPrefix, urlSuffix, mchId, serialNo, null, keyPath, body, file); - } - - /** - * 发放企业红包 - * - * @param params 请求参数 - * @param certPath 证书文件路径 - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String sendWorkWxRedPack(Map params, String certPath, String certPass) { - return execution(getReqUrl(WechatApiEnum.SEND_WORK_WX_RED_PACK), params, certPath, certPass); - } - - /** - * 发放企业红包 - * - * @param params 请求参数 - * @param certFile 证书文件的 InputStream - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String sendWorkWxRedPack(Map params, InputStream certFile, String certPass) { - return execution(getReqUrl(WechatApiEnum.SEND_WORK_WX_RED_PACK), params, certFile, certPass); - } - - /** - * 查询向员工付款记录 - * - * @param params 请求参数 - * @param certPath 证书文件路径 - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String queryWorkWxRedPack(Map params, String certPath, String certPass) { - return execution(getReqUrl(WechatApiEnum.QUERY_WORK_WX_RED_PACK), params, certPath, certPass); - } - - /** - * 查询向员工付款记录 - * - * @param params 请求参数 - * @param certFile 证书文件的 InputStream - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String queryWorkWxRedPack(Map params, InputStream certFile, String certPass) { - return execution(getReqUrl(WechatApiEnum.QUERY_WORK_WX_RED_PACK), params, certFile, certPass); - } - - /** - * 向员工付款 - * - * @param params 请求参数 - * @param certPath 证书文件路径 - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String trans2pocket(Map params, String certPath, String certPass) { - return execution(getReqUrl(WechatApiEnum.PAY_WWS_TRANS_2_POCKET), params, certPath, certPass); - } - - /** - * 向员工付款 - * - * @param params 请求参数 - * @param certFile 证书文件的 InputStream - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String trans2pocket(Map params, InputStream certFile, String certPass) { - return execution(getReqUrl(WechatApiEnum.PAY_WWS_TRANS_2_POCKET), params, certFile, certPass); - } - - /** - * 查询向员工付款记录 - * - * @param params 请求参数 - * @param certPath 证书文件路径 - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String queryTrans2pocket(Map params, String certPath, String certPass) { - return execution(getReqUrl(WechatApiEnum.QUERY_WWS_TRANS_2_POCKET), params, certPath, certPass); - } - - /** - * 查询向员工付款记录 - * - * @param params 请求参数 - * @param certFile 证书文件的 InputStream - * @param certPass 证书密码 - * @return {@link String} 请求返回的结果 - */ - public static String queryTrans2pocket(Map params, InputStream certFile, String certPass) { - return execution(getReqUrl(WechatApiEnum.QUERY_WWS_TRANS_2_POCKET), params, certFile, certPass); - } - - /** - * @param url 请求url - * @param params 请求参数 - * @return {@link String} 请求返回的结果 - */ - public static String doGet(String url, Map params) { - return HttpKit.getDelegate().get(url, params); - } - - /** - * get 请求 - * - * @param url 请求url - * @param params 请求参数 - * @param headers 请求头 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse get(String url, Map params, Map headers) { - return HttpKit.getDelegate().get(url, params, headers); - } - - /** - * get 请求 - * - * @param url 请求url - * @param authorization 授权信息 - * @param serialNumber 公钥证书序列号 - * @param params 请求参数 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse get(String url, String authorization, String serialNumber, Map params) { - return get(url, params, getHeaders(authorization, serialNumber)); - } - - /** - * post 请求 - * - * @param url 请求url - * @param data 请求参数 - * @param headers 请求头 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse post(String url, String data, Map headers) { - return HttpKit.getDelegate().post(url, data, headers); - } - - /** - * post 请求 - * - * @param url 请求url - * @param authorization 授权信息 - * @param serialNumber 公钥证书序列号 - * @param data 请求参数 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse post(String url, String authorization, String serialNumber, String data) { - return post(url, data, getHeaders(authorization, serialNumber)); - } - - /** - * delete 请求 - * - * @param url 请求url - * @param data 请求参数 - * @param headers 请求头 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse delete(String url, String data, Map headers) { - return HttpKit.getDelegate().delete(url, data, headers); - } - - /** - * delete 请求 - * - * @param url 请求url - * @param authorization 授权信息 - * @param serialNumber 公钥证书序列号 - * @param data 请求参数 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse delete(String url, String authorization, String serialNumber, String data) { - return delete(url, data, getHeaders(authorization, serialNumber)); - } - - /** - * upload 请求 - * - * @param url 请求url - * @param params 请求参数 - * @param headers 请求头 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse upload(String url, Map params, Map headers) { - return HttpKit.getDelegate().post(url, params, headers); - } - - /** - * upload 请求 - * - * @param url 请求url - * @param authorization 授权信息 - * @param serialNumber 公钥证书序列号 - * @param data 请求参数 - * @param file 上传文件 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse upload(String url, String authorization, String serialNumber, String data, File file) { - Map paramMap = new HashMap<>(2); - paramMap.put("file", file); - paramMap.put("meta", data); - return upload(url, paramMap, getUploadHeaders(authorization, serialNumber)); - } - - - /** - * put 请求 - * - * @param url 请求url - * @param data 请求参数 - * @param headers 请求头 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse put(String url, String data, Map headers) { - return HttpKit.getDelegate().put(url, data, headers); - } - - /** - * put 请求 - * - * @param url 请求url - * @param authorization 授权信息 - * @param serialNumber 公钥证书序列号 - * @param data 请求参数 - * @return {@link PaymentHttpResponse} 请求返回的结果 - */ - public static PaymentHttpResponse put(String url, String authorization, String serialNumber, String data) { - return put(url, data, getHeaders(authorization, serialNumber)); - } - - public static String doPost(String url, Map params) { - return HttpKit.getDelegate().post(url, WxPayKit.toXml(params)); - } - - public static String doPostSsl(String url, Map params, String certPath, String certPass) { - return HttpKit.getDelegate().post(url, WxPayKit.toXml(params), certPath, certPass); - } - - public static String doPostSsl(String url, Map params, InputStream certFile, String certPass) { - return HttpKit.getDelegate().post(url, WxPayKit.toXml(params), certFile, certPass); - } - - public static String doPostSsl(String url, Map params, String certPath) { - if (params.isEmpty() || !params.containsKey("mch_id")) { - throw new RuntimeException("请求参数中必须包含 mch_id,如接口参考中不包 mch_id, 请使用其他同名构造方法。"); - } - String certPass = params.get("mch_id"); - return doPostSsl(url, params, certPath, certPass); - } - - public static String doPostSsl(String url, Map params, InputStream certFile) { - if (params.isEmpty() || !params.containsKey("mch_id")) { - throw new RuntimeException("请求参数中必须包含 mch_id,如接口参考中不包 mch_id, 请使用其他同名构造方法。"); - } - String certPass = params.get("mch_id"); - return doPostSsl(url, params, certFile, certPass); - } - - public static String doUploadSsl(String url, Map params, String certPath, String certPass, String filePath) { - return HttpKit.getDelegate().upload(url, WxPayKit.toXml(params), certPath, certPass, filePath); - } - - public static String doUploadSsl(String url, Map params, String certPath, String filePath) { - if (params.isEmpty() || !params.containsKey("mch_id")) { - throw new RuntimeException("请求参数中必须包含 mch_id,如接口参考中不包 mch_id, 请使用其他同名构造方法。"); - } - String certPass = params.get("mch_id"); - return doUploadSsl(url, params, certPath, certPass, filePath); - } - - - public static Map getBaseHeaders(String authorization) { - Map headers = new HashMap<>(5); - headers.put("Accept", ContentType.JSON.toString()); - headers.put("Authorization", authorization); - return headers; - } - - public static Map getHeaders(String authorization, String serialNumber) { - Map headers = getBaseHeaders(authorization); - headers.put("Content-Type", ContentType.JSON.toString()); - if (StrUtil.isNotEmpty(serialNumber)) { - headers.put("Wechatpay-Serial", serialNumber); - } - return headers; - } - - public static Map getUploadHeaders(String authorization, String serialNumber) { - Map headers = getBaseHeaders(authorization); - headers.put("Content-Type", "multipart/form-data;boundary=\"boundary\""); - if (StrUtil.isNotEmpty(serialNumber)) { - headers.put("Wechatpay-Serial", serialNumber); - } - return headers; - } - - /** - * 构建返回参数 - * - * @param response {@link PaymentHttpResponse} - * @return {@link Map} - */ - public static Map buildResMap(PaymentHttpResponse response) { - if (response == null) { - return null; - } - Map map = new HashMap<>(6); - String timestamp = response.getHeader("Wechatpay-Timestamp"); - String nonceStr = response.getHeader("Wechatpay-Nonce"); - String serialNo = response.getHeader("Wechatpay-Serial"); - String signature = response.getHeader("Wechatpay-Signature"); - String body = response.getBody(); - int status = response.getStatus(); - map.put("timestamp", timestamp); - map.put("nonceStr", nonceStr); - map.put("serialNumber", serialNo); - map.put("signature", signature); - map.put("body", body); - map.put("status", status); - return map; - } -} +//package cn.lili.modules.payment.kit.plugin.wechat; +// +//import cn.hutool.core.util.StrUtil; +//import cn.hutool.http.ContentType; +//import cn.lili.modules.payment.kit.core.PaymentHttpResponse; +//import cn.lili.modules.payment.kit.core.enums.RequestMethodEnums; +//import cn.lili.modules.payment.kit.core.kit.HttpKit; +//import cn.lili.modules.payment.kit.core.kit.PayKit; +//import cn.lili.modules.payment.kit.core.kit.WxPayKit; +//import cn.lili.modules.payment.kit.plugin.wechat.enums.WechatApiEnum; +//import cn.lili.modules.payment.kit.plugin.wechat.enums.WechatDomain; +// +//import java.io.File; +//import java.io.InputStream; +//import java.security.PrivateKey; +//import java.util.HashMap; +//import java.util.Map; +// +///** +// * 微信支付相关接口 +// * +// * @author Chopper +// * @since 2021/1/26 15:25 +// */ +// +//public class WechatApi { +// +// private WechatApi() { +// } +// +// /** +// * 获取接口请求的 URL +// * +// * @param wechatApiEnum {@link WechatApiEnum} 支付 API 接口枚举 +// * @return {@link String} 返回完整的接口请求URL +// */ +// public static String getReqUrl(WechatApiEnum wechatApiEnum) { +// return getReqUrl(wechatApiEnum, null, false); +// } +// +// /** +// * 获取接口请求的 URL +// * +// * @param wechatApiEnum {@link WechatApiEnum} 支付 API 接口枚举 +// * @param isSandBox 是否是沙箱环境 +// * @return {@link String} 返回完整的接口请求URL +// */ +// public static String getReqUrl(WechatApiEnum wechatApiEnum, boolean isSandBox) { +// return getReqUrl(wechatApiEnum, null, isSandBox); +// } +// +// /** +// * 获取接口请求的 URL +// * +// * @param wechatApiEnum {@link WechatApiEnum} 支付 API 接口枚举 +// * @param wechatDomain {@link WechatDomain} 支付 API 接口域名枚举 +// * @param isSandBox 是否是沙箱环境 +// * @return {@link String} 返回完整的接口请求URL +// */ +// public static String getReqUrl(WechatApiEnum wechatApiEnum, WechatDomain wechatDomain, boolean isSandBox) { +// if (wechatDomain == null) { +// wechatDomain = WechatDomain.CHINA; +// } +// return wechatDomain.getType() +// .concat(isSandBox ? WechatApiEnum.SAND_BOX_NEW.getUrl() : "") +// .concat(wechatApiEnum.getUrl()); +// } +// +// /** +// * 发起请求 +// * +// * @param apiUrl 接口 URL +// * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} +// * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 +// * @param params 接口请求参数 +// * @return {@link String} 请求返回的结果 +// */ +// public static String execution(String apiUrl, Map params) { +// return doPost(apiUrl, params); +// } +// +// /** +// * 发起请求 +// * +// * @param apiUrl 接口 URL +// * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} +// * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 +// * @param params 接口请求参数 +// * @return {@link String} 请求返回的结果 +// */ +// public static String executionByGet(String apiUrl, Map params) { +// return doGet(apiUrl, params); +// } +// +// /** +// * 发起请求 +// * +// * @param apiUrl 接口 URL +// * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} +// * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 +// * @param params 接口请求参数 +// * @param certPath 证书文件路径 +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String execution(String apiUrl, Map params, String certPath, String certPass) { +// return doPostSsl(apiUrl, params, certPath, certPass); +// } +// +// /** +// * 发起请求 +// * +// * @param apiUrl 接口 URL +// * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} +// * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 +// * @param params 接口请求参数 +// * @param certPath 证书文件路径 +// * @return {@link String} 请求返回的结果 +// */ +// public static String execution(String apiUrl, Map params, String certPath) { +// return doPostSsl(apiUrl, params, certPath); +// } +// +// /** +// * 发起请求 +// * +// * @param apiUrl 接口 URL +// * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} +// * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 +// * @param params 接口请求参数 +// * @param certFile 证书文件输入流 +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String execution(String apiUrl, Map params, InputStream certFile, String certPass) { +// return doPostSsl(apiUrl, params, certFile, certPass); +// } +// +// /** +// * 发起请求 +// * +// * @param apiUrl 接口 URL +// * 通过 {@link WechatApi#getReqUrl(WechatApiEnum)} +// * 或者 {@link WechatApi#getReqUrl(WechatApiEnum, WechatDomain, boolean)} 来获取 +// * @param params 接口请求参数 +// * @param certFile 证书文件输入流 +// * @return {@link String} 请求返回的结果 +// */ +// public static String execution(String apiUrl, Map params, InputStream certFile) { +// return doPostSsl(apiUrl, params, certFile); +// } +// +// public static String execution(String apiUrl, Map params, +// String certPath, String certPass, String filePath) { +// return doUploadSsl(apiUrl, params, certPath, certPass, filePath); +// } +// +// +// /** +// * V3 接口统一执行入口 +// * +// * @param method {@link RequestMethodEnums} 请求方法 +// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +// * @param mchId 商户Id +// * @param serialNo 商户 API 证书序列号 +// * @param platSerialNo 平台序列号,接口中包含敏感信息时必传 +// * @param key apiclient_key.pem 证书 +// +// * @param publicKey 公钥证书 +// * @param body 接口请求参数 +// * @param nonceStr 随机字符库 +// * @param timestamp 时间戳 +// * @param authType 认证类型 +// * @param file 文件 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// * @throws Exception 接口执行异常 +// */ +// public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, +// String mchId, String serialNo, String platSerialNo, String key,String publicKey , +// String body, String nonceStr, long timestamp, String authType, +// File file) throws Exception { +// //构建 Authorization +// String authorization = WxPayKit.buildAuthorization(method, urlSuffix, mchId, serialNo, +// key,publicKey,body, nonceStr, timestamp, authType); +// +// if (StrUtil.isEmpty(platSerialNo)) { +// platSerialNo = serialNo; +// } +// if (method == RequestMethodEnums.GET) { +// return get(urlPrefix.concat(urlSuffix), authorization, platSerialNo, null); +// } else if (method == RequestMethodEnums.POST) { +// return post(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); +// } else if (method == RequestMethodEnums.DELETE) { +// return delete(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); +// } else if (method == RequestMethodEnums.UPLOAD) { +// return upload(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body, file); +// } else if (method == RequestMethodEnums.PUT) { +// return put(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); +// } +// return null; +// } +// +// /** +// * V3 接口统一执行入口 +// * +// * @param method {@link RequestMethodEnums} 请求方法 +// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +// * @param mchId 商户Id +// * @param serialNo 商户 API 证书序列号 +// * @param platSerialNo 平台序列号,接口中包含敏感信息时必传 +// * @param privateKey 商户私钥 +// * @param body 接口请求参数 +// * @param nonceStr 随机字符库 +// * @param timestamp 时间戳 +// * @param authType 认证类型 +// * @param file 文件 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// * @throws Exception 接口执行异常 +// */ +// public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, +// String mchId, String serialNo, String platSerialNo, PrivateKey privateKey, +// String body, String nonceStr, long timestamp, String authType, +// File file) throws Exception { +// //构建 Authorization +// String authorization = WxPayKit.buildAuthorization(method, urlSuffix, mchId, serialNo, +// privateKey, body, nonceStr, timestamp, authType); +// +// if (StrUtil.isEmpty(platSerialNo)) { +// platSerialNo = serialNo; +// } +// +// if (method == RequestMethodEnums.GET) { +// return get(urlPrefix.concat(urlSuffix), authorization, platSerialNo, null); +// } else if (method == RequestMethodEnums.POST) { +// return post(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); +// } else if (method == RequestMethodEnums.DELETE) { +// return delete(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); +// } else if (method == RequestMethodEnums.UPLOAD) { +// return upload(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body, file); +// } else if (method == RequestMethodEnums.PUT) { +// return put(urlPrefix.concat(urlSuffix), authorization, platSerialNo, body); +// } +// return null; +// } +// +// /** +// * V3 接口统一执行入口 +// * +// * @param method {@link RequestMethodEnums} 请求方法 +// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +// * @param mchId 商户Id +// * @param serialNo 商户 API 证书序列号 +// * @param platSerialNo 平台序列号 +// * @param key apiclient_key.pem 证书 +// * @param publicKey 公钥证书 +// * @param body 接口请求参数 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// * @throws Exception 接口执行异常 +// */ +// public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, String mchId, +// String serialNo, String platSerialNo, String key, String publicKey ,String body) throws Exception { +// long timestamp = System.currentTimeMillis() / 1000; +// String authType = "WECHATPAY2-SHA256-RSA2048"; +// String nonceStr = WxPayKit.generateStr(); +// return v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, key,publicKey,body, nonceStr, timestamp, authType, null); +// } +// +// /** +// * V3 接口统一执行入口 +// * +// * @param method {@link RequestMethodEnums} 请求方法 +// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +// * @param mchId 商户Id +// * @param serialNo 商户 API 证书序列号 +// * @param platSerialNo 平台序列号 +// * @param privateKey 商户私钥 +// * @param body 接口请求参数 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// * @throws Exception 接口执行异常 +// */ +// public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, String mchId, +// String serialNo, String platSerialNo, PrivateKey privateKey, String body) throws Exception { +// long timestamp = System.currentTimeMillis() / 1000; +// String authType = "WECHATPAY2-SHA256-RSA2048"; +// String nonceStr = WxPayKit.generateStr(); +// return v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, privateKey, body, nonceStr, timestamp, authType, null); +// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param method {@link RequestMethodEnums} 请求方法 +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param platSerialNo 平台序列号 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param params Get 接口请求参数 +//// * @return {@link PaymentHttpResponse} 请求返回的结果 +//// * @throws Exception 接口执行异常 +//// */ +//// public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, +//// String mchId, String serialNo, String platSerialNo, String keyPath, +//// Map params) throws Exception { +//// long timestamp = System.currentTimeMillis() / 1000; +//// String authType = "WECHATPAY2-SHA256-RSA2048"; +//// String nonceStr = WxPayKit.generateStr(); +//// if (null != params && !params.keySet().isEmpty()) { +//// urlSuffix = urlSuffix.concat("?").concat(PayKit.createLinkString(params, true)); +//// } +//// return v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, "", nonceStr, timestamp, authType, null); +//// } +// +// /** +// * V3 接口统一执行入口 +// * +// * @param method {@link RequestMethodEnums} 请求方法 +// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +// * @param mchId 商户Id +// * @param serialNo 商户 API 证书序列号 +// * @param platSerialNo 平台序列号 +// * @param privateKey 商户私钥 +// * @param params Get 接口请求参数 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// * @throws Exception 接口执行异常 +// */ +// public static PaymentHttpResponse v3(RequestMethodEnums method, String urlPrefix, String urlSuffix, +// String mchId, String serialNo, String platSerialNo, PrivateKey privateKey, +// Map params) throws Exception { +// long timestamp = System.currentTimeMillis() / 1000; +// String authType = "WECHATPAY2-SHA256-RSA2048"; +// String nonceStr = WxPayKit.generateStr(); +// if (null != params && !params.keySet().isEmpty()) { +// urlSuffix = urlSuffix.concat("?").concat(PayKit.createLinkString(params, true)); +// } +// return v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, privateKey, "", nonceStr, timestamp, authType, null); +// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param platSerialNo 平台序列号 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param body 接口请求参数 +//// * @param file 文件 +//// * @return {@link PaymentHttpResponse} 请求返回的结果 +//// * @throws Exception 接口执行异常 +//// */ +//// public static PaymentHttpResponse v3(String urlPrefix, String urlSuffix, String mchId, String serialNo, String platSerialNo, String keyPath, String body, File file) throws Exception { +//// long timestamp = System.currentTimeMillis() / 1000; +//// String authType = "WECHATPAY2-SHA256-RSA2048"; +//// String nonceStr = WxPayKit.generateStr(); +//// return v3(RequestMethodEnums.UPLOAD, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, body, nonceStr, timestamp, authType, file); +//// } +// +// /** +// * V3 接口统一执行入口 +// * +// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +// * @param mchId 商户Id +// * @param serialNo 商户 API 证书序列号 +// * @param platSerialNo 平台序列号 +// * @param privateKey 商户私钥 +// * @param body 接口请求参数 +// * @param file 文件 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// * @throws Exception 接口执行异常 +// */ +// public static PaymentHttpResponse v3(String urlPrefix, String urlSuffix, String mchId, String serialNo, +// String platSerialNo, PrivateKey privateKey, String body, File file) throws Exception { +// long timestamp = System.currentTimeMillis() / 1000; +// String authType = "WECHATPAY2-SHA256-RSA2048"; +// String nonceStr = WxPayKit.generateStr(); +// return v3(RequestMethodEnums.UPLOAD, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, privateKey, body, nonceStr, timestamp, authType, file); +// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param method {@link RequestMethodEnums} 请求方法 +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param platSerialNo 平台序列号,接口中包含敏感信息时必传 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param body 接口请求参数 +//// * @param nonceStr 随机字符库 +//// * @param timestamp 时间戳 +//// * @param authType 认证类型 +//// * @param file 文件 +//// * @return {@link Map} 请求返回的结果 +//// * @throws Exception 接口执行异常 +//// */ +//// @Deprecated +//// public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, +//// String mchId, String serialNo, String platSerialNo, String keyPath, +//// String body, String nonceStr, long timestamp, String authType, +//// File file) throws Exception { +//// PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, body, nonceStr, timestamp, authType, file); +//// return buildResMap(response); +//// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param method {@link RequestMethodEnums} 请求方法 +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param body 接口请求参数 +//// * @return {@link Map} 请求返回的结果 +//// */ +//// @Deprecated +//// public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, String mchId, +//// String serialNo, String keyPath, String body) throws Exception { +//// PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, null, keyPath, body); +//// return buildResMap(response); +//// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param method {@link RequestMethodEnums} 请求方法 +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param platSerialNo 平台序列号 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param body 接口请求参数 +//// * @return {@link Map} 请求返回的结果 +//// * @throws Exception 接口执行异常 +//// */ +//// @Deprecated +//// public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, String mchId, +//// String serialNo, String platSerialNo, String keyPath, String body) throws Exception { +//// PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, body); +//// return buildResMap(response); +//// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param method {@link RequestMethodEnums} 请求方法 +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param platSerialNo 平台序列号 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param params Get 接口请求参数 +//// * @return {@link Map} 请求返回的结果 +//// * @throws Exception 接口执行异常 +//// */ +//// @Deprecated +//// public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, +//// String mchId, String serialNo, String platSerialNo, String keyPath, +//// Map params) throws Exception { +//// PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, params); +//// return buildResMap(response); +//// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param method {@link RequestMethodEnums} 请求方法 +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param params Get 接口请求参数 +//// * @return {@link Map} 请求返回的结果 +//// * @throws Exception 接口执行异常 +//// */ +//// @Deprecated +//// public static Map v3Execution(RequestMethodEnums method, String urlPrefix, String urlSuffix, +//// String mchId, String serialNo, String keyPath, +//// Map params) throws Exception { +//// PaymentHttpResponse response = v3(method, urlPrefix, urlSuffix, mchId, serialNo, null, keyPath, params); +//// return buildResMap(response); +//// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param platSerialNo 平台序列号 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param body 接口请求参数 +//// * @param file 文件 +//// * @return {@link Map} 请求返回的结果 +//// * @throws Exception 接口执行异常 +//// */ +//// @Deprecated +//// public static Map v3Upload(String urlPrefix, String urlSuffix, String mchId, String serialNo, String platSerialNo, String keyPath, String body, File file) throws Exception { +//// PaymentHttpResponse response = v3(urlPrefix, urlSuffix, mchId, serialNo, platSerialNo, keyPath, body, file); +//// return buildResMap(response); +//// } +// +//// /** +//// * V3 接口统一执行入口 +//// * +//// * @param urlPrefix 可通过 {@link WechatDomain}来获取 +//// * @param urlSuffix 可通过 {@link WechatApiEnum} 来获取,URL挂载参数需要自行拼接 +//// * @param mchId 商户Id +//// * @param serialNo 商户 API 证书序列号 +//// * @param keyPath apiclient_key.pem 证书路径 +//// * @param body 接口请求参数 +//// * @param file 文件 +//// * @return {@link Map} 请求返回的结果 +//// * @throws Exception 接口执行异常 +//// */ +//// @Deprecated +//// public static Map v3Upload(String urlPrefix, String urlSuffix, String mchId, String serialNo, String keyPath, String body, File file) throws Exception { +//// return v3Upload(urlPrefix, urlSuffix, mchId, serialNo, null, keyPath, body, file); +//// } +// +// /** +// * 发放企业红包 +// * +// * @param params 请求参数 +// * @param certPath 证书文件路径 +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String sendWorkWxRedPack(Map params, String certPath, String certPass) { +// return execution(getReqUrl(WechatApiEnum.SEND_WORK_WX_RED_PACK), params, certPath, certPass); +// } +// +// /** +// * 发放企业红包 +// * +// * @param params 请求参数 +// * @param certFile 证书文件的 InputStream +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String sendWorkWxRedPack(Map params, InputStream certFile, String certPass) { +// return execution(getReqUrl(WechatApiEnum.SEND_WORK_WX_RED_PACK), params, certFile, certPass); +// } +// +// /** +// * 查询向员工付款记录 +// * +// * @param params 请求参数 +// * @param certPath 证书文件路径 +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String queryWorkWxRedPack(Map params, String certPath, String certPass) { +// return execution(getReqUrl(WechatApiEnum.QUERY_WORK_WX_RED_PACK), params, certPath, certPass); +// } +// +// /** +// * 查询向员工付款记录 +// * +// * @param params 请求参数 +// * @param certFile 证书文件的 InputStream +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String queryWorkWxRedPack(Map params, InputStream certFile, String certPass) { +// return execution(getReqUrl(WechatApiEnum.QUERY_WORK_WX_RED_PACK), params, certFile, certPass); +// } +// +// /** +// * 向员工付款 +// * +// * @param params 请求参数 +// * @param certPath 证书文件路径 +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String trans2pocket(Map params, String certPath, String certPass) { +// return execution(getReqUrl(WechatApiEnum.PAY_WWS_TRANS_2_POCKET), params, certPath, certPass); +// } +// +// /** +// * 向员工付款 +// * +// * @param params 请求参数 +// * @param certFile 证书文件的 InputStream +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String trans2pocket(Map params, InputStream certFile, String certPass) { +// return execution(getReqUrl(WechatApiEnum.PAY_WWS_TRANS_2_POCKET), params, certFile, certPass); +// } +// +// /** +// * 查询向员工付款记录 +// * +// * @param params 请求参数 +// * @param certPath 证书文件路径 +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String queryTrans2pocket(Map params, String certPath, String certPass) { +// return execution(getReqUrl(WechatApiEnum.QUERY_WWS_TRANS_2_POCKET), params, certPath, certPass); +// } +// +// /** +// * 查询向员工付款记录 +// * +// * @param params 请求参数 +// * @param certFile 证书文件的 InputStream +// * @param certPass 证书密码 +// * @return {@link String} 请求返回的结果 +// */ +// public static String queryTrans2pocket(Map params, InputStream certFile, String certPass) { +// return execution(getReqUrl(WechatApiEnum.QUERY_WWS_TRANS_2_POCKET), params, certFile, certPass); +// } +// +// /** +// * @param url 请求url +// * @param params 请求参数 +// * @return {@link String} 请求返回的结果 +// */ +// public static String doGet(String url, Map params) { +// return HttpKit.getDelegate().get(url, params); +// } +// +// /** +// * get 请求 +// * +// * @param url 请求url +// * @param params 请求参数 +// * @param headers 请求头 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse get(String url, Map params, Map headers) { +// return HttpKit.getDelegate().get(url, params, headers); +// } +// +// /** +// * get 请求 +// * +// * @param url 请求url +// * @param authorization 授权信息 +// * @param serialNumber 公钥证书序列号 +// * @param params 请求参数 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse get(String url, String authorization, String serialNumber, Map params) { +// return get(url, params, getHeaders(authorization, serialNumber)); +// } +// +// /** +// * post 请求 +// * +// * @param url 请求url +// * @param data 请求参数 +// * @param headers 请求头 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse post(String url, String data, Map headers) { +// return HttpKit.getDelegate().post(url, data, headers); +// } +// +// /** +// * post 请求 +// * +// * @param url 请求url +// * @param authorization 授权信息 +// * @param serialNumber 公钥证书序列号 +// * @param data 请求参数 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse post(String url, String authorization, String serialNumber, String data) { +// return post(url, data, getHeaders(authorization, serialNumber)); +// } +// +// /** +// * delete 请求 +// * +// * @param url 请求url +// * @param data 请求参数 +// * @param headers 请求头 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse delete(String url, String data, Map headers) { +// return HttpKit.getDelegate().delete(url, data, headers); +// } +// +// /** +// * delete 请求 +// * +// * @param url 请求url +// * @param authorization 授权信息 +// * @param serialNumber 公钥证书序列号 +// * @param data 请求参数 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse delete(String url, String authorization, String serialNumber, String data) { +// return delete(url, data, getHeaders(authorization, serialNumber)); +// } +// +// /** +// * upload 请求 +// * +// * @param url 请求url +// * @param params 请求参数 +// * @param headers 请求头 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse upload(String url, Map params, Map headers) { +// return HttpKit.getDelegate().post(url, params, headers); +// } +// +// /** +// * upload 请求 +// * +// * @param url 请求url +// * @param authorization 授权信息 +// * @param serialNumber 公钥证书序列号 +// * @param data 请求参数 +// * @param file 上传文件 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse upload(String url, String authorization, String serialNumber, String data, File file) { +// Map paramMap = new HashMap<>(2); +// paramMap.put("file", file); +// paramMap.put("meta", data); +// return upload(url, paramMap, getUploadHeaders(authorization, serialNumber)); +// } +// +// +// /** +// * put 请求 +// * +// * @param url 请求url +// * @param data 请求参数 +// * @param headers 请求头 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse put(String url, String data, Map headers) { +// return HttpKit.getDelegate().put(url, data, headers); +// } +// +// /** +// * put 请求 +// * +// * @param url 请求url +// * @param authorization 授权信息 +// * @param serialNumber 公钥证书序列号 +// * @param data 请求参数 +// * @return {@link PaymentHttpResponse} 请求返回的结果 +// */ +// public static PaymentHttpResponse put(String url, String authorization, String serialNumber, String data) { +// return put(url, data, getHeaders(authorization, serialNumber)); +// } +// +// public static String doPost(String url, Map params) { +// return HttpKit.getDelegate().post(url, WxPayKit.toXml(params)); +// } +// +// public static String doPostSsl(String url, Map params, String certPath, String certPass) { +// return HttpKit.getDelegate().post(url, WxPayKit.toXml(params), certPath, certPass); +// } +// +// public static String doPostSsl(String url, Map params, InputStream certFile, String certPass) { +// return HttpKit.getDelegate().post(url, WxPayKit.toXml(params), certFile, certPass); +// } +// +// public static String doPostSsl(String url, Map params, String certPath) { +// if (params.isEmpty() || !params.containsKey("mch_id")) { +// throw new RuntimeException("请求参数中必须包含 mch_id,如接口参考中不包 mch_id, 请使用其他同名构造方法。"); +// } +// String certPass = params.get("mch_id"); +// return doPostSsl(url, params, certPath, certPass); +// } +// +// public static String doPostSsl(String url, Map params, InputStream certFile) { +// if (params.isEmpty() || !params.containsKey("mch_id")) { +// throw new RuntimeException("请求参数中必须包含 mch_id,如接口参考中不包 mch_id, 请使用其他同名构造方法。"); +// } +// String certPass = params.get("mch_id"); +// return doPostSsl(url, params, certFile, certPass); +// } +// +// public static String doUploadSsl(String url, Map params, String certPath, String certPass, String filePath) { +// return HttpKit.getDelegate().upload(url, WxPayKit.toXml(params), certPath, certPass, filePath); +// } +// +// public static String doUploadSsl(String url, Map params, String certPath, String filePath) { +// if (params.isEmpty() || !params.containsKey("mch_id")) { +// throw new RuntimeException("请求参数中必须包含 mch_id,如接口参考中不包 mch_id, 请使用其他同名构造方法。"); +// } +// String certPass = params.get("mch_id"); +// return doUploadSsl(url, params, certPath, certPass, filePath); +// } +// +// +// public static Map getBaseHeaders(String authorization) { +// Map headers = new HashMap<>(5); +// headers.put("Accept", ContentType.JSON.toString()); +// headers.put("Authorization", authorization); +// return headers; +// } +// +// public static Map getHeaders(String authorization, String serialNumber) { +// Map headers = getBaseHeaders(authorization); +// headers.put("Content-Type", ContentType.JSON.toString()); +// if (StrUtil.isNotEmpty(serialNumber)) { +// headers.put("Wechatpay-Serial", serialNumber); +// } +// return headers; +// } +// +// public static Map getUploadHeaders(String authorization, String serialNumber) { +// Map headers = getBaseHeaders(authorization); +// headers.put("Content-Type", "multipart/form-data;boundary=\"boundary\""); +// if (StrUtil.isNotEmpty(serialNumber)) { +// headers.put("Wechatpay-Serial", serialNumber); +// } +// return headers; +// } +// +// /** +// * 构建返回参数 +// * +// * @param response {@link PaymentHttpResponse} +// * @return {@link Map} +// */ +// public static Map buildResMap(PaymentHttpResponse response) { +// if (response == null) { +// return null; +// } +// Map map = new HashMap<>(6); +// String timestamp = response.getHeader("Wechatpay-Timestamp"); +// String nonceStr = response.getHeader("Wechatpay-Nonce"); +// String serialNo = response.getHeader("Wechatpay-Serial"); +// String signature = response.getHeader("Wechatpay-Signature"); +// String body = response.getBody(); +// int status = response.getStatus(); +// map.put("timestamp", timestamp); +// map.put("nonceStr", nonceStr); +// map.put("serialNumber", serialNo); +// map.put("signature", signature); +// map.put("body", body); +// map.put("status", status); +// return map; +// } +//} diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatPlugin.java b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatPlugin.java index 5a27dbf9..cf467e7f 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatPlugin.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatPlugin.java @@ -1,16 +1,14 @@ package cn.lili.modules.payment.kit.plugin.wechat; +import cn.hutool.core.convert.Convert; import cn.hutool.core.net.URLDecoder; import cn.hutool.core.net.URLEncoder; -import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; -import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ResultCode; import cn.lili.common.enums.ResultUtil; import cn.lili.common.exception.ServiceException; -import cn.lili.common.properties.ApiProperties; import cn.lili.common.security.context.UserContext; import cn.lili.common.utils.CurrencyUtil; import cn.lili.common.utils.SnowFlake; @@ -29,7 +27,9 @@ import cn.lili.modules.payment.kit.Payment; import cn.lili.modules.payment.kit.core.PaymentHttpResponse; import cn.lili.modules.payment.kit.core.enums.RequestMethodEnums; import cn.lili.modules.payment.kit.core.enums.SignType; -import cn.lili.modules.payment.kit.core.kit.*; +import cn.lili.modules.payment.kit.core.kit.HttpKit; +import cn.lili.modules.payment.kit.core.kit.IpKit; +import cn.lili.modules.payment.kit.core.kit.WxPayKit; import cn.lili.modules.payment.kit.core.utils.DateTimeZoneUtil; import cn.lili.modules.payment.kit.dto.PayParam; import cn.lili.modules.payment.kit.dto.PaymentSuccessParams; @@ -51,6 +51,30 @@ import cn.lili.modules.wallet.entity.dto.TransferResultDTO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.google.gson.Gson; +import com.wechat.pay.java.core.Config; +import com.wechat.pay.java.core.RSAAutoCertificateConfig; +import com.wechat.pay.java.core.RSAPublicKeyConfig; +import com.wechat.pay.java.core.exception.ValidationException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.core.util.StringUtil; +import com.wechat.pay.java.service.payments.app.AppService; +import com.wechat.pay.java.service.payments.h5.H5Service; +import com.wechat.pay.java.service.payments.jsapi.JsapiService; +import com.wechat.pay.java.service.payments.model.Transaction; +import com.wechat.pay.java.service.payments.nativepay.NativePayService; +import com.wechat.pay.java.service.payments.nativepay.model.Amount; +import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest; +import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse; +import com.wechat.pay.java.service.refund.RefundService; +import com.wechat.pay.java.service.refund.model.AmountReq; +import com.wechat.pay.java.service.refund.model.CreateRequest; +import com.wechat.pay.java.service.refund.model.Refund; +import com.wechat.pay.java.service.transferbatch.TransferBatchService; +import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest; +import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse; +import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -58,8 +82,6 @@ import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; -import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -141,31 +163,28 @@ public class WechatPlugin implements Payment { if (appid == null) { throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING); } - UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() - .setAppid(appid) - .setMchid(setting.getMchId()) - .setDescription(cashierParam.getDetail()) - .setOut_trade_no(outOrderNo) - .setTime_expire(timeExpire) - .setAttach(attach) - .setNotify_url(notifyUrl(wechatPaymentSetting().getCallbackUrl(),PaymentMethodEnum.WECHAT)) - .setAmount(new Amount().setTotal(fen)).setScene_info(sceneInfo); - log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); - PaymentHttpResponse response = WechatApi.v3( - RequestMethodEnums.POST, - WechatDomain.CHINA.toString(), - WechatApiEnum.H5_PAY.toString(), - setting.getMchId(), - setting.getSerialNumber(), - null, - setting.getApiclient_key(), - JSONUtil.toJsonStr(unifiedOrderModel) - ); + Config config =this.getConfig(setting); + // 构建service + H5Service service = new H5Service.Builder().config(config).build(); + com.wechat.pay.java.service.payments.h5.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.h5.model.PrepayRequest(); + com.wechat.pay.java.service.payments.h5.model.Amount amount = new com.wechat.pay.java.service.payments.h5.model.Amount(); + amount.setTotal(fen); + prepayRequest.setAmount(amount); + prepayRequest.setAppid(appid); + prepayRequest.setMchid(setting.getMchId()); + prepayRequest.setDescription(cashierParam.getDetail()); + prepayRequest.setNotifyUrl(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)); + prepayRequest.setAttach(attach); + prepayRequest.setTimeExpire(timeExpire); + prepayRequest.setOutTradeNo(outOrderNo); + + // 调用下单方法,得到应答 + com.wechat.pay.java.service.payments.h5.model.PrepayResponse response = service.prepay(prepayRequest); updateOrderPayNo(payParam,outOrderNo); - return ResultUtil.data(JSONUtil.toJsonStr(response.getBody())); + return ResultUtil.data(response.getH5Url()); } catch (Exception e) { log.error("微信H5支付错误", e); throw new ServiceException(ResultCode.PAY_ERROR); @@ -183,8 +202,7 @@ public class WechatPlugin implements Payment { return null; } - Payer payer = new Payer(); - payer.setOpenid(connect.getUnionId()); + CashierParam cashierParam = cashierSupport.cashierParam(payParam); @@ -202,46 +220,33 @@ public class WechatPlugin implements Payment { if (appid == null) { throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING); } - UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() - .setAppid(appid) - .setMchid(setting.getMchId()) - .setDescription(cashierParam.getDetail()) - .setOut_trade_no(outOrderNo) - .setTime_expire(timeExpire) - .setAttach(attach) - .setNotify_url(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)) - .setAmount(new Amount().setTotal(fen)) - .setPayer(payer); - log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); - PaymentHttpResponse response = WechatApi.v3( - RequestMethodEnums.POST, - WechatDomain.CHINA.toString(), - WechatApiEnum.JS_API_PAY.toString(), - setting.getMchId(), - setting.getSerialNumber(), - null, - setting.getApiclient_key(), - JSONUtil.toJsonStr(unifiedOrderModel) - ); - //根据证书序列号查询对应的证书来验证签名结果 - boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert()); - log.info("verifySignature: {}", verifySignature); - log.info("统一下单响应 {}", response); + Config config =this.getConfig(setting); + // 构建service + JsapiService service = new JsapiService.Builder().config(config).build(); - if (verifySignature) { - String body = response.getBody(); - JSONObject jsonObject = JSONUtil.parseObj(body); - String prepayId = jsonObject.getStr("prepay_id"); - Map map = WxPayKit.jsApiCreateSign(appid, prepayId, setting.getApiclient_key()); - log.info("唤起支付参数:{}", map); + com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest(); + com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount(); - updateOrderPayNo(payParam,outOrderNo); + com.wechat.pay.java.service.payments.jsapi.model.Payer payer = new com.wechat.pay.java.service.payments.jsapi.model.Payer(); + payer.setOpenid(connect.getUnionId()); + amount.setTotal(fen); + prepayRequest.setAmount(amount); + prepayRequest.setAppid(appid); + prepayRequest.setMchid(setting.getMchId()); + prepayRequest.setDescription(cashierParam.getDetail()); + prepayRequest.setNotifyUrl(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)); + prepayRequest.setAttach(attach); + prepayRequest.setTimeExpire(timeExpire); + prepayRequest.setOutTradeNo(outOrderNo); + prepayRequest.setPayer(payer); + // 调用下单方法,得到应答 + com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse response = service.prepay(prepayRequest); + updateOrderPayNo(payParam,outOrderNo); - return ResultUtil.data(map); - } - log.error("微信支付参数验证错误,请及时处理"); - throw new ServiceException(ResultCode.PAY_ERROR); + Map map = WxPayKit.jsApiCreateSign(appid, response.getPrepayId(), setting.getApiclientKey()); + log.info("唤起支付参数:{}", map); + return ResultUtil.data(map); } catch (Exception e) { log.error("支付异常", e); throw new ServiceException(ResultCode.PAY_ERROR); @@ -269,48 +274,34 @@ public class WechatPlugin implements Payment { if (appid == null) { throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING); } - UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() - .setAppid(appid) - .setMchid(setting.getMchId()) - .setDescription(cashierParam.getDetail()) - .setOut_trade_no(outOrderNo) - .setTime_expire(timeExpire) - .setAttach(attach) - .setNotify_url(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)) - .setAmount(new Amount().setTotal(fen)); + Config config =this.getConfig(setting); + // 构建service + AppService service = new AppService.Builder().config(config).build(); - log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); - PaymentHttpResponse response = WechatApi.v3( - RequestMethodEnums.POST, - WechatDomain.CHINA.toString(), - WechatApiEnum.APP_PAY.toString(), + com.wechat.pay.java.service.payments.app.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.app.model.PrepayRequest(); + com.wechat.pay.java.service.payments.app.model.Amount amount = new com.wechat.pay.java.service.payments.app.model.Amount(); + amount.setTotal(fen); + prepayRequest.setAmount(amount); + prepayRequest.setAppid(appid); + prepayRequest.setMchid(setting.getMchId()); + prepayRequest.setDescription(cashierParam.getDetail()); + prepayRequest.setNotifyUrl(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)); + prepayRequest.setAttach(attach); + prepayRequest.setTimeExpire(timeExpire); + prepayRequest.setOutTradeNo(outOrderNo); + + // 调用下单方法,得到应答 + com.wechat.pay.java.service.payments.app.model.PrepayResponse response = service.prepay(prepayRequest); + updateOrderPayNo(payParam,outOrderNo); + Map map = WxPayKit.appPrepayIdCreateSign(appid, setting.getMchId(), - setting.getSerialNumber(), - null, - setting.getApiclient_key(), - JSONUtil.toJsonStr(unifiedOrderModel) - ); - //根据证书序列号查询对应的证书来验证签名结果 - boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert()); - log.info("verifySignature: {}", verifySignature); - log.info("统一下单响应 {}", response); - - if (verifySignature) { - JSONObject jsonObject = JSONUtil.parseObj(response.getBody()); - String prepayId = jsonObject.getStr("prepay_id"); - Map map = WxPayKit.appPrepayIdCreateSign(appid, - setting.getMchId(), - prepayId, - setting.getApiclient_key(), SignType.MD5); - log.info("唤起支付参数:{}", map); - - updateOrderPayNo(payParam,outOrderNo); - - return ResultUtil.data(map); - } - log.error("微信支付参数验证错误,请及时处理"); - throw new ServiceException(ResultCode.PAY_ERROR); + response.getPrepayId(), + setting.getApiclientKey(), SignType.MD5); + log.info("唤起支付参数:{}", map); + //修改付款单号 + updateOrderPayNo(payParam,outOrderNo); + return ResultUtil.data(map); } catch (Exception e) { log.error("支付异常", e); throw new ServiceException(ResultCode.PAY_ERROR); @@ -339,41 +330,28 @@ public class WechatPlugin implements Payment { if (appid == null) { throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING); } - UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() - .setAppid(appid) - .setMchid(setting.getMchId()) - .setDescription(cashierParam.getDetail()) - .setOut_trade_no(outOrderNo) - .setTime_expire(timeExpire) - //回传参数 - .setAttach(attach) - .setNotify_url(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)) - .setAmount(new Amount().setTotal(fen)); - log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); - PaymentHttpResponse response = WechatApi.v3( - RequestMethodEnums.POST, - WechatDomain.CHINA.toString(), - WechatApiEnum.NATIVE_PAY.toString(), - setting.getMchId(), - setting.getSerialNumber(), - null, - setting.getApiclient_key(), - JSONUtil.toJsonStr(unifiedOrderModel) - ); - log.info("统一下单响应 {}", response); - //根据证书序列号查询对应的证书来验证签名结果 - boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert()); - log.info("verifySignature: {}", verifySignature); + Config config =this.getConfig(setting); + // 构建service + NativePayService service = new NativePayService.Builder().config(config).build(); - if (verifySignature) { - updateOrderPayNo(payParam,outOrderNo); + PrepayRequest prepayRequest = new PrepayRequest(); + Amount amount = new Amount(); + amount.setTotal(fen); + prepayRequest.setAmount(amount); + prepayRequest.setAppid(appid); + prepayRequest.setMchid(setting.getMchId()); + prepayRequest.setDescription(cashierParam.getDetail()); + prepayRequest.setNotifyUrl(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)); + prepayRequest.setAttach(attach); + prepayRequest.setTimeExpire(timeExpire); + prepayRequest.setOutTradeNo(outOrderNo); + + // 调用下单方法,得到应答 + PrepayResponse response = service.prepay(prepayRequest); + updateOrderPayNo(payParam,outOrderNo); + return ResultUtil.data(response.getCodeUrl()); - return ResultUtil.data(new JSONObject(response.getBody()).getStr("code_url")); - } else { - log.error("微信支付参数验证错误,请及时处理"); - throw new ServiceException(ResultCode.PAY_ERROR); - } } catch (ServiceException e) { log.error("支付异常", e); throw new ServiceException(ResultCode.PAY_ERROR); @@ -381,6 +359,7 @@ public class WechatPlugin implements Payment { log.error("支付异常", e); throw new ServiceException(ResultCode.PAY_ERROR); } + } @Override @@ -394,7 +373,7 @@ public class WechatPlugin implements Payment { return null; } - Payer payer = new Payer(); + com.wechat.pay.java.service.payments.jsapi.model.Payer payer = new com.wechat.pay.java.service.payments.jsapi.model.Payer(); payer.setOpenid(connect.getUnionId()); CashierParam cashierParam = cashierSupport.cashierParam(payParam); @@ -415,44 +394,32 @@ public class WechatPlugin implements Payment { String attach = URLEncoder.createDefault().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8); WechatPaymentSetting setting = wechatPaymentSetting(); - UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() - .setAppid(appid) - .setMchid(setting.getMchId()) - .setDescription(cashierParam.getDetail()) - .setOut_trade_no(outOrderNo) - .setTime_expire(timeExpire) - .setAttach(attach) - .setNotify_url(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)) - .setAmount(new Amount().setTotal(fen)) - .setPayer(payer); - log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); - PaymentHttpResponse response = WechatApi.v3( - RequestMethodEnums.POST, - WechatDomain.CHINA.toString(), - WechatApiEnum.JS_API_PAY.toString(), - setting.getMchId(), - setting.getSerialNumber(), - null, - setting.getApiclient_key(), - JSONUtil.toJsonStr(unifiedOrderModel) - ); - //根据证书序列号查询对应的证书来验证签名结果 - boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert()); - log.info("verifySignature: {}", verifySignature); - log.info("统一下单响应 {}", response); + Config config =this.getConfig(setting); + // 构建service + JsapiService service = new JsapiService.Builder().config(config).build(); + + com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest(); + com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount(); + amount.setTotal(fen); + prepayRequest.setAmount(amount); + prepayRequest.setAppid(appid); + prepayRequest.setMchid(setting.getMchId()); + prepayRequest.setDescription(cashierParam.getDetail()); + prepayRequest.setNotifyUrl(notifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)); + prepayRequest.setAttach(attach); + prepayRequest.setTimeExpire(timeExpire); + prepayRequest.setOutTradeNo(outOrderNo); + prepayRequest.setPayer(payer); + // 调用下单方法,得到应答 + com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse response = service.prepay(prepayRequest); + updateOrderPayNo(payParam,outOrderNo); + + Map map = WxPayKit.jsApiCreateSign(appid, response.getPrepayId(), setting.getApiclientKey()); + log.info("唤起支付参数:{}", map); + + return ResultUtil.data(map); - if (verifySignature) { - String body = response.getBody(); - JSONObject jsonObject = JSONUtil.parseObj(body); - String prepayId = jsonObject.getStr("prepay_id"); - Map map = WxPayKit.jsApiCreateSign(appid, prepayId, setting.getApiclient_key()); - log.info("唤起支付参数:{}", map); - updateOrderPayNo(payParam,outOrderNo); - return ResultUtil.data(map); - } - log.error("微信支付参数验证错误,请及时处理"); - throw new ServiceException(ResultCode.PAY_ERROR); } catch (Exception e) { log.error("支付异常", e); throw new ServiceException(ResultCode.PAY_ERROR); @@ -514,48 +481,46 @@ public class WechatPlugin implements Payment { } } - //获取微信设置 - WechatPaymentSetting wechatPaymentSetting = wechatPaymentSetting(); + + //获取用户openId Connect connect = connectService.queryConnect( ConnectQueryDTO.builder().userId(memberWithdrawApply.getMemberId()) .unionType(source).build() ); - //构建提现,发起申请 - TransferModel transferModel = new TransferModel() - .setAppid(withdrawalSetting.getWechatAppId()) - .setOut_batch_no(SnowFlake.createStr("T")) - .setBatch_name("用户提现") - .setBatch_remark("用户提现") - .setTotal_amount(CurrencyUtil.fen(memberWithdrawApply.getApplyMoney())) - .setTotal_num(1) - .setTransfer_scene_id("1000"); + //获取微信设置 + WechatPaymentSetting setting = wechatPaymentSetting(); + + Config config =this.getConfig(setting); + // 构建service + TransferBatchService service = new TransferBatchService.Builder().config(config).build(); + + InitiateBatchTransferRequest request = new InitiateBatchTransferRequest(); + request.setAppid(withdrawalSetting.getWechatAppId()); + request.setOutBatchNo(SnowFlake.createStr("T")); + request.setBatchName("用户提现"); + request.setBatchRemark("用户提现"); + request.setTotalAmount(CurrencyUtil.getFenLong(memberWithdrawApply.getApplyMoney())); + request.setTotalNum(1); + request.setTransferSceneId("1000"); + List transferDetailListList = new ArrayList<>(); { TransferDetailInput transferDetailInput = new TransferDetailInput(); - transferDetailInput.setOut_detail_no(SnowFlake.createStr("TD")); - transferDetailInput.setTransfer_amount(CurrencyUtil.fen(memberWithdrawApply.getApplyMoney())); - transferDetailInput.setTransfer_remark("用户提现"); + transferDetailInput.setOutDetailNo(SnowFlake.createStr("TD")); + transferDetailInput.setTransferAmount(CurrencyUtil.getFenLong(memberWithdrawApply.getApplyMoney())); + transferDetailInput.setTransferRemark("用户提现"); transferDetailInput.setOpenid(connect.getUnionId()); transferDetailListList.add(transferDetailInput); } - transferModel.setTransfer_detail_list(transferDetailListList); + request.setTransferDetailList(transferDetailListList); - PaymentHttpResponse response = WechatApi.v3( - RequestMethodEnums.POST, - WechatDomain.CHINA.toString(), - WechatApiEnum.TRANSFER_BATCHES.toString(), - wechatPaymentSetting.getMchId(), - wechatPaymentSetting.getSerialNumber(), - null, - wechatPaymentSetting.getApiclient_key(), - JSONUtil.toJsonStr(transferModel) - ); + // 调用下单方法,得到应答 + InitiateBatchTransferResponse response = service.initiateBatchTransfer(request); log.info("微信提现响应 {}", response); - String body = response.getBody(); - JSONObject jsonObject = JSONUtil.parseObj(body); - return TransferResultDTO.builder().result(jsonObject.getStr("batch_id") != null).response(body).build(); + + return TransferResultDTO.builder().result(response.getBatchId()!= null).build(); //根据自身业务进行接下来的任务处理 } catch (Exception e) { e.printStackTrace(); @@ -572,41 +537,51 @@ public class WechatPlugin implements Payment { */ private void verifyNotify(HttpServletRequest request) throws Exception { - String timestamp = request.getHeader("Wechatpay-Timestamp"); - String nonce = request.getHeader("Wechatpay-Nonce"); - String serialNo = request.getHeader("Wechatpay-Serial"); - String signature = request.getHeader("Wechatpay-Signature"); - - log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature); - String result = HttpKit.readData(request); - log.info("微信支付通知密文 {}", result); + // 构造 RequestParam + RequestParam requestParam = new RequestParam.Builder() + .serialNumber(request.getHeader("Wechatpay-Serial")) + .nonce(request.getHeader("Wechatpay-Nonce")) + .signature(request.getHeader("Wechatpay-Signature")) + .timestamp(request.getHeader("Wechatpay-Timestamp")) + .body(HttpKit.readData(request)) + .build(); WechatPaymentSetting setting = wechatPaymentSetting(); - //校验服务器端响应¬ - String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, - setting.getApiKey3(), Objects.requireNonNull(getPlatformCert())); - log.info("微信支付通知明文 {}", plainText); - - JSONObject jsonObject = JSONUtil.parseObj(plainText); - - String payParamStr = jsonObject.getStr("attach"); - String payParamJson = URLDecoder.decode(payParamStr, StandardCharsets.UTF_8); - PayParam payParam = JSONUtil.toBean(payParamJson, PayParam.class); + NotificationConfig config = new RSAAutoCertificateConfig.Builder() + .merchantId(setting.getMchId()) + .privateKey(setting.getApiclientKey()) + .merchantSerialNumber(setting.getSerialNumber()) + .apiV3Key(setting.getApiKey3()) + .build(); - String tradeNo = jsonObject.getStr("transaction_id"); - Double totalAmount = CurrencyUtil.reversalFen(jsonObject.getJSONObject("amount").getDouble("total")); + // 初始化 NotificationParser + NotificationParser parser = new NotificationParser(config); - PaymentSuccessParams paymentSuccessParams = new PaymentSuccessParams( - PaymentMethodEnum.WECHAT.name(), - tradeNo, - totalAmount, - payParam - ); + try { + // 以支付通知回调为例,验签、解密并转换成 Transaction + Transaction transaction = parser.parse(requestParam, Transaction.class); + + String payParamJson = URLDecoder.decode(transaction.getAttach(), StandardCharsets.UTF_8); + PayParam payParam = JSONUtil.toBean(payParamJson, PayParam.class); + + Double totalAmount = CurrencyUtil.reversalFen(transaction.getAmount().getTotal()); + + PaymentSuccessParams paymentSuccessParams = new PaymentSuccessParams( + PaymentMethodEnum.WECHAT.name(), + transaction.getTransactionId(), + totalAmount, + payParam + ); + + paymentService.success(paymentSuccessParams); + } catch (ValidationException e) { + // 签名验证失败,返回 401 UNAUTHORIZED 状态码 + log.error("sign verification failed", e); + + } - paymentService.success(paymentSuccessParams); - log.info("微信支付回调:支付成功{}", plainText); } @Override @@ -614,39 +589,28 @@ public class WechatPlugin implements Payment { try { - Amount amount = new Amount().setRefund(CurrencyUtil.fen(refundLog.getTotalAmount())) - .setTotal(CurrencyUtil.fen(orderService.getPaymentTotal(refundLog.getOrderSn()))); - - //退款参数准备 - RefundModel refundModel = new RefundModel() - .setTransaction_id(refundLog.getPaymentReceivableNo()) - .setOut_refund_no(refundLog.getOutOrderNo()) - .setReason(refundLog.getRefundReason()) - .setAmount(amount) - .setNotify_url(refundNotifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)); - + AmountReq amount = new AmountReq(); + amount.setRefund(CurrencyUtil.getFenLong(refundLog.getTotalAmount())); + amount.setTotal(CurrencyUtil.getFenLong(orderService.getPaymentTotal(refundLog.getOrderSn()))); + amount.setCurrency("CNY"); + //获取微信设置 WechatPaymentSetting setting = wechatPaymentSetting(); - log.info("微信退款参数 {}", JSONUtil.toJsonStr(refundModel)); - PaymentHttpResponse response = WechatApi.v3( - RequestMethodEnums.POST, - WechatDomain.CHINA.toString(), - WechatApiEnum.DOMESTIC_REFUNDS.toString(), - setting.getMchId(), - setting.getSerialNumber(), - null, - setting.getApiclient_key(), - JSONUtil.toJsonStr(refundModel) - ); - log.info("微信退款响应 {}", response); - //退款申请成功 - if (response.getStatus() == 200) { - refundLogService.save(refundLog); - } else { - //退款申请失败 - refundLog.setErrorMessage(response.getBody()); - refundLogService.save(refundLog); - } + Config config =this.getConfig(setting); + // 构建service + RefundService refundService = new RefundService.Builder().config(config).build(); + + CreateRequest request = new CreateRequest(); + request.setTransactionId(refundLog.getPaymentReceivableNo()); + request.setAmount(amount); + request.setOutRefundNo(refundLog.getOutOrderNo()); + request.setReason(refundLog.getRefundReason()); + request.setNotifyUrl(refundNotifyUrl(wechatPaymentSetting().getCallbackUrl(), PaymentMethodEnum.WECHAT)); + + Refund refund=refundService.create(request); + + log.info("微信退款响应 {}", refund); + refundLogService.save(refundLog); } catch (Exception e) { log.error("微信退款申请失败", e); } @@ -664,10 +628,10 @@ public class WechatPlugin implements Payment { String result = HttpKit.readData(request); log.info("微信退款通知密文 {}", result); JSONObject ciphertext = JSONUtil.parseObj(result); - + WechatPaymentSetting setting = wechatPaymentSetting(); try { //校验服务器端响应¬ String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, - wechatPaymentSetting().getApiKey3(), Objects.requireNonNull(getPlatformCert())); + wechatPaymentSetting().getApiKey3(), Objects.requireNonNull(setting.getPublicKey())); log.info("微信退款通知明文 {}", plainText); if (("REFUND.SUCCESS").equals(ciphertext.getStr("event_type"))) { @@ -721,78 +685,22 @@ public class WechatPlugin implements Payment { } /** - * 获取平台公钥 - * - * @return 平台公钥 + * 获取微信支付配置 + * @param setting + * @return */ - private X509Certificate getPlatformCert() { - //获取缓存中的平台公钥,如果有则直接返回,否则去微信请求 - String publicCert = cache.getString(CachePrefix.WECHAT_PLAT_FORM_CERT.getPrefix()); - if (!StringUtils.isEmpty(publicCert)) { - return PayKit.getCertificate(publicCert); - } - //获取平台证书列表 - try { - - WechatPaymentSetting setting = wechatPaymentSetting(); - - PaymentHttpResponse response = WechatApi.v3( - RequestMethodEnums.GET, - WechatDomain.CHINA.toString(), - WechatApiEnum.GET_CERTIFICATES.toString(), - setting.getMchId(), - setting.getSerialNumber(), - null, - setting.getApiclient_key(), - "" - ); - String body = response.getBody(); - log.info("获取微信平台证书body: {}", body); - if (response.getStatus() == 200) { - JSONObject jsonObject = JSONUtil.parseObj(body); - JSONArray dataArray = jsonObject.getJSONArray("data"); - //默认认为只有一个平台证书 - JSONObject encryptObject = dataArray.getJSONObject(0); - JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate"); - String associatedData = encryptCertificate.getStr("associated_data"); - String cipherText = encryptCertificate.getStr("ciphertext"); - String nonce = encryptCertificate.getStr("nonce"); - publicCert = getPlatformCertStr(associatedData, nonce, cipherText); - long second = (PayKit.getCertificate(publicCert).getNotAfter().getTime() - System.currentTimeMillis()) / 1000; - cache.put(CachePrefix.WECHAT_PLAT_FORM_CERT.getPrefix(), publicCert, second); - } else { - log.error("证书获取失败:{}" + body); - throw new ServiceException(ResultCode.WECHAT_CERT_ERROR); - } - return PayKit.getCertificate(publicCert); - } catch (Exception e) { - log.error("证书获取失败", e); - } - return null; + private RSAPublicKeyConfig getConfig(WechatPaymentSetting setting){ + return + new RSAPublicKeyConfig.Builder() + .merchantId(setting.getMchId()) + .privateKey(setting.getApiclientKey()) + .publicKey(setting.getPublicKey()) + .publicKeyId(setting.getPublicId()) + .merchantSerialNumber(setting.getSerialNumber()) + .apiV3Key(setting.getApiKey3()) + .build(); } - /** - * 获取平台证书缓存的字符串 - * 下列各个密钥参数 - * - * @param associatedData 密钥参数 - * @param nonce 密钥参数 - * @param cipherText 密钥参数 - * @return platform key - * @throws GeneralSecurityException 密钥获取异常 - */ - private String getPlatformCertStr(String associatedData, String nonce, String cipherText) throws GeneralSecurityException { - - - AesUtil aesUtil = new AesUtil(wechatPaymentSetting().getApiKey3().getBytes(StandardCharsets.UTF_8)); - //平台证书密文解密 - //encrypt_certificate 中的 associated_data nonce ciphertext - return aesUtil.decryptToString( - associatedData.getBytes(StandardCharsets.UTF_8), - nonce.getBytes(StandardCharsets.UTF_8), - cipherText - ); - } /** * 修改订单支付单号 diff --git a/framework/src/main/java/cn/lili/modules/system/entity/dto/payment/WechatPaymentSetting.java b/framework/src/main/java/cn/lili/modules/system/entity/dto/payment/WechatPaymentSetting.java index b26efad0..3b40db2a 100644 --- a/framework/src/main/java/cn/lili/modules/system/entity/dto/payment/WechatPaymentSetting.java +++ b/framework/src/main/java/cn/lili/modules/system/entity/dto/payment/WechatPaymentSetting.java @@ -37,10 +37,22 @@ public class WechatPaymentSetting { * 商户号 */ private String mchId; + /** + * 商户证书序列号 + */ + private String serialNumber; /** * 私钥 */ - private String apiclient_key; + private String apiclientKey; + /** + * 公钥ID + */ + private String publicId; + /** + * 公钥 + */ + private String publicKey; // /** // * pem 证书 // */ @@ -49,10 +61,7 @@ public class WechatPaymentSetting { // * p12 证书 // */ // private String apiclient_cert_p12; - /** - * 商户证书序列号 - */ - private String serialNumber; + /** * apiv3私钥 */