com.hn.pay.wxpay.utils.WxPayKit Maven / Gradle / Ivy
package com.hn.pay.wxpay.utils;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.HmacAlgorithm;
import com.hn.pay.enums.SignType;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* 微信支付工具类
*
* @author Javen
*/
public class WxPayKit {
private static final String FIELD_SIGN = "sign";
private static final String FIELD_SIGN_TYPE = "sign_type";
public static String hmacSha256(String data, String key) {
return SecureUtil.hmac(HmacAlgorithm.HmacSHA256, key).digestHex(data, CharsetUtil.UTF_8);
}
public static String md5(String data) {
return SecureUtil.md5(data);
}
/**
* AES 解密
*
* @param base64Data 需要解密的数据
* @param key 密钥
* @return 解密后的数据
*/
public static String decryptData(String base64Data, String key) {
return SecureUtil.aes(md5(key).toLowerCase().getBytes()).decryptStr(base64Data);
}
/**
* AES 加密
*
* @param data 需要加密的数据
* @param key 密钥
* @return 加密后的数据
*/
public static String encryptData(String data, String key) {
return SecureUtil.aes(md5(key).toLowerCase().getBytes()).encryptBase64(data.getBytes());
}
public static String generateStr() {
return IdUtil.fastSimpleUUID();
}
/**
* 组装签名的字段
*
* @param params 参数
* @param urlEncoder 是否urlEncoder
* @return {String}
*/
public static String packageSign(Map params, boolean urlEncoder) {
// 先将参数以其参数名的字典序升序进行排序
TreeMap sortedParams = new TreeMap(params);
// 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起
StringBuilder sb = new StringBuilder();
boolean first = true;
for (Map.Entry param : sortedParams.entrySet()) {
String value = param.getValue();
if (StrUtil.isEmpty(value)) {
continue;
}
if (first) {
first = false;
} else {
sb.append("&");
}
sb.append(param.getKey()).append("=");
if (urlEncoder) {
try {
value = urlEncode(value);
} catch (UnsupportedEncodingException e) {
}
}
sb.append(value);
}
return sb.toString();
}
public static String urlEncode(String src) throws UnsupportedEncodingException {
return URLEncoder.encode(src, CharsetUtil.UTF_8).replace("+", "%20");
}
/**
* 生成签名
*
* @param params 需要签名的参数
* @param partnerKey 密钥
* @param signType 签名类型
* @return 签名后的数据
*/
public static String createSign(Map params, String partnerKey, SignType signType) {
if (signType == null) {
signType = SignType.MD5;
}
// 生成签名前先去除sign
params.remove(FIELD_SIGN);
String tempStr = packageSign(params, false);
String stringSignTemp = tempStr + "&key=" + partnerKey;
if (signType == SignType.MD5) {
return md5(stringSignTemp).toUpperCase();
} else {
return hmacSha256(stringSignTemp, partnerKey).toUpperCase();
}
}
/**
* 构建签名
*
* @param params 需要签名的参数
* @param partnerKey 密钥
* @param signType 签名类型
* @return 签名后的 Map
*/
public static Map buildSign(Map params, String partnerKey, SignType signType) {
if (signType == null) {
signType = SignType.MD5;
}
params.put(FIELD_SIGN_TYPE, signType.getType());
String sign = createSign(params, partnerKey, signType);
params.put(FIELD_SIGN, sign);
return params;
}
/**
* 微信下单 map to xml
*
* @param params Map 参数
* @return xml 字符串
*/
public static String toXml(Map params) {
StringBuilder xml = new StringBuilder();
xml.append("");
for (Map.Entry entry : params.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
// 略过空值
if (StrUtil.isEmpty(value)) {
continue;
}
xml.append("<").append(key).append(">");
xml.append(entry.getValue());
xml.append("").append(key).append(">");
}
xml.append(" ");
return xml.toString();
}
/**
* 针对支付的 xml,没有嵌套节点的简单处理
*
* @param xmlStr xml 字符串
* @return 转化后的 Map
*/
public static Map xmlToMap(String xmlStr) {
XmlHelper xmlHelper = XmlHelper.of(xmlStr);
return xmlHelper.toMap();
}
/**
* 生成二维码链接
* 原生支付接口模式一(扫码模式一)
*
* @param sign 签名
* @param appId 公众账号ID
* @param mchId 商户号
* @param productId 商品ID
* @param timeStamp 时间戳
* @param nonceStr 随机字符串
* @return 二维码链接
*/
public static String bizPayUrl(String sign, String appId, String mchId, String productId, String timeStamp, String nonceStr) {
String rules = "weixin://wxpay/bizpayurl?sign=Temp&appid=Temp&mch_id=Temp&product_id=Temp&time_stamp=Temp&nonce_str=Temp";
return replace(rules, "Temp", sign, appId, mchId, productId, timeStamp, nonceStr);
}
/**
* 生成二维码链接
* 原生支付接口模式一(扫码模式一)
*
* @param partnerKey 密钥
* @param appId 公众账号ID
* @param mchId 商户号
* @param productId 商品ID
* @param timeStamp 时间戳
* @param nonceStr 随机字符串
* @param signType 签名类型
* @return 二维码链接
*/
public static String bizPayUrl(String partnerKey, String appId, String mchId, String productId, String timeStamp, String nonceStr, SignType signType) {
HashMap map = new HashMap();
map.put("appid", appId);
map.put("mch_id", mchId);
map.put("time_stamp", StrUtil.isEmpty(timeStamp) ? Long.toString(System.currentTimeMillis() / 1000) : timeStamp);
map.put("nonce_str", StrUtil.isEmpty(nonceStr) ? WxPayKit.generateStr() : nonceStr);
map.put("product_id", productId);
return bizPayUrl(createSign(map, partnerKey, signType), appId, mchId, productId, timeStamp, nonceStr);
}
/**
* 生成二维码链接
* 原生支付接口模式一(扫码模式一)
*
* @param partnerKey 密钥
* @param appId 公众账号ID
* @param mchId 商户号
* @param productId 商品ID
* @return String
*/
public static String bizPayUrl(String partnerKey, String appId, String mchId, String productId) {
String timeStamp = Long.toString(System.currentTimeMillis() / 1000);
String nonceStr = WxPayKit.generateStr();
HashMap map = new HashMap();
map.put("appid", appId);
map.put("mch_id", mchId);
map.put("time_stamp", timeStamp);
map.put("nonce_str", nonceStr);
map.put("product_id", productId);
return bizPayUrl(createSign(map, partnerKey, null), appId, mchId, productId, timeStamp, nonceStr);
}
/**
* 替换url中的参数
*
* @param str 原始字符串
* @param regex 表达式
* @param args 替换字符串
* @return {String}
*/
public static String replace(String str, String regex, String... args) {
for (String arg : args) {
str = str.replaceFirst(regex, arg);
}
return str;
}
/**
* 判断接口返回的 code
*
* @param codeValue code 值
* @return 是否是 SUCCESS
*/
public static boolean codeIsOk(String codeValue) {
return StrUtil.isNotEmpty(codeValue) && "SUCCESS".equals(codeValue);
}
/**
* 公众号支付-预付订单再次签名
* 注意此处签名方式需与统一下单的签名类型一致
* @param prepayId 预付订单号
* @param appId 应用编号
* @param partnerKey API Key
* @param signType signType
* @return 再次签名后的 Map
*/
public static Map prepayIdCreateSign(String prepayId, String appId, String partnerKey, SignType signType) {
Map packageParams = new HashMap();
packageParams.put("appId", appId);
packageParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
packageParams.put("nonceStr", String.valueOf(System.currentTimeMillis()));
packageParams.put("package", "prepay_id=" + prepayId);
if (signType == null) {
signType = SignType.MD5;
}
packageParams.put("signType", signType.getType());
String packageSign = WxPayKit.createSign(packageParams, partnerKey, signType);
packageParams.put("paySign", packageSign);
return packageParams;
}
/**
* APP 支付-预付订单再次签名
* 注意此处签名方式需与统一下单的签名类型一致
*
* @param appId 应用ID 或者 子商户应用ID
* @param partnerId 商户号 或者 子商户号
* @param prepayId 预支付交易会话ID
* @param partnerKey API Key
* @param signType 签名方式
* @return 再次签名后的 Map
*/
public static Map appPrepayIdCreateSign(String appId, String partnerId, String prepayId, String partnerKey, SignType signType) {
Map packageParams = new HashMap();
packageParams.put("appId", appId);
packageParams.put("partnerid", partnerId);
packageParams.put("prepayid", prepayId);
packageParams.put("package", "Sign=WXPay");
packageParams.put("nonceStr", String.valueOf(System.currentTimeMillis()));
packageParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
if (signType == null) {
signType = SignType.MD5;
}
packageParams.put("signType", signType.getType());
String packageSign = WxPayKit.createSign(packageParams, partnerKey, signType);
packageParams.put("paySign", packageSign);
return packageParams;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy