支付调整

This commit is contained in:
2026-01-14 17:04:48 +08:00
parent e8be5dee9d
commit 4eaedcce41
70 changed files with 1065 additions and 829 deletions

View File

@@ -1,276 +0,0 @@
package com.czg;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.czg.entity.CzgBaseReqParams;
import com.czg.entity.CzgBaseRespParams;
import com.czg.entity.req.*;
import com.czg.entity.resp.*;
import com.czg.enums.CzgPayEnum;
import com.czg.resp.CzgRespCode;
import com.czg.resp.CzgResult;
import com.czg.utils.AssertUtil;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
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
* CzgResult<CzgH5PayResp>
*/
public static CzgResult<Map<String, Object>> h5Pay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgH5PayReq bizData) {
return execPayResult(sendCzg(domain.concat(CzgPayEnum.H5PAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgH5PayResp.class));
}
/**
* js支付
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* CzgResult<CzgJsPayResp>
*/
public static CzgResult<Map<String, Object>> jsPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgJsPayReq bizData) {
return execPayResult(sendCzg(domain.concat(CzgPayEnum.JSPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgJsPayResp.class));
}
/**
* 小程序支付
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* CzgResult<CzgLtPayResp>
*/
public static CzgResult<Map<String, Object>> ltPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgLtPayReq bizData) {
return execPayResult(sendCzg(domain.concat(CzgPayEnum.LTPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgLtPayResp.class));
}
/**
* PC扫码支付
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* CzgResult<CzgScanPayResp>
*/
public static CzgResult<Map<String, Object>> scanPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgScanPayReq bizData) {
return execPayResult(sendCzg(domain.concat(CzgPayEnum.SCANPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgScanPayResp.class));
}
/**
* 聚合反扫
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* CzgResult<CzgMicroPayResp>
*/
public static CzgResult<Map<String, Object>> microPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgMicroPayReq bizData) {
return execPayResult(sendCzg(domain.concat(CzgPayEnum.MICROPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgMicroPayResp.class));
}
/**
* 订单查询
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* @param payOrderId 平台订单号
* @param mchOrderNo 商户订单号
*/
public static CzgResult<CzgBaseResp> 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), CzgBaseResp.class);
}
/**
* 订单退款
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
*/
public static CzgResult<CzgRefundResp> refundOrder(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgRefundReq bizData) {
return sendCzg(domain.concat(CzgPayEnum.REFUND.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgRefundResp.class);
}
/**
* 退款订单查询
*
* @param domain 域名
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* @param mchRefundNo 商户退款订单号 二选一
* @param refundOrderId 平台退款订单号 二选一
*/
public static CzgResult<CzgRefundResp> 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), CzgRefundResp.class);
}
/**
* 回调数据处理
*/
public static JSONObject getCzg(CzgBaseRespParams respParams) {
AssertUtil.isNull(respParams, "超掌柜交易 回调数据为空");
log.info("超掌柜交易请求响应,{}", respParams);
if (!"000000".equals(respParams.getCode())) {
log.error("超掌柜回调响应失败,{}", respParams);
return null;
}
// if (StrUtil.isNotBlank(respParams.getSign())) {
// if (validateSign(respParams.getSign(), respParams.getBizData())) {
// log.error("超掌柜回调 验签失败");
// }
// }
return JSONObject.parse(respParams.getBizData());
}
/**
* 默认Post
*
* @param url 请求地址
* @param params 参数实体
* @return {
* "code": "状态码", 200为成功
* "msg": "描述"
* "data": "返回Json数据",
* }
*/
private static <T> CzgResult<T> sendCzg(String url, CzgBaseReqParams params, Class<T> clazz) {
CzgResult<T> result = CzgResult.success();
Map<String, Object> reqMap = BeanUtil.beanToMap(params, false, false);
params.setSign(MD5.create().digestHex(sortFields(new TreeMap<>(reqMap))));
log.info("超掌柜交易请求参数,{}", JSONObject.toJSONString(params));
try (HttpResponse resp = HttpRequest.post(url).body(JSONObject.toJSONString(params)).execute()) {
if (resp.isOk()) {
// 获取响应体
String respStr = resp.body();
if (StrUtil.isNotEmpty(respStr)) {
log.info("超掌柜交易请求响应元数据,{}", 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())) {
// if (validateSign(respParams.getSign(), JSONObject.toJSONString(respParams))) {
// result.setCode(CzgRespCode.FAILURE.getCode());
// result.setMsg("验签失败");
// log.info("验签失败");
// }
result.setData(JSONObject.parseObject(respParams.getBizData(), clazz));
}
} else {
result.setCode(resp.getStatus());
result.setMsg("超掌柜交易请求失败");
log.error("超掌柜交易请求失败,状态码: {}", resp.getStatus());
}
} else {
result.setCode(resp.getStatus());
result.setMsg("超掌柜交易请求失败");
}
} catch (Exception e) {
log.error("超掌柜交易请求异常", e);
}
return result;
}
/**
* @param sign 签名
* @param dataJsonStr 业务数据
* @return false 验签通过 true 验签失败
*/
private static boolean validateSign(String sign, String dataJsonStr) {
Map<String, Object> dataMap = JSONObject.parseObject(dataJsonStr, new TypeReference<>() {
});
String newSign = MD5.create().digestHex((sortFields(new TreeMap<>(dataMap))));
return !StrUtil.equals(sign, newSign);
}
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;
}
private static CzgResult<Map<String, Object>> execPayResult(CzgResult<? extends CzgBaseResp> res) {
CzgResult<Map<String, Object>> result = CzgResult.success();
if (res.getCode() != 200 || res.getData() == null) {
result.setCode(500);
result.setMsg(res.getMsg());
return result;
}
CzgBaseResp data = res.getData();
Map<String, Object> map = new HashMap<>();
switch (data) {
case CzgMicroPayResp ignored -> {
if ("TRADE_SUCCESS".equals(data.getState())) {
return result;
} else if ("TRADE_AWAIT".equals(data.getState())) {
result.setCode(CzgRespCode.WAIT_PAY.getCode());
result.setMsg("等待用户付款");
} else {
result.setCode(CzgRespCode.FAILURE.getCode());
}
}
case CzgH5PayResp h5PayResp ->
map = JSONObject.parseObject(JSONObject.toJSONString(h5PayResp.getPayInfo()));
case CzgJsPayResp jsPayResp ->
map = JSONObject.parseObject(JSONObject.toJSONString(jsPayResp.getPayInfo()));
case CzgLtPayResp ltPayResp ->
map = JSONObject.parseObject(JSONObject.toJSONString(ltPayResp.getPayInfo()));
case CzgScanPayResp scanPayResp ->
map = JSONObject.parseObject(JSONObject.toJSONString(scanPayResp.getPayInfo()));
default -> throw new IllegalStateException("Unexpected value: " + data);
}
result.setData(map);
return result;
}
}

View File

@@ -1,89 +0,0 @@
package com.czg.entity;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
/**
* @author ww
*/
@Data
public class CzgBaseReqParams {
/**
* 应用ID tb_shop_merchant 表中的 app_id
*/
private String appId;
/**
* 签名
* MD5 appSecret 参数不做排序 直接放末尾)
* 加签字符串拼接方式为字段名 = 字段值并用&符号连接,需要按照既定排序方式相连,并且在末端连接 appSecret=xxx
* 使用 MD5 加签时,验签时使用同样的方式加签对比签名值即可
* <p>
* RSA2
* 加签字符串拼接方式为字段名=字段值并用 & 符号连接,使用应用私钥对该拼接串进行签名
*/
private String sign;
/**
* 签名方式
* 可选值 MD5、RSA2
*/
private String signType = "MD5";
/**
* 业务数据
* JSON 形式的字符串
*/
private String bizData;
/**
* 版本号 目前固定 1.0
*/
private String version = "1.0";
/**
* 请求时间 格式为 yyyyMMddHHmmss
*/
private String reqTime = DateUtil.format(new DateTime(), DatePattern.PURE_DATETIME_PATTERN);
/**
* 唯一请求 Id String(40)
*/
private String reqId = IdUtil.simpleUUID();
/**
* 应用密钥 tb_shop_merchant 表中的 app_secret
*/
private String appSecret;
/**
* 必填字段
*
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* @param bizData JSON 形式的字符串
*/
public CzgBaseReqParams(String appId, String bizData, String appSecret) {
this.appId = appId;
this.bizData = bizData;
this.appSecret = appSecret;
}
/**
* 必填字段
*
* @param appId 应用id tb_shop_merchant 表中的 app_id
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
* @param bizData JSON 形式的字符串
*/
public static CzgBaseReqParams getInstance(String appId, String appSecret, Object bizData) {
return new CzgBaseReqParams(appId, ObjectUtil.isNotEmpty(bizData) ? JSONObject.toJSONString(bizData) : "", appSecret);
}
}

View File

@@ -1,44 +0,0 @@
package com.czg.entity;
import lombok.Data;
/**
* @author ww
*/
@Data
public class CzgBaseRespParams {
/**
* 000000-处理成功
* 其他-处理有误,详见错误码
*/
private String code;
/**
* 具体错误原因
*/
private String msg;
/**
* 对data内数据签名,如data为空则不返回
*/
private String sign;
/**
* 返回json格式数据
*/
private String bizData;
/**
* 返回时间 yyyyMMddHHmmss
*/
private String timestamp;
@Override
public String toString() {
return "{" +
"\"code\":" + code +
", \"msg\":" + msg +
", \"sign\":" + sign +
", \"bizData\":" + bizData +
", \"timestamp\":" + timestamp +
'}';
}
}

View File

@@ -1,45 +0,0 @@
package com.czg.entity.notify;
import com.czg.entity.resp.CzgBaseResp;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author ww
* @description
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgPayNotifyDTO extends CzgBaseResp {
/**
* 消息类型 String(30)
* sft.trade.notify 支付通知
* sft.refund.notify 退款通知
* sft.division.notify 分账通知
*/
private String msgType;
/**
* 门店ID String(30)
*/
private String storeId;
/**
* 货币代码
*/
private String currency;
private String subject;
private String body;
//非必填
private String userId;
/**
* 支付成功时间
* yyyy-MM-dd HH:mm:ss
*/
private String payTime;
}

View File

@@ -1,87 +0,0 @@
package com.czg.entity.notify;
import lombok.Data;
/**
* @author ww
* @description
*/
@Data
public class CzgRefundNotifyDTO {
/**
* 消息类型 String(30)
* sft.trade.notify 支付通知
* sft.refund.notify 退款通知
* sft.division.notify 分账通知
*/
private String msgType;
/**
* 商户退款订单号 String(30)
* 商户上送的退款订单号
*/
private String mchRefundNo;
/**
* 平台退款订单号 String(30)
*/
private String refundOrderId;
/**
* 退款状态 String(10)
* INIT初始化
* ING退款中
* SUCCESS退款成功
* FAIL退款失败
* CLOSE退款关闭
*/
private String state;
/**
* 原平台交易单号 String(32)
*/
private String oriPayOrderId;
/**
* 商户号 String(30)
*/
private String mercNo;
/**
* 原订单交易金额
* 单位 分
*/
private Long oriAmount;
/**
* 退款金额
* 单位 分
*/
private Long refundAmt;
/**
* 退款原因
*/
private String refundReason;
//非必填
/**
* 所属渠道 String(10)
*/
private String ifCode;
/**
* 备注 String(30)
*/
private String note;
/**
* 退款完成时间 String(20)
* 格式yyyy-MM-dd HH:mm:ss
*/
private String refundTime;
/**
* 自定义扩展参数 String(256)
* * 扩展参数
* * {
* * "pay_type": "order/vip"
* * }
*/
private String extParam;
/**
* 支付方式
* WECHAT微信
* ALIPAY支付宝
* UNIONPAY银联云闪付
*/
private String payType;
}

View File

