记得上下班打卡 | git大法好,push需谨慎

Commit fd0e404d authored by 姜秀龙's avatar 姜秀龙

Merge remote-tracking branch 'origin/dev-1.6-shouqianba' into dev-1.6-shouqianba

parents 9d6fdcc2 ca0f6dcc
...@@ -54,6 +54,7 @@ CREATE TABLE `goblin_sqb_order` ( ...@@ -54,6 +54,7 @@ CREATE TABLE `goblin_sqb_order` (
`sqb_order_sn` VARCHAR(64) COMMENT '收钱吧订单号', `sqb_order_sn` VARCHAR(64) COMMENT '收钱吧订单号',
`sqb_order_signature` VARCHAR(256) COMMENT '收钱吧订单签名', `sqb_order_signature` VARCHAR(256) COMMENT '收钱吧订单签名',
`sqb_acquiring_sn` VARCHAR(64) COMMENT '收钱吧收单号', `sqb_acquiring_sn` VARCHAR(64) COMMENT '收钱吧收单号',
`sqb_acquiring_sign` VARCHAR(255) DEFAULT '' COMMENT '收钱吧收单密钥',
`sqb_checkout_items_id` VARCHAR(64) COMMENT '结算明细ID', `sqb_checkout_items_id` VARCHAR(64) COMMENT '结算明细ID',
`coupon_sn` VARCHAR(64) COMMENT '券码编号', `coupon_sn` VARCHAR(64) COMMENT '券码编号',
`coupon_qr_code` VARCHAR(512) COMMENT '核销二维码', `coupon_qr_code` VARCHAR(512) COMMENT '核销二维码',
......
...@@ -27,6 +27,12 @@ ...@@ -27,6 +27,12 @@
<artifactId>liquidnet-service-dragon-api</artifactId> <artifactId>liquidnet-service-dragon-api</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-common-third-sqb</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
...@@ -446,4 +446,10 @@ public class GoblinRedisConst { ...@@ -446,4 +446,10 @@ public class GoblinRedisConst {
*/ */
public static final String SQB_ORDER_LOCK = PREFIX.concat("sqb:order:lock:"); public static final String SQB_ORDER_LOCK = PREFIX.concat("sqb:order:lock:");
/**
* 收钱吧 用户订单列表
*/
public static final String SQB_GOBLIN_ORDER_LIST = PREFIX.concat("sqb:order:id:list:");//用户订单id列表 key:$uid
} }
package com.liquidnet.service.goblin.dto.manage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ApiModel(value = "GoblinSqbOrderParam")
@Data
public class GoblinSqbOrderParam {
@ApiModelProperty(required = true, value = "apuId")
@NotBlank(message = "商品不能为空")
private String spuId;
@ApiModelProperty(required = true, value = "skuId")
@NotBlank(message = "商品规格不能为空")
private String skuId;
@ApiModelProperty(required = true, value = "购买数量")
@NotNull(message = "购买数量不能为空")
private Integer quantity;
@ApiModelProperty(required = true, value = "关联演出ID")
@NotBlank(message = "关联演出ID不能为空")
private String performancesId;
}
package com.liquidnet.service.goblin.dto.manage; package com.liquidnet.service.goblin.dto.manage;
import com.liquidnet.common.third.sqb.param.response.data.MallProductsQueryData;
import com.liquidnet.commons.lang.constant.LnsRegex; import com.liquidnet.commons.lang.constant.LnsRegex;
import com.liquidnet.commons.lang.util.CollectionUtil; import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator; import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.goblin.dto.GoblinGoodsSpecDto; import com.liquidnet.service.goblin.dto.GoblinGoodsSpecDto;
import com.liquidnet.service.goblin.dto.vo.*; import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
...@@ -152,7 +151,6 @@ public class GoblinStoreMgtGoodsSqbAddParam implements Serializable { ...@@ -152,7 +151,6 @@ public class GoblinStoreMgtGoodsSqbAddParam implements Serializable {
} }
/** /**
* 编辑SPU参数整理 * 编辑SPU参数整理
* *
......
...@@ -78,7 +78,7 @@ public class GoblinOrderSkuVo implements Serializable, Cloneable { ...@@ -78,7 +78,7 @@ public class GoblinOrderSkuVo implements Serializable, Cloneable {
* ---------------------------- 以下为券类商品-代金券属性 ---------------------------- * ---------------------------- 以下为券类商品-代金券属性 ----------------------------
*/ */
@ApiModelProperty(value = "商品类型[0-常规|1-数字藏品|2-券类商品]") @ApiModelProperty(value = "商品类型[0-常规|1-数字藏品|2-券类商品] 33-收钱吧商品")
private Integer skuType; private Integer skuType;
@ApiModelProperty(value = "是否实名[0-否|1-是,表示该商品需要实名关联],这里默认0") @ApiModelProperty(value = "是否实名[0-否|1-是,表示该商品需要实名关联],这里默认0")
private Integer isTrueName; private Integer isTrueName;
......
package com.liquidnet.service.goblin.dto.vo; package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
@Data @Data
@ApiModel(value = "用户端-查询券码-VO")
public class GoblinSqbCouponVo implements Serializable { public class GoblinSqbCouponVo implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private String couponSn; private String couponSn;
......
package com.liquidnet.service.goblin.dto.vo; package com.liquidnet.service.goblin.dto.vo;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
@Data @Data
...@@ -16,13 +17,17 @@ public class GoblinSqbOrderVo implements Serializable { ...@@ -16,13 +17,17 @@ public class GoblinSqbOrderVo implements Serializable {
private String sqbOrderSn; private String sqbOrderSn;
private String sqbOrderSignature; private String sqbOrderSignature;
private String sqbAcquiringSn; private String sqbAcquiringSn;
private String sqbAcquiringSign;
private String sqbCheckoutItemsId; private String sqbCheckoutItemsId;
private String couponSn; private String couponSn;
private String couponQrCode; private String couponQrCode;
private String couponExpireTime; private String couponExpireTime;
private Integer status; // 0-待支付 1-已支付 2-已核销 3-已退款 4-退款中 9-失败 private Integer status; // 0-待支付 1-已支付 2-已核销 3-已退款 4-退款中 9-失败
private Integer couponUsedStatus; // 0-未核销 1-已核销
private String refundReason; private String refundReason;
private String createdAt; private String createdAt;
private String updatedAt; private String updatedAt;
// 扩展属性
private Integer couponUsedStatus; // 0-未核销 1-已核销
} }
package com.liquidnet.service.goblin.dto.vo; package com.liquidnet.service.goblin.dto.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData; import com.liquidnet.common.third.sqb.param.response.data.MallProductsQueryData;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
......
package com.liquidnet.service.goblin.param.shouqianba.callback;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "CallbackParams", description = "收钱吧微信小店订单推送请求体")
public class CallbackParams {
@ApiModelProperty(value = "推送事件ID,全局唯一", example = "2024013000594610646")
private Long eventId;
@ApiModelProperty(value = "推送时间戳,当前时间毫秒值", example = "1706679507593")
private Long timestamp;
@ApiModelProperty(value = "随机字串,用于签名", example = "j9xd5kc7ixcryy7at5rrrv24xty783th")
private String nonce;
@ApiModelProperty(value = "订单数据 JSON字符串 (详见 SqbOrderContentDTO)")
private String content;
@ApiModelProperty(value = "报文签名", example = "bryyeKJ6opUothNTz1s3+F98LOl2Teji6T4XcEAejxdt...")
private String signature;
}
package com.liquidnet.service.goblin.param.shouqianba.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "券码状态同步")
public class CouponStatusSyncRequest {
@ApiModelProperty(required = true, value = "应用ID(聚合收单唯一ID,需申请)")
private String appid;
@ApiModelProperty(required = true, value = "券号")
private List<String> voucherNos;
@ApiModelProperty(required = true, value = "用户ID(自定义,核销用户id)")
private String redeemMerchantId;
@ApiModelProperty(required = true, value = "外部单号(${AppCode}+id,AppCode需要分配)")
private String redeemExternalOrderSn;
@ApiModelProperty(required = true, value = "来源(固定值:EXTERN)")
private String redeemSource;
@ApiModelProperty(required = true, value = "核销终端号(自定义)")
private String clientSn;
@ApiModelProperty(required = true, value = "券使用状态(0未核销,1已核销)")
private Byte status;
}
package com.liquidnet.service.goblin.param.shouqianba.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 收钱吧商品同步单项参数
*/
@Data
public class GoblinSqbGoodsSyncParam implements Serializable {
private static final long serialVersionUID = 1L;
@NotBlank(message = "收钱吧商品 ID 不能为空")
@ApiModelProperty(value = "收钱吧商品 ID (对应 spuId)", required = true)
private String sqbProductId;
@ApiModelProperty(value = "收钱吧商品编码 (非必填)")
private String sqbProductSn;
@NotBlank(message = "商城编号不能为空")
@ApiModelProperty(value = "收钱吧商城编号", required = true)
private String mallSn;
@NotBlank(message = "商城签名不能为空")
@ApiModelProperty(value = "收钱吧商城签名", required = true)
private String mallSignature;
}
package com.liquidnet.service.goblin.service;
import com.liquidnet.service.goblin.param.shouqianba.callback.CallbackParams;
import com.liquidnet.service.goblin.param.shouqianba.request.*;
import com.liquidnet.service.goblin.param.shouqianba.response.data.*;
import java.util.List;
import java.util.Map;
/**
* 收钱吧对接接口定义
*
* @author liquidnet
* @since 2026-03-16
*/
public interface IGoblinShouQianBaService {
/**
* 创建结算明细
* <p>
* 对接收钱吧「创建结算明细」接口,向收钱吧上传订单结算数据。
* </p>
*
* @param request 创建结算明细请求参数
* @return 收钱吧响应结果;调用失败时返回 null
*/
SettlementCreateData createSettlement(SettlementCreateRequest request);
/**
*
* @param mallSn 商城ID
* @param signature 商城密钥
* @param userId 正在用户ID
* @param checkoutItems 商品
* @return
*/
SettlementCreateData createSettlement(String mallSn, String signature, String userId, List<SettlementCreateRequest.CheckoutItem> checkoutItems);
/**
* 创建订单
*
* @param request
* @return
*/
OrderCreateData createOrder(OrderCreateRequest request);
/**
*
* @param mallSn 商城ID
* @param signature 商城密钥
* @param checkoutItemsId 创建结算明细 返回的 结算项ID
* @param userId 正在用户ID
* @param requestId 请求ID
* @param subject 标题
* @return
*/
OrderCreateData createOrder(String mallSn, String signature, String checkoutItemsId, String userId, String requestId, String subject);
/**
* 创建收单
* 如果上一步创建收单失败 可以使用这个接口重新创建收单
*
* @return
*/
AcquiringCreateData createAcquiring(AcquiringCreateRequest request);
/**
* 查询收银台
*
* @param request
* @return
*/
CashierQueryData queryCashier(CashierQueryRequest request);
/**
* 查询收银台
* @param acquiringSn 收单号
* @param acquiringSignature 收单密钥
* @param userId 正在用户ID
* @return
*/
CashierQueryData queryCashier(String acquiringSn, String acquiringSignature, String userId);
/**
* 创建微信预支付订单
*
* @param request
* @return
*/
CreateWechatPrepayOrderData createWechatPrepayOrder(CreateWechatPrepayOrderRequest request);
/**
* 创建微信预支付订单
*
* @param acquiringSn 收单号
* @param signature 收单签名
* @param userId 正在用户ID
* @param amount 支付金额
* @param requestSn 支付请求号
* @param payTool 支付工具代码
* @param channelExt 通道扩展参数
* @param selectedSignature 支付工具签名
* @param seq 序列号 上一步seq(查询收银台)
* @return
*/
CreateWechatPrepayOrderData createWechatPrepayOrder(String acquiringSn,
String signature,
String userId,
String amount,
String requestSn,
CashierQueryData.PayTool payTool,
Map<String, Object> channelExt,
String selectedSignature,
String seq);
/**
* 查询券码
*
* @param request
* @return
*/
CouponQueryData queryCoupon(CouponQueryRequest request);
/**
* 查询券码
* @param sn 订单ID
* @param signature 订单密码
* @return
*/
CouponQueryData queryCoupon(String sn, String signature);
/**
* 券码状态同步
*
* @param request
* @return
*/
boolean syncCouponStatus(CouponStatusSyncRequest request);
/**
* 券码状态同步
* @param redeemMerchantId 用户ID(自定义,核销用户id)
* @param voucherNos 券号
* @param redeemExternalOrderSn 外部单号(${AppCode}+id,AppCode需要分配)
* @param clientSn 核销终端号(自定义)
* @param status 券使用状态(0未核销,1已核销)
* @return
*/
boolean syncCouponStatus(String redeemMerchantId,
List<String> voucherNos,
String redeemExternalOrderSn,
String clientSn,
Byte status);
/**
* 券退款
*
* @param request
* @return
*/
CouponRefundData refundCoupon(CouponRefundRequest request);
/**
* @param sn 单号(前置操作后拿到)
* @param signature 密码(前置操作后拿到)
* @param applyAmount 金额
* @param type 退款类型(1商品 2金额)
* @param item
* @param refundReason 退款原因
* @param requestId 退款请求id(${AppCode}+id)
* @return
*/
CouponRefundData refundCoupon(String sn,
String signature,
Long applyAmount,
Byte type,
List<CouponRefundRequest.RefundItem> item,
String refundReason,
String requestId);
/**
* 商城列表接口
*
* @param request
* @return
*/
List<MallListQueryData> queryMallList(MallListQueryRequest request);
/**
*
* @param endCursor 结束游标 上一页的结束游标(首次查询传 null)
* @param count 查询数量 每页返回的最大订单数
* @return
*/
List<MallListQueryData> queryMallList(String endCursor, Integer count);
/**
* 商城商品接口
*
* @param request
* @return
*/
List<MallProductsQueryData> queryMallProducts(MallProductsQueryRequest request);
/**
* 商城商品接口
* @param mallSn 商城ID
* @param signature 商城密码
* @return
*/
List<MallProductsQueryData> queryMallProducts(String mallSn, String signature);
/**
* 验签
* @param callbackParams
* @return
*/
boolean verifySignature(CallbackParams callbackParams);
}
package com.liquidnet.service.goblin.service; package com.liquidnet.service.goblin.service;
import com.liquidnet.common.third.sqb.param.callback.CouponCallbackContent;
import com.liquidnet.common.third.sqb.param.callback.OrderCallbackContent;
import com.liquidnet.common.third.sqb.param.callback.RefundCallbackContent;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbCouponVo; import com.liquidnet.service.goblin.dto.manage.GoblinSqbOrderParam;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderCreateVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderCreateVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderDetailVo;
import com.liquidnet.service.goblin.param.shouqianba.callback.CouponCallbackContent;
import com.liquidnet.service.goblin.param.shouqianba.callback.OrderCallbackContent;
import com.liquidnet.service.goblin.param.shouqianba.callback.RefundCallbackContent;
import java.util.List;
/** /**
* 收钱吧订单服务接口 * 收钱吧订单服务接口
...@@ -19,50 +16,31 @@ public interface IGoblinSqbOrderService { ...@@ -19,50 +16,31 @@ public interface IGoblinSqbOrderService {
* 创建收钱吧订单 * 创建收钱吧订单
* *
* @param userId 用户ID(从 token 获取) * @param userId 用户ID(从 token 获取)
* @param spuId 商品 SPU ID * @param orderParam
* @param skuId 商品 SKU ID
* @param quantity 购买数量
* @param performancesId 关联演出 ID
* @return 订单创建结果(orderId、acquiringSn、paymentVoucher) * @return 订单创建结果(orderId、acquiringSn、paymentVoucher)
*/ */
ResponseDto<GoblinSqbOrderCreateVo> createOrder(String userId, String spuId, String skuId, ResponseDto<GoblinSqbOrderCreateVo> createOrder(String userId, GoblinSqbOrderParam orderParam);
Integer quantity, String performancesId);
/**
* 查询支付状态
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @return 支付状态(0-待支付 1-已支付 9-失败)
*/
ResponseDto<Integer> queryPayStatus(String userId, String orderId);
/** /**
* 获取核销二维码(券码 * 再次付款(待支付状态下重新拉起微信支付
* *
* @param userId 用户ID * @param userId 用户ID
* @param orderId 本地订单ID * @param orderId 本地订单ID
* @return 券码信息(couponSn、couponQrCode、couponExpireTime * @return 新的 paymentVoucher(复用原 orderId
*/ */
ResponseDto<GoblinSqbCouponVo> queryCoupon(String userId, String orderId); ResponseDto<GoblinSqbOrderCreateVo> repay(String userId, String orderId);
/**
* 申请退款
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @return 退款结果
*/
ResponseDto<Boolean> refund(String userId, String orderId);
/** /**
* 主动同步核销状态 * 查询支付状态
* *
* @param userId 用户ID * @param userId 用户ID
* @param orderId 本地订单ID * @param orderId 本地订单ID
* @return 同步结果 * @return 支付状态(0-待支付 1-已支付 9-失败)
*/ */
ResponseDto<Boolean> syncCouponStatus(String userId, String orderId); ResponseDto<Integer> queryPayStatus(String userId, String orderId);
/** /**
* 支付成功回调(收钱吧主动推送) * 支付成功回调(收钱吧主动推送)
...@@ -85,37 +63,4 @@ public interface IGoblinSqbOrderService { ...@@ -85,37 +63,4 @@ public interface IGoblinSqbOrderService {
*/ */
ResponseDto<String> handleCouponCallback(CouponCallbackContent callbackContent); ResponseDto<String> handleCouponCallback(CouponCallbackContent callbackContent);
/**
* 演出结束自动退款(定时任务调用)
*
* @param performancesId 演出ID
* @return 处理结果摘要(成功/失败笔数)
*/
ResponseDto<String> autoRefundByPerformance(String performancesId);
/**
* 查询用户收钱吧订单列表
*
* @param userId 用户ID
* @return 收钱吧订单列表(仅 skuType=33 的订单,按下单时间倒序)
*/
ResponseDto<List<GoblinSqbOrderDetailVo>> getOrderList(String userId);
/**
* 查询收钱吧订单详情
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @return 订单详情(基础信息 + 收钱吧扩展信息)
*/
ResponseDto<GoblinSqbOrderDetailVo> getOrderDetail(String userId, String orderId);
/**
* 再次付款(待支付状态下重新拉起微信支付)
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @return 新的 paymentVoucher(复用原 orderId)
*/
ResponseDto<GoblinSqbOrderCreateVo> repay(String userId, String orderId);
} }
package com.liquidnet.service.goblin.service;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbCouponVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderDetailVo;
import java.util.List;
public interface IGoblinSqbService {
/**
* 获取核销二维码(券码)
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @return 券码信息(couponSn、couponQrCode、couponExpireTime)
*/
ResponseDto<GoblinSqbCouponVo> queryCoupon(String userId, String orderId);
/**
* 申请退款
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @return 退款结果
*/
ResponseDto<Boolean> refund(String userId, String orderId);
/**
* 主动同步核销状态
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @return 同步结果
*/
ResponseDto<Boolean> syncCouponStatus(String userId, String orderId);
/**
* 演出结束自动退款(定时任务调用)
* TODO
* @param performancesId 演出ID
* @return 处理结果摘要(成功/失败笔数)
*/
ResponseDto<String> autoRefundByPerformance(String performancesId);
/**
* 查询用户收钱吧订单列表
*
* @param userId 用户ID
* @return 收钱吧订单列表(仅 skuType=33 的订单,按下单时间倒序)
*/
ResponseDto<List<GoblinSqbOrderDetailVo>> getOrderList(String userId);
/**
* 查询收钱吧订单详情
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @return 订单详情(基础信息 + 收钱吧扩展信息)
*/
ResponseDto<GoblinSqbOrderDetailVo> getOrderDetail(String userId, String orderId);
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-common-third</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>liquidnet-common-third-sqb</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-common-base</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.liquidnet.service.goblin.service.impl; package com.liquidnet.common.third.sqb.biz;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.liquidnet.commons.lang.util.MD5Utils; import com.liquidnet.commons.lang.util.MD5Utils;
import com.liquidnet.service.goblin.config.properties.ShouqianbaProperties; import com.liquidnet.common.third.sqb.config.SqbConfig;
import com.liquidnet.service.goblin.param.shouqianba.callback.CallbackParams; import com.liquidnet.common.third.sqb.param.callback.CallbackParams;
import com.liquidnet.service.goblin.param.shouqianba.request.*; import com.liquidnet.common.third.sqb.param.request.*;
import com.liquidnet.service.goblin.param.shouqianba.response.*; import com.liquidnet.common.third.sqb.param.response.*;
import com.liquidnet.service.goblin.param.shouqianba.response.data.*; import com.liquidnet.common.third.sqb.param.response.data.*;
import com.liquidnet.service.goblin.service.IGoblinShouQianBaService; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
...@@ -31,23 +31,22 @@ import java.util.List; ...@@ -31,23 +31,22 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* 收钱吧对接实现 * 收钱吧对接公共工具
* *
* @author liquidnet * @author liquidnet
* @since 2026-03-16
*/ */
@Slf4j @Slf4j
@Service @Component
public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { public class SqbBiz {
@Getter
private final ShouqianbaProperties shouqianbaProperties; private final SqbConfig sqbConfig;
private final CommonRequest.Seller cachedSeller; private final CommonRequest.Seller cachedSeller;
public GoblinShouQianBaServiceImpl(ShouqianbaProperties properties) { public SqbBiz(SqbConfig properties) {
this.shouqianbaProperties = properties; this.sqbConfig = properties;
if (this.shouqianbaProperties == null) { if (this.sqbConfig == null) {
throw new IllegalArgumentException("找不到应用配置"); throw new IllegalArgumentException("找不到收钱吧应用配置");
} }
// 商户信息来自配置,整个生命周期内不变,提前构建并缓存 // 商户信息来自配置,整个生命周期内不变,提前构建并缓存
this.cachedSeller = new CommonRequest.Seller(); this.cachedSeller = new CommonRequest.Seller();
...@@ -59,7 +58,6 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -59,7 +58,6 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
private static final ObjectMapper objectMapper; private static final ObjectMapper objectMapper;
private static final RestTemplate restTemplate; private static final RestTemplate restTemplate;
static { static {
// 1. 初始化 RestTemplate 并强制设置 String 转换器为 UTF-8 // 1. 初始化 RestTemplate 并强制设置 String 转换器为 UTF-8
restTemplate = new RestTemplate(); restTemplate = new RestTemplate();
...@@ -77,15 +75,12 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -77,15 +75,12 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
* @param request 创建结算明细请求参数 * @param request 创建结算明细请求参数
* @return 收钱吧响应结果;调用失败时返回 null * @return 收钱吧响应结果;调用失败时返回 null
*/ */
@Override
public SettlementCreateData createSettlement(SettlementCreateRequest request) { public SettlementCreateData createSettlement(SettlementCreateRequest request) {
return executeShouQianBaRequest("/optimus/core/mall/createCheckoutItems", "创建结算明细", request, SettlementCreateResponse.class); return executeShouQianBaRequest("/optimus/core/mall/createCheckoutItems", "创建结算明细", request, SettlementCreateResponse.class);
} }
@Override
public SettlementCreateData createSettlement(String mallSn, String signature, String userId, List<SettlementCreateRequest.CheckoutItem> checkoutItems) { public SettlementCreateData createSettlement(String mallSn, String signature, String userId, List<SettlementCreateRequest.CheckoutItem> checkoutItems) {
SettlementCreateRequest request = new SettlementCreateRequest(); SettlementCreateRequest request = new SettlementCreateRequest();
request.setAppid(shouqianbaProperties.getAppId()); request.setAppid(sqbConfig.getAppId());
request.setMallID(buildMall(mallSn, signature)); request.setMallID(buildMall(mallSn, signature));
request.setSeller(cachedSeller); request.setSeller(cachedSeller);
request.setBuyer(buildBuyer(userId)); request.setBuyer(buildBuyer(userId));
...@@ -93,34 +88,15 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -93,34 +88,15 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
return createSettlement(request); return createSettlement(request);
} }
private CommonRequest.Mall buildMall(String mallSn, String signature) {
CommonRequest.Mall mall = new CommonRequest.Mall();
mall.setMallSn(mallSn);
mall.setSignature(signature);
return mall;
}
private CommonRequest.Buyer buildBuyer(String userId) {
CommonRequest.Buyer buyer = new CommonRequest.Buyer();
buyer.setBuyerId(userId);
return buyer;
}
/** /**
* 创建订单 * 创建订单
*
* @param request
* @return
*/ */
@Override
public OrderCreateData createOrder(OrderCreateRequest request) { public OrderCreateData createOrder(OrderCreateRequest request) {
return executeShouQianBaRequest("/optimus/core/order/placeOrder", "创建订单", request, OrderCreateResponse.class); return executeShouQianBaRequest("/optimus/core/order/placeOrder", "创建订单", request, OrderCreateResponse.class);
} }
@Override
public OrderCreateData createOrder(String mallSn, String signature, String checkoutItemsId, String userId, String requestId, String subject) { public OrderCreateData createOrder(String mallSn, String signature, String checkoutItemsId, String userId, String requestId, String subject) {
OrderCreateRequest orderCreateRequest = new OrderCreateRequest(); OrderCreateRequest orderCreateRequest = new OrderCreateRequest();
orderCreateRequest.setAppid(shouqianbaProperties.getAppId()); orderCreateRequest.setAppid(sqbConfig.getAppId());
orderCreateRequest.setMallID(buildMall(mallSn, signature)); orderCreateRequest.setMallID(buildMall(mallSn, signature));
orderCreateRequest.setSeller(cachedSeller); orderCreateRequest.setSeller(cachedSeller);
orderCreateRequest.setCheckoutItemsId(checkoutItemsId); orderCreateRequest.setCheckoutItemsId(checkoutItemsId);
...@@ -132,33 +108,23 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -132,33 +108,23 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
/** /**
* 创建收单 * 创建收单
* 如果上一步创建收单失败 可以使用这个接口重新创建收单
*
* @return
*/ */
@Override
public AcquiringCreateData createAcquiring(AcquiringCreateRequest request) { public AcquiringCreateData createAcquiring(AcquiringCreateRequest request) {
return executeShouQianBaRequest("/optimus/core/order/createAcquiring", "创建收单环节", request, AcquiringCreateResponse.class); return executeShouQianBaRequest("/optimus/core/order/createAcquiring", "创建收单环节", request, AcquiringCreateResponse.class);
} }
/** /**
* 查询收银台 * 查询收银台
*
* @param request
* @return
*/ */
@Override
public CashierQueryData queryCashier(CashierQueryRequest request) { public CashierQueryData queryCashier(CashierQueryRequest request) {
return executeShouQianBaRequest("/optimus/core/cashier/queryCashierPage", "查询收银台", request, CashierQueryResponse.class); return executeShouQianBaRequest("/optimus/core/cashier/queryCashierPage", "查询收银台", request, CashierQueryResponse.class);
} }
@Override
public CashierQueryData queryCashier(String acquiringSn, String acquiringSignature, String userId) { public CashierQueryData queryCashier(String acquiringSn, String acquiringSignature, String userId) {
CashierQueryRequest.PaymentEnv paymentEnv = new CashierQueryRequest.PaymentEnv(); CashierQueryRequest.PaymentEnv paymentEnv = new CashierQueryRequest.PaymentEnv();
paymentEnv.setClient("wechat"); paymentEnv.setClient("wechat");
CashierQueryRequest cashierQueryRequest = new CashierQueryRequest(); CashierQueryRequest cashierQueryRequest = new CashierQueryRequest();
cashierQueryRequest.setAppid(shouqianbaProperties.getAppId()); cashierQueryRequest.setAppid(sqbConfig.getAppId());
cashierQueryRequest.setSeller(cachedSeller); cashierQueryRequest.setSeller(cachedSeller);
cashierQueryRequest.setPaymentMode(4); cashierQueryRequest.setPaymentMode(4);
cashierQueryRequest.setPaymentEnv(paymentEnv); cashierQueryRequest.setPaymentEnv(paymentEnv);
...@@ -170,16 +136,10 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -170,16 +136,10 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
/** /**
* 创建微信预支付订单 * 创建微信预支付订单
*
* @param request
* @return
*/ */
@Override
public CreateWechatPrepayOrderData createWechatPrepayOrder(CreateWechatPrepayOrderRequest request) { public CreateWechatPrepayOrderData createWechatPrepayOrder(CreateWechatPrepayOrderRequest request) {
return executeShouQianBaRequest("/optimus/core/cashier/proxyPreCreatedPay", "创建微信预支付订单", request, CreateWechatPrepayOrderResponse.class); return executeShouQianBaRequest("/optimus/core/cashier/proxyPreCreatedPay", "创建微信预支付订单", request, CreateWechatPrepayOrderResponse.class);
} }
@Override
public CreateWechatPrepayOrderData createWechatPrepayOrder(String acquiringSn, public CreateWechatPrepayOrderData createWechatPrepayOrder(String acquiringSn,
String signature, String signature,
String userId, String userId,
...@@ -190,7 +150,7 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -190,7 +150,7 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
String selectedSignature, String selectedSignature,
String seq) { String seq) {
CreateWechatPrepayOrderRequest orderRequest = new CreateWechatPrepayOrderRequest(); CreateWechatPrepayOrderRequest orderRequest = new CreateWechatPrepayOrderRequest();
orderRequest.setAppid(shouqianbaProperties.getAppId()); orderRequest.setAppid(sqbConfig.getAppId());
orderRequest.setSeller(cachedSeller); orderRequest.setSeller(cachedSeller);
orderRequest.setAcquiringSn(acquiringSn); orderRequest.setAcquiringSn(acquiringSn);
orderRequest.setSignature(signature); orderRequest.setSignature(signature);
...@@ -200,39 +160,16 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -200,39 +160,16 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
return createWechatPrepayOrder(orderRequest); return createWechatPrepayOrder(orderRequest);
} }
private List<CreateWechatPrepayOrderRequest.UsingPayTool> buildUsingPayTools(String requestSn,
CashierQueryData.PayTool payTool,
Map<String, Object> channelExt,
String amount,
String userId) {
CreateWechatPrepayOrderRequest.UsingPayTool tool = new CreateWechatPrepayOrderRequest.UsingPayTool();
tool.setId(payTool.getId());
tool.setPayTool(Integer.valueOf(payTool.getCode()));
tool.setPayMode(4); // TODO 需要确认
tool.setAmount(amount);
tool.setIdentity(userId);
tool.setAmountComposition(payTool.getAmountComposition());
tool.setRequestSn(requestSn);
tool.setChannelExt(channelExt);
return Collections.singletonList(tool);
}
/** /**
* 查询券码 * 查询券码
*
* @param request
* @return
*/ */
@Override
public CouponQueryData queryCoupon(CouponQueryRequest request) { public CouponQueryData queryCoupon(CouponQueryRequest request) {
return executeShouQianBaRequest("/optimus/core/voucher/queryOrderVoucherList", "查询优惠券", request, CouponQueryResponse.class); return executeShouQianBaRequest("/optimus/core/voucher/queryOrderVoucherList", "查询优惠券", request, CouponQueryResponse.class);
} }
@Override
public CouponQueryData queryCoupon(String sn, String signature) { public CouponQueryData queryCoupon(String sn, String signature) {
CouponQueryRequest couponQueryRequest = new CouponQueryRequest(); CouponQueryRequest couponQueryRequest = new CouponQueryRequest();
couponQueryRequest.setAppid(shouqianbaProperties.getAppId()); couponQueryRequest.setAppid(sqbConfig.getAppId());
couponQueryRequest.setSeller(cachedSeller); couponQueryRequest.setSeller(cachedSeller);
couponQueryRequest.setOrderID(new CommonRequest.OrderInfo(sn, signature)); couponQueryRequest.setOrderID(new CommonRequest.OrderInfo(sn, signature));
return queryCoupon(couponQueryRequest); return queryCoupon(couponQueryRequest);
...@@ -240,20 +177,14 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -240,20 +177,14 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
/** /**
* 券码状态同步 * 券码状态同步
*
* @param request
* @return
*/ */
@Override
public boolean syncCouponStatus(CouponStatusSyncRequest request) { public boolean syncCouponStatus(CouponStatusSyncRequest request) {
CouponStatusSyncResponse response = executeRequestAndGetResponse("/optimus/core/voucher/modifyOrderVoucherList", "同步优惠券状态", request, CouponStatusSyncResponse.class); CouponStatusSyncResponse response = executeRequestAndGetResponse("/optimus/core/voucher/modifyOrderVoucherList", "同步优惠券状态", request, CouponStatusSyncResponse.class);
return response != null && Boolean.TRUE.equals(response.getSuccess()); return response != null && Boolean.TRUE.equals(response.getSuccess());
} }
@Override
public boolean syncCouponStatus(String redeemMerchantId, List<String> voucherNos, String redeemExternalOrderSn, String clientSn, Byte status) { public boolean syncCouponStatus(String redeemMerchantId, List<String> voucherNos, String redeemExternalOrderSn, String clientSn, Byte status) {
CouponStatusSyncRequest couponStatusSyncRequest = new CouponStatusSyncRequest(); CouponStatusSyncRequest couponStatusSyncRequest = new CouponStatusSyncRequest();
couponStatusSyncRequest.setAppid(shouqianbaProperties.getAppId()); couponStatusSyncRequest.setAppid(sqbConfig.getAppId());
couponStatusSyncRequest.setVoucherNos(voucherNos); couponStatusSyncRequest.setVoucherNos(voucherNos);
couponStatusSyncRequest.setRedeemSource("EXTERN"); couponStatusSyncRequest.setRedeemSource("EXTERN");
couponStatusSyncRequest.setRedeemExternalOrderSn(redeemExternalOrderSn); couponStatusSyncRequest.setRedeemExternalOrderSn(redeemExternalOrderSn);
...@@ -265,16 +196,10 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -265,16 +196,10 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
/** /**
* 券退款 * 券退款
*
* @param request
* @return
*/ */
@Override
public CouponRefundData refundCoupon(CouponRefundRequest request) { public CouponRefundData refundCoupon(CouponRefundRequest request) {
return executeShouQianBaRequest("/optimus/core/aftersale/applyRefund", "退款优惠券", request, CouponRefundResponse.class); return executeShouQianBaRequest("/optimus/core/aftersale/applyRefund", "退款优惠券", request, CouponRefundResponse.class);
} }
@Override
public CouponRefundData refundCoupon(String sn, public CouponRefundData refundCoupon(String sn,
String signature, String signature,
Long applyAmount, Long applyAmount,
...@@ -283,7 +208,7 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -283,7 +208,7 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
String refundReason, String refundReason,
String requestId) { String requestId) {
CouponRefundRequest couponRefundRequest = new CouponRefundRequest(); CouponRefundRequest couponRefundRequest = new CouponRefundRequest();
couponRefundRequest.setAppid(shouqianbaProperties.getAppId()); couponRefundRequest.setAppid(sqbConfig.getAppId());
couponRefundRequest.setSeller(cachedSeller); couponRefundRequest.setSeller(cachedSeller);
couponRefundRequest.setOrderID(new CommonRequest.OrderInfo(sn, signature)); couponRefundRequest.setOrderID(new CommonRequest.OrderInfo(sn, signature));
couponRefundRequest.setRefundInfo(new CouponRefundRequest.RefundInfo(applyAmount, type, item, refundReason)); couponRefundRequest.setRefundInfo(new CouponRefundRequest.RefundInfo(applyAmount, type, item, refundReason));
...@@ -294,18 +219,11 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -294,18 +219,11 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
/** /**
* 商城列表接口 * 商城列表接口
*
* @param request
* @return
*/ */
@Override
public List<MallListQueryData> queryMallList(MallListQueryRequest request) { public List<MallListQueryData> queryMallList(MallListQueryRequest request) {
return executeShouQianBaRequest("/optimus/core/open/mall/queryMallList", "查询门店列表", request, MallListQueryResponse.class); return executeShouQianBaRequest("/optimus/core/open/mall/queryMallList", "查询门店列表", request, MallListQueryResponse.class);
} }
@Override
public List<MallListQueryData> queryMallList(String endCursor, Integer count) { public List<MallListQueryData> queryMallList(String endCursor, Integer count) {
MallListQueryRequest.Filter filter = new MallListQueryRequest.Filter(); MallListQueryRequest.Filter filter = new MallListQueryRequest.Filter();
filter.setSeller(cachedSeller); filter.setSeller(cachedSeller);
...@@ -319,7 +237,7 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -319,7 +237,7 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
sort.setSort("DESC"); sort.setSort("DESC");
MallListQueryRequest mallListQueryRequest = new MallListQueryRequest(); MallListQueryRequest mallListQueryRequest = new MallListQueryRequest();
mallListQueryRequest.setAppid(shouqianbaProperties.getAppId()); mallListQueryRequest.setAppid(sqbConfig.getAppId());
mallListQueryRequest.setFilter(filter); mallListQueryRequest.setFilter(filter);
mallListQueryRequest.setCursor(cursor); mallListQueryRequest.setCursor(cursor);
mallListQueryRequest.setSort(sort); mallListQueryRequest.setSort(sort);
...@@ -328,19 +246,13 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -328,19 +246,13 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
/** /**
* 商城商品接口 * 商城商品接口
*
* @param request
* @return
*/ */
@Override
public List<MallProductsQueryData> queryMallProducts(MallProductsQueryRequest request) { public List<MallProductsQueryData> queryMallProducts(MallProductsQueryRequest request) {
return executeShouQianBaRequest("/optimus/core/open/mall/queryMallProducts", "查询门店商品", request, MallProductsQueryResponse.class); return executeShouQianBaRequest("/optimus/core/open/mall/queryMallProducts", "查询门店商品", request, MallProductsQueryResponse.class);
} }
@Override
public List<MallProductsQueryData> queryMallProducts(String mallSn, String signature) { public List<MallProductsQueryData> queryMallProducts(String mallSn, String signature) {
MallProductsQueryRequest request = new MallProductsQueryRequest(); MallProductsQueryRequest request = new MallProductsQueryRequest();
request.setAppid(shouqianbaProperties.getAppId()); request.setAppid(sqbConfig.getAppId());
request.setSeller(cachedSeller); request.setSeller(cachedSeller);
request.setMallID(new CommonRequest.Mall(mallSn, signature)); request.setMallID(new CommonRequest.Mall(mallSn, signature));
return queryMallProducts(request); return queryMallProducts(request);
...@@ -351,7 +263,7 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -351,7 +263,7 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
*/ */
private <T extends BaseResponse<?>> T executeRequestAndGetResponse( private <T extends BaseResponse<?>> T executeRequestAndGetResponse(
String apiPath, String businessName, Object request, Class<T> responseClass) { String apiPath, String businessName, Object request, Class<T> responseClass) {
final String url = shouqianbaProperties.getBaseApi() + apiPath; final String url = sqbConfig.getBaseApi() + apiPath;
log.info("[收钱吧] {}, 请求URL: {}, 请求参数: {}", businessName, url, request); log.info("[收钱吧] {}, 请求URL: {}, 请求参数: {}", businessName, url, request);
try { try {
...@@ -368,7 +280,6 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -368,7 +280,6 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
headers.add("X-env-flag", "41508"); headers.add("X-env-flag", "41508");
// 4. 发送请求 // 4. 发送请求
// 注意:传入的是 String jsonBody,接收的也是 String.class,确保不被二次处理
HttpEntity<String> entity = new HttpEntity<>(requestBody, headers); HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
...@@ -403,33 +314,61 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService { ...@@ -403,33 +314,61 @@ public class GoblinShouQianBaServiceImpl implements IGoblinShouQianBaService {
private String getSign(String bodyJsonStr) { private String getSign(String bodyJsonStr) {
try { try {
// 签名算法: sign = MD5( CONCAT( body + appkey ) ) // 签名算法: sign = MD5( CONCAT( body + appkey ) )
String rawStr = bodyJsonStr + shouqianbaProperties.getAppKey(); String rawStr = bodyJsonStr + sqbConfig.getAppKey();
String sign = MD5Utils.md5(rawStr); String sign = MD5Utils.md5(rawStr);
// 签名首部: Authorization: appid + " " + sign // 签名首部: Authorization: appid + " " + sign
return shouqianbaProperties.getAppId() + " " + sign; return sqbConfig.getAppId() + " " + sign;
} catch (Exception e) { } catch (Exception e) {
log.error("[收钱吧] 生成签名发生异常", e); log.error("[收钱吧] 生成签名发生异常", e);
return ""; return "";
} }
} }
private CommonRequest.Mall buildMall(String mallSn, String signature) {
CommonRequest.Mall mall = new CommonRequest.Mall();
mall.setMallSn(mallSn);
mall.setSignature(signature);
return mall;
}
private CommonRequest.Buyer buildBuyer(String userId) {
CommonRequest.Buyer buyer = new CommonRequest.Buyer();
buyer.setBuyerId(userId);
return buyer;
}
private List<CreateWechatPrepayOrderRequest.UsingPayTool> buildUsingPayTools(String requestSn,
CashierQueryData.PayTool payTool,
Map<String, Object> channelExt,
String amount,
String userId) {
CreateWechatPrepayOrderRequest.UsingPayTool tool = new CreateWechatPrepayOrderRequest.UsingPayTool();
tool.setId(payTool.getId());
tool.setPayTool(Integer.valueOf(payTool.getCode()));
tool.setPayMode(4); // TODO 需要确认
tool.setAmount(amount);
tool.setIdentity(userId);
tool.setAmountComposition(payTool.getAmountComposition());
tool.setRequestSn(requestSn);
tool.setChannelExt(channelExt);
return Collections.singletonList(tool);
}
/** /**
* 收钱吧回调推送验签 * 收钱吧回调推送验签
*
* @param callbackParams@return 验签是否通过
*/ */
public boolean verifySignature(CallbackParams callbackParams) { public boolean verifySignature(CallbackParams callbackParams) {
// 签名原串 = eventId + timestamp + nonce + content // 签名原串 = eventId + timestamp + nonce + content
String plaintext = callbackParams.getEventId() + callbackParams.getTimestamp() + callbackParams.getNonce() + callbackParams.getContent(); String plaintext = callbackParams.getEventId() + callbackParams.getTimestamp() + callbackParams.getNonce() + callbackParams.getContent();
return verifySignatureSHA256WithRSA(plaintext, callbackParams.getSignature(), shouqianbaProperties.getPublicKey()); return verifySignatureSHA256WithRSA(plaintext, callbackParams.getSignature(), sqbConfig.getPublicKey());
} }
public boolean verifySignatureSHA256WithRSA(String plaintext, String inputSignature, String pubKey) { private boolean verifySignatureSHA256WithRSA(String plaintext, String inputSignature, String pubKey) {
return verifySignatureSHA256WithRSA(plaintext.getBytes(StandardCharsets.UTF_8), inputSignature, pubKey); return verifySignatureSHA256WithRSA(plaintext.getBytes(StandardCharsets.UTF_8), inputSignature, pubKey);
} }
public boolean verifySignatureSHA256WithRSA(byte[] plaintextByte, String inputSignature, String pubKey) { private boolean verifySignatureSHA256WithRSA(byte[] plaintextByte, String inputSignature, String pubKey) {
try { try {
X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(pubKey)); X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(pubKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); KeyFactory keyFactory = KeyFactory.getInstance("RSA");
......
package com.liquidnet.service.goblin.config.properties; package com.liquidnet.common.third.sqb.config;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
...@@ -9,7 +9,7 @@ import org.springframework.stereotype.Component; ...@@ -9,7 +9,7 @@ import org.springframework.stereotype.Component;
@Component @Component
@Setter @Setter
@Getter @Getter
public class ShouqianbaProperties { public class SqbConfig {
private String appId; private String appId;
......
package com.liquidnet.common.third.sqb.param.callback;
import lombok.Data;
@Data
/**
* CallbackParams
*/
public class CallbackParams {
/** 推送事件ID,全局唯一 */
private Long eventId;
/** 推送时间戳,当前时间毫秒值 */
private Long timestamp;
/** 随机字串,用于签名 */
private String nonce;
/** 订单数据 JSON字符串 (详见 SqbOrderContentDTO) */
private String content;
/** 报文签名 */
private String signature;
}
package com.liquidnet.service.goblin.param.shouqianba.callback; package com.liquidnet.common.third.sqb.param.callback;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
@Data @Data
@ApiModel(value = "SqbVoucherStatusDTO", description = "收钱吧券状态推送内容详情") /**
* SqbVoucherStatusDTO
*/
public class CouponCallbackContent { public class CouponCallbackContent {
@ApiModelProperty(value = "订单Sn") /** 订单Sn */
private String orderSn; private String orderSn;
@ApiModelProperty(value = "商城Sn") /** 商城Sn */
private String mallSn; private String mallSn;
@ApiModelProperty(value = "商户Sn") /** 商户Sn */
private String merchantSn; private String merchantSn;
@ApiModelProperty(value = "门店id") /** 门店id */
private String storeId; private String storeId;
@ApiModelProperty(value = "券列表信息") /** 券列表信息 */
private List<VoucherItem> voucherList; private List<VoucherItem> voucherList;
@Data @Data
@ApiModel("VoucherItem") /**
* VoucherItem
*/
public static class VoucherItem { public static class VoucherItem {
@ApiModelProperty(value = "券号") /** 券号 */
private String voucherNo; private String voucherNo;
@ApiModelProperty(value = "类型") /** 类型 */
private String type; private String type;
@ApiModelProperty(value = "券状态 (0未核销, 1已核销, 2未核销退款, 3已核销退款中, 4未核销退款完成, 5已核销退款完成, 6已失效)") /** 券状态 (0未核销, 1已核销, 2未核销退款, 3已核销退款中, 4未核销退款完成, 5已核销退款完成, 6已失效) */
private Byte targetState; private Byte targetState;
@ApiModelProperty(value = "券原状态") /** 券原状态 */
private Byte sourceState; private Byte sourceState;
@ApiModelProperty(value = "券名称") /** 券名称 */
private String voucherName; private String voucherName;
@ApiModelProperty(value = "操作时间 (yyyy-MM-dd HH:mm:ss)") /** 操作时间 (yyyy-MM-dd HH:mm:ss) */
private String operationTime; private String operationTime;
@ApiModelProperty(value = "券对应的商品信息") /** 券对应的商品信息 */
private VoucherProductInfo item; private VoucherProductInfo item;
@ApiModelProperty(value = "券二维码地址") /** 券二维码地址 */
private String qrCodeUrl; private String qrCodeUrl;
@ApiModelProperty(value = "券二维码内容") /** 券二维码内容 */
private String qrCodeContent; private String qrCodeContent;
@ApiModelProperty(value = "原金额 (单位:分)") /** 原金额 (单位:分) */
private Long oriAmount; private Long oriAmount;
@ApiModelProperty(value = "实收金额 (单位:分)") /** 实收金额 (单位:分) */
private Long receivedAmount; private Long receivedAmount;
@ApiModelProperty(value = "核销信息 (已核销会有这部分)") /** 核销信息 (已核销会有这部分) */
private RedeemInfo redeemInfo; private RedeemInfo redeemInfo;
} }
@Data @Data
@ApiModel("VoucherProductInfo") /**
* VoucherProductInfo
*/
public static class VoucherProductInfo { public static class VoucherProductInfo {
@ApiModelProperty(value = "spuId") /** spuId */
private Long spuId; private Long spuId;
@ApiModelProperty(value = "skuId") /** skuId */
private Long skuId; private Long skuId;
@ApiModelProperty(value = "商品标题") /** 商品标题 */
private String title; private String title;
@ApiModelProperty(value = "商品图片地址") /** 商品图片地址 */
private String img; private String img;
} }
@Data @Data
@ApiModel("RedeemInfo") /**
* RedeemInfo
*/
public static class RedeemInfo { public static class RedeemInfo {
@ApiModelProperty(value = "操作来源 (如: EXTERN)") /** 操作来源 (如: EXTERN) */
private String redeemSource; private String redeemSource;
@ApiModelProperty(value = "操作appId") /** 操作appId */
private String redeemAppId; private String redeemAppId;
@ApiModelProperty(value = "客户端编码") /** 客户端编码 */
private String redeemClientSn; private String redeemClientSn;
@ApiModelProperty(value = "外部编码 (appId + 请求号)") /** 外部编码 (appId + 请求号) */
private String redeemExternalOrderSn; private String redeemExternalOrderSn;
@ApiModelProperty(value = "操作商户 (userId)") /** 操作商户 (userId) */
private String operatorMerchantId; private String operatorMerchantId;
} }
......
package com.liquidnet.service.goblin.param.shouqianba.callback; package com.liquidnet.common.third.sqb.param.callback;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@Data @Data
@ApiModel(value = "OrderCallbackContent", description = "收钱吧订单推送 Content 具体数据") /**
* OrderCallbackContent
*/
public class OrderCallbackContent { public class OrderCallbackContent {
@ApiModelProperty(value = "订单号", example = "71655367906162") /** 订单号 */
private String orderSn; private String orderSn;
@ApiModelProperty(value = "支付流水号列表", example = "[\"7894259297368060\"]") /** 支付流水号列表 */
private List<String> payTsnList; private List<String> payTsnList;
@ApiModelProperty(value = "终端号", example = "2101056320290541156") /** 终端号 */
private String terminalSn; private String terminalSn;
@ApiModelProperty(value = "门店号", example = "21590000000630325") /** 门店号 */
private String storeSn; private String storeSn;
@ApiModelProperty(value = "商城名称", example = "智能商城0206-17:35") /** 商城名称 */
private String mallName; private String mallName;
@ApiModelProperty(value = "订单金额", example = "2") /** 订单金额 */
private BigDecimal orderAmount; private BigDecimal orderAmount;
@ApiModelProperty(value = "创建时间", example = "2024-02-20 10:46:32") /** 创建时间 */
private String createdAt; private String createdAt;
@ApiModelProperty(value = "订单状态码 0:已创建 10:已支付 35:已完成 40:已取消", example = "35") /** 订单状态码 0:已创建 10:已支付 35:已完成 40:已取消 */
private Integer orderStateCode; private Integer orderStateCode;
@ApiModelProperty(value = "商品明细列表") /** 商品明细列表 */
private List<Item> items; private List<Item> items;
@ApiModelProperty(value = "收集的信息 JSON字符串", example = "[{\"type\":\"text\",\"form\":\"basic\",\"fieldName\":\"姓名\",\"content\":\"\"}]") /** 收集的信息 JSON字符串 */
private String collectedInfo; private String collectedInfo;
@ApiModelProperty(value = "预订单编码") /** 预订单编码 */
private List<String> preOrderSns; private List<String> preOrderSns;
@ApiModelProperty(value = "订单签名") /** 订单签名 */
private String orderSignature; private String orderSignature;
@ApiModelProperty(value = "支付的代客下单数据") /** 支付的代客下单数据 */
private List<PreOrder> preOrderList; private List<PreOrder> preOrderList;
@Data @Data
@ApiModel(value = "商品明细") /**
* 商品明细
*/
public static class Item { public static class Item {
@ApiModelProperty(value = "商品标题") /** 商品标题 */
private String title; private String title;
@ApiModelProperty(value = "规格描述") /** 规格描述 */
private String skuDesc; private String skuDesc;
@ApiModelProperty(value = "数量") /** 数量 */
private String quantity; private String quantity;
@ApiModelProperty(value = "单位") /** 单位 */
private String unit; private String unit;
} }
@Data @Data
@ApiModel(value = "采集数据") /**
* 采集数据
*/
public static class CollectedInfo { public static class CollectedInfo {
@ApiModelProperty(value = "控件类型") /** 控件类型 */
private String type; private String type;
@ApiModelProperty(value = "控件格式") /** 控件格式 */
private String form; private String form;
@ApiModelProperty(value = "字段名") /** 字段名 */
private String fieldName; private String fieldName;
@ApiModelProperty(value = "采集数据内容") /** 采集数据内容 */
private String content; private String content;
} }
@Data @Data
@ApiModel(value = "支付的代客下单数据") /**
* 支付的代客下单数据
*/
public static class PreOrder { public static class PreOrder {
@ApiModelProperty(value = "预订单id") /** 预订单id */
private String preOrderId; private String preOrderId;
@ApiModelProperty(value = "预订单编号") /** 预订单编号 */
private String preOrderSn; private String preOrderSn;
@ApiModelProperty(value = "请求号") /** 请求号 */
private String requestId; private String requestId;
} }
......
package com.liquidnet.service.goblin.param.shouqianba.callback; package com.liquidnet.common.third.sqb.param.callback;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
@Data @Data
@ApiModel(value = "SqbRefundContentDTO", description = "收钱吧退款推送内容详情") /**
* SqbRefundContentDTO
*/
public class RefundCallbackContent { public class RefundCallbackContent {
@ApiModelProperty(value = "售后单号 (全局唯一)", example = "71582143744560") /** 售后单号 (全局唯一) */
private String ticketSn; private String ticketSn;
@ApiModelProperty(value = "订单号", example = "2101056320290513285") /** 订单号 */
private String orderSn; private String orderSn;
@ApiModelProperty(value = "原状态") /** 原状态 */
private Integer sourceState; private Integer sourceState;
@ApiModelProperty(value = "目标状态 (20:完成, 15:退款完成, 0:创建, 10:退款中, 30:取消退款)", example = "15") /** 目标状态 (20:完成, 15:退款完成, 0:创建, 10:退款中, 30:取消退款) */
private Integer targetState; private Integer targetState;
@ApiModelProperty(value = "下单金额 (单位:分)", example = "100") /** 下单金额 (单位:分) */
private Long amount; private Long amount;
@ApiModelProperty(value = "申请金额 (单位:分)", example = "100") /** 申请金额 (单位:分) */
private Long applyAmount; private Long applyAmount;
@ApiModelProperty(value = "请求号") /** 请求号 */
private String requestId; private String requestId;
@ApiModelProperty(value = "来源 (如: EXTERN)") /** 来源 (如: EXTERN) */
private String requestSource; private String requestSource;
@ApiModelProperty(value = "退款的商品信息") /** 退款的商品信息 */
private SqbRefundItemContainer item; private SqbRefundItemContainer item;
@Data @Data
@ApiModel("SqbRefundItemContainer") /**
* SqbRefundItemContainer
*/
public static class SqbRefundItemContainer { public static class SqbRefundItemContainer {
@ApiModelProperty(value = "退款类型 (1:商品, 2:金额)") /** 退款类型 (1:商品, 2:金额) */
private Byte type; private Byte type;
@ApiModelProperty(value = "商品明细列表") /** 商品明细列表 */
private List<SqbRefundItemDetail> items; private List<SqbRefundItemDetail> items;
} }
@Data @Data
@ApiModel("SqbRefundItemDetail") /**
* SqbRefundItemDetail
*/
public static class SqbRefundItemDetail { public static class SqbRefundItemDetail {
@ApiModelProperty(value = "spu id") /** spu id */
private String spuId; private String spuId;
@ApiModelProperty(value = "sku id") /** sku id */
private String skuId; private String skuId;
@ApiModelProperty(value = "标题") /** 标题 */
private String title; private String title;
@ApiModelProperty(value = "数量") /** 数量 */
private String quantity; private String quantity;
@ApiModelProperty(value = "退款类型 (0:正常商品, 1:自定义商品)") /** 退款类型 (0:正常商品, 1:自定义商品) */
private Byte type; private Byte type;
} }
} }
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
/**
* 创建收单请求
*/
@Data @Data
@ApiModel(value = "创建收单请求")
public class AcquiringCreateRequest { public class AcquiringCreateRequest {
@ApiModelProperty(required = true, value = "应用id", example = "202507xxxxxxx") /**
* 应用id
*/
private String appid; private String appid;
@ApiModelProperty(required = true, value = "卖家信息") /**
* 卖家信息
*/
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
@ApiModelProperty(required = true, value = "卖家信息") /**
* 卖家信息
*/
private Order orderID; private Order orderID;
/**
* 订单信息
*/
@Data @Data
@ApiModel(value = "订单信息")
public static class Order { public static class Order {
@ApiModelProperty(required = true, value = "订单ID") /**
* 订单ID
*/
private String sn; private String sn;
@ApiModelProperty(required = true, value = "订单密码") /**
* 订单密码
*/
private String signature; private String signature;
} }
......
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
/**
* 收银台查询请求
*/
@Data @Data
@ApiModel(value = "收银台查询请求")
public class CashierQueryRequest { public class CashierQueryRequest {
@ApiModelProperty(required = true, value = "应用id", example = "202507xxxxxxx") /** 应用id */
private String appid; private String appid;
@ApiModelProperty(required = true, value = "商户信息") /** 商户信息 */
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
@ApiModelProperty(required = true, value = "支付模式代码", example = "4") /** 支付模式代码 */
private Integer paymentMode; private Integer paymentMode;
@ApiModelProperty(required = true, value = "支付环境") /** 支付环境 */
private PaymentEnv paymentEnv; private PaymentEnv paymentEnv;
@ApiModelProperty(required = false, value = "付款人信息") /** 付款人信息 */
private CommonRequest.Payer payer; private CommonRequest.Payer payer;
@ApiModelProperty(required = true, value = "收单信息") /** 收单信息 */
private CommonRequest.Acquiring acquiringInfo; private CommonRequest.Acquiring acquiringInfo;
@Data @Data
@ApiModel(value = "支付环境信息") /**
* 支付环境信息
*/
public static class PaymentEnv { public static class PaymentEnv {
@ApiModelProperty(required = false, value = "ip地址 最大40位") /** ip地址 最大40位 */
private String ip; private String ip;
@ApiModelProperty(required = true, value = "支付客户端 最大32位", example = "wechat") /** 支付客户端 最大32位 */
private String client; private String client;
@ApiModelProperty(required = false, value = "设备号 最大64位") /** 设备号 最大64位 */
private String device; private String device;
@ApiModelProperty(required = false, value = "版本号", example = "1.4") /** 版本号 */
private String version; private String version;
} }
......
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
...@@ -12,97 +10,141 @@ import java.util.List; ...@@ -12,97 +10,141 @@ import java.util.List;
@Data @Data
public class CommonRequest { public class CommonRequest {
/**
* 商城信息
*/
@Data @Data
@ApiModel(value = "商城信息")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public static class Mall{ public static class Mall {
@ApiModelProperty(required = true, value = "商城ID") /**
* 商城ID
*/
private String mallSn; private String mallSn;
@ApiModelProperty(required = true, value = "商城密码") /**
* 商城密码
*/
private String signature; private String signature;
} }
/**
* 卖家信息/商户信息
*/
@Data @Data
@ApiModel(value = "卖家信息/商户信息")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public static class Seller { public static class Seller {
@ApiModelProperty(required = true, value = "商户ID") /**
* 商户ID
*/
private String merchantId; private String merchantId;
@ApiModelProperty(required = true, value = "商户userID") /**
* 商户userID
*/
private String merchantUserId; private String merchantUserId;
@ApiModelProperty(required = true, value = "角色 固定值(super_admin)") /**
* 角色 固定值(super_admin)
*/
private String role; private String role;
} }
/**
* 买家信息
*/
@Data @Data
@ApiModel("买家信息")
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class Buyer{ public static class Buyer {
@ApiModelProperty(required = true, value = "买家ID(用户唯一标识)") /**
* 买家ID(用户唯一标识)
*/
private String buyerId; private String buyerId;
} }
/**
* 付款人信息
*/
@Data @Data
@ApiModel("付款人信息")
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class Payer{ public static class Payer {
@ApiModelProperty(required = true, value = "付款人ID") /**
* 付款人ID
*/
private String userId; private String userId;
} }
@ApiModel(value = "收单信息") /**
* 收单信息
*/
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public static class Acquiring{ public static class Acquiring {
@ApiModelProperty(value = "收单号") /**
* 收单号
*/
private String acquiringSn; private String acquiringSn;
@ApiModelProperty(value = "收单密钥") /**
* 收单密钥
*/
private String signature; private String signature;
} }
/**
* 金额构成信息
*/
@Data @Data
@ApiModel(value = "金额构成信息")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class AmountComposition { public static class AmountComposition {
@ApiModelProperty(required = true, value = "金额构成项列表") /**
* 金额构成项列表
*/
private List<CompositionItem> compositionItems; private List<CompositionItem> compositionItems;
} }
/**
* 金额构成项详情
*/
@Data @Data
@ApiModel(value = "金额构成项详情")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class CompositionItem { public static class CompositionItem {
@ApiModelProperty(required = true, value = "构成项类目") /**
* 构成项类目
*/
private String category; private String category;
@ApiModelProperty(required = true, value = "构成项金额") /**
* 构成项金额
*/
private Long amount; private Long amount;
} }
/**
* 订单信息
*/
@Data @Data
@ApiModel(value = "订单信息")
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public static class OrderInfo { public static class OrderInfo {
@ApiModelProperty(required = true, value = "订单ID") /**
* 订单ID
*/
private String sn; private String sn;
@ApiModelProperty(required = true, value = "订单密码") /**
* 订单密码
*/
private String signature; private String signature;
} }
......
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
/**
* 查询券码请求
*/
@Data @Data
@ApiModel(value = "查询券码请求")
public class CouponQueryRequest { public class CouponQueryRequest {
@ApiModelProperty(required = true, value = "应用id", example = "202507xxxxxxx") /** 应用id */
private String appid; private String appid;
@ApiModelProperty(required = true, value = "订单信息") /** 订单信息 */
private CommonRequest.OrderInfo orderID; private CommonRequest.OrderInfo orderID;
@ApiModelProperty(required = true, value = "卖家信息", example = "4") /** 卖家信息 */
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
......
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.List; import java.util.List;
/**
* 券退款请求参数
*/
@Data @Data
@ApiModel(value = "券退款请求参数")
public class CouponRefundRequest { public class CouponRefundRequest {
@ApiModelProperty(required = true, value = "应用ID(收钱吧分配的应用id)") /** 应用ID(收钱吧分配的应用id) */
private String appid; private String appid;
@ApiModelProperty(required = true, value = "卖家信息") /** 卖家信息 */
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
@ApiModelProperty(required = true, value = "订单信息") /** 订单信息 */
private CommonRequest.OrderInfo orderID; private CommonRequest.OrderInfo orderID;
@ApiModelProperty(required = true, value = "申请退款信息不能为空") /** 申请退款信息不能为空 */
private RefundInfo refundInfo; private RefundInfo refundInfo;
@ApiModelProperty(required = false, value = "退款请求id(${AppCode}+id)") /** 退款请求id(${AppCode}+id) */
private String requestId; private String requestId;
@ApiModelProperty(required = true, value = "退款来源(固定值:EXTERN)") /** 退款来源(固定值:EXTERN) */
private String requestSource; private String requestSource;
@Data @Data
@ApiModel(value = "退款信息") /**
* 退款信息
*/
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public static class RefundInfo { public static class RefundInfo {
@ApiModelProperty(required = true, value = "金额") /** 金额 */
private Long applyAmount; private Long applyAmount;
@ApiModelProperty(required = true, value = "退款类型(1商品 2金额)") /** 退款类型(1商品 2金额) */
private Byte type; private Byte type;
@ApiModelProperty(required = false, value = "退款明细(商品必填)") /** 退款明细(商品必填) */
private List<RefundItem> items; private List<RefundItem> items;
@ApiModelProperty(required = true, value = "退款原因") /** 退款原因 */
private String refundReason; private String refundReason;
} }
@Data @Data
@ApiModel(value = "退款明细商品") /**
* 退款明细商品
*/
public static class RefundItem { public static class RefundItem {
@ApiModelProperty(required = true, value = "spu") /** spu */
private String spuId; private String spuId;
@ApiModelProperty(required = true, value = "sku") /** sku */
private String skuId; private String skuId;
@ApiModelProperty(required = true, value = "标题") /** 标题 */
private String title; private String title;
@ApiModelProperty(required = true, value = "商品图片") /** 商品图片 */
private String img; private String img;
@ApiModelProperty(required = true, value = "数量") /** 数量 */
private String quantity; private String quantity;
@ApiModelProperty(required = false, value = "退款类型(0正常商品 1自定义商品)") /** 退款类型(0正常商品 1自定义商品) */
private Byte type; private Byte type;
} }
......
package com.liquidnet.common.third.sqb.param.request;
import lombok.Data;
import java.util.List;
/**
* 券码状态同步
*/
@Data
public class CouponStatusSyncRequest {
/** 应用ID(聚合收单唯一ID,需申请) */
private String appid;
/** 券号 */
private List<String> voucherNos;
/** 用户ID(自定义,核销用户id) */
private String redeemMerchantId;
/** 外部单号(${AppCode}+id,AppCode需要分配) */
private String redeemExternalOrderSn;
/** 来源(固定值:EXTERN) */
private String redeemSource;
/** 核销终端号(自定义) */
private String clientSn;
/** 券使用状态(0未核销,1已核销) */
private Byte status;
}
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/**
* 创建微信预支付订单请求
*/
@Data @Data
@ApiModel(value = "创建微信预支付订单请求")
public class CreateWechatPrepayOrderRequest { public class CreateWechatPrepayOrderRequest {
@ApiModelProperty(required = true, value = "应用id", example = "202507xxxxxxx") /** 应用id */
private String appid; private String appid;
@ApiModelProperty(required = true, value = "商户信息") /** 商户信息 */
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
@ApiModelProperty(required = true, value = "收单号") /** 收单号 */
private String acquiringSn; private String acquiringSn;
@ApiModelProperty(required = true, value = "收单签名") /** 收单签名 */
private String signature; private String signature;
@ApiModelProperty(required = true, value = "支付工具") /** 支付工具 */
private List<UsingPayTool> usingPayTools; private List<UsingPayTool> usingPayTools;
@ApiModelProperty(required = false, value = "支付环境") /** 支付环境 */
private PaymentEnv paymentEnv; private PaymentEnv paymentEnv;
@ApiModelProperty(required = true, value = "支付工具签名", notes = "上一步签名") /** 支付工具签名 */
private String selectedSignature; private String selectedSignature;
@ApiModelProperty(required = true, value = "序列号", notes = "上一步seq") /** 序列号 */
private String seq; private String seq;
@Data @Data
@ApiModel(value = "支付工具使用详情") /**
* 支付工具使用详情
*/
public static class UsingPayTool { public static class UsingPayTool {
@ApiModelProperty(required = true, value = "支付工具ID") /** 支付工具ID */
private Long id; private Long id;
@ApiModelProperty(required = true, value = "支付工具代码") /** 支付工具代码 */
private Integer payTool; private Integer payTool;
@ApiModelProperty(required = true, value = "支付模式", example = "4") /** 支付模式 */
private Integer payMode; private Integer payMode;
@ApiModelProperty(required = true, value = "支付金额") /** 支付金额 */
private String amount; private String amount;
@ApiModelProperty(required = true, value = "金额构成") /** 金额构成 */
private CommonRequest.AmountComposition amountComposition; private CommonRequest.AmountComposition amountComposition;
@ApiModelProperty(required = true, value = "用户身份信息", example = "wzwl") /** 用户身份信息 */
private String identity; private String identity;
@ApiModelProperty(required = true, value = "支付请求号", notes = "不超过40位") /** 支付请求号 */
private String requestSn; private String requestSn;
@ApiModelProperty(required = true, value = "通道扩展参数", example = "{\"sub_appid\":\"wx36e68952a6\"}") /** 通道扩展参数 */
private Map<String, Object> channelExt; private Map<String, Object> channelExt;
} }
@Data @Data
@ApiModel(value = "支付环境信息") /**
* 支付环境信息
*/
public static class PaymentEnv { public static class PaymentEnv {
@ApiModelProperty(required = false, value = "付款终端ip") /** 付款终端ip */
private String clientIp; private String clientIp;
@ApiModelProperty(required = false, value = "付款经纬度") /** 付款经纬度 */
private ClientPoi clientPoi; private ClientPoi clientPoi;
@ApiModelProperty(required = false, value = "支付入口") /** 支付入口 */
private String paymentEntry; private String paymentEntry;
} }
@Data @Data
@ApiModel(value = "地理位置信息") /**
* 地理位置信息
*/
public static class ClientPoi { public static class ClientPoi {
@ApiModelProperty(required = false, value = "经度信息") /** 经度信息 */
private String longitude; private String longitude;
@ApiModelProperty(required = false, value = "纬度信息") /** 纬度信息 */
private String latitude; private String latitude;
} }
......
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
@ApiModel(value = "商城列表接口") /**
* 商城列表接口
*/
@Data @Data
public class MallListQueryRequest implements Serializable { public class MallListQueryRequest implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "应用ID", example = "2025912312") /** 应用ID */
private String appid; private String appid;
@ApiModelProperty(value = "过滤条件") /** 过滤条件 */
private Filter filter; private Filter filter;
@ApiModelProperty(value = "分页游标") /** 分页游标 */
private Cursor cursor; private Cursor cursor;
@ApiModelProperty(value = "排序条件") /** 排序条件 */
private Sort sort; private Sort sort;
@Data @Data
@ApiModel("查询过滤条件") /**
* 查询过滤条件
*/
public static class Filter { public static class Filter {
@ApiModelProperty(value = "商户信息") /** 商户信息 */
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
@ApiModelProperty(value = "商城行业筛选") /** 商城行业筛选 */
private List<String> industryCodes; private List<String> industryCodes;
@ApiModelProperty(value = "商城状态筛选") /** 商城状态筛选 */
private List<Byte> states; private List<Byte> states;
@ApiModelProperty(value = "商城状态筛选") /** 商城状态筛选 */
private Byte state; private Byte state;
@ApiModelProperty(value = "创建时间起始") /** 创建时间起始 */
private String beginDateTime; private String beginDateTime;
@ApiModelProperty(value = "创建时间截止") /** 创建时间截止 */
private String endDateTime; private String endDateTime;
} }
@Data @Data
@ApiModel("排序规则") /**
* 排序规则
*/
public static class Sort { public static class Sort {
@ApiModelProperty(value = "排序方式: DESC/ASC") /** 排序方式: DESC/ASC */
private String sort; private String sort;
@ApiModelProperty(value = "排序字段") /** 排序字段 */
private String sortField; private String sortField;
} }
@Data @Data
@ApiModel("分页游标") /**
* 分页游标
*/
public static class Cursor { public static class Cursor {
@ApiModelProperty(value = "游标字段 分页依据的字段(固定为id)") /** 游标字段 分页依据的字段(固定为id) */
private String cursorField; private String cursorField;
@ApiModelProperty(value = "结束游标 上一页的结束游标(首次查询传 null)") /** 结束游标 上一页的结束游标(首次查询传 null) */
private String endCursor; private String endCursor;
@ApiModelProperty(value = "查询数量 每页返回的最大订单数") /** 查询数量 每页返回的最大订单数 */
private Integer count; private Integer count;
} }
} }
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
/**
* 商城列表查询响应数据
*/
@Data @Data
@ApiModel(value = "商城商品查询请求参数")
public class MallProductsQueryRequest { public class MallProductsQueryRequest {
@ApiModelProperty(value = "应用ID", required = true) /** 应用ID */
private String appid; private String appid;
@ApiModelProperty(value = "商户信息", required = true) /** 商户信息 */
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
@ApiModelProperty(value = "商城标识", required = true) /** 商城标识 */
private CommonRequest.Mall mallID; private CommonRequest.Mall mallID;
} }
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
...@@ -14,31 +12,30 @@ import java.util.List; ...@@ -14,31 +12,30 @@ import java.util.List;
* @author liquidnet * @author liquidnet
* @since 2026-03-16 * @since 2026-03-16
*/ */
@ApiModel(value = "创建订单")
@Data @Data
public class OrderCreateRequest implements Serializable { public class OrderCreateRequest implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ApiModelProperty(required = true, value = "应用ID(聚合收单唯一ID,需申请)") /** 应用ID(聚合收单唯一ID,需申请) */
private String appid; private String appid;
@ApiModelProperty(required = true, value = "商城信息") /** 商城信息 */
private CommonRequest.Mall mallID; private CommonRequest.Mall mallID;
@ApiModelProperty(required = true, value = "商户信息") /** 商户信息 */
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
@ApiModelProperty(required = true, value = "结算项ID") /** 结算项ID */
private String checkoutItemsId; private String checkoutItemsId;
@ApiModelProperty(required = true, value = "买家信息") /** 买家信息 */
private CommonRequest.Buyer buyer; private CommonRequest.Buyer buyer;
@ApiModelProperty(required = true, value = "请求ID 不超过40位") /** 请求ID 不超过40位 */
private String requestId; private String requestId;
@ApiModelProperty(required = true, value = "标题 不超过32") /** 标题 不超过32 */
private String subject; private String subject;
} }
package com.liquidnet.service.goblin.param.shouqianba.request; package com.liquidnet.common.third.sqb.param.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
...@@ -13,54 +11,55 @@ import java.util.List; ...@@ -13,54 +11,55 @@ import java.util.List;
* @author liquidnet * @author liquidnet
* @since 2026-03-16 * @since 2026-03-16
*/ */
@ApiModel(value = "创建结算明细请求参数")
@Data @Data
public class SettlementCreateRequest implements Serializable { public class SettlementCreateRequest implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ApiModelProperty(required = true, value = "应用ID(聚合收单唯一ID,需申请)") /** 应用ID(聚合收单唯一ID,需申请) */
private String appid; private String appid;
@ApiModelProperty(required = true, value = "商城信息") /** 商城信息 */
private CommonRequest.Mall mallID; private CommonRequest.Mall mallID;
@ApiModelProperty(required = true, value = "商户信息") /** 商户信息 */
private CommonRequest.Seller seller; private CommonRequest.Seller seller;
@ApiModelProperty(required = true, value = "买家信息") /** 买家信息 */
private CommonRequest.Buyer buyer; private CommonRequest.Buyer buyer;
@ApiModelProperty(required = false, value = "结算明细组(结算条目列表)") /** 结算明细组(结算条目列表) */
private List<CheckoutItem> checkoutItems; private List<CheckoutItem> checkoutItems;
@ApiModelProperty(required = false, value = "结算总金额(单位:分)") /** 结算总金额(单位:分) */
private Long amount; private Long amount;
@Data @Data
@ApiModel(value = "结算明细条目") /**
* 结算明细条目
*/
public static class CheckoutItem{ public static class CheckoutItem{
@ApiModelProperty(required = true, value = "商品识别号(商品唯一标识,如 spuId)") /** 商品识别号(商品唯一标识,如 spuId) */
private String spuId; private String spuId;
@ApiModelProperty(required = true, value = "规格识别号(SKU唯一标识,如 skuId)") /** 规格识别号(SKU唯一标识,如 skuId) */
private String skuId; private String skuId;
@ApiModelProperty(required = true, value = "单价(单位:分)") /** 单价(单位:分) */
private Long price; private Long price;
@ApiModelProperty(required = true, value = "购买数量") /** 购买数量 */
private String quantity; private String quantity;
@ApiModelProperty(required = true, value = "商品类型(0 正常商品 1 自定义商品)") /** 商品类型(0 正常商品 1 自定义商品) */
private Byte type; private Byte type;
@ApiModelProperty(required = true, value = "商品标题") /** 商品标题 */
private String title; private String title;
@ApiModelProperty(required = true, value = "商品图片链接") /** 商品图片链接 */
private String image; private String image;
} }
} }
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.AcquiringCreateData; import com.liquidnet.common.third.sqb.param.response.data.AcquiringCreateData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
/**
* 创建收单响应参数
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "创建收单响应参数")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AcquiringCreateResponse extends BaseResponse<AcquiringCreateData> { public class AcquiringCreateResponse extends BaseResponse<AcquiringCreateData> {
......
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
/**
* 收钱吧基础响应参数
*/
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel(value = "收钱吧基础响应参数")
public class BaseResponse<T> { public class BaseResponse<T> {
@ApiModelProperty(value = "是否成功(true-成功,false-失败)") /** 是否成功(true-成功,false-失败) */
private Boolean success; private Boolean success;
@ApiModelProperty(value = "业务码(200-成功,4001等-失败码)") /** 业务码(200-成功,4001等-失败码) */
private String code; private String code;
@ApiModelProperty(value = "失败信息(success为false时返回失败原因描述)") /** 失败信息(success为false时返回失败原因描述) */
private String msg; private String msg;
@ApiModelProperty(value = "data") /** data */
private T data; private T data;
} }
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.CashierQueryData; import com.liquidnet.common.third.sqb.param.response.data.CashierQueryData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
/**
* 自助收银查询响应
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "自助收银查询响应")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CashierQueryResponse extends BaseResponse<CashierQueryData>{ public class CashierQueryResponse extends BaseResponse<CashierQueryData>{
......
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.CouponQueryData; import com.liquidnet.common.third.sqb.param.response.data.CouponQueryData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
/**
* 券详情查询响应
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "券详情查询响应")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CouponQueryResponse extends BaseResponse<CouponQueryData>{ public class CouponQueryResponse extends BaseResponse<CouponQueryData>{
......
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.CouponRefundData; import com.liquidnet.common.third.sqb.param.response.data.CouponRefundData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
/**
* 券退款响应
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "券退款响应")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CouponRefundResponse extends BaseResponse<CouponRefundData>{ public class CouponRefundResponse extends BaseResponse<CouponRefundData>{
......
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
/**
* 券状态变更响应
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "券状态变更响应")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CouponStatusSyncResponse extends BaseResponse<String>{ public class CouponStatusSyncResponse extends BaseResponse<String>{
......
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.CreateWechatPrepayOrderData; import com.liquidnet.common.third.sqb.param.response.data.CreateWechatPrepayOrderData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
/**
* 创建微信预支付订单响应
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "创建微信预支付订单响应")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CreateWechatPrepayOrderResponse extends BaseResponse<CreateWechatPrepayOrderData>{ public class CreateWechatPrepayOrderResponse extends BaseResponse<CreateWechatPrepayOrderData>{
......
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallListQueryData; import com.liquidnet.common.third.sqb.param.response.data.MallListQueryData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.util.List; import java.util.List;
/**
* 商城列表查询响应参数
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel(value = "商城列表查询响应参数")
public class MallListQueryResponse extends BaseResponse<List<MallListQueryData>> { public class MallListQueryResponse extends BaseResponse<List<MallListQueryData>> {
} }
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData; import com.liquidnet.common.third.sqb.param.response.data.MallProductsQueryData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.util.List; import java.util.List;
/**
* 商城商品接口响应
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "商城商品接口响应")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class MallProductsQueryResponse extends BaseResponse<List<MallProductsQueryData>>{ public class MallProductsQueryResponse extends BaseResponse<List<MallProductsQueryData>>{
......
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.OrderCreateData; import com.liquidnet.common.third.sqb.param.response.data.OrderCreateData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
...@@ -13,7 +13,6 @@ import lombok.EqualsAndHashCode; ...@@ -13,7 +13,6 @@ import lombok.EqualsAndHashCode;
* @since 2026-03-16 * @since 2026-03-16
*/ */
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "创建订单响应参数")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class OrderCreateResponse extends BaseResponse<OrderCreateData>{ public class OrderCreateResponse extends BaseResponse<OrderCreateData>{
......
package com.liquidnet.service.goblin.param.shouqianba.response; package com.liquidnet.common.third.sqb.param.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.response.data.SettlementCreateData; import com.liquidnet.common.third.sqb.param.response.data.SettlementCreateData;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
...@@ -13,7 +13,6 @@ import lombok.EqualsAndHashCode; ...@@ -13,7 +13,6 @@ import lombok.EqualsAndHashCode;
* @since 2026-03-16 * @since 2026-03-16
*/ */
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ApiModel(value = "创建结算明细响应参数")
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class SettlementCreateResponse extends BaseResponse<SettlementCreateData> { public class SettlementCreateResponse extends BaseResponse<SettlementCreateData> {
......
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.request.CommonRequest; import com.liquidnet.common.third.sqb.param.request.CommonRequest;
import io.swagger.annotations.ApiModel;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
/**
* 创建收单Data
*/
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
@ApiModel(value = "创建收单Data")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class AcquiringCreateData extends CommonRequest.Acquiring { public class AcquiringCreateData extends CommonRequest.Acquiring {
......
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.request.CommonRequest; import com.liquidnet.common.third.sqb.param.request.CommonRequest;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
/**
* 收银台查询Data
*/
@Data @Data
@ApiModel(value = "收银台查询Data")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CashierQueryData { public class CashierQueryData {
@ApiModelProperty(value = "支付工具列表") /** 支付工具列表 */
private List<PayTool> payTools; private List<PayTool> payTools;
@ApiModelProperty(value = "已选中的支付工具签名") /** 已选中的支付工具签名 */
private String selectedSignature; private String selectedSignature;
@ApiModelProperty(value = "全局提示") /** 全局提示 */
private List<String> globalTips; private List<String> globalTips;
@ApiModelProperty(value = "响应唯一序列号") /** 响应唯一序列号 */
private String seq; private String seq;
@ApiModelProperty(value = "收单金额") /** 收单金额 */
private Long amount; private Long amount;
@ApiModelProperty(value = "收款方信息") /** 收款方信息 */
private Payee payee; private Payee payee;
@ApiModelProperty(value = "业务信息") /** 业务信息 */
private BizInfo bizInfo; private BizInfo bizInfo;
@ApiModelProperty(value = "金额模型") /** 金额模型 */
private CashierAmount cashierAmount; private CashierAmount cashierAmount;
@Data @Data
@ApiModel(value = "支付工具详情") /**
* 支付工具详情
*/
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class PayTool { public static class PayTool {
@ApiModelProperty(value = "支付工具id") /** 支付工具id */
private Long id; private Long id;
@ApiModelProperty(value = "支付工具代码") /** 支付工具代码 */
private String code; private String code;
@ApiModelProperty(value = "支付工具名称") /** 支付工具名称 */
private String name; private String name;
@ApiModelProperty(value = "支付工具类型 (0表示微信)") /** 支付工具类型 (0表示微信) */
private Integer type; private Integer type;
@ApiModelProperty(value = "是否可选") /** 是否可选 */
private Boolean selectable; private Boolean selectable;
@ApiModelProperty(value = "是否选中") /** 是否选中 */
private Boolean selected; private Boolean selected;
@ApiModelProperty(value = "展示金额") /** 展示金额 */
private Long showAmount; private Long showAmount;
@ApiModelProperty(value = "提示列表") /** 提示列表 */
private List<String> tips; private List<String> tips;
@ApiModelProperty(value = "金额构成") /** 金额构成 */
private CommonRequest.AmountComposition amountComposition; private CommonRequest.AmountComposition amountComposition;
} }
@Data @Data
@ApiModel(value = "收款方信息") /**
* 收款方信息
*/
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class Payee { public static class Payee {
@ApiModelProperty(value = "商户id") /** 商户id */
private String merchantId; private String merchantId;
@ApiModelProperty(value = "商户名称") /** 商户名称 */
private String merchantName; private String merchantName;
@ApiModelProperty(value = "门店id") /** 门店id */
private String storeId; private String storeId;
@ApiModelProperty(value = "门店名称") /** 门店名称 */
private String storeName; private String storeName;
@ApiModelProperty(value = "终端号") /** 终端号 */
private String terminalSn; private String terminalSn;
} }
@Data @Data
@ApiModel(value = "业务信息") /**
* 业务信息
*/
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class BizInfo { public static class BizInfo {
@ApiModelProperty(value = "业务方") /** 业务方 */
private String bizParty; private String bizParty;
@ApiModelProperty(value = "交易应用") /** 交易应用 */
private String tradeApp; private String tradeApp;
} }
@Data @Data
@ApiModel(value = "金额明细模型") /**
* 金额明细模型
*/
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class CashierAmount { public static class CashierAmount {
@ApiModelProperty(value = "原始支付金额") /** 原始支付金额 */
private Long oriPaymentAmount; private Long oriPaymentAmount;
@ApiModelProperty(value = "实际支付金额") /** 实际支付金额 */
private Long discPaymentAmount; private Long discPaymentAmount;
@ApiModelProperty(value = "优惠金额") /** 优惠金额 */
private Long discAmount; private Long discAmount;
} }
......
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel(value = "查询券码响应Data") /**
* 查询券码响应Data
*/
public class CouponQueryData { public class CouponQueryData {
@ApiModelProperty(value = "券名称") /** 券名称 */
private String voucherName; private String voucherName;
@ApiModelProperty(value = "商品SPU") /** 商品SPU */
private String spuId; private String spuId;
@ApiModelProperty(value = "商品SKU") /** 商品SKU */
private String skuId; private String skuId;
@ApiModelProperty(value = "商品地址") /** 商品地址 */
private String itemImageUrl; private String itemImageUrl;
@ApiModelProperty(value = "券二维码") /** 券二维码 */
private String url; private String url;
@ApiModelProperty(value = "券号") /** 券号 */
private String voucherNo; private String voucherNo;
@ApiModelProperty(value = "券类型 0金额券 1商品券") /** 券类型 0金额券 1商品券 */
private Byte type; private Byte type;
@ApiModelProperty(value = "券状态 0未核销 1已核销 2未核销退款 3已核销退款中 4未核销退款完成 5已核销退款完成 6已失效") /** 券状态 0未核销 1已核销 2未核销退款 3已核销退款中 4未核销退款完成 5已核销退款完成 6已失效 */
private Byte status; private Byte status;
@ApiModelProperty(value = "操作时间") /** 操作时间 */
private String operationTime; private String operationTime;
......
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
/**
* 券退款响应结果
*/
@Data @Data
@ApiModel(value = "券退款响应结果")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CouponRefundData { public class CouponRefundData {
@ApiModelProperty(value = "退款单号") /** 退款单号 */
private String ticketsSn; private String ticketsSn;
@ApiModelProperty(value = "单号密码") /** 单号密码 */
private String ticketSignature; private String ticketSignature;
} }
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
/**
* 创建微信预支付订单响应
*/
@Data @Data
@ApiModel(value = "创建微信预支付订单响应")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class CreateWechatPrepayOrderData { public class CreateWechatPrepayOrderData {
@ApiModelProperty(value = "收单号") /** 收单号 */
private String acquiringSn; private String acquiringSn;
@ApiModelProperty(value = "收单签名") /** 收单签名 */
private String signature; private String signature;
@ApiModelProperty(value = "收单状态", notes = "0:已创建, 1:待支付, 2:部分支付成功, 3:全部支付成功, 4:已部分退款, 5:已全额退款, 6:已关闭") /** 收单状态 */
private Byte acquiringState; private Byte acquiringState;
@ApiModelProperty(value = "金额明细") /** 金额明细 */
private AmountDetails amount; private AmountDetails amount;
@ApiModelProperty(value = "支付凭证", notes = "用于唤起微信支付") /** 支付凭证 */
private PaymentVoucher paymentVoucher; private PaymentVoucher paymentVoucher;
@ApiModelProperty(value = "通道信息") /** 通道信息 */
private ChannelInfo channelInfo; private ChannelInfo channelInfo;
@Data @Data
@ApiModel(value = "订单金额明细") /**
* 订单金额明细
*/
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class AmountDetails { public static class AmountDetails {
@ApiModelProperty(value = "收单总金额") /** 收单总金额 */
private Long totalAmount; private Long totalAmount;
@ApiModelProperty(value = "已付总金额") /** 已付总金额 */
private Long paidAmount; private Long paidAmount;
@ApiModelProperty(value = "已退总金额") /** 已退总金额 */
private Long refundedAmount; private Long refundedAmount;
} }
@Data @Data
@ApiModel(value = "支付凭证详情") /**
* 支付凭证详情
*/
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class PaymentVoucher { public static class PaymentVoucher {
@ApiModelProperty(value = "时间戳") /** 时间戳 */
private String timeStamp; private String timeStamp;
@ApiModelProperty(value = "订单详情扩展字符串") /** 订单详情扩展字符串 */
private String packageStr; private String packageStr;
@ApiModelProperty(value = "签名") /** 签名 */
private String paySign; private String paySign;
@ApiModelProperty(value = "Appid") /** Appid */
private String appId; private String appId;
@ApiModelProperty(value = "签名方式") /** 签名方式 */
private String signType; private String signType;
@ApiModelProperty(value = "随机字符串") /** 随机字符串 */
private String nonceStr; private String nonceStr;
} }
@Data @Data
@ApiModel(value = "通道信息详情") /**
* 通道信息详情
*/
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public static class ChannelInfo { public static class ChannelInfo {
@ApiModelProperty(value = "收钱吧通道流水号") /** 收钱吧通道流水号 */
private String payTsn; private String payTsn;
} }
......
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
/**
* 商城列表查询响应数据
*/
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel(value = "商城列表查询响应数据")
public class MallListQueryData { public class MallListQueryData {
@ApiModelProperty("商城编号") /** 商城编号 */
private String mallSn; private String mallSn;
@ApiModelProperty("商城签名") /** 商城签名 */
private String signature; private String signature;
@ApiModelProperty("商城名称") /** 商城名称 */
private String mallName; private String mallName;
@ApiModelProperty("商城状态 0:待上线 1:已上线 2:已下线") /** 商城状态 0:待上线 1:已上线 2:已下线 */
private Byte state; private Byte state;
@ApiModelProperty("商城状态描述") /** 商城状态描述 */
private String stateDesc; private String stateDesc;
@ApiModelProperty("内部状态 1启用 0禁用") /** 内部状态 1启用 0禁用 */
private Byte internalState; private Byte internalState;
@ApiModelProperty("内部状态描述") /** 内部状态描述 */
private String internalStateDesc; private String internalStateDesc;
@ApiModelProperty("删除状态 0未删除 1已删除") /** 删除状态 0未删除 1已删除 */
private Byte isDelete; private Byte isDelete;
@ApiModelProperty("删除时间") /** 删除时间 */
private String deleteTime; private String deleteTime;
@ApiModelProperty("大额开通状态") /** 大额开通状态 */
private Byte crossCityPaymentStatus; private Byte crossCityPaymentStatus;
@ApiModelProperty("大额开通状态描述") /** 大额开通状态描述 */
private String crossCityPaymentStatusDesc; private String crossCityPaymentStatusDesc;
@ApiModelProperty("应用类型 0拼塔商城 目前都是0,无需关注") /** 应用类型 0拼塔商城 目前都是0,无需关注 */
private Integer appType; private Integer appType;
@ApiModelProperty("行业code") /** 行业code */
private String industryCode; private String industryCode;
@ApiModelProperty("商户信息") /** 商户信息 */
private Seller seller; private Seller seller;
@ApiModelProperty("订单统计") /** 订单统计 */
private OrderStatistics orderStatistics; private OrderStatistics orderStatistics;
@ApiModelProperty("商户统计") /** 商户统计 */
private SellerStatisticsModel sellerStatisticsModel; private SellerStatisticsModel sellerStatisticsModel;
@ApiModelProperty("创建时间") /** 创建时间 */
private String ctime; private String ctime;
@ApiModelProperty("跨城状态明细") /** 跨城状态明细 */
private List<CrossCityPayment> crossCityPayments; private List<CrossCityPayment> crossCityPayments;
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel("商户信息") /**
* 商户信息
*/
public static class Seller { public static class Seller {
@ApiModelProperty("商户号") /** 商户号 */
private String merchantSn; private String merchantSn;
@ApiModelProperty("商户id") /** 商户id */
private String merchantId; private String merchantId;
@ApiModelProperty("商户名称") /** 商户名称 */
private String merchantName; private String merchantName;
@ApiModelProperty("门店号") /** 门店号 */
private String storeSn; private String storeSn;
@ApiModelProperty("门店id") /** 门店id */
private String storeId; private String storeId;
@ApiModelProperty("门店名称") /** 门店名称 */
private String storeName; private String storeName;
@ApiModelProperty("终端号") /** 终端号 */
private String terminalSn; private String terminalSn;
@ApiModelProperty("大额终端编号") /** 大额终端编号 */
private String crossCityTerminalSn; private String crossCityTerminalSn;
} }
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel("订单统计") /**
* 订单统计
*/
public static class OrderStatistics { public static class OrderStatistics {
@ApiModelProperty("订单数量") /** 订单数量 */
private Long totalNum; private Long totalNum;
@ApiModelProperty("商品数量") /** 商品数量 */
private String totalQuantity; private String totalQuantity;
@ApiModelProperty("订单总额(分)") /** 订单总额(分) */
private Long totalAmount; private Long totalAmount;
} }
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel("商户统计") /**
* 商户统计
*/
public static class SellerStatisticsModel { public static class SellerStatisticsModel {
@ApiModelProperty("异地交易失败订单数量") /** 异地交易失败订单数量 */
private Long orderFailNum; private Long orderFailNum;
} }
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel("跨城支付明细") /**
* 跨城支付明细
*/
public static class CrossCityPayment { public static class CrossCityPayment {
@ApiModelProperty("支付工具code 2:支付宝 3:微信") /** 支付工具code 2:支付宝 3:微信 */
private Byte payToolCode; private Byte payToolCode;
@ApiModelProperty("支付工具描述") /** 支付工具描述 */
private String payToolCodeDesc; private String payToolCodeDesc;
@ApiModelProperty("大额开通状态") /** 大额开通状态 */
private Integer status; private Integer status;
@ApiModelProperty("大额开通状态描述") /** 大额开通状态描述 */
private String statusDesc; private String statusDesc;
} }
} }
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
/**
* 商城商品接口响应数据
*/
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel(value = "商城商品接口响应数据")
public class MallProductsQueryData { public class MallProductsQueryData {
@ApiModelProperty(value = "商品spuId") /** 商品spuId */
private String spuId; private String spuId;
@ApiModelProperty(value = "商品图片") /** 商品图片 */
private List<String> converImages; private List<String> converImages;
@ApiModelProperty(value = "商品描述") /** 商品描述 */
private String productIntroduction; private String productIntroduction;
@ApiModelProperty(value = "商品标题") /** 商品标题 */
private String title; private String title;
@ApiModelProperty(value = "商品规格") /** 商品规格 */
private List<Sku> skuResults; private List<Sku> skuResults;
@Data @Data
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel(value = "商品规格") /**
* 商品规格
*/
public static class Sku { public static class Sku {
@ApiModelProperty(value = "库存类型") /** 库存类型 */
private Integer stockType; private Integer stockType;
@ApiModelProperty(value = "商品skuId") /** 商品skuId */
private String skuId; private String skuId;
@ApiModelProperty(value = "库存值") /** 库存值 */
private BigDecimal quantity; private BigDecimal quantity;
@ApiModelProperty(value = "规格标题") /** 规格标题 */
private String skuTitle; private String skuTitle;
@ApiModelProperty(value = "规格名称") /** 规格名称 */
private String skuName; private String skuName;
@ApiModelProperty(value = "价格") /** 价格 */
private Long price; private Long price;
} }
} }
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.liquidnet.service.goblin.param.shouqianba.request.CommonRequest; import com.liquidnet.common.third.sqb.param.request.CommonRequest;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.Data;
/**
* 收钱吧创建订单响应参数Data
*/
@Data @Data
@ApiModel(value = "收钱吧创建订单响应参数Data")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class OrderCreateData { public class OrderCreateData {
@ApiModelProperty(value = "订单编号)") /** 订单编号) */
private String orderSn; private String orderSn;
@ApiModelProperty(value = "订单密钥)") /** 订单密钥) */
private String orderSignature; private String orderSignature;
@ApiModelProperty(value = "收单信息)") /** 收单信息) */
private CommonRequest.Acquiring acquiring; private CommonRequest.Acquiring acquiring;
......
package com.liquidnet.service.goblin.param.shouqianba.response.data; package com.liquidnet.common.third.sqb.param.response.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.Data;
/**
* 收钱吧创建结算明细响应参数Data
*/
@Data @Data
@ApiModel(value = "收钱吧创建结算明细响应参数Data")
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class SettlementCreateData { public class SettlementCreateData {
@ApiModelProperty(value = "结算项ID)") /** 结算项ID) */
private String checkoutItemsId; private String checkoutItemsId;
} }
...@@ -16,5 +16,6 @@ ...@@ -16,5 +16,6 @@
<module>liquidnet-common-third-zxlnft</module> <module>liquidnet-common-third-zxlnft</module>
<module>liquidnet-common-third-antchain</module> <module>liquidnet-common-third-antchain</module>
<module>liquidnet-common-third-xuper</module> <module>liquidnet-common-third-xuper</module>
<module>liquidnet-common-third-sqb</module>
</modules> </modules>
</project> </project>
...@@ -109,6 +109,12 @@ ...@@ -109,6 +109,12 @@
<artifactId>dg-java-sdk</artifactId> <artifactId>dg-java-sdk</artifactId>
<version>3.0.27</version> <version>3.0.27</version>
</dependency> </dependency>
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-common-third-sqb</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
...@@ -3,20 +3,17 @@ package com.liquidnet.service.goblin.controller; ...@@ -3,20 +3,17 @@ package com.liquidnet.service.goblin.controller;
import com.liquidnet.commons.lang.util.CurrentUtil; import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbCouponVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbCouponVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderCreateVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderDetailVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderDetailVo;
import com.liquidnet.service.goblin.service.IGoblinSqbOrderService; import com.liquidnet.service.goblin.service.IGoblinSqbService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import java.util.List;
/** /**
* 收钱吧订单 Controller * 收钱吧订单 Controller
...@@ -24,51 +21,12 @@ import javax.validation.constraints.NotNull; ...@@ -24,51 +21,12 @@ import javax.validation.constraints.NotNull;
@Slf4j @Slf4j
@Api(tags = "收钱吧订单") @Api(tags = "收钱吧订单")
@RestController @RestController
@RequestMapping("/goblin/sqb/order") @RequestMapping("/goblin/sqb")
public class GoblinSqbOrderController { public class GoblinSqbController {
@Autowired @Autowired
private IGoblinSqbOrderService goblinSqbOrderService; private IGoblinSqbService goblinSqbService;
/**
* 创建收钱吧订单
*/
@PostMapping("/create")
@ApiOperation("创建收钱吧订单")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "spuId", value = "商品 SPU ID"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "skuId", value = "商品 SKU ID"),
@ApiImplicitParam(type = "form", required = true, dataType = "Integer", name = "quantity", value = "购买数量", example = "1"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "performancesId", value = "关联演出 ID"),
})
public ResponseDto<GoblinSqbOrderCreateVo> createOrder(
@NotBlank(message = "spuId 不能为空") @RequestParam("spuId") String spuId,
@NotBlank(message = "skuId 不能为空") @RequestParam("skuId") String skuId,
@NotNull(message = "quantity 不能为空")
@Min(value = 1, message = "购买数量至少为 1") @RequestParam("quantity") Integer quantity,
@NotBlank(message = "performancesId 不能为空") @RequestParam("performancesId") String performancesId) {
String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧下单] 接收请求 userId={}, spuId={}, skuId={}, quantity={}, performancesId={}",
userId, spuId, skuId, quantity, performancesId);
return goblinSqbOrderService.createOrder(userId, spuId, skuId, quantity, performancesId);
}
/**
* 查询支付状态
*/
@GetMapping("/pay/status")
@ApiOperation("查询支付状态")
@ApiImplicitParam(type = "query", required = true, dataType = "String", name = "orderId", value = "本地订单ID")
public ResponseDto<Integer> queryPayStatus(
@NotBlank(message = "orderId 不能为空") @RequestParam("orderId") String orderId) {
String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧支付状态] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbOrderService.queryPayStatus(userId, orderId);
}
/** /**
* 获取核销二维码(券码) * 获取核销二维码(券码)
...@@ -82,7 +40,7 @@ public class GoblinSqbOrderController { ...@@ -82,7 +40,7 @@ public class GoblinSqbOrderController {
String userId = CurrentUtil.getCurrentUid(); String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧券码] 接收请求 userId={}, orderId={}", userId, orderId); log.info("[收钱吧券码] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbOrderService.queryCoupon(userId, orderId); return goblinSqbService.queryCoupon(userId, orderId);
} }
/** /**
...@@ -97,9 +55,10 @@ public class GoblinSqbOrderController { ...@@ -97,9 +55,10 @@ public class GoblinSqbOrderController {
String userId = CurrentUtil.getCurrentUid(); String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧退款] 接收请求 userId={}, orderId={}", userId, orderId); log.info("[收钱吧退款] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbOrderService.refund(userId, orderId); return goblinSqbService.refund(userId, orderId);
} }
/** /**
* 主动同步核销状态 * 主动同步核销状态
*/ */
...@@ -110,7 +69,7 @@ public class GoblinSqbOrderController { ...@@ -110,7 +69,7 @@ public class GoblinSqbOrderController {
@NotBlank(message = "orderId 不能为空") @RequestParam("orderId") String orderId) { @NotBlank(message = "orderId 不能为空") @RequestParam("orderId") String orderId) {
String userId = CurrentUtil.getCurrentUid(); String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧核销同步] 接收请求 userId={}, orderId={}", userId, orderId); log.info("[收钱吧核销同步] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbOrderService.syncCouponStatus(userId, orderId); return goblinSqbService.syncCouponStatus(userId, orderId);
} }
/** /**
...@@ -118,10 +77,10 @@ public class GoblinSqbOrderController { ...@@ -118,10 +77,10 @@ public class GoblinSqbOrderController {
*/ */
@GetMapping("/list") @GetMapping("/list")
@ApiOperation("用户收钱吧订单列表") @ApiOperation("用户收钱吧订单列表")
public ResponseDto<java.util.List<GoblinSqbOrderDetailVo>> getOrderList() { public ResponseDto<List<GoblinSqbOrderDetailVo>> getOrderList() {
String userId = CurrentUtil.getCurrentUid(); String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧订单列表] 接收请求 userId={}", userId); log.info("[收钱吧订单列表] 接收请求 userId={}", userId);
return goblinSqbOrderService.getOrderList(userId); return goblinSqbService.getOrderList(userId);
} }
/** /**
...@@ -134,19 +93,8 @@ public class GoblinSqbOrderController { ...@@ -134,19 +93,8 @@ public class GoblinSqbOrderController {
@NotBlank(message = "orderId 不能为空") @PathVariable("orderId") String orderId) { @NotBlank(message = "orderId 不能为空") @PathVariable("orderId") String orderId) {
String userId = CurrentUtil.getCurrentUid(); String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧订单详情] 接收请求 userId={}, orderId={}", userId, orderId); log.info("[收钱吧订单详情] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbOrderService.getOrderDetail(userId, orderId); return goblinSqbService.getOrderDetail(userId, orderId);
} }
/**
* 再次付款(待支付状态下重新拉起微信支付)
*/
@PostMapping("/repay")
@ApiOperation("再次付款")
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "本地订单ID")
public ResponseDto<GoblinSqbOrderCreateVo> repay(
@NotBlank(message = "orderId 不能为空") @RequestParam("orderId") String orderId) {
String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧再次付款] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbOrderService.repay(userId, orderId);
}
} }
package com.liquidnet.service.goblin.controller.Inner; package com.liquidnet.service.goblin.controller.Inner;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.service.IGoblinSqbOrderService; import com.liquidnet.service.goblin.service.IGoblinSqbService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -29,12 +29,12 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -29,12 +29,12 @@ import org.springframework.web.bind.annotation.RestController;
public class GoblinSqbJobController { public class GoblinSqbJobController {
@Autowired @Autowired
private IGoblinSqbOrderService goblinSqbOrderService; private IGoblinSqbService goblinSqbService;
@PostMapping("/autoRefund") @PostMapping("/autoRefund")
@ApiOperation("演出结束自动退款") @ApiOperation("演出结束自动退款")
public ResponseDto<String> autoRefund(@RequestParam("performancesId") String performancesId) { public ResponseDto<String> autoRefund(@RequestParam("performancesId") String performancesId) {
log.info("[收钱吧自动退款] 收到任务,performancesId={}", performancesId); log.info("[收钱吧自动退款] 收到任务,performancesId={}", performancesId);
return goblinSqbOrderService.autoRefundByPerformance(performancesId); return goblinSqbService.autoRefundByPerformance(performancesId);
} }
} }
...@@ -2,6 +2,8 @@ package com.liquidnet.service.goblin.controller.manage; ...@@ -2,6 +2,8 @@ package com.liquidnet.service.goblin.controller.manage;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.liquidnet.common.third.sqb.biz.SqbBiz;
import com.liquidnet.common.third.sqb.param.response.data.MallProductsQueryData;
import com.liquidnet.commons.lang.util.CurrentUtil; import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.JsonUtils; import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ErrorMapping; import com.liquidnet.service.base.ErrorMapping;
...@@ -13,8 +15,6 @@ import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSpecVo; ...@@ -13,8 +15,6 @@ import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSpecVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import com.liquidnet.service.goblin.entity.GoblinSqbGoodsExt; import com.liquidnet.service.goblin.entity.GoblinSqbGoodsExt;
import com.liquidnet.service.goblin.mapper.GoblinSqbGoodsExtMapper; import com.liquidnet.service.goblin.mapper.GoblinSqbGoodsExtMapper;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData;
import com.liquidnet.service.goblin.service.IGoblinShouQianBaService;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtSqbGoodsService; import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtSqbGoodsService;
import com.liquidnet.service.goblin.util.GoblinRedisUtils; import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil; import com.liquidnet.service.goblin.util.ObjectUtil;
...@@ -51,7 +51,7 @@ public class GoblinStoreMgtSqbGoodsController { ...@@ -51,7 +51,7 @@ public class GoblinStoreMgtSqbGoodsController {
@Autowired @Autowired
private GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper; private GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper;
@Autowired @Autowired
private IGoblinShouQianBaService goblinShouQianBaService; private SqbBiz goblinShouQianBaService;
/** /**
* 查询所有商城及商品列表 * 查询所有商城及商品列表
......
package com.liquidnet.service.goblin.service.impl;
import com.liquidnet.common.third.sqb.biz.SqbBiz;
import com.liquidnet.common.third.sqb.param.request.CommonRequest;
import com.liquidnet.common.third.sqb.param.request.CouponQueryRequest;
import com.liquidnet.common.third.sqb.param.request.CouponRefundRequest;
import com.liquidnet.common.third.sqb.param.request.CouponStatusSyncRequest;
import com.liquidnet.common.third.sqb.param.response.data.CouponQueryData;
import com.liquidnet.common.third.sqb.param.response.data.CouponRefundData;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.service.IGoblinSqbService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.GoblinSqbRedisUtils;
import com.liquidnet.service.goblin.util.QueueUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 收钱吧订单服务实现
*/
@Slf4j
@Service
public class GoblinSqbServiceImpl implements IGoblinSqbService {
@Autowired
private GoblinSqbRedisUtils goblinSqbRedisUtils;
@Autowired
private GoblinRedisUtils goblinRedisUtils;
@Autowired
private GoblinMongoUtils goblinMongoUtils;
@Autowired
private QueueUtils queueUtils;
@Autowired
private SqbBiz sqbBiz;
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// ================================ 获取券码 ================================
@Override
public ResponseDto<GoblinSqbCouponVo> queryCoupon(String userId, String orderId) {
log.info("[收钱吧券码] 开始获取 userId={}, orderId={}", userId, orderId);
GoblinSqbOrderVo orderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
if (orderVo == null) return ResponseDto.failure("订单不存在");
if (!userId.equals(orderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
if (!Integer.valueOf(1).equals(orderVo.getStatus())) return ResponseDto.failure("订单未支付,无法获取券码");
// 幂等:已存在则直接返回
if (orderVo.getCouponQrCode() != null && !orderVo.getCouponQrCode().isEmpty()) {
GoblinSqbCouponVo couponVo = new GoblinSqbCouponVo();
couponVo.setCouponSn(orderVo.getCouponSn());
couponVo.setCouponQrCode(orderVo.getCouponQrCode());
couponVo.setCouponExpireTime(orderVo.getCouponExpireTime());
return ResponseDto.success(couponVo);
}
// 调用收钱吧查询券码
CouponQueryRequest req = new CouponQueryRequest();
req.setAppid(sqbBiz.getSqbConfig().getAppId());
req.setSeller(buildSeller());
CouponQueryData couponData = sqbBiz.queryCoupon(req);
if (couponData == null) return ResponseDto.failure("获取券码失败");
// 更新订单 coupon 字段
String now = LocalDateTime.now().format(DTF);
orderVo.setCouponSn(couponData.getVoucherNo());
orderVo.setCouponQrCode(couponData.getUrl());
orderVo.setCouponExpireTime(couponData.getOperationTime());
orderVo.setUpdatedAt(now);
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
// 券码信息保存在 Redis,MySQL和MongoDB商城基础模型无此字段,无需同步
GoblinSqbCouponVo couponVo = new GoblinSqbCouponVo();
couponVo.setCouponSn(couponData.getVoucherNo());
couponVo.setCouponQrCode(couponData.getUrl());
couponVo.setCouponExpireTime(couponData.getOperationTime());
log.info("[收钱吧券码] 获取成功,orderId={}", orderId);
return ResponseDto.success(couponVo);
}
// ================================ 申请退款 ================================
@Override
public ResponseDto<Boolean> refund(String userId, String orderId) {
log.info("[收钱吧退款] 开始 userId={}, orderId={}", userId, orderId);
GoblinSqbOrderVo orderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
if (orderVo == null) return ResponseDto.failure("订单不存在");
if (!userId.equals(orderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
if (!Integer.valueOf(1).equals(orderVo.getStatus())) return ResponseDto.failure("订单状态不可退款");
if (Integer.valueOf(1).equals(orderVo.getCouponUsedStatus())) return ResponseDto.failure("券码已核销,不可退款");
// 更新状态为退款中
String now = LocalDateTime.now().format(DTF);
orderVo.setStatus(4);
orderVo.setUpdatedAt(now);
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
syncOrderStatus(orderId, 4);
try {
// 调用收钱吧退款
CouponRefundRequest refundReq = new CouponRefundRequest();
refundReq.setAppid(sqbBiz.getSqbConfig().getAppId());
refundReq.setSeller(buildSeller());
refundReq.setRequestSource("EXTERN");
refundReq.setRequestId(IDGenerator.nextSnowId());
CouponRefundRequest.RefundInfo refundInfo = new CouponRefundRequest.RefundInfo();
// amount 字段待接入实际金额(GoblinSqbOrderVo 需补充 amount)
refundInfo.setApplyAmount(0L); // TODO: 替换为实际订单金额
refundInfo.setType((byte) 2); // 2-按金额退款
refundInfo.setRefundReason("用户申请退款");
refundReq.setRefundInfo(refundInfo);
CouponRefundData refundData = sqbBiz.refundCoupon(refundReq);
if (refundData == null) {
// 退款失败,回滚状态
orderVo.setStatus(1);
orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
syncOrderStatus(orderId, 1);
return ResponseDto.failure("退款失败,请稍后重试");
}
// 退款成功
orderVo.setStatus(3);
orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
goblinRedisUtils.incrSkuStock(null, orderVo.getSkuId(), orderVo.getQuantity());
syncOrderStatus(orderId, 3);
log.info("[收钱吧退款] 退款成功,orderId={}", orderId);
return ResponseDto.success(Boolean.TRUE);
} catch (Exception e) {
log.error("[收钱吧退款] 退款异常,orderId={},回滚 status=1", orderId, e);
orderVo.setStatus(1);
orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
syncOrderStatus(orderId, 1);
return ResponseDto.failure("退款失败:" + e.getMessage());
}
}
// ================================ 同步核销状态 ================================
@Override
public ResponseDto<Boolean> syncCouponStatus(String userId, String orderId) {
log.info("[收钱吧核销同步] 开始 userId={}, orderId={}", userId, orderId);
GoblinSqbOrderVo orderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
if (orderVo == null) return ResponseDto.failure("订单不存在");
if (!userId.equals(orderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
CouponStatusSyncRequest req = new CouponStatusSyncRequest();
req.setAppid(sqbBiz.getSqbConfig().getAppId());
req.setRedeemSource("EXTERN");
// TODO: 填充 voucherNos(券号列表)、redeemMerchantId、redeemExternalOrderSn、clientSn、status
// 需要从 orderVo 中获取 couponSn 和其他必要字段
if (orderVo.getCouponSn() != null) {
req.setVoucherNos(java.util.Collections.singletonList(orderVo.getCouponSn()));
}
req.setRedeemMerchantId(sqbBiz.getSqbConfig().getMerchantId());
req.setRedeemExternalOrderSn(IDGenerator.nextSnowId());
req.setClientSn("terminal_001"); // TODO: 配置终端号
req.setStatus((byte) 1); // 1-已核销
boolean couponUsed = sqbBiz.syncCouponStatus(req);
if (couponUsed) {
String now = LocalDateTime.now().format(DTF);
orderVo.setStatus(2);
orderVo.setCouponUsedStatus(1);
orderVo.setUpdatedAt(now);
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
syncOrderStatus(orderId, 2);
log.info("[收钱吧核销同步] 核销成功,orderId={}", orderId);
}
return ResponseDto.success(couponUsed);
}
// ================================ 自动退款(定时任务) ================================
@Override
public ResponseDto<String> autoRefundByPerformance(String performancesId) {
log.info("[收钱吧自动退款] 开始处理演出 performancesId={}", performancesId);
// 查询该演出下 status=1(已支付)的订单(MySQL)
// TODO: 通过 GoblinSqbOrderMapper 查询(需注入后解注释)
// LambdaQueryWrapper<GoblinSqbOrder> query = new LambdaQueryWrapper<>();
// query.eq(GoblinSqbOrder::getPerformancesId, performancesId).eq(GoblinSqbOrder::getStatus, 1);
// List<GoblinSqbOrder> orders = goblinSqbOrderMapper.selectList(query);
int successCount = 0;
int failCount = 0;
// TODO: 取消注释并接入 GoblinSqbOrderMapper 后启用
// for (GoblinSqbOrder order : orders) {
// try {
// ResponseDto<Boolean> result = refund(order.getUserId(), order.getOrderId());
// if (result != null && result.isSuccess()) {
// successCount++;
// } else {
// log.warn("[收钱吧自动退款] 订单退款失败 orderId={}", order.getOrderId());
// failCount++;
// }
// } catch (Exception e) {
// log.error("[收钱吧自动退款] 订单退款异常 orderId={}", order.getOrderId(), e);
// failCount++;
// }
// }
String summary = String.format("演出 %s 自动退款完成:成功 %d 笔,失败 %d 笔", performancesId, successCount, failCount);
log.info("[收钱吧自动退款] {}", summary);
return ResponseDto.success(summary);
}
// ================================ 订单列表 ================================
@Override
public ResponseDto<List<GoblinSqbOrderDetailVo>> getOrderList(String userId) {
log.info("[收钱吧订单列表] userId={}", userId);
List<String> orderIds = goblinRedisUtils.getOrderList(userId);
if (CollectionUtils.isEmpty(orderIds)) {
return ResponseDto.success(Collections.emptyList());
}
List<GoblinSqbOrderDetailVo> result = new ArrayList<>();
for (String orderId : orderIds) {
GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
if (storeOrderVo == null) continue;
// 取第一个 orderSkuId 判断 skuType
List<String> orderSkuVoIds = storeOrderVo.getOrderSkuVoIds();
if (CollectionUtils.isEmpty(orderSkuVoIds)) continue;
GoblinOrderSkuVo skuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuVoIds.get(0));
if (skuVo == null) continue;
// 过滤:只处理 skuType=33 的收钱吧订单
if (!Integer.valueOf(33).equals(skuVo.getSkuType())) continue;
GoblinSqbOrderVo sqbOrderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
result.add(buildDetailVo(storeOrderVo, skuVo, sqbOrderVo));
}
// 按创建时间倒序排列
result.sort((a, b) -> {
if (a.getCreatedAt() == null) return 1;
if (b.getCreatedAt() == null) return -1;
return b.getCreatedAt().compareTo(a.getCreatedAt());
});
log.info("[收钱吧订单列表] userId={}, 共 {} 条", userId, result.size());
return ResponseDto.success(result);
}
// ================================ 订单详情 ================================
@Override
public ResponseDto<GoblinSqbOrderDetailVo> getOrderDetail(String userId, String orderId) {
log.info("[收钱吧订单详情] userId={}, orderId={}", userId, orderId);
GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
if (storeOrderVo == null) return ResponseDto.failure("订单不存在");
if (!userId.equals(storeOrderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
List<String> orderSkuVoIds = storeOrderVo.getOrderSkuVoIds();
if (CollectionUtils.isEmpty(orderSkuVoIds)) return ResponseDto.failure("订单数据异常");
GoblinOrderSkuVo skuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuVoIds.get(0));
if (skuVo == null) return ResponseDto.failure("订单商品数据异常");
// 校验是收钱吧订单
if (!Integer.valueOf(33).equals(skuVo.getSkuType())) {
return ResponseDto.failure("该订单非收钱吧订单");
}
GoblinSqbOrderVo sqbOrderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
GoblinSqbOrderDetailVo detailVo = buildDetailVo(storeOrderVo, skuVo, sqbOrderVo);
log.info("[收钱吧订单详情] 查询成功,orderId={}", orderId);
return ResponseDto.success(detailVo);
}
// ================================ 私有辅助方法 ================================
private CommonRequest.Seller buildSeller() {
CommonRequest.Seller seller = new CommonRequest.Seller();
seller.setMerchantId(sqbBiz.getSqbConfig().getMerchantId());
seller.setMerchantUserId(sqbBiz.getSqbConfig().getMerchantUserId());
seller.setRole(sqbBiz.getSqbConfig().getRole());
return seller;
}
private GoblinSqbOrderDetailVo buildDetailVo(GoblinStoreOrderVo storeOrderVo,
GoblinOrderSkuVo skuVo,
GoblinSqbOrderVo sqbOrderVo) {
GoblinSqbOrderDetailVo detailVo = new GoblinSqbOrderDetailVo();
// 来自 GoblinStoreOrderVo
detailVo.setOrderId(storeOrderVo.getOrderId());
detailVo.setOrderCode(storeOrderVo.getOrderCode());
detailVo.setStatus(storeOrderVo.getStatus());
detailVo.setPriceActual(storeOrderVo.getPriceActual());
detailVo.setCreatedAt(storeOrderVo.getCreatedAt());
detailVo.setPayTime(storeOrderVo.getPayTime());
// 来自 GoblinOrderSkuVo
detailVo.setSpuId(skuVo.getSpuId());
detailVo.setSpuName(skuVo.getSpuName());
detailVo.setSkuId(skuVo.getSkuId());
detailVo.setSkuName(skuVo.getSkuName());
detailVo.setSkuImage(skuVo.getSkuImage());
detailVo.setQuantity(skuVo.getNum());
// 来自 GoblinSqbOrderVo
if (sqbOrderVo != null) {
detailVo.setSqbStatus(sqbOrderVo.getStatus());
detailVo.setPerformancesId(sqbOrderVo.getPerformancesId());
detailVo.setSqbAcquiringSn(sqbOrderVo.getSqbAcquiringSn());
detailVo.setCouponSn(sqbOrderVo.getCouponSn());
detailVo.setCouponQrCode(sqbOrderVo.getCouponQrCode());
detailVo.setCouponExpireTime(sqbOrderVo.getCouponExpireTime());
detailVo.setCouponUsedStatus(sqbOrderVo.getCouponUsedStatus());
}
return detailVo;
}
/**
* 构建收钱吧请求唯一ID,规则:AppCode(4位)+ id,总长不超过40位。
*
* @param id 业务唯一标识(如雪花ID)
* @return 不超过40位的请求ID字符串
*/
private String buildRequestId(String id) {
String appCode = sqbBiz.getSqbConfig().getAppCode();
if (appCode == null) appCode = "";
String raw = appCode + id;
return raw.length() > 40 ? raw.substring(0, 40) : raw;
}
/**
* 构建收钱吧订单标题,不超过32位。
*
* @param name 商品名称
* @return 不超过32位的标题字符串
*/
private String buildTitle(String name) {
if (name == null || name.isEmpty()) return "商品支付";
return name.length() > 32 ? name.substring(0, 32) : name;
}
private void syncOrderStatus(String orderId, int status) {
GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
if (storeOrderVo == null) return;
String now = LocalDateTime.now().format(DTF);
storeOrderVo.setStatus(status);
if (status == 1) { // 支付成功
storeOrderVo.setPayTime(now);
}
// 1. 同步 Redis
goblinRedisUtils.setGoblinOrder(orderId, storeOrderVo);
// 2. 同步 MongoDB
goblinMongoUtils.updateGoblinStoreOrderVo(orderId, storeOrderVo);
// 3. 同步 MySQL (复用下单 MQ 发送 Update 语句)
String sql;
Object[] data;
if (status == 1) {
sql = "UPDATE goblin_store_order SET status = ?, pay_time = ?, updated_at = ? WHERE order_id = ?";
data = new Object[]{status, now, now, orderId};
} else {
sql = "UPDATE goblin_store_order SET status = ?, updated_at = ? WHERE order_id = ?";
data = new Object[]{status, now, orderId};
}
java.util.LinkedList<String> sqls = new java.util.LinkedList<>();
sqls.add(sql);
java.util.LinkedList<Object[]> sqlData = new java.util.LinkedList<>();
sqlData.add(data);
if (queueUtils != null) {
queueUtils.sendMsgByRedis(com.liquidnet.service.base.constant.MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(),
com.liquidnet.service.base.SqlMapping.gets(sqls, sqlData));
}
}
}
package com.liquidnet.service.goblin.service.impl.manage; package com.liquidnet.service.goblin.service.impl.manage;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.liquidnet.common.third.sqb.biz.SqbBiz;
import com.liquidnet.common.third.sqb.param.request.CommonRequest;
import com.liquidnet.common.third.sqb.param.request.MallListQueryRequest;
import com.liquidnet.common.third.sqb.param.request.MallProductsQueryRequest;
import com.liquidnet.common.third.sqb.param.response.data.MallListQueryData;
import com.liquidnet.common.third.sqb.param.response.data.MallProductsQueryData;
import com.liquidnet.commons.lang.util.CollectionUtil; import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.JsonUtils; import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping; import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst; import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.config.properties.ShouqianbaProperties;
import com.liquidnet.service.goblin.dto.GoblinGoodsSpecDto; import com.liquidnet.service.goblin.dto.GoblinGoodsSpecDto;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsSqbAddParam; import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsSqbAddParam;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinMgtCategorySpecVo; import com.liquidnet.service.goblin.dto.manage.vo.GoblinMgtCategorySpecVo;
import com.liquidnet.service.goblin.dto.vo.*; import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinSqbGoodsExt; import com.liquidnet.service.goblin.entity.GoblinSqbGoodsExt;
import com.liquidnet.service.goblin.mapper.GoblinSqbGoodsExtMapper; import com.liquidnet.service.goblin.mapper.GoblinSqbGoodsExtMapper;
import com.liquidnet.service.goblin.param.shouqianba.request.CommonRequest;
import com.liquidnet.service.goblin.param.shouqianba.request.MallListQueryRequest;
import com.liquidnet.service.goblin.param.shouqianba.request.MallProductsQueryRequest;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallListQueryData;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData;
import com.liquidnet.service.goblin.service.IGoblinShouQianBaService;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtSqbGoodsService; import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtSqbGoodsService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils; import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils; import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil;
import com.liquidnet.service.goblin.util.QueueUtils; import com.liquidnet.service.goblin.util.QueueUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
...@@ -51,9 +49,8 @@ public class GoblinStoreMgtSqbGoodsServiceImpl implements IGoblinStoreMgtSqbGood ...@@ -51,9 +49,8 @@ public class GoblinStoreMgtSqbGoodsServiceImpl implements IGoblinStoreMgtSqbGood
@Autowired @Autowired
GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper; GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper;
@Autowired @Autowired
private IGoblinShouQianBaService goblinShouQianBaService; private SqbBiz goblinShouQianBaService;
@Autowired
private ShouqianbaProperties shouqianbaProperties;
@Override @Override
public ResponseDto<List<GoblinSqbPerfGoodsVo>> getProductList() { public ResponseDto<List<GoblinSqbPerfGoodsVo>> getProductList() {
...@@ -114,7 +111,7 @@ public class GoblinStoreMgtSqbGoodsServiceImpl implements IGoblinStoreMgtSqbGood ...@@ -114,7 +111,7 @@ public class GoblinStoreMgtSqbGoodsServiceImpl implements IGoblinStoreMgtSqbGood
String lastMallSn = null; String lastMallSn = null;
while (true) { while (true) {
MallListQueryRequest mallRequest = new MallListQueryRequest(); MallListQueryRequest mallRequest = new MallListQueryRequest();
mallRequest.setAppid(shouqianbaProperties.getAppId()); mallRequest.setAppid(goblinShouQianBaService.getSqbConfig().getAppId());
MallListQueryRequest.Filter filter = new MallListQueryRequest.Filter(); MallListQueryRequest.Filter filter = new MallListQueryRequest.Filter();
filter.setSeller(buildSeller()); filter.setSeller(buildSeller());
mallRequest.setFilter(filter); mallRequest.setFilter(filter);
...@@ -148,7 +145,7 @@ public class GoblinStoreMgtSqbGoodsServiceImpl implements IGoblinStoreMgtSqbGood ...@@ -148,7 +145,7 @@ public class GoblinStoreMgtSqbGoodsServiceImpl implements IGoblinStoreMgtSqbGood
*/ */
private List<MallProductsQueryData> fetchAllProducts(MallListQueryData mall) { private List<MallProductsQueryData> fetchAllProducts(MallListQueryData mall) {
MallProductsQueryRequest productRequest = new MallProductsQueryRequest(); MallProductsQueryRequest productRequest = new MallProductsQueryRequest();
productRequest.setAppid(shouqianbaProperties.getAppId()); productRequest.setAppid(goblinShouQianBaService.getSqbConfig().getAppId());
productRequest.setSeller(buildSeller()); productRequest.setSeller(buildSeller());
CommonRequest.Mall mallId = new CommonRequest.Mall(); CommonRequest.Mall mallId = new CommonRequest.Mall();
mallId.setMallSn(mall.getMallSn()); mallId.setMallSn(mall.getMallSn());
...@@ -159,9 +156,9 @@ public class GoblinStoreMgtSqbGoodsServiceImpl implements IGoblinStoreMgtSqbGood ...@@ -159,9 +156,9 @@ public class GoblinStoreMgtSqbGoodsServiceImpl implements IGoblinStoreMgtSqbGood
} }
private CommonRequest.Seller buildSeller() { private CommonRequest.Seller buildSeller() {
CommonRequest.Seller seller = new CommonRequest.Seller(); CommonRequest.Seller seller = new CommonRequest.Seller();
seller.setMerchantId(shouqianbaProperties.getMerchantId()); seller.setMerchantId(goblinShouQianBaService.getSqbConfig().getMerchantId());
seller.setMerchantUserId(shouqianbaProperties.getMerchantUserId()); seller.setMerchantUserId(goblinShouQianBaService.getSqbConfig().getMerchantUserId());
seller.setRole(shouqianbaProperties.getRole()); seller.setRole(goblinShouQianBaService.getSqbConfig().getRole());
return seller; return seller;
} }
......
package com.liquidnet.service.goblin.util; package com.liquidnet.service.goblin.util;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.base.constant.RedisKeyExpireConst;
import com.liquidnet.common.cache.redis.util.RedisUtil; import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.service.base.constant.RedisKeyExpireConst;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -73,4 +74,18 @@ public class GoblinSqbRedisUtils { ...@@ -73,4 +74,18 @@ public class GoblinSqbRedisUtils {
String key = GoblinRedisConst.SQB_ORDER_LOCK.concat(userId).concat(":").concat(skuId); String key = GoblinRedisConst.SQB_ORDER_LOCK.concat(userId).concat(":").concat(skuId);
redisUtil.uLock(key); redisUtil.uLock(key);
} }
// 获取 收钱吧订单id列表
public List<String> getSqbOrderList(String uid) {
String redisKey = GoblinRedisConst.SQB_GOBLIN_ORDER_LIST.concat(uid);
Object obj = redisUtil.get(redisKey);
if (obj == null) {
return CollectionUtil.arrayListString();
} else {
return (List<String>) obj;
}
}
} }
...@@ -193,8 +193,9 @@ goblin_nft_order.update_artwork=UPDATE goblin_nft_order SET artwork_id=? WHERE o ...@@ -193,8 +193,9 @@ goblin_nft_order.update_artwork=UPDATE goblin_nft_order SET artwork_id=? WHERE o
goblin_sku.stock=UPDATE goblin_goods_sku SET sku_stock = ? , stock = ?, updated_at = ? WHERE sku_erp_code = ? and erp_warehouse_no = ? goblin_sku.stock=UPDATE goblin_goods_sku SET sku_stock = ? , stock = ?, updated_at = ? WHERE sku_erp_code = ? and erp_warehouse_no = ?
#---- #----
candy_user_coupon.update_apply_refund=UPDATE candy_user_coupon SET state=?,operator=?,updated_at=? WHERE ucoupon_id=? candy_user_coupon.update_apply_refund=UPDATE candy_user_coupon SET state=?,operator=?,updated_at=? WHERE ucoupon_id=?
#---- # ----- \u6536\u94B1\u5427 ----
#---- goblin_sqb_order.insert=INSERT INTO goblin_sqb_order (order_id,user_id,performances_id,spu_id,sku_id,quantity,amount,sqb_order_sn,sqb_order_signature,sqb_acquiring_sn, sqb_acquiring_sign,sqb_checkout_items_id,status,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
# ---- \u624B\u73AF\u8BA2\u5355 ---- # ---- \u624B\u73AF\u8BA2\u5355 ----
goblin_bracelet_order_insert = INSERT INTO `goblin_bracelet_order`(`order_id`, `user_id`, `bind_name`, `bind_mobile`, `bind_idcard`, `req_date`, `goods_desc`, `wristband_id`, `wristband_price`, `amount_id`, `amount_price`, `req_seq_id`, `hf_seq_id`, `trade_type`, `party_order_id`, `price`, `price_total`, `price_refund`, `refund_price_charges`, `refund_number`, `status`, `pay_status`, `created_at`, `updated_at`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) goblin_bracelet_order_insert = INSERT INTO `goblin_bracelet_order`(`order_id`, `user_id`, `bind_name`, `bind_mobile`, `bind_idcard`, `req_date`, `goods_desc`, `wristband_id`, `wristband_price`, `amount_id`, `amount_price`, `req_seq_id`, `hf_seq_id`, `trade_type`, `party_order_id`, `price`, `price_total`, `price_refund`, `refund_price_charges`, `refund_number`, `status`, `pay_status`, `created_at`, `updated_at`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
gpblin_bracelet_order_update= update goblin_bracelet_order set out_trans_id=?, end_time=?, acct_date=?, price_actual=?, time_pay=?, status=?, pay_status=?, updated_at=? where order_id=? gpblin_bracelet_order_update= update goblin_bracelet_order set out_trans_id=?, end_time=?, acct_date=?, price_actual=?, time_pay=?, status=?, pay_status=?, updated_at=? where order_id=?
......
...@@ -76,6 +76,12 @@ ...@@ -76,6 +76,12 @@
<scope>system</scope> <scope>system</scope>
<systemPath>${basedir}/lib/taobao-sdk-java-auto_1600401599540-20210607-impl.jar</systemPath> <systemPath>${basedir}/lib/taobao-sdk-java-auto_1600401599540-20210607-impl.jar</systemPath>
</dependency> </dependency>
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-common-third-sqb</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package com.liquidnet.service.goblin.controller; package com.liquidnet.service.order.controller;
import com.liquidnet.common.third.sqb.biz.SqbBiz;
import com.liquidnet.common.third.sqb.param.callback.CallbackParams;
import com.liquidnet.common.third.sqb.param.callback.CouponCallbackContent;
import com.liquidnet.common.third.sqb.param.callback.OrderCallbackContent;
import com.liquidnet.common.third.sqb.param.callback.RefundCallbackContent;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.JsonUtils; import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.param.shouqianba.callback.CallbackParams; import com.liquidnet.service.base.codec.vo.EncryptedReq;
import com.liquidnet.service.goblin.param.shouqianba.callback.CouponCallbackContent; import com.liquidnet.service.goblin.dto.manage.GoblinSqbOrderParam;
import com.liquidnet.service.goblin.param.shouqianba.callback.OrderCallbackContent; import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderCreateVo;
import com.liquidnet.service.goblin.param.shouqianba.callback.RefundCallbackContent;
import com.liquidnet.service.goblin.service.IGoblinShouQianBaService;
import com.liquidnet.service.goblin.service.IGoblinSqbOrderService; import com.liquidnet.service.goblin.service.IGoblinSqbOrderService;
import com.liquidnet.service.goblin.service.IGoblinSqbService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import javax.validation.constraints.NotBlank;
import org.springframework.web.bind.annotation.RestController;
@Slf4j @Slf4j
@Api(tags = "收钱吧相关") @Api(tags = "商城-收钱吧支付相关")
@RestController @RestController
@RequestMapping("/sqb") @RequestMapping("/goblin/sqb")
public class GoblinShouqianbaController { public class GoblinSqbOrderController {
@Autowired @Autowired
private IGoblinShouQianBaService shouQianBaService; private IGoblinSqbOrderService goblinSqbOrderService;
@Autowired @Autowired
private IGoblinSqbOrderService sqbOrderService; private SqbBiz sqbBiz;
/**
* 创建收钱吧订单
*/
@PostMapping("/pre")
@ApiOperation("创建收钱吧下单")
public ResponseDto<GoblinSqbOrderCreateVo> preOrder(EncryptedReq<GoblinSqbOrderParam> param) {
String userId = CurrentUtil.getCurrentUid();
GoblinSqbOrderParam orderParam = param.getData();
return goblinSqbOrderService.createOrder(userId, orderParam);
}
/**
* 查询支付状态
*/
@GetMapping("/pay/status")
@ApiOperation("查询支付状态")
@ApiImplicitParam(type = "query", required = true, dataType = "String", name = "orderId", value = "本地订单ID")
public ResponseDto<Integer> queryPayStatus(
@NotBlank(message = "orderId 不能为空") @RequestParam("orderId") String orderId) {
String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧支付状态] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbOrderService.queryPayStatus(userId, orderId);
}
/**
* 再次付款(待支付状态下重新拉起微信支付)
*/
@PostMapping("/repay")
@ApiOperation("再次付款")
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "本地订单ID")
public ResponseDto<GoblinSqbOrderCreateVo> repay(
@NotBlank(message = "orderId 不能为空") @RequestParam("orderId") String orderId) {
String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧再次付款] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbOrderService.repay(userId, orderId);
}
//******************************** 回调相关 *******************************
@ApiOperation("下单回调") @ApiOperation("下单回调")
@PostMapping("/order/callback") @PostMapping("/order/callback")
public ResponseDto<String> orderCallback(@RequestBody CallbackParams callbackParams) { public ResponseDto<String> orderCallback(@RequestBody CallbackParams callbackParams) {
...@@ -36,7 +82,7 @@ public class GoblinShouqianbaController { ...@@ -36,7 +82,7 @@ public class GoblinShouqianbaController {
log.error("下单回调参数为空"); log.error("下单回调参数为空");
return ResponseDto.failure("下单回调参数为空"); return ResponseDto.failure("下单回调参数为空");
} }
boolean verified = shouQianBaService.verifySignature(callbackParams); boolean verified = sqbBiz.verifySignature(callbackParams);
if (!verified) { if (!verified) {
log.error("下单回调验签失败"); log.error("下单回调验签失败");
return ResponseDto.failure("验签失败"); return ResponseDto.failure("验签失败");
...@@ -45,7 +91,7 @@ public class GoblinShouqianbaController { ...@@ -45,7 +91,7 @@ public class GoblinShouqianbaController {
OrderCallbackContent orderCallbackContent = JsonUtils.fromJson(callbackParams.getContent(), OrderCallbackContent.class); OrderCallbackContent orderCallbackContent = JsonUtils.fromJson(callbackParams.getContent(), OrderCallbackContent.class);
log.info("下单回调content: {}", callbackParams.getContent()); log.info("下单回调content: {}", callbackParams.getContent());
// 业务 // 业务
return sqbOrderService.handlePayCallback(orderCallbackContent); return goblinSqbOrderService.handlePayCallback(orderCallbackContent);
} }
@ApiOperation("退款回调") @ApiOperation("退款回调")
...@@ -55,7 +101,7 @@ public class GoblinShouqianbaController { ...@@ -55,7 +101,7 @@ public class GoblinShouqianbaController {
log.error("退款回调参数为空"); log.error("退款回调参数为空");
return ResponseDto.failure("退款回调参数为空"); return ResponseDto.failure("退款回调参数为空");
} }
boolean verified = shouQianBaService.verifySignature(callbackParams); boolean verified = sqbBiz.verifySignature(callbackParams);
if (!verified) { if (!verified) {
log.error("退款回调验签失败"); log.error("退款回调验签失败");
return ResponseDto.failure("验签失败"); return ResponseDto.failure("验签失败");
...@@ -64,7 +110,7 @@ public class GoblinShouqianbaController { ...@@ -64,7 +110,7 @@ public class GoblinShouqianbaController {
RefundCallbackContent refundCallbackContent = JsonUtils.fromJson(callbackParams.getContent(), RefundCallbackContent.class); RefundCallbackContent refundCallbackContent = JsonUtils.fromJson(callbackParams.getContent(), RefundCallbackContent.class);
log.info("退款回调content: {}", callbackParams.getContent()); log.info("退款回调content: {}", callbackParams.getContent());
// 业务 // 业务
return sqbOrderService.handleRefundCallback(refundCallbackContent); return goblinSqbOrderService.handleRefundCallback(refundCallbackContent);
} }
@ApiOperation("券状态回调") @ApiOperation("券状态回调")
...@@ -74,7 +120,7 @@ public class GoblinShouqianbaController { ...@@ -74,7 +120,7 @@ public class GoblinShouqianbaController {
log.error("券状态回调参数为空"); log.error("券状态回调参数为空");
return ResponseDto.failure("券状态回调参数为空"); return ResponseDto.failure("券状态回调参数为空");
} }
boolean verified = shouQianBaService.verifySignature(callbackParams); boolean verified = sqbBiz.verifySignature(callbackParams);
if (!verified) { if (!verified) {
log.error("券状态回调验签失败"); log.error("券状态回调验签失败");
return ResponseDto.failure("验签失败"); return ResponseDto.failure("验签失败");
...@@ -84,7 +130,6 @@ public class GoblinShouqianbaController { ...@@ -84,7 +130,6 @@ public class GoblinShouqianbaController {
log.info("券状态回调content: {}", callbackParams.getContent()); log.info("券状态回调content: {}", callbackParams.getContent());
// 业务 // 业务
return sqbOrderService.handleCouponCallback(callbackContent); return goblinSqbOrderService.handleCouponCallback(callbackContent);
} }
} }
package com.liquidnet.service.goblin.service.impl; package com.liquidnet.service.order.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.liquidnet.common.third.sqb.biz.SqbBiz;
import com.liquidnet.common.third.sqb.param.callback.CouponCallbackContent;
import com.liquidnet.common.third.sqb.param.callback.OrderCallbackContent;
import com.liquidnet.common.third.sqb.param.callback.RefundCallbackContent;
import com.liquidnet.common.third.sqb.param.request.CashierQueryRequest;
import com.liquidnet.common.third.sqb.param.request.CommonRequest;
import com.liquidnet.common.third.sqb.param.request.CreateWechatPrepayOrderRequest;
import com.liquidnet.common.third.sqb.param.request.SettlementCreateRequest;
import com.liquidnet.common.third.sqb.param.response.data.*;
import com.liquidnet.commons.lang.util.IDGenerator; import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.config.properties.ShouqianbaProperties; import com.liquidnet.service.goblin.dto.manage.GoblinSqbOrderParam;
import com.liquidnet.service.goblin.dto.vo.*; import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinSqbPerformanceGoods;
import com.liquidnet.service.goblin.mapper.GoblinSqbPerformanceGoodsMapper;
import com.liquidnet.service.goblin.param.shouqianba.callback.CouponCallbackContent;
import com.liquidnet.service.goblin.param.shouqianba.callback.OrderCallbackContent;
import com.liquidnet.service.goblin.param.shouqianba.callback.RefundCallbackContent;
import com.liquidnet.service.goblin.param.shouqianba.request.*;
import com.liquidnet.service.goblin.param.shouqianba.response.data.*;
import com.liquidnet.service.goblin.service.IGoblinShouQianBaService;
import com.liquidnet.service.goblin.service.IGoblinSqbOrderService; import com.liquidnet.service.goblin.service.IGoblinSqbOrderService;
import com.liquidnet.service.goblin.util.GoblinRedisUtils; import com.liquidnet.service.order.utils.*;
import com.liquidnet.service.goblin.util.GoblinSqbConvertUtils;
import com.liquidnet.service.goblin.util.GoblinSqbRedisUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
/**
* 收钱吧订单服务实现
*/
@Slf4j
@Service @Service
@Slf4j
public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
@Autowired
private GoblinSqbRedisUtils goblinSqbRedisUtils;
@Autowired @Autowired
private GoblinRedisUtils goblinRedisUtils; private GoblinRedisUtils goblinRedisUtils;
@Autowired @Autowired
private com.liquidnet.service.goblin.util.GoblinMongoUtils goblinMongoUtils; private GoblinSqbRedisUtils goblinSqbRedisUtils;
@Autowired @Autowired
private com.liquidnet.service.goblin.util.QueueUtils queueUtils; private GoblinMongoUtils goblinMongoUtils;
@Autowired @Autowired
private GoblinSqbPerformanceGoodsMapper goblinSqbPerformanceGoodsMapper; private QueueUtils queueUtils;
@Autowired @Autowired
private IGoblinShouQianBaService goblinShouQianBaService; private SqbBiz sqbBiz;
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired
private ShouqianbaProperties shouqianbaProperties;
@Autowired @Autowired
private GoblinSqbConvertUtils sqbConvertUtils; private GoblinSqbConvertUtils sqbConvertUtils;
// ================================ 创建订单 ================================ // ================================ 创建订单 ================================
@Override @Override
public ResponseDto<GoblinSqbOrderCreateVo> createOrder(String userId, String spuId, String skuId, public ResponseDto<GoblinSqbOrderCreateVo> createOrder(String userId, GoblinSqbOrderParam orderParam) {
Integer quantity, String performancesId) { log.info("[收钱吧下单] 下单开始 userId={}, param: {}", userId, JsonUtils.toJson(orderParam));
log.info("[收钱吧下单] 开始 userId={}, spuId={}, skuId={}, quantity={}, performancesId={}",
userId, spuId, skuId, quantity, performancesId); String skuId = orderParam.getSkuId();
String spuId = orderParam.getSpuId();
String performancesId = orderParam.getPerformancesId();
Integer quantity = orderParam.getQuantity();
// Step 1: 分布式锁防重 // Step 1: 分布式锁防重
boolean locked = goblinSqbRedisUtils.tryOrderLock(userId, skuId); boolean locked = goblinSqbRedisUtils.tryOrderLock(userId, skuId);
...@@ -76,18 +71,28 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -76,18 +71,28 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
try { try {
// Step 2: 校验演出-商品关联 // Step 2: 校验演出-商品关联
LambdaQueryWrapper<GoblinSqbPerformanceGoods> query = new LambdaQueryWrapper<>(); List<GoblinSqbPerfGoodsVo> perfGoods = goblinSqbRedisUtils.getPerfGoods(performancesId);
query.eq(GoblinSqbPerformanceGoods::getPerformancesId, performancesId) if (perfGoods.isEmpty()) {
.eq(GoblinSqbPerformanceGoods::getSkuId, skuId) log.error("[收钱吧下单] 演出关联商品列表为空,performancesId={}, skuId={}", performancesId, skuId);
.eq(GoblinSqbPerformanceGoods::getStatus, 1); return ResponseDto.failure("商品与演出关联不存在");
GoblinSqbPerformanceGoods relation = goblinSqbPerformanceGoodsMapper.selectOne(query); }
if (relation == null) {
log.warn("[收钱吧下单] 演出-商品关联不存在或已禁用,performancesId={}, skuId={}", performancesId, skuId); boolean skuIdExists = false;
for (GoblinSqbPerfGoodsVo perfGood : perfGoods) {
for (MallProductsQueryData.Sku skuResult : perfGood.getSkuResults()) {
if (skuId.equals(skuResult.getSkuId())) {
skuIdExists = true;
}
}
}
if (!skuIdExists) {
log.error("[收钱吧下单] 演出-商品关联不存在或已禁用,performancesId={}, skuId={}", performancesId, skuId);
return ResponseDto.failure("商品与演出关联不存在"); return ResponseDto.failure("商品与演出关联不存在");
} }
// Step 3: 原子扣减库存 // Step 3: 原子扣减库存
long remaining = goblinRedisUtils.decrSkuStock(null, skuId, quantity); int remaining = goblinRedisUtils.decrSkuStock(null, skuId, quantity);
if (remaining < 0) { if (remaining < 0) {
goblinRedisUtils.incrSkuStock(null, skuId, quantity); goblinRedisUtils.incrSkuStock(null, skuId, quantity);
log.warn("[收钱吧下单] 库存不足,skuId={}, quantity={}", skuId, quantity); log.warn("[收钱吧下单] 库存不足,skuId={}, quantity={}", skuId, quantity);
...@@ -98,6 +103,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -98,6 +103,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId); GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
if (skuVo == null) { if (skuVo == null) {
log.error("[收钱吧下单] 未找到商品, skuId: {}, spuId: {}", skuId, spuId); log.error("[收钱吧下单] 未找到商品, skuId: {}, spuId: {}", skuId, spuId);
return ResponseDto.failure("商品不存在");
} }
if (!skuId.equals(skuVo.getSkuId())) { if (!skuId.equals(skuVo.getSkuId())) {
return ResponseDto.failure("下单失败"); return ResponseDto.failure("下单失败");
...@@ -106,7 +112,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -106,7 +112,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
//TODO 获取该商品对应的商城的编号和密码 //TODO 获取该商品对应的商城的编号和密码
Map<String, String> sqbInfoMap = sqbConvertUtils.getSqbInfoByzhengzaiSkuIdAndSpuId(skuId, spuId); Map<String, String> sqbInfoMap = sqbConvertUtils.getSqbInfoByzhengzaiSkuIdAndSpuId(skuId, spuId);
SettlementCreateData settlementData = goblinShouQianBaService.createSettlement( SettlementCreateData settlementData = sqbBiz.createSettlement(
sqbInfoMap.get("mallSn"), sqbInfoMap.get("mallSn"),
sqbInfoMap.get("signature"), sqbInfoMap.get("signature"),
userId, userId,
...@@ -119,13 +125,14 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -119,13 +125,14 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
log.info("[收钱吧下单] 创建结算明细成功,checkoutItemsId={}", checkoutItemsId); log.info("[收钱吧下单] 创建结算明细成功,checkoutItemsId={}", checkoutItemsId);
// Step 4.2: createOrder → 得 sqbOrderSn + sqbOrderSignature + sqbAcquiringSn // Step 4.2: createOrder → 得 sqbOrderSn + sqbOrderSignature + sqbAcquiringSn
OrderCreateData orderData = goblinShouQianBaService.createOrder( String goodsName = skuVo.getName();
OrderCreateData orderData = sqbBiz.createOrder(
sqbInfoMap.get("mallSn"), sqbInfoMap.get("mallSn"),
sqbInfoMap.get("signature"), sqbInfoMap.get("signature"),
checkoutItemsId, checkoutItemsId,
userId, userId,
"", // TODO 构建请求ID buildRequestId(IDGenerator.nextSnowId()),
"" // TODO 构建标题 buildTitle(goodsName)
); );
if (orderData == null) { if (orderData == null) {
goblinRedisUtils.incrSkuStock(null, skuId, quantity); goblinRedisUtils.incrSkuStock(null, skuId, quantity);
...@@ -138,7 +145,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -138,7 +145,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
log.info("[收钱吧下单] 创建订单成功,订单编号={}, 收单号={}", sqbOrderSn, sqbAcquiringSn); log.info("[收钱吧下单] 创建订单成功,订单编号={}, 收单号={}", sqbOrderSn, sqbAcquiringSn);
// Step 4.3: queryCashier → 得 selectedSignature + seq // Step 4.3: queryCashier → 得 selectedSignature + seq
CashierQueryData cashierData = goblinShouQianBaService.queryCashier(sqbAcquiringSn, sqbAcquiringSign, userId); CashierQueryData cashierData = sqbBiz.queryCashier(sqbAcquiringSn, sqbAcquiringSign, userId);
if (cashierData == null) { if (cashierData == null) {
goblinRedisUtils.incrSkuStock(null, skuId, quantity); goblinRedisUtils.incrSkuStock(null, skuId, quantity);
return ResponseDto.failure("查询收银台失败"); return ResponseDto.failure("查询收银台失败");
...@@ -148,11 +155,11 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -148,11 +155,11 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
String seq = cashierData.getSeq(); // 响应唯一序列号 String seq = cashierData.getSeq(); // 响应唯一序列号
log.info("[收钱吧下单] 查询收银台成功,selectedSignature={}, seq={}", selectedSignature, seq); log.info("[收钱吧下单] 查询收银台成功,selectedSignature={}, seq={}", selectedSignature, seq);
CreateWechatPrepayOrderData prepayData = goblinShouQianBaService.createWechatPrepayOrder(sqbAcquiringSn, CreateWechatPrepayOrderData prepayData = sqbBiz.createWechatPrepayOrder(sqbAcquiringSn,
sqbAcquiringSign, sqbAcquiringSign,
userId, userId,
"", String.valueOf(cashierData.getAmount()),
"", buildRequestId(IDGenerator.nextSnowId()),
cashierData.getPayTools().get(0), cashierData.getPayTools().get(0),
new HashMap<String, Object>(), new HashMap<String, Object>(),
selectedSignature, selectedSignature,
...@@ -187,15 +194,15 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -187,15 +194,15 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
storeOrderVo.setUserName(""); storeOrderVo.setUserName("");
storeOrderVo.setUserMobile(""); storeOrderVo.setUserMobile("");
java.math.BigDecimal skuPrice = skuInfo != null ? skuInfo.getPrice() : java.math.BigDecimal.ZERO; BigDecimal skuPrice = skuInfo != null ? skuInfo.getPrice() : BigDecimal.ZERO;
java.math.BigDecimal priceTotal = skuPrice.multiply(new java.math.BigDecimal(quantity)); BigDecimal priceTotal = skuPrice.multiply(new BigDecimal(quantity));
storeOrderVo.setPriceTotal(priceTotal); storeOrderVo.setPriceTotal(priceTotal);
storeOrderVo.setPriceActual(priceTotal); // 收钱吧暂无运费及优惠逻辑,实际价格等于总价 storeOrderVo.setPriceActual(priceTotal); // 收钱吧暂无运费及优惠逻辑,实际价格等于总价
storeOrderVo.setPriceRefund(java.math.BigDecimal.ZERO); storeOrderVo.setPriceRefund(BigDecimal.ZERO);
storeOrderVo.setPriceExpress(java.math.BigDecimal.ZERO); storeOrderVo.setPriceExpress(BigDecimal.ZERO);
storeOrderVo.setPriceCoupon(java.math.BigDecimal.ZERO); storeOrderVo.setPriceCoupon(BigDecimal.ZERO);
storeOrderVo.setStorePriceCoupon(java.math.BigDecimal.ZERO); storeOrderVo.setStorePriceCoupon(BigDecimal.ZERO);
storeOrderVo.setPriceVoucher(java.math.BigDecimal.ZERO); storeOrderVo.setPriceVoucher(BigDecimal.ZERO);
// 待支付 // 待支付
storeOrderVo.setStatus(0); storeOrderVo.setStatus(0);
storeOrderVo.setPayType("SQB_PAY"); // 标识为收钱吧支付类型 storeOrderVo.setPayType("SQB_PAY"); // 标识为收钱吧支付类型
...@@ -219,7 +226,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -219,7 +226,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
orderSkuVo.setSkuName(skuInfo != null ? skuInfo.getName() : "收钱吧未匹配SKU"); orderSkuVo.setSkuName(skuInfo != null ? skuInfo.getName() : "收钱吧未匹配SKU");
orderSkuVo.setSkuImage(skuInfo != null ? skuInfo.getSkuPic() : ""); orderSkuVo.setSkuImage(skuInfo != null ? skuInfo.getSkuPic() : "");
orderSkuVo.setSkuSpecs("[]"); orderSkuVo.setSkuSpecs("[]");
orderSkuVo.setPriceVoucher(java.math.BigDecimal.ZERO); orderSkuVo.setPriceVoucher(BigDecimal.ZERO);
orderSkuVo.setCreatedAt(now); orderSkuVo.setCreatedAt(now);
// 特殊标识类型:33 // 特殊标识类型:33
orderSkuVo.setSkuType(33); orderSkuVo.setSkuType(33);
...@@ -243,6 +250,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -243,6 +250,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
orderVo.setSqbOrderSn(sqbOrderSn); orderVo.setSqbOrderSn(sqbOrderSn);
orderVo.setSqbOrderSignature(sqbOrderSignature); orderVo.setSqbOrderSignature(sqbOrderSignature);
orderVo.setSqbAcquiringSn(sqbAcquiringSn); orderVo.setSqbAcquiringSn(sqbAcquiringSn);
orderVo.setSqbAcquiringSign(sqbAcquiringSign);
orderVo.setSqbCheckoutItemsId(checkoutItemsId); orderVo.setSqbCheckoutItemsId(checkoutItemsId);
// 内部状态同步使用 // 内部状态同步使用
orderVo.setStatus(0); orderVo.setStatus(0);
...@@ -250,7 +258,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -250,7 +258,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
orderVo.setUpdatedAt(now); orderVo.setUpdatedAt(now);
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo); goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
goblinRedisUtils.addOrderList(userId, orderId); goblinSqbRedisUtils.addSqbOrderList(userId, orderId);
log.info("[收钱吧下单] 订单写入 Redis 成功,orderId={}", orderId); log.info("[收钱吧下单] 订单写入 Redis 成功,orderId={}", orderId);
// Step 6: 写 MongoDB + 发送复用的 SQL MQ // Step 6: 写 MongoDB + 发送复用的 SQL MQ
...@@ -260,11 +268,12 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -260,11 +268,12 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
// 收钱吧扩展暂无需单独写 MongoDB 除非专门需要查询 // 收钱吧扩展暂无需单独写 MongoDB 除非专门需要查询
// 拼接 SQL 数据并丢队列 // 拼接 SQL 数据并丢队列
java.util.LinkedList<String> sqls = new java.util.LinkedList<>(); LinkedList<String> sqls = new LinkedList<>();
sqls.add(com.liquidnet.service.base.SqlMapping.get("goblin.order.create.sku_insert")); sqls.add(com.liquidnet.service.base.SqlMapping.get("goblin.order.create.sku_insert"));
sqls.add(com.liquidnet.service.base.SqlMapping.get("goblin.order.create.order_insert")); sqls.add(com.liquidnet.service.base.SqlMapping.get("goblin.order.create.order_insert"));
sqls.add(com.liquidnet.service.base.SqlMapping.get("goblin_sqb_order.insert"));
java.util.LinkedList<Object[]> sqlDataSku = new java.util.LinkedList<>(); LinkedList<Object[]> sqlDataSku = new LinkedList<>();
sqlDataSku.add(new Object[]{ sqlDataSku.add(new Object[]{
orderSkuVo.getOrderSkuId(), orderSkuVo.getOrderId(), orderSkuVo.getSpuId(), orderSkuVo.getSpuName(), (goodsInfo != null ? goodsInfo.getCoverPic() : ""), orderSkuVo.getOrderSkuId(), orderSkuVo.getOrderId(), orderSkuVo.getSpuId(), orderSkuVo.getSpuName(), (goodsInfo != null ? goodsInfo.getCoverPic() : ""),
orderSkuVo.getSkuId(), orderSkuVo.getNum(), orderSkuVo.getSkuPrice(), orderSkuVo.getSkuPriceActual(), orderSkuVo.getSkuName(), orderSkuVo.getSkuId(), orderSkuVo.getNum(), orderSkuVo.getSkuPrice(), orderSkuVo.getSkuPriceActual(), orderSkuVo.getSkuName(),
...@@ -273,7 +282,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -273,7 +282,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
orderSkuVo.getCreatedAt() orderSkuVo.getCreatedAt()
}); });
java.util.LinkedList<Object[]> sqlDataOrder = new java.util.LinkedList<>(); LinkedList<Object[]> sqlDataOrder = new LinkedList<>();
sqlDataOrder.add(new Object[]{ sqlDataOrder.add(new Object[]{
storeOrderVo.getMasterOrderCode(), storeOrderVo.getOrderId(), storeOrderVo.getStoreId(), storeOrderVo.getStoreName(), storeOrderVo.getOrderCode(), storeOrderVo.getMasterOrderCode(), storeOrderVo.getOrderId(), storeOrderVo.getStoreId(), storeOrderVo.getStoreName(), storeOrderVo.getOrderCode(),
storeOrderVo.getUserId(), storeOrderVo.getUserName(), storeOrderVo.getUserMobile(), storeOrderVo.getPriceTotal(), storeOrderVo.getPayCode(), storeOrderVo.getUserId(), storeOrderVo.getUserName(), storeOrderVo.getUserMobile(), storeOrderVo.getPriceTotal(), storeOrderVo.getPayCode(),
...@@ -283,10 +292,21 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -283,10 +292,21 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
storeOrderVo.getIpAddress(), storeOrderVo.getMarketId(), storeOrderVo.getMarketType(), storeOrderVo.getCreatedAt(), "", "" storeOrderVo.getIpAddress(), storeOrderVo.getMarketId(), storeOrderVo.getMarketType(), storeOrderVo.getCreatedAt(), "", ""
}); });
// 收钱吧订单扩展表写库数据
// order_id, user_id, performances_id, spu_id, sku_id, quantity, amount(分),
// sqb_order_sn, sqb_order_signature, sqb_acquiring_sn, sqb_checkout_items_id, status, created_at, updated_at
LinkedList<Object[]> sqlDataSqbOrder = new LinkedList<>();
sqlDataSqbOrder.add(new Object[]{
orderId, userId, performancesId, spuId, skuId, quantity,
sqbConvertUtils.yuanToFen(priceTotal),
sqbOrderSn, sqbOrderSignature, sqbAcquiringSn, sqbAcquiringSign, checkoutItemsId,
0, now, now
});
// 借用 Base 模块中 ConsumerGoblinOrderCPRdsReceiver 这个队列消费类进行写库 // 借用 Base 模块中 ConsumerGoblinOrderCPRdsReceiver 这个队列消费类进行写库
if (queueUtils != null) { if (queueUtils != null) {
queueUtils.sendMsgByRedis(com.liquidnet.service.base.constant.MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(), queueUtils.sendMsgByRedis(com.liquidnet.service.base.constant.MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(),
com.liquidnet.service.base.SqlMapping.gets(sqls, sqlDataSku, sqlDataOrder)); com.liquidnet.service.base.SqlMapping.gets(sqls, sqlDataSku, sqlDataOrder, sqlDataSqbOrder));
// 待支付超时回调等处理也可放入原有股票队列逻辑,暂省略 // 待支付超时回调等处理也可放入原有股票队列逻辑,暂省略
} }
log.info("[收钱吧下单] 完成 MongoDB 及 MQ 落库,orderId={}, masterCode={}", orderId, masterOrderCode); log.info("[收钱吧下单] 完成 MongoDB 及 MQ 落库,orderId={}, masterCode={}", orderId, masterOrderCode);
...@@ -317,6 +337,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -317,6 +337,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
/** /**
* 构建收钱吧-结算明细条目 * 构建收钱吧-结算明细条目
*
* @param skuVo * @param skuVo
* @param quantity * @param quantity
* @param sqbSkuId * @param sqbSkuId
...@@ -358,7 +379,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -358,7 +379,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
// 调用收钱吧查询收单状态 // 调用收钱吧查询收单状态
CommonRequest.Seller seller = buildSeller(); CommonRequest.Seller seller = buildSeller();
CashierQueryRequest cashierReq = buildCashierQueryRequest(seller, orderVo.getSqbAcquiringSn(), orderVo.getSqbOrderSignature()); CashierQueryRequest cashierReq = buildCashierQueryRequest(seller, orderVo.getSqbAcquiringSn(), orderVo.getSqbOrderSignature());
CashierQueryData cashierData = goblinShouQianBaService.queryCashier(cashierReq); CashierQueryData cashierData = sqbBiz.queryCashier(cashierReq);
if (cashierData == null) { if (cashierData == null) {
log.warn("[收钱吧支付状态] queryCashier 调用失败,orderId={}", orderId); log.warn("[收钱吧支付状态] queryCashier 调用失败,orderId={}", orderId);
...@@ -381,151 +402,10 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -381,151 +402,10 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
return ResponseDto.success(orderVo.getStatus()); return ResponseDto.success(orderVo.getStatus());
} }
// ================================ 获取券码 ================================
@Override
public ResponseDto<GoblinSqbCouponVo> queryCoupon(String userId, String orderId) {
log.info("[收钱吧券码] 开始获取 userId={}, orderId={}", userId, orderId);
GoblinSqbOrderVo orderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
if (orderVo == null) return ResponseDto.failure("订单不存在");
if (!userId.equals(orderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
if (!Integer.valueOf(1).equals(orderVo.getStatus())) return ResponseDto.failure("订单未支付,无法获取券码");
// 幂等:已存在则直接返回
if (orderVo.getCouponQrCode() != null && !orderVo.getCouponQrCode().isEmpty()) {
GoblinSqbCouponVo couponVo = new GoblinSqbCouponVo();
couponVo.setCouponSn(orderVo.getCouponSn());
couponVo.setCouponQrCode(orderVo.getCouponQrCode());
couponVo.setCouponExpireTime(orderVo.getCouponExpireTime());
return ResponseDto.success(couponVo);
}
// 调用收钱吧查询券码
CouponQueryRequest req = new CouponQueryRequest();
req.setAppid(shouqianbaProperties.getAppId());
req.setSeller(buildSeller());
CouponQueryData couponData = goblinShouQianBaService.queryCoupon(req);
if (couponData == null) return ResponseDto.failure("获取券码失败");
// 更新订单 coupon 字段
String now = LocalDateTime.now().format(DTF);
orderVo.setCouponSn(couponData.getVoucherNo());
orderVo.setCouponQrCode(couponData.getUrl());
orderVo.setCouponExpireTime(couponData.getOperationTime());
orderVo.setUpdatedAt(now);
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
// 券码信息保存在 Redis,MySQL和MongoDB商城基础模型无此字段,无需同步
GoblinSqbCouponVo couponVo = new GoblinSqbCouponVo();
couponVo.setCouponSn(couponData.getVoucherNo());
couponVo.setCouponQrCode(couponData.getUrl());
couponVo.setCouponExpireTime(couponData.getOperationTime());
log.info("[收钱吧券码] 获取成功,orderId={}", orderId);
return ResponseDto.success(couponVo);
}
// ================================ 申请退款 ================================ // ================================ 申请退款 ================================
@Override
public ResponseDto<Boolean> refund(String userId, String orderId) {
log.info("[收钱吧退款] 开始 userId={}, orderId={}", userId, orderId);
GoblinSqbOrderVo orderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
if (orderVo == null) return ResponseDto.failure("订单不存在");
if (!userId.equals(orderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
if (!Integer.valueOf(1).equals(orderVo.getStatus())) return ResponseDto.failure("订单状态不可退款");
if (Integer.valueOf(1).equals(orderVo.getCouponUsedStatus())) return ResponseDto.failure("券码已核销,不可退款");
// 更新状态为退款中
String now = LocalDateTime.now().format(DTF);
orderVo.setStatus(4);
orderVo.setUpdatedAt(now);
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
syncOrderStatus(orderId, 4);
try {
// 调用收钱吧退款
CouponRefundRequest refundReq = new CouponRefundRequest();
refundReq.setAppid(shouqianbaProperties.getAppId());
refundReq.setSeller(buildSeller());
refundReq.setRequestSource("EXTERN");
refundReq.setRequestId(IDGenerator.nextSnowId());
CouponRefundRequest.RefundInfo refundInfo = new CouponRefundRequest.RefundInfo();
// amount 字段待接入实际金额(GoblinSqbOrderVo 需补充 amount)
refundInfo.setApplyAmount(0L); // TODO: 替换为实际订单金额
refundInfo.setType((byte) 2); // 2-按金额退款
refundInfo.setRefundReason("用户申请退款");
refundReq.setRefundInfo(refundInfo);
CouponRefundData refundData = goblinShouQianBaService.refundCoupon(refundReq);
if (refundData == null) {
// 退款失败,回滚状态
orderVo.setStatus(1);
orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
syncOrderStatus(orderId, 1);
return ResponseDto.failure("退款失败,请稍后重试");
}
// 退款成功
orderVo.setStatus(3);
orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
goblinRedisUtils.incrSkuStock(null, orderVo.getSkuId(), orderVo.getQuantity());
syncOrderStatus(orderId, 3);
log.info("[收钱吧退款] 退款成功,orderId={}", orderId);
return ResponseDto.success(Boolean.TRUE);
} catch (Exception e) {
log.error("[收钱吧退款] 退款异常,orderId={},回滚 status=1", orderId, e);
orderVo.setStatus(1);
orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
syncOrderStatus(orderId, 1);
return ResponseDto.failure("退款失败:" + e.getMessage());
}
}
// ================================ 同步核销状态 ================================
@Override
public ResponseDto<Boolean> syncCouponStatus(String userId, String orderId) {
log.info("[收钱吧核销同步] 开始 userId={}, orderId={}", userId, orderId);
GoblinSqbOrderVo orderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
if (orderVo == null) return ResponseDto.failure("订单不存在");
if (!userId.equals(orderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
CouponStatusSyncRequest req = new CouponStatusSyncRequest();
req.setAppid(shouqianbaProperties.getAppId());
req.setRedeemSource("EXTERN");
// TODO: 填充 voucherNos(券号列表)、redeemMerchantId、redeemExternalOrderSn、clientSn、status
// 需要从 orderVo 中获取 couponSn 和其他必要字段
if (orderVo.getCouponSn() != null) {
req.setVoucherNos(java.util.Collections.singletonList(orderVo.getCouponSn()));
}
req.setRedeemMerchantId(shouqianbaProperties.getMerchantId());
req.setRedeemExternalOrderSn(IDGenerator.nextSnowId());
req.setClientSn("terminal_001"); // TODO: 配置终端号
req.setStatus((byte) 1); // 1-已核销
boolean couponUsed = goblinShouQianBaService.syncCouponStatus(req);
if (couponUsed) {
String now = LocalDateTime.now().format(DTF);
orderVo.setStatus(2);
orderVo.setCouponUsedStatus(1);
orderVo.setUpdatedAt(now);
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
syncOrderStatus(orderId, 2);
log.info("[收钱吧核销同步] 核销成功,orderId={}", orderId);
}
return ResponseDto.success(couponUsed);
}
// ================================ 回调处理 ================================ // ================================ 回调处理 ================================
...@@ -590,109 +470,6 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -590,109 +470,6 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
return ResponseDto.success("success"); return ResponseDto.success("success");
} }
// ================================ 自动退款(定时任务) ================================
@Override
public ResponseDto<String> autoRefundByPerformance(String performancesId) {
log.info("[收钱吧自动退款] 开始处理演出 performancesId={}", performancesId);
// 查询该演出下 status=1(已支付)的订单(MySQL)
// TODO: 通过 GoblinSqbOrderMapper 查询(需注入后解注释)
// LambdaQueryWrapper<GoblinSqbOrder> query = new LambdaQueryWrapper<>();
// query.eq(GoblinSqbOrder::getPerformancesId, performancesId).eq(GoblinSqbOrder::getStatus, 1);
// List<GoblinSqbOrder> orders = goblinSqbOrderMapper.selectList(query);
int successCount = 0;
int failCount = 0;
// TODO: 取消注释并接入 GoblinSqbOrderMapper 后启用
// for (GoblinSqbOrder order : orders) {
// try {
// ResponseDto<Boolean> result = refund(order.getUserId(), order.getOrderId());
// if (result != null && result.isSuccess()) {
// successCount++;
// } else {
// log.warn("[收钱吧自动退款] 订单退款失败 orderId={}", order.getOrderId());
// failCount++;
// }
// } catch (Exception e) {
// log.error("[收钱吧自动退款] 订单退款异常 orderId={}", order.getOrderId(), e);
// failCount++;
// }
// }
String summary = String.format("演出 %s 自动退款完成:成功 %d 笔,失败 %d 笔", performancesId, successCount, failCount);
log.info("[收钱吧自动退款] {}", summary);
return ResponseDto.success(summary);
}
// ================================ 订单列表 ================================
@Override
public ResponseDto<List<GoblinSqbOrderDetailVo>> getOrderList(String userId) {
log.info("[收钱吧订单列表] userId={}", userId);
List<String> orderIds = goblinRedisUtils.getOrderList(userId);
if (CollectionUtils.isEmpty(orderIds)) {
return ResponseDto.success(Collections.emptyList());
}
List<GoblinSqbOrderDetailVo> result = new ArrayList<>();
for (String orderId : orderIds) {
GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
if (storeOrderVo == null) continue;
// 取第一个 orderSkuId 判断 skuType
List<String> orderSkuVoIds = storeOrderVo.getOrderSkuVoIds();
if (CollectionUtils.isEmpty(orderSkuVoIds)) continue;
GoblinOrderSkuVo skuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuVoIds.get(0));
if (skuVo == null) continue;
// 过滤:只处理 skuType=33 的收钱吧订单
if (!Integer.valueOf(33).equals(skuVo.getSkuType())) continue;
GoblinSqbOrderVo sqbOrderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
result.add(buildDetailVo(storeOrderVo, skuVo, sqbOrderVo));
}
// 按创建时间倒序排列
result.sort((a, b) -> {
if (a.getCreatedAt() == null) return 1;
if (b.getCreatedAt() == null) return -1;
return b.getCreatedAt().compareTo(a.getCreatedAt());
});
log.info("[收钱吧订单列表] userId={}, 共 {} 条", userId, result.size());
return ResponseDto.success(result);
}
// ================================ 订单详情 ================================
@Override
public ResponseDto<GoblinSqbOrderDetailVo> getOrderDetail(String userId, String orderId) {
log.info("[收钱吧订单详情] userId={}, orderId={}", userId, orderId);
GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
if (storeOrderVo == null) return ResponseDto.failure("订单不存在");
if (!userId.equals(storeOrderVo.getUserId())) return ResponseDto.failure("无权限访问该订单");
List<String> orderSkuVoIds = storeOrderVo.getOrderSkuVoIds();
if (CollectionUtils.isEmpty(orderSkuVoIds)) return ResponseDto.failure("订单数据异常");
GoblinOrderSkuVo skuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuVoIds.get(0));
if (skuVo == null) return ResponseDto.failure("订单商品数据异常");
// 校验是收钱吧订单
if (!Integer.valueOf(33).equals(skuVo.getSkuType())) {
return ResponseDto.failure("该订单非收钱吧订单");
}
GoblinSqbOrderVo sqbOrderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
GoblinSqbOrderDetailVo detailVo = buildDetailVo(storeOrderVo, skuVo, sqbOrderVo);
log.info("[收钱吧订单详情] 查询成功,orderId={}", orderId);
return ResponseDto.success(detailVo);
}
// ================================ 再次付款 ================================ // ================================ 再次付款 ================================
@Override @Override
...@@ -715,14 +492,14 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -715,14 +492,14 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
// 重新查询收银台,获取新的 selectedSignature + seq // 重新查询收银台,获取新的 selectedSignature + seq
CashierQueryRequest cashierReq = buildCashierQueryRequest( CashierQueryRequest cashierReq = buildCashierQueryRequest(
seller, orderVo.getSqbAcquiringSn(), orderVo.getSqbOrderSignature()); seller, orderVo.getSqbAcquiringSn(), orderVo.getSqbOrderSignature());
CashierQueryData cashierData = goblinShouQianBaService.queryCashier(cashierReq); CashierQueryData cashierData = sqbBiz.queryCashier(cashierReq);
if (cashierData == null) return ResponseDto.failure("查询收银台失败,请稍后重试"); if (cashierData == null) return ResponseDto.failure("查询收银台失败,请稍后重试");
// 重新创建微信预支付 // 重新创建微信预支付
CreateWechatPrepayOrderRequest prepayReq = buildWechatPrepayRequest( CreateWechatPrepayOrderRequest prepayReq = buildWechatPrepayRequest(
seller, orderVo.getSqbAcquiringSn(), orderVo.getSqbOrderSignature(), seller, orderVo.getSqbAcquiringSn(), orderVo.getSqbOrderSignature(),
cashierData.getSelectedSignature(), cashierData.getSeq(), cashierData); cashierData.getSelectedSignature(), cashierData.getSeq(), cashierData);
CreateWechatPrepayOrderData prepayData = goblinShouQianBaService.createWechatPrepayOrder(prepayReq); CreateWechatPrepayOrderData prepayData = sqbBiz.createWechatPrepayOrder(prepayReq);
if (prepayData == null || prepayData.getPaymentVoucher() == null) { if (prepayData == null || prepayData.getPaymentVoucher() == null) {
return ResponseDto.failure("创建微信预支付失败,请稍后重试"); return ResponseDto.failure("创建微信预支付失败,请稍后重试");
} }
...@@ -751,16 +528,16 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -751,16 +528,16 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
private CommonRequest.Seller buildSeller() { private CommonRequest.Seller buildSeller() {
CommonRequest.Seller seller = new CommonRequest.Seller(); CommonRequest.Seller seller = new CommonRequest.Seller();
seller.setMerchantId(shouqianbaProperties.getMerchantId()); seller.setMerchantId(sqbBiz.getSqbConfig().getMerchantId());
seller.setMerchantUserId(shouqianbaProperties.getMerchantUserId()); seller.setMerchantUserId(sqbBiz.getSqbConfig().getMerchantUserId());
seller.setRole(shouqianbaProperties.getRole()); seller.setRole(sqbBiz.getSqbConfig().getRole());
return seller; return seller;
} }
private CashierQueryRequest buildCashierQueryRequest(CommonRequest.Seller seller, private CashierQueryRequest buildCashierQueryRequest(CommonRequest.Seller seller,
String acquiringSn, String acquiringSignature) { String acquiringSn, String acquiringSignature) {
CashierQueryRequest req = new CashierQueryRequest(); CashierQueryRequest req = new CashierQueryRequest();
req.setAppid(shouqianbaProperties.getAppId()); req.setAppid(sqbBiz.getSqbConfig().getAppId());
req.setSeller(seller); req.setSeller(seller);
req.setPaymentMode(4); // 4-微信小程序支付 req.setPaymentMode(4); // 4-微信小程序支付
...@@ -782,7 +559,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -782,7 +559,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
String seq, String seq,
CashierQueryData cashierData) { CashierQueryData cashierData) {
CreateWechatPrepayOrderRequest req = new CreateWechatPrepayOrderRequest(); CreateWechatPrepayOrderRequest req = new CreateWechatPrepayOrderRequest();
req.setAppid(shouqianbaProperties.getAppId()); req.setAppid(sqbBiz.getSqbConfig().getAppId());
req.setSeller(seller); req.setSeller(seller);
req.setAcquiringSn(acquiringSn); req.setAcquiringSn(acquiringSn);
req.setSignature(acquiringSignature); req.setSignature(acquiringSignature);
...@@ -810,42 +587,31 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService { ...@@ -810,42 +587,31 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
return req; return req;
} }
private GoblinSqbOrderDetailVo buildDetailVo(GoblinStoreOrderVo storeOrderVo,
GoblinOrderSkuVo skuVo, /**
GoblinSqbOrderVo sqbOrderVo) { * 构建收钱吧请求唯一ID,规则:AppCode(4位)+ id,总长不超过40位。
GoblinSqbOrderDetailVo detailVo = new GoblinSqbOrderDetailVo(); *
// 来自 GoblinStoreOrderVo * @param id 业务唯一标识(如雪花ID)
detailVo.setOrderId(storeOrderVo.getOrderId()); * @return 不超过40位的请求ID字符串
detailVo.setOrderCode(storeOrderVo.getOrderCode()); */
detailVo.setStatus(storeOrderVo.getStatus()); private String buildRequestId(String id) {
detailVo.setPriceActual(storeOrderVo.getPriceActual()); String appCode = sqbBiz.getSqbConfig().getAppCode();
detailVo.setCreatedAt(storeOrderVo.getCreatedAt()); if (appCode == null) appCode = "";
detailVo.setPayTime(storeOrderVo.getPayTime()); String raw = appCode + id;
// 来自 GoblinOrderSkuVo return raw.length() > 40 ? raw.substring(0, 40) : raw;
detailVo.setSpuId(skuVo.getSpuId()); }
detailVo.setSpuName(skuVo.getSpuName());
detailVo.setSkuId(skuVo.getSkuId()); /**
detailVo.setSkuName(skuVo.getSkuName()); * 构建收钱吧订单标题,不超过32位。
detailVo.setSkuImage(skuVo.getSkuImage()); *
detailVo.setQuantity(skuVo.getNum()); * @param name 商品名称
// 来自 GoblinSqbOrderVo * @return 不超过32位的标题字符串
if (sqbOrderVo != null) { */
detailVo.setSqbStatus(sqbOrderVo.getStatus()); private String buildTitle(String name) {
detailVo.setPerformancesId(sqbOrderVo.getPerformancesId()); if (name == null || name.isEmpty()) return "商品支付";
detailVo.setSqbAcquiringSn(sqbOrderVo.getSqbAcquiringSn()); return name.length() > 32 ? name.substring(0, 32) : name;
detailVo.setCouponSn(sqbOrderVo.getCouponSn()); }
detailVo.setCouponQrCode(sqbOrderVo.getCouponQrCode());
detailVo.setCouponExpireTime(sqbOrderVo.getCouponExpireTime());
detailVo.setCouponUsedStatus(sqbOrderVo.getCouponUsedStatus());
}
return detailVo;
}
// private String getOrderIdFromParams(Map<String, Object> params) {
// String orderId = (String) params.get("orderId");
// if (orderId == null) orderId = (String) params.get("acquiringSn");
// return orderId;
// }
private void syncOrderStatus(String orderId, int status) { private void syncOrderStatus(String orderId, int status) {
GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId); GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
......
package com.liquidnet.service.order.utils;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.service.base.constant.RedisKeyExpireConst;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbOrderVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 收钱吧相关 Redis 操作封装
*/
@Slf4j
@Component
public class GoblinSqbRedisUtils {
@Autowired
private RedisUtil redisUtil;
/* ---------------------------------------- 订单操作(TTL 2h) ---------------------------------------- */
public void setSqbOrder(String orderId, GoblinSqbOrderVo vo) {
redisUtil.set(GoblinRedisConst.SQB_ORDER.concat(orderId), vo, RedisKeyExpireConst.SQB_ORDER_EXPIRE);
}
public GoblinSqbOrderVo getSqbOrder(String orderId) {
return (GoblinSqbOrderVo) redisUtil.get(GoblinRedisConst.SQB_ORDER.concat(orderId));
}
public void delSqbOrder(String orderId) {
redisUtil.del(GoblinRedisConst.SQB_ORDER.concat(orderId));
}
/* ---------------------------------------- 演出关联商品缓存(TTL 5min) ---------------------------------------- */
public void setPerfGoods(String performancesId, List<GoblinSqbPerfGoodsVo> list) {
redisUtil.set(GoblinRedisConst.SQB_PERFORMANCE_GOODS.concat(performancesId), list, RedisKeyExpireConst.SQB_PERFORMANCE_GOODS_EXPIRE);
}
public List<GoblinSqbPerfGoodsVo> getPerfGoods(String performancesId) {
return (List<GoblinSqbPerfGoodsVo>) redisUtil.get(GoblinRedisConst.SQB_PERFORMANCE_GOODS.concat(performancesId));
}
public void delPerfGoods(String performancesId) {
redisUtil.del(GoblinRedisConst.SQB_PERFORMANCE_GOODS.concat(performancesId));
}
/* ---------------------------------------- 下单防重锁(TTL 10s) ---------------------------------------- */
/**
* 尝试获取下单防重锁
*
* @param userId 用户ID
* @param skuId SKU ID
* @return true 获取成功,false 已被锁定
*/
public boolean tryOrderLock(String userId, String skuId) {
String key = GoblinRedisConst.SQB_ORDER_LOCK.concat(userId).concat(":").concat(skuId);
return redisUtil.lock(key, 1, RedisKeyExpireConst.SQB_ORDER_LOCK_EXPIRE);
}
/**
* 释放下单防重锁
*
* @param userId 用户ID
* @param skuId SKU ID
*/
public void releaseOrderLock(String userId, String skuId) {
String key = GoblinRedisConst.SQB_ORDER_LOCK.concat(userId).concat(":").concat(skuId);
redisUtil.uLock(key);
}
/**
* 添加用户 收钱吧订单列表
* @param userId
* @param orderId
*/
public void addSqbOrderList(String userId, String orderId) {
String redisKey = GoblinRedisConst.SQB_GOBLIN_ORDER_LIST.concat(userId);
List<String> list = getSqbOrderList(userId);
if (list.size() >= 40) {
list.remove(0);
list.add(orderId);
} else {
list.add(orderId);
}
redisUtil.set(redisKey, list);
}
/**
* 获取 收钱吧订单id列表
* @param uid
* @return
*/
public List<String> getSqbOrderList(String uid) {
String redisKey = GoblinRedisConst.SQB_GOBLIN_ORDER_LIST.concat(uid);
Object obj = redisUtil.get(redisKey);
if (obj == null) {
return CollectionUtil.arrayListString();
} else {
return (List<String>) obj;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment