日志命名

MD5工具类
This commit is contained in:
wangw 2025-02-10 14:55:31 +08:00
parent e1215ca441
commit 7f8db2a727
1 changed files with 228 additions and 0 deletions

View File

@ -0,0 +1,228 @@
package com.czg;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSONObject;
import com.czg.entity.CzgBaseReqParams;
import com.czg.entity.CzgBaseRespParams;
import com.czg.entity.req.*;
import com.czg.enums.CzgPayEnum;
import com.czg.resp.CzgResult;
import com.czg.utils.MD5Util;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
/**
* @author ww
* @description 超掌柜支付类
*/
@Slf4j
public class CzgPayUtils {
/**
* h5支付
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
*/
public static CzgResult<Object> h5Pay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgH5PayReq bizData) {
return sendCzg(domain.concat(CzgPayEnum.H5PAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData));
}
/**
* js支付
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
*/
public static CzgResult<Object> jsPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgJsPayReq bizData) {
return sendCzg(domain.concat(CzgPayEnum.JSPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData));
}
/**
* 小程序支付
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
*/
public static CzgResult<Object> ltPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgLtPayReq bizData) {
return sendCzg(domain.concat(CzgPayEnum.LTPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData));
}
/**
* PC扫码支付
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
*/
public static CzgResult<Object> scanPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgScanPayReq bizData) {
return sendCzg(domain.concat(CzgPayEnum.SCANPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData));
}
/**
* 聚合反扫
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
*/
public static CzgResult<Object> microPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgMicroPayReq bizData) {
return sendCzg(domain.concat(CzgPayEnum.MICROPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData));
}
/**
* 订单查询
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* @param payOrderId 平台订单号
* @param mchOrderNo 商户订单号
*/
public static CzgResult<Object> queryPayOrder(@NonNull String domain, @NonNull String appId, @NonNull String appSecret,
String payOrderId, String mchOrderNo) {
JSONObject queryPayOrder = new JSONObject();
queryPayOrder.put("payOrderId", payOrderId);
queryPayOrder.put("mchOrderNo", mchOrderNo);
return sendCzg(domain.concat(CzgPayEnum.TRADE.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, queryPayOrder));
}
/**
* 订单退款
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
*/
public static CzgResult<Object> refundOrder(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgRefundReq bizData) {
return sendCzg(domain.concat(CzgPayEnum.REFUND.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData));
}
/**
* 退款订单查询
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* @param mchRefundNo 商户退款订单号 二选一
* @param refundOrderId 平台退款订单号 二选一
*/
public static CzgResult<Object> queryRefundOrder(@NonNull String domain, @NonNull String appId, @NonNull String appSecret,
String mchRefundNo, String refundOrderId) {
JSONObject queryPayOrder = new JSONObject();
queryPayOrder.put("mchRefundNo", mchRefundNo);
queryPayOrder.put("refundOrderId", refundOrderId);
return sendCzg(domain.concat(CzgPayEnum.QUERY_REFUND.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, queryPayOrder));
}
/**
* 回调数据处理 返回任意实体
*
* @param dataJsonStr 带解析数据
* @param clazz 返回的实体类
*/
public static <T> T getCzg(String dataJsonStr, Class<T> clazz) throws Exception {
if (StrUtil.isNotEmpty(dataJsonStr)) {
CzgBaseRespParams respParams = JSONObject.parseObject(dataJsonStr, CzgBaseRespParams.class);
log.info("超掌柜交易请求响应,{}", respParams);
if (!"000000".equals(respParams.getCode())) {
log.error("超掌柜回调响应失败,{}", respParams);
throw new Exception("超掌柜回调响应失败");
}
if (StrUtil.isNotBlank(respParams.getSign())) {
validateSign(respParams.getSign(), respParams.getBizData());
}
return JSONObject.parseObject(respParams.getBizData(), clazz);
} else {
throw new Exception("超掌柜回调接收内容异常");
}
}
/**
* 默认Post
*
* @param url 请求地址
* @param params 参数实体
* @return {
* "code": "状态码", 200为成功
* "data": "返回Json数据/返回错误描述",
* }
*/
private static CzgResult<Object> sendCzg(String url, CzgBaseReqParams params) {
CzgResult<Object> result = CzgResult.success();
Map<String, Object> reqMap = BeanUtil.beanToMap(params, false, false);
params.setSign(MD5Util.md5AsHex(sortFields(new TreeMap<>(reqMap))));
log.info("超掌柜交易请求参数,{}", params);
try (HttpResponse resp = HttpRequest.post(url).body(params.toString()).execute()) {
if (resp.isOk()) {
// 获取响应体
String respStr = resp.body();
if (StrUtil.isNotEmpty(respStr)) {
CzgBaseRespParams respParams = JSONObject.parseObject(respStr, CzgBaseRespParams.class);
log.info("超掌柜交易请求响应,{}", respParams);
result.setCode("000000".equals(respParams.getCode()) ? 200 : Integer.parseInt(respParams.getCode()));
result.setMsg(respParams.getMsg());
if ("000000".equals(respParams.getCode()) && StrUtil.isNotBlank(respParams.getSign())) {
validateSign(respParams.getSign(), respParams.getBizData());
result.setData(respParams.getBizData());
}
} else {
throw new Exception("超掌柜交易请求异常");
}
} else {
result.setCode(resp.getStatus());
result.setMsg("超掌柜交易请求失败");
log.error("超掌柜交易请求失败,状态码: {}", resp.getStatus());
}
} catch (Exception e) {
log.error("超掌柜交易请求异常", e);
}
return result;
}
/**
* @param sign 签名
* @param dataJsonStr 业务数据
* @throws Exception 验签失败
*/
private static void validateSign(String sign, String dataJsonStr) throws Exception {
Map dataMap = JSONObject.parseObject(dataJsonStr, Map.class);
String newSign = MD5Util.md5AsHex(sortFields(new TreeMap<>(dataMap)));
if (!sign.equals(newSign)) {
throw new Exception("验签失败");
}
}
private static String sortFields(TreeMap<String, Object> map) {
if (CollectionUtil.isEmpty(map)) {
log.error("超掌柜支付参数为空!!!");
throw new RuntimeException("参数为空");
}
String sortParam = map.entrySet().stream()
// 过滤掉键为 "sign" 的元素
.filter(entry -> !"sign".equals(entry.getKey()) && !"appSecret".equals(entry.getKey()))
// 将每个键值对转换为 "key=value" 格式的字符串
.map(entry -> entry.getKey() + "=" + entry.getValue())
// 使用 "&" 连接所有转换后的字符串
.collect(Collectors.joining("&"));
if (map.containsKey("appSecret")) {
sortParam = sortParam.concat("&" + "appSecret=" + map.get("appSecret"));
}
return sortParam;
}
}