@@ -1,124 +0,0 @@
package com.czg.entity.req;
import lombok.Data;
import lombok.NonNull;
/**
* @author ww
*/
@Data
public class CzgBaseReq {
//必填范围
/**
* 订单标题
*/
private String subject;
/**
* 订单描述 String(256)
*/
private String body;
/**
* 交易金额
*/
private Long amount;
/**
* 货币类型 cny
*/
private String currency = "cny";
/**
* 商户订单号 String(30)
* 操作方式+雪花算法
* 收银机客户端 PC+雪花ID
* 微信小程序 WX+雪花ID
* 支付宝小程序 ALI+雪花ID
* PC管理端 WEB+雪花ID
* APP管理端 APP+雪花ID
* <p>
* 退款 re+雪花ID
*/
private String mchOrderNo;
/**
* 门店编号 tb_shop_merchant 的 store_id
*/
private String storeId;
//非必填项
/**
* 订单备注 String(50)
*/
private String buyerRemark;
/**
* 异步通知地址 String(128)
* 支付结果异步回调URL,只有传了该值才会发起回调
*/
private String notifyUrl;
/**
* 失效时间 int 15
* 订单失效时间,单位分钟,默认15小时.
* 取值范围 5-1440 分钟
* 订单在(创建时间+失效时间)后失效
*/
private Integer expiredTime;
/**
* 分账模式:
* 0-该笔订单不允许分账[默认],
* 1-实时分账
* 2-延时分账
*/
private Integer divisionMode;
/**
* 分账详情
*/
private String divisionDetail;
/**
* 扩展参数 String(512)
* 商户扩展参数,回调时会原样返回
* * 扩展参数
* * {
* * "pay_type": "order/vip"
* * }
*/
private String extParam;
/**
* 花呗分期数
* 支付宝交易时可传 而且金额需要大于或等于 100.00元时生效
* 3/6/12
*/
private Integer hbFqNum;
/**
* 卖家是否承担手续费
* 100卖家承担手续费
* 0买家承担手续费
*/
private Integer hbFqPercent;
/**
* 是否禁用信用卡
* -1不禁用 1禁用
* 不传默认为不限制
*/
private Integer limitPay;
public CzgBaseReq() {
}
public CzgBaseReq(String mchOrderNo, Long amount, String body,
String buyerRemark, String extParam) {
this.mchOrderNo = mchOrderNo;
this.body = body;
this.amount = amount;
this.buyerRemark = buyerRemark;
this.extParam = extParam;
}
public void assignMerchant(@NonNull String storeId, @NonNull String subject, @NonNull String notifyUrl) {
this.storeId = storeId;
this.subject = subject;
this.notifyUrl = notifyUrl;
}
}

View File

@@ -1,39 +0,0 @@
package com.czg.entity.req;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
/**
* h5支付请求参数
*
* @author ww
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgH5PayReq extends CzgBaseReq {
//必填范围
/**
* 用户IP 支付的用户IP
*/
private String clientIp;
private String payType;
//?
private String openId;
//非必填范围
/**
* 跳转通知地址
* 支付结果同步跳转通知URL
*/
private String returnUrl;
public CzgH5PayReq(@NonNull String mchOrderNo, @NonNull Long amount, String body, @NonNull String clientIp,
String returnUrl, String buyerRemark, @NonNull String extParam) {
super(mchOrderNo, amount, body, buyerRemark, extParam);
this.clientIp = clientIp;
this.returnUrl = returnUrl;
}
}

View File

@@ -1,71 +0,0 @@
package com.czg.entity.req;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
/**
* 公众号/生活号/银联js支付
*
* @author ww
* <p>
* ● 码牌、台卡、立牌等
* 用户通过扫描微信/支付宝/云闪付APP静态二维码输入订单金额进行付款动作。
* ● 公众号 / 生活号商城
* 用户通过公众号下单,输入密码完成付款动作。适用于自有公众号主体交易
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgJsPayReq extends CzgBaseReq {
//必填范围
/**
* 用户唯一标识 String(30)
* 微信支付时传入用户的openId
* 支付宝支付和银联支付时传入用户的userId
*/
private String userId;
/**
* 用户IP
* 需要传付款用户客户端IP地址
*/
private String clientIp;
/**
* 微信 WECHAT
* 支付宝 ALIPAY
* 银联云闪付 UNIONPAY
*/
private String payType;
//非必填范围
/**
* 子商户appid ,微信付款支付的时候 需要上送
*/
private String subAppid;
/**
* 跳转通知地址
* 支付结果同步跳转通知URL
*/
private String returnUrl;
/**
* 银联js支付成功前端跳转
*/
private String frontUrl;
/**
* 银联js支付失败前端跳转地址
*/
private String frontFailUrl;
public CzgJsPayReq(@NonNull String mchOrderNo,
@NonNull Long amount, String body,
@NonNull String openId, @NonNull String clientIp,
String returnUrl, String buyerRemark,@NonNull String extParam) {
super(mchOrderNo, amount, body, buyerRemark, extParam);
this.userId = openId;
this.clientIp = clientIp;
this.returnUrl = returnUrl;
}
}

