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

Commit b36cf747 authored by wangyifan's avatar wangyifan

修改表结构;收钱吧订单状态转换正在商品订单状态

parent 4e833f12
......@@ -61,6 +61,8 @@ CREATE TABLE `goblin_sqb_order` (
`coupon_expire_time` DATETIME COMMENT '券码过期时间',
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '0-待支付 1-已支付 2-已核销 3-已退款 4-退款中 9-失败',
`refund_reason` VARCHAR(256) COMMENT '退款原因',
`sqb_refund_sn` VARCHAR(256) COMMENT '收钱吧-退款号',
`sqb_refund_signature` VARCHAR(256) COMMENT '收钱吧-退款号密码',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`mid`),
......
......@@ -14,8 +14,10 @@ public class GoblinSqbOrderVo implements Serializable {
private String performancesId;
// 正在spuId
private String spuId;
// 正在skuId
private String skuId;
// 数量
......@@ -54,6 +56,12 @@ public class GoblinSqbOrderVo implements Serializable {
// 退款备注
private String refundReason;
// 退款单号
private String refundSn;
// 退款单号密码
private String refundSignature;
// 创建时间
private String createdAt;
......
......@@ -22,9 +22,10 @@ public interface IGoblinSqbService {
*
* @param userId 用户ID
* @param orderId 本地订单ID
* @param reason 退款原因
* @return 退款结果
*/
ResponseDto<Boolean> refund(String userId, String orderId);
ResponseDto<Boolean> refund(String userId, String orderId, String reason);
/**
......
......@@ -13,67 +13,99 @@ import java.util.List;
@Data
public class CouponRefundRequest {
/** 应用ID(收钱吧分配的应用id) */
/**
* 应用ID(收钱吧分配的应用id)
*/
private String appid;
/** 卖家信息 */
/**
* 卖家信息
*/
private CommonRequest.Seller seller;
/** 订单信息 */
/**
* 订单信息
*/
private CommonRequest.OrderInfo orderID;
/** 申请退款信息不能为空 */
/**
* 申请退款信息不能为空
*/
private RefundInfo refundInfo;
/** 退款请求id(${AppCode}+id) */
/**
* 退款请求id(${AppCode}+id)
*/
private String requestId;
/** 退款来源(固定值:EXTERN) */
/**
* 退款来源(固定值:EXTERN)
*/
private String requestSource;
@Data
/**
* 退款信息
*/
* 退款信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class RefundInfo {
/** 金额 */
/**
* 金额
*/
private Long applyAmount;
/** 退款类型(1商品 2金额) */
/**
* 退款类型(1商品 2金额)
*/
private Byte type;
/** 退款明细(商品必填) */
/**
* 退款明细(商品必填)
*/
private List<RefundItem> items;
/** 退款原因 */
/**
* 退款原因
*/
private String refundReason;
}
@Data
/**
* 退款明细商品
*/
* 退款明细商品
*/
@Data
public static class RefundItem {
/** spu */
/**
* spu
*/
private String spuId;
/** sku */
/**
* sku
*/
private String skuId;
/** 标题 */
/**
* 标题
*/
private String title;
/** 商品图片 */
/**
* 商品图片
*/
private String img;
/** 数量 */
/**
* 数量
*/
private String quantity;
/** 退款类型(0正常商品 1自定义商品) */
/**
* 退款类型(0正常商品 1自定义商品)
*/
private Byte type;
}
......
......@@ -16,50 +16,76 @@ public class SettlementCreateRequest implements Serializable {
private static final long serialVersionUID = 1L;
/** 应用ID(聚合收单唯一ID,需申请) */
/**
* 应用ID(聚合收单唯一ID,需申请)
*/
private String appid;
/** 商城信息 */
/**
* 商城信息
*/
private CommonRequest.Mall mallID;
/** 商户信息 */
/**
* 商户信息
*/
private CommonRequest.Seller seller;
/** 买家信息 */
/**
* 买家信息
*/
private CommonRequest.Buyer buyer;
/** 结算明细组(结算条目列表) */
/**
* 结算明细组(结算条目列表)
*/
private List<CheckoutItem> checkoutItems;
/** 结算总金额(单位:分) */
/**
* 结算总金额(单位:分)
*/
private Long amount;
@Data
/**
* 结算明细条目
*/
public static class CheckoutItem{
* 结算明细条目
*/
@Data
public static class CheckoutItem {
/** 商品识别号(商品唯一标识,如 spuId) */
/**
* sqb 商品识别号(商品唯一标识,如 spuId)
*/
private String spuId;
/** 规格识别号(SKU唯一标识,如 skuId) */
/**
* sqb 规格识别号(SKU唯一标识,如 skuId)
*/
private String skuId;
/** 单价(单位:分) */
/**
* 单价(单位:分)
*/
private Long price;
/** 购买数量 */
/**
* 购买数量
*/
private String quantity;
/** 商品类型(0 正常商品 1 自定义商品) */
/**
* 商品类型(0 正常商品 1 自定义商品)
*/
private Byte type;
/** 商品标题 */
/**
* 商品标题
*/
private String title;
/** 商品图片链接 */
/**
* 商品图片链接
*/
private String image;
}
}
......@@ -76,6 +76,11 @@ public class GoblinSqbOrder implements Serializable {
*/
private String sqbAcquiringSn;
/**
* 收钱吧收单号密码
*/
private String sqbAcquiringSign;
/**
* 结算明细ID
*/
......@@ -97,10 +102,20 @@ public class GoblinSqbOrder implements Serializable {
private String couponExpireTime;
/**
* 状态 0-待支付 1-已支付 2-已核销 3-已退款 4-退款中 9-失败
* 状态 0-待支付 1-已支付 2-已核销 3-已退款 4-退款中 5-已取消 9-失败
*/
private Integer status;
/**
* 收钱吧-退款号
*/
private String sqbRefundSn;
/**
* 收钱吧-退款号密码
*/
private String sqbRefundSignature;
/**
* 退款原因
*/
......
......@@ -54,13 +54,13 @@ public class GoblinSqbController {
@PostMapping("/refund")
@ApiOperation("申请退款")
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "本地订单ID")
public ResponseDto<Boolean> refund(
@NotBlank(message = "orderId 不能为空") @RequestParam("orderId") String orderId) {
public ResponseDto<Boolean> refund(@NotBlank(message = "orderId 不能为空")
@RequestParam(value = "orderId") String orderId) {
String userId = CurrentUtil.getCurrentUid();
log.info("[收钱吧退款] 接收请求 userId={}, orderId={}", userId, orderId);
return goblinSqbService.refund(userId, orderId);
return goblinSqbService.refund(userId, orderId, "用户申请退款");
}
......
......@@ -3,12 +3,12 @@ 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.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.service.IGoblinSqbService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
......@@ -75,7 +75,7 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
req.setAppid(sqbBiz.getSqbConfig().getAppId());
req.setSeller(buildSeller());
CouponQueryData couponData = sqbBiz.queryCoupon(req);
CouponQueryData couponData = sqbBiz.queryCoupon(orderVo.getSqbOrderSn(), orderVo.getSqbOrderSignature());
if (couponData == null) return ResponseDto.failure("获取券码失败");
// 更新订单 coupon 字段
......@@ -99,7 +99,7 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
// ================================ 申请退款 ================================
@Override
public ResponseDto<Boolean> refund(String userId, String orderId) {
public ResponseDto<Boolean> refund(String userId, String orderId, String reason) {
log.info("[收钱吧退款] 开始 userId={}, orderId={}", userId, orderId);
GoblinSqbOrderVo orderVo = goblinSqbRedisUtils.getSqbOrder(orderId);
......@@ -116,21 +116,14 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
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);
CouponRefundData refundData = sqbBiz.refundCoupon(orderVo.getSqbOrderSn(),
orderVo.getSqbOrderSignature(),
orderVo.getAmount(),
(byte) 2, // 2-按金额退款
new ArrayList<>(), // TODO 需要构建退款商品
reason,
buildRequestId(IDGenerator.nextSnowId())
);
if (refundData == null) {
// 退款失败,回滚状态
orderVo.setStatus(1);
......@@ -141,6 +134,9 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
}
// 退款成功
orderVo.setRefundSn(refundData.getTicketsSn());
orderVo.setRefundSignature(refundData.getTicketSignature());
orderVo.setRefundReason(reason);
orderVo.setStatus(3);
orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
......@@ -367,13 +363,22 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
}
/**
* 同步正在商品订单状态
*
* @param orderId
* @param status
*/
private void syncOrderStatus(String orderId, int status) {
final int zhengzaiStatus = sqbOrderStatusConvert(status);
GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
if (storeOrderVo == null) return;
String now = LocalDateTime.now().format(DTF);
storeOrderVo.setStatus(status);
if (status == 1) { // 支付成功
storeOrderVo.setStatus(zhengzaiStatus);
if (zhengzaiStatus == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) { // 支付成功
storeOrderVo.setPayTime(now);
}
......@@ -386,12 +391,12 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
// 3. 同步 MySQL (复用下单 MQ 发送 Update 语句)
String sql;
Object[] data;
if (status == 1) {
if (zhengzaiStatus == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) {
sql = "UPDATE goblin_store_order SET status = ?, pay_time = ?, updated_at = ? WHERE order_id = ?";
data = new Object[]{status, now, now, orderId};
data = new Object[]{zhengzaiStatus, storeOrderVo.getPayTime(), now, orderId};
} else {
sql = "UPDATE goblin_store_order SET status = ?, updated_at = ? WHERE order_id = ?";
data = new Object[]{status, now, orderId};
data = new Object[]{zhengzaiStatus, now, orderId};
}
java.util.LinkedList<String> sqls = new java.util.LinkedList<>();
......@@ -404,4 +409,47 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
com.liquidnet.service.base.SqlMapping.gets(sqls, sqlData));
}
}
/**
* goblin_sqb_order表status 转换成 goblin_store_order表对应status
*
* @param sqbOrderStatus
* @return
*/
private int sqbOrderStatusConvert(Integer sqbOrderStatus) {
if (null == sqbOrderStatus) {
return -1;
}
switch (sqbOrderStatus) {
case 0:
// 0-待支付 -> 对应枚举 ORDER_STATUS_0
return GoblinStatusConst.Status.ORDER_STATUS_0.getValue();
case 1:
// 1-已支付 -> 对应枚举 ORDER_STATUS_2 (代发货)
return GoblinStatusConst.Status.ORDER_STATUS_2.getValue();
case 2:
// 2-已核销 -> 对应枚举 ORDER_STATUS_4 (已完成)
return GoblinStatusConst.Status.ORDER_STATUS_4.getValue();
case 3:
// 3-已退款 -> 对应枚举 ORDER_STATUS_6 (退款通过)
return GoblinStatusConst.Status.ORDER_STATUS_6.getValue();
case 4:
// 4-退款中 -> 对应枚举 ORDER_STATUS_61 (发起-退款)
return GoblinStatusConst.Status.ORDER_STATUS_61.getValue();
case 5:
// 5-已取消 -> 对应枚举 ORDER_STATUS_5
return GoblinStatusConst.Status.ORDER_STATUS_5.getValue();
case 9:
// 9-失败 -> 这里归类为 ORDER_STATUS_5 (取消/终态),如有特殊需求可调整
return sqbOrderStatus;
default:
return sqbOrderStatus;
}
}
}
......@@ -29,7 +29,13 @@ public class GoblinSqbRedisUtils {
}
public GoblinSqbOrderVo getSqbOrder(String orderId) {
return (GoblinSqbOrderVo) redisUtil.get(GoblinRedisConst.SQB_ORDER.concat(orderId));
String redisKey = GoblinRedisConst.SQB_ORDER.concat(orderId);
Object object = redisUtil.get(redisKey);
if (null == object) {
return null;
} else {
return (GoblinSqbOrderVo) object;
}
}
public void delSqbOrder(String orderId) {
......
......@@ -12,6 +12,7 @@ import com.liquidnet.common.third.sqb.param.response.data.*;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.manage.GoblinSqbOrderParam;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.service.IGoblinSqbOrderService;
......@@ -251,6 +252,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
orderVo.setSpuId(spuId);
orderVo.setSkuId(skuId);
orderVo.setQuantity(quantity);
orderVo.setAmount(sqbConvertUtils.yuanToFen(priceTotal));
orderVo.setSqbOrderSn(sqbOrderSn);
orderVo.setSqbOrderSignature(sqbOrderSignature);
orderVo.setSqbAcquiringSn(sqbAcquiringSn);
......@@ -597,34 +599,37 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
private void syncOrderStatus(String orderId, int status) {
final int zhengzaiStatus = sqbOrderStatusConvert(status);
GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
if (storeOrderVo == null) return;
String now = LocalDateTime.now().format(DTF);
storeOrderVo.setStatus(status);
if (status == 1) { // 支付成功
storeOrderVo.setStatus(zhengzaiStatus);
if (zhengzaiStatus == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) { // 支付成功
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) {
if (zhengzaiStatus == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) {
sql = "UPDATE goblin_store_order SET status = ?, pay_time = ?, updated_at = ? WHERE order_id = ?";
data = new Object[]{status, now, now, orderId};
data = new Object[]{zhengzaiStatus, storeOrderVo.getPayTime(), now, orderId};
} else {
sql = "UPDATE goblin_store_order SET status = ?, updated_at = ? WHERE order_id = ?";
data = new Object[]{status, now, orderId};
data = new Object[]{zhengzaiStatus, now, orderId};
}
LinkedList<String> sqls = new LinkedList<>();
java.util.LinkedList<String> sqls = new java.util.LinkedList<>();
sqls.add(sql);
LinkedList<Object[]> sqlData = new LinkedList<>();
java.util.LinkedList<Object[]> sqlData = new java.util.LinkedList<>();
sqlData.add(data);
if (queueUtils != null) {
......@@ -632,4 +637,48 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
com.liquidnet.service.base.SqlMapping.gets(sqls, sqlData));
}
}
/**
* goblin_sqb_order表status 转换成 goblin_store_order表对应status
*
* @param sqbOrderStatus
* @return
*/
private int sqbOrderStatusConvert(Integer sqbOrderStatus) {
if (null == sqbOrderStatus) {
return -1;
}
switch (sqbOrderStatus) {
case 0:
// 0-待支付 -> 对应枚举 ORDER_STATUS_0
return GoblinStatusConst.Status.ORDER_STATUS_0.getValue();
case 1:
// 1-已支付 -> 对应枚举 ORDER_STATUS_2 (代发货)
return GoblinStatusConst.Status.ORDER_STATUS_2.getValue();
case 2:
// 2-已核销 -> 对应枚举 ORDER_STATUS_4 (已完成)
return GoblinStatusConst.Status.ORDER_STATUS_4.getValue();
case 3:
// 3-已退款 -> 对应枚举 ORDER_STATUS_6 (退款通过)
return GoblinStatusConst.Status.ORDER_STATUS_6.getValue();
case 4:
// 4-退款中 -> 对应枚举 ORDER_STATUS_61 (发起-退款)
return GoblinStatusConst.Status.ORDER_STATUS_61.getValue();
case 5:
// 5-已取消 -> 对应枚举 ORDER_STATUS_5
return GoblinStatusConst.Status.ORDER_STATUS_5.getValue();
case 9:
// 9-失败 -> 这里归类为 ORDER_STATUS_5 (取消/终态),如有特殊需求可调整
return sqbOrderStatus;
default:
return sqbOrderStatus;
}
}
}
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