View File

@@ -1,63 +0,0 @@
package com.czg.entity.req;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
/**
* 小程序支付
*
* @author ww
* 自有小程序拉起支付
* 自有小程序拉起服务商小程序,(微信)半屏小程序支付
* 半屏小程序需要在商户自己的小程序中的半屏小程序配置里面申请 否则会拉起全屏小程序支付
* <p>
* 半屏小程序支付适用场景是商户自己的小程序被纳入微信实物电商类型小程序导致间联商户无法绑定这类的小程序APPID
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgLtPayReq extends CzgBaseReq {
//必填范围
/**
* 用户唯一标识 String(30)
* 微信支付时,传入用户的 openId
* 支付宝支付和银联支付时,传入用户的 userId
*/
private String userId;
private String payType;
/**
* 用户 IP 支付的用户 IP
*/
private String clientIp;
//非必填范围
/**
* 跳转通知地址
* 支付结果同步跳转通知 URL
*/
private String returnUrl;
/**
* 子商户 appid ,微信付款支付的时候 需要上送
* isScreen 为 false 的情况下需要传入
*/
private String subAppid;
/**
* 是否半屏
* 是否使用半屏小程序,默认为 false
* 前提小程序被纳入了实物电商类型的小程序,间联商户无法绑定这类的小程序的 appid
*/
private boolean isScreen;
public CzgLtPayReq(@NonNull String mchOrderNo, @NonNull Long amount, @NonNull String payType,
String body, @NonNull String openId, @NonNull String clientIp,
String returnUrl, String buyerRemark, @NonNull String extParam) {
super(mchOrderNo, amount, body, buyerRemark, extParam);
this.userId = openId;
this.payType = "aliPay".equals(payType) ? "ALIPAY" : "WECHAT";
this.clientIp = clientIp;
this.returnUrl = returnUrl;
}
}

View File

@@ -1,37 +0,0 @@
package com.czg.entity.req;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
/**
* 反扫请求参数
*
* @author ww
* <p>
* 被扫免密同步返回支付结果,不推送异步通知。
* 被扫输密,推送异步通知。
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgMicroPayReq extends CzgBaseReq {
//必填范围
/**
* 付款码信息 String(30)
* 扫码设备获取微信或支付宝上付款的信息
*/
private String authCode;
//非必填范围
/**
* 子商户appid ,微信付款支付的时候 需要上送
*/
private String subAppid;
public CzgMicroPayReq(@NonNull String mchOrderNo, @NonNull Long amount, String body,
@NonNull String authCode, String buyerRemark, @NonNull String extParam) {
super(mchOrderNo, amount, body, buyerRemark, extParam);
this.authCode = authCode;
}
}

View File

@@ -1,61 +0,0 @@
package com.czg.entity.req;
import lombok.Data;
import lombok.NonNull;
/**
* @author ww
*/
@Data
public class CzgRefundReq {
//必填范围
/**
* 退款订单号
* 商户退款订单号
*/
private String mchRefundNo;
/**
* 退款原因
*/
private String refundReason;
/**
* 退款金额
* 单位为分
*/
private Long refundAmount;
//非必填范围
/**
* 原平台订单号 (二选一)
*/
private String payOrderId;
/**
* 原商户订单号 (二选一)
*/
private String mchOrderNo;
/**
* 扩展参数
* * 扩展参数
* * {
* * "pay_type": "order/vip"
* * }
*/
private String extParam;
/**
* 回调地址
*/
private String notifyUrl;
/**
* payOrderId和mchOrderNo 二选一 必填
*/
public CzgRefundReq(@NonNull String mchRefundNo, @NonNull String refundReason, @NonNull Long refundAmount,
String mchOrderNo, String extParam) {
this.mchRefundNo = mchRefundNo;
this.refundReason = refundReason;
this.refundAmount = refundAmount;
this.mchOrderNo = mchOrderNo;
this.extParam = extParam;
}
}

View File

@@ -1,35 +0,0 @@
package com.czg.entity.req;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
/**
* 正扫支付请求参数
*
* @author ww
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgScanPayReq extends CzgBaseReq {
// 必填项
/**
* 用户IP 支付的用户IP
*/
private String clientIp;
//非必填项
/**
* 跳转通知地址
* String(128)
*/
private String returnUrl;
public CzgScanPayReq(@NonNull String mchOrderNo, @NonNull Long amount, String body,
@NonNull String clientIp, String returnUrl, String buyerRemark, @NonNull String extParam) {
super(mchOrderNo, amount, body, buyerRemark, extParam);
this.clientIp = clientIp;
this.returnUrl = returnUrl;
}
}

View File

@@ -1,117 +0,0 @@
package com.czg.entity.resp;
import lombok.Data;
/**
* 超掌柜通用响应参数
*
* @author ww
*/
@Data
public class CzgBaseResp {
//必填范围
/**
* 交易金额
* 单位:分
*/
private Long amount;
/**
* String (32)
* 商户订单号
*/
private String mchOrderNo;
/**
* 平台订单号
*/
private String payOrderId;
/**
* 商户号
*/
private String mercNo;
/**
* 订单状态
* INIT - 订单初始化;
* TRADE_AWAIT - 待支付;
* TRADE_SUCCESS - 支付成功;
* TRADE_FAIL -支付失败;
* TRADE_CANCEL -交易取消;
* TRADE_REFUND -已退款;
* REFUND_ING - 退款中;
* TRADE_CLOSE -订单关闭
*/
private String state;
/**
* 订单类型
* 微信 WECHAT
* 支付宝 ALIPAY
* 银联云闪付 UNIONPAY
*/
private String payType;
/**
* 支付通道编码
*/
private String ifCode;
//非必填范围
/**
* 发往渠道的流水号
* 微信 / 支付宝订单详情中的商户单号
*/
private String channelSendNo;
/**
* 渠道订单号
* 微信 / 支付宝订单号
*/
private String channelTradeNo;
private String extParam;
/**
* 描述 如:等待用户付款
*/
private String note;
/**
* 交易手续费
*/
private Long tradeFee;
/**
* 门店 id
*/
private String storeId;
/**
* 订单标题
*/
private String subject;
/**
* 交易卡类型
* 00借记卡
* 01贷记卡
* 02零钱/余额
* 03花呗
* 04数字货币
* 99其他
*/
private String drType;
/**
* 退款金额
*/
private Long refundAmt;
/**
* 退款状态类型
* 0-未发生实际退款, 1-部分退款, 2-全额退款
*/
private Integer refundState;
/**
* 垫资手续费
*/
private String cashFee;
/**
* 结算类型 D0/D1/T1
*/
private String settlementType;
}

View File

@@ -1,16 +0,0 @@
package com.czg.entity.resp;
import com.czg.entity.resp.pay.CzgH5PayInfo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author ww
* @description H5支付响应参数
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgH5PayResp extends CzgBaseResp {
private CzgH5PayInfo payInfo;
}

View File

@@ -1,17 +0,0 @@
package com.czg.entity.resp;
import com.czg.entity.resp.pay.CzgPayInfo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* js支付响应参数
*
* @author ww
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgJsPayResp extends CzgBaseResp {
private CzgPayInfo payInfo;
}

View File

@@ -1,26 +0,0 @@
package com.czg.entity.resp;
import com.czg.entity.resp.pay.CzgLitePayInfo;
import com.czg.entity.resp.pay.CzgPayInfo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 小程序支付 响应
*
* @author ww
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgLtPayResp extends CzgBaseResp{
/**
* 支付信息
*/
private CzgPayInfo payInfo;
/**
* 小程序支付信息
*/
private CzgLitePayInfo liteInfo;
}

View File

@@ -1,16 +0,0 @@
package com.czg.entity.resp;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 反扫请求 响应
*
* @author ww
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgMicroPayResp extends CzgBaseResp{
}

View File

@@ -1,83 +0,0 @@
package com.czg.entity.resp;
import lombok.Data;
/**
* @author ww
* @description
*/
@Data
public class CzgRefundResp {
/**
* 商户上送的退款订单号
* String(30)
*/
private String mchRefundNo;
/**
* 平台退款订单号
* String(30)
*/
private String refundOrderId;
/**
* 退款状态
* String(10)
* INIT初始化
* ING退款中
* SUCCESS退款成功
* FAIL退款失败
* CLOSE退款关闭
*/
private String state;
/**
* 备注 String(30)
*/
private String note;
/**
* 原平台交易单号
* String(32)
*/
private String oriPayOrderId;
/**
* 商户号
* String(30)
*/
private String mercNo;
/**
* 原订单交易金额
* 单位分
*/
private Long oriAmount;
/**
* 退款金额
* 单位分
*/
private Long refundAmt;
/**
* 退款原因
*/
private String refundReason;
/**
* 所属渠道
* String(10)
* sxfpay
*/
private String ifCode;
/**
* 退款完成时间
* String(20)
* 格式yyyy-MM-dd HH:mm:ss
*/
private String refundTime;
/**
* 扩展参数
*/
private String extParam;
/**
* 支付类型
* String(10)
* WECHAT微信
* ALIPAY支付宝
* UNIONPAY银联云闪付
*/
private String payType;
}

View File

@@ -1,16 +0,0 @@
package com.czg.entity.resp;
import com.czg.entity.resp.pay.CzgScanPayInfo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author ww
* @description H5支付响应参数
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CzgScanPayResp extends CzgBaseResp {
private CzgScanPayInfo payInfo;
}

View File

@@ -1,15 +0,0 @@
package com.czg.entity.resp.pay;
import lombok.Data;
/**
* @author ww
* @description h5支付参数
*/
@Data
public class CzgH5PayInfo {
/**
* 支付跳转地址
*/
private String payUrl;
}

View File

@@ -1,36 +0,0 @@
package com.czg.entity.resp.pay;
import lombok.Data;
/**
* 支付信息
*
* @author ww
*/
@Data
public class CzgLitePayInfo {
/**
* 微信Appid
*/
private String appId;
/**
* 支付路径
*/
private String path;
/**
* 小程序的 版本env
* release - 正式、
* test - 开发、
* preview - 体验
*/
private String envVersion;
/**
* 微信小程序原始ID
*/
private String ghId;
/**
* 支付宝小程序路径
*/
private String alipayPath;
}

View File

@@ -1,50 +0,0 @@
package com.czg.entity.resp.pay;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* 支付信息
* @author ww
*/
@Data
public class CzgPayInfo {
/**
* 微信 Appid
*/
private String appId;
/**
* 微信 timeStamp
*/
private String timeStamp;
/**
* 微信 package
*/
@JSONField(name = "package")
private String wechatPackage;
/**
* 微信支付签名
*/
private String paySign;
/**
* 签名类型
* MD5/RSA
*/
private String signType;
/**
* 微信 nonceStr 微信支付下返回
*/
private String nonceStr;
/**
* 支付宝流水号
* 对应 trade_no
*/
private String tradeNo;
/**
* 银联重定向跳转地址 银联场景下返回
*/
private String redirectUrl;
}

View File

@@ -1,16 +0,0 @@
package com.czg.entity.resp.pay;
import lombok.Data;
/**
* 扫码支付参数
* @author ww
* @description
*/
@Data
public class CzgScanPayInfo {
/**
* 付款二维码地址 qrCodeUrl
*/
private String payUrl;
}

View File

@@ -1,29 +0,0 @@
package com.czg.enums;
import lombok.Getter;
/**
* @author ww
*/
@Getter
public enum CzgPayEnum {
SCANPAY("/api/open/payment/scanpay", "PC扫码支付"),
MICROPAY("/api/open/payment/micropay", "聚合反扫B扫C/ 快捷收款"),
JSPAY("/api/open/payment/jspay", "公众号/生活号/银联js支付"),
LTPAY("/api/open/payment/ltpay", "小程序支付"),
H5PAY("/api/open/payment/h5pay", "手机网页支付"),
TRADE("/api/open/query/trade", "订单状态查询"),
REFUND("/api/open/order/refund", "统一退款 D0退款需要使用平台户退款"),
QUERY_REFUND("/api/open/query/refund", "退款状态查询"),
;
private final String uri;
private final String msg;
CzgPayEnum(String uri, String msg) {
this.uri = uri;
this.msg = msg;
}
}