Compare commits
35 Commits
pay
...
59932b00f4
| Author | SHA1 | Date | |
|---|---|---|---|
| 59932b00f4 | |||
| e8b2924d60 | |||
| f3c42856fc | |||
| 0b02f66fb5 | |||
| acf04b8534 | |||
| cc8be70559 | |||
| ee635dcc32 | |||
| dc7146942b | |||
| 93b2309fcd | |||
| 0684e0459f | |||
| a4fc02dcc3 | |||
| d854ff9e30 | |||
| befd2942a2 | |||
| 7384b67c50 | |||
| 329d9dfb3d | |||
| 0ca2a6c7f8 | |||
| 58104d2afa | |||
| 3d6061342a | |||
| 76f6e7776e | |||
|
|
87797e5812 | ||
| 057f851dcf | |||
| dc3be2f1d8 | |||
| 232bfe84df | |||
| ff09e8e92b | |||
| 5d9c01f427 | |||
| 5d7aaa2dca | |||
| 5595a8009b | |||
| 233c226dca | |||
| 76c6e12c72 | |||
| 5b030ea361 | |||
| 266e782fc0 | |||
| aa7483b1b1 | |||
| 7eeeb8a30f | |||
| 70307e3833 | |||
| 8bde6b15f6 |
@@ -1,39 +0,0 @@
|
|||||||
package com.czg.controller;
|
|
||||||
|
|
||||||
import com.czg.account.entity.ShopUser;
|
|
||||||
import com.czg.account.service.ShopInfoService;
|
|
||||||
import com.czg.account.service.ShopUserFlowService;
|
|
||||||
import com.czg.account.service.ShopUserService;
|
|
||||||
import com.czg.account.service.TestService;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author GYJoker
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/notify/test")
|
|
||||||
public class TestController {
|
|
||||||
@Resource
|
|
||||||
private ShopUserFlowService shopUserFlowService;
|
|
||||||
@Resource
|
|
||||||
private ShopInfoService shopInfoService;
|
|
||||||
@Resource
|
|
||||||
private ShopUserService shopUserService;
|
|
||||||
@Resource
|
|
||||||
private TestService testService;
|
|
||||||
|
|
||||||
@RequestMapping("/hello")
|
|
||||||
public String hello() {
|
|
||||||
shopUserFlowService.list().forEach(item -> {
|
|
||||||
ShopUser shopUserInfo = shopUserService.getShopUserInfo(item.getShopId(), item.getUserId());
|
|
||||||
if (shopUserInfo != null) {
|
|
||||||
item.setShopUserId(shopUserInfo.getId());
|
|
||||||
shopUserFlowService.updateById(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// return testService.insertData();
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,14 +4,18 @@ import com.czg.account.dto.menu.MenuAddDTO;
|
|||||||
import com.czg.account.dto.menu.MenuDelDTO;
|
import com.czg.account.dto.menu.MenuDelDTO;
|
||||||
import com.czg.account.dto.menu.MenuEditDTO;
|
import com.czg.account.dto.menu.MenuEditDTO;
|
||||||
import com.czg.account.entity.CashMenu;
|
import com.czg.account.entity.CashMenu;
|
||||||
|
import com.czg.account.entity.QuickMenu;
|
||||||
import com.czg.account.entity.SysMenu;
|
import com.czg.account.entity.SysMenu;
|
||||||
|
import com.czg.account.service.QuickMenuService;
|
||||||
import com.czg.account.service.SysMenuService;
|
import com.czg.account.service.SysMenuService;
|
||||||
import com.czg.account.vo.MenuVO;
|
import com.czg.account.vo.MenuVO;
|
||||||
import com.czg.annotation.SaAdminCheckPermission;
|
import com.czg.annotation.SaAdminCheckPermission;
|
||||||
import com.czg.annotation.SaAdminCheckRole;
|
import com.czg.annotation.SaAdminCheckRole;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
import com.czg.sa.StpKit;
|
import com.czg.sa.StpKit;
|
||||||
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -19,6 +23,7 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单管理
|
* 菜单管理
|
||||||
|
*
|
||||||
* @author zs
|
* @author zs
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@@ -27,9 +32,12 @@ public class MenuController {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SysMenuService menuService;
|
private SysMenuService menuService;
|
||||||
|
@Resource
|
||||||
|
private QuickMenuService quickMenuService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前用户菜单列表
|
* 获取当前用户菜单列表
|
||||||
|
*
|
||||||
* @return 菜单结构
|
* @return 菜单结构
|
||||||
*/
|
*/
|
||||||
@GetMapping
|
@GetMapping
|
||||||
@@ -40,6 +48,7 @@ public class MenuController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 收银机菜单
|
* 收银机菜单
|
||||||
|
*
|
||||||
* @return 所有菜单
|
* @return 所有菜单
|
||||||
*/
|
*/
|
||||||
@GetMapping("/list/cash")
|
@GetMapping("/list/cash")
|
||||||
@@ -49,6 +58,7 @@ public class MenuController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有菜单
|
* 获取所有菜单
|
||||||
|
*
|
||||||
* @return 菜单结构
|
* @return 菜单结构
|
||||||
*/
|
*/
|
||||||
@SaAdminCheckPermission(parentName = "菜单管理", value = "menu:list", name = "菜单列表")
|
@SaAdminCheckPermission(parentName = "菜单管理", value = "menu:list", name = "菜单列表")
|
||||||
@@ -62,6 +72,7 @@ public class MenuController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单详情
|
* 菜单详情
|
||||||
|
*
|
||||||
* @return 菜单结构
|
* @return 菜单结构
|
||||||
*/
|
*/
|
||||||
@SaAdminCheckRole("管理员")
|
@SaAdminCheckRole("管理员")
|
||||||
@@ -73,6 +84,7 @@ public class MenuController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单添加
|
* 菜单添加
|
||||||
|
*
|
||||||
* @return 是否成功
|
* @return 是否成功
|
||||||
*/
|
*/
|
||||||
@SaAdminCheckRole("管理员")
|
@SaAdminCheckRole("管理员")
|
||||||
@@ -84,6 +96,7 @@ public class MenuController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单修改
|
* 菜单修改
|
||||||
|
*
|
||||||
* @return 是否成功
|
* @return 是否成功
|
||||||
*/
|
*/
|
||||||
@SaAdminCheckRole("管理员")
|
@SaAdminCheckRole("管理员")
|
||||||
@@ -95,12 +108,15 @@ public class MenuController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单删除
|
* 菜单删除
|
||||||
|
*
|
||||||
* @return 是否成功
|
* @return 是否成功
|
||||||
*/
|
*/
|
||||||
@SaAdminCheckRole("管理员")
|
@SaAdminCheckRole("管理员")
|
||||||
@SaAdminCheckPermission(parentName = "菜单管理", value = "menu:del", name = "菜单删除")
|
@SaAdminCheckPermission(parentName = "菜单管理", value = "menu:del", name = "菜单删除")
|
||||||
@DeleteMapping()
|
@DeleteMapping()
|
||||||
|
@Transactional
|
||||||
public CzgResult<Boolean> edit(@RequestBody @Validated MenuDelDTO menuDelDTO) {
|
public CzgResult<Boolean> edit(@RequestBody @Validated MenuDelDTO menuDelDTO) {
|
||||||
|
quickMenuService.remove(QueryWrapper.create().eq(QuickMenu::getMenuId, menuDelDTO.getId()));
|
||||||
return CzgResult.success(menuService.removeById(menuDelDTO.getId()));
|
return CzgResult.success(menuService.removeById(menuDelDTO.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.czg.controller.admin;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import com.czg.account.entity.QuickMenu;
|
||||||
|
import com.czg.account.service.QuickMenuService;
|
||||||
|
import com.czg.annotation.SaAdminCheckPermission;
|
||||||
|
import com.czg.resp.CzgResult;
|
||||||
|
import com.czg.sa.StpKit;
|
||||||
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 悬浮窗/快捷菜单
|
||||||
|
*
|
||||||
|
* @author ww
|
||||||
|
* @description
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/admin/quick")
|
||||||
|
@Slf4j
|
||||||
|
public class QuickMenuController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private QuickMenuService quickMenuService;
|
||||||
|
|
||||||
|
@SaAdminCheckPermission(parentName = "悬浮窗", value = "quick:list", name = "悬浮窗-列表")
|
||||||
|
@GetMapping
|
||||||
|
public CzgResult<List<QuickMenu>> getQuickList(@RequestParam(required = false) Integer status,
|
||||||
|
@RequestParam(required = false, defaultValue = "0") Integer isEdit) {
|
||||||
|
List<QuickMenu> list = quickMenuService.list(QueryWrapper.create()
|
||||||
|
.eq(QuickMenu::getShopId, StpKit.USER.getShopId())
|
||||||
|
.eq(QuickMenu::getStatus, status)
|
||||||
|
.orderBy(QuickMenu::getSort, true));
|
||||||
|
if (isEdit.equals(0)) {
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
list = quickMenuService.list(QueryWrapper.create()
|
||||||
|
.eq(QuickMenu::getShopId, 1)
|
||||||
|
.eq(QuickMenu::getStatus, status)
|
||||||
|
.orderBy(QuickMenu::getSort, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CzgResult.success(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SaAdminCheckPermission(parentName = "悬浮窗", value = "quick:list", name = "悬浮窗-新增")
|
||||||
|
@PostMapping
|
||||||
|
public CzgResult<Boolean> saveQuick(@RequestBody @Validated QuickMenu quickMenu) {
|
||||||
|
quickMenu.setShopId(StpKit.USER.getShopId());
|
||||||
|
return CzgResult.success(quickMenuService.save(quickMenu));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SaAdminCheckPermission(parentName = "悬浮窗", value = "quick:list", name = "悬浮窗-修改")
|
||||||
|
@PutMapping
|
||||||
|
public CzgResult<Boolean> updateQuick(@RequestBody @Validated QuickMenu quickMenu) {
|
||||||
|
return CzgResult.success(quickMenuService.update(quickMenu, QueryWrapper.create()
|
||||||
|
.eq(QuickMenu::getId, quickMenu.getId()).eq(QuickMenu::getShopId, StpKit.USER.getShopId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SaAdminCheckPermission(parentName = "悬浮窗", value = "quick:list", name = "悬浮窗-删除")
|
||||||
|
@DeleteMapping
|
||||||
|
public CzgResult<Boolean> deleteQuick(@RequestBody Set<Long> ids) {
|
||||||
|
return CzgResult.success(quickMenuService.remove(QueryWrapper.create().in(QuickMenu::getId, ids).eq(QuickMenu::getShopId, StpKit.USER.getShopId())));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import com.czg.market.vo.InviteUserVO;
|
|||||||
import com.czg.market.vo.MkDistributionConfigVO;
|
import com.czg.market.vo.MkDistributionConfigVO;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
import com.czg.sa.StpKit;
|
import com.czg.sa.StpKit;
|
||||||
|
import com.czg.task.DistributionTask;
|
||||||
import com.czg.utils.AssertUtil;
|
import com.czg.utils.AssertUtil;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@@ -37,6 +38,22 @@ public class UDistributionController {
|
|||||||
private MkDistributionWithdrawFlowService withdrawFlowService;
|
private MkDistributionWithdrawFlowService withdrawFlowService;
|
||||||
@Resource
|
@Resource
|
||||||
private MkDistributionFlowService distributionFlowService;
|
private MkDistributionFlowService distributionFlowService;
|
||||||
|
@Resource
|
||||||
|
private DistributionTask distributionTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分销员中心-获取配置
|
||||||
|
*/
|
||||||
|
@GetMapping("/task")
|
||||||
|
public CzgResult<String> task(@RequestParam Long shopId) {
|
||||||
|
try {
|
||||||
|
distributionTask.deliver(shopId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return CzgResult.failure(e.getMessage());
|
||||||
|
}
|
||||||
|
return CzgResult.success("任务执行成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分销员中心-获取配置
|
* 分销员中心-获取配置
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* market服务 任务总调度
|
* market服务 任务总调度
|
||||||
|
*
|
||||||
* @author ww
|
* @author ww
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@@ -18,9 +19,9 @@ public class AAMarketTasks {
|
|||||||
|
|
||||||
|
|
||||||
// 分销延时发放
|
// 分销延时发放
|
||||||
@Scheduled(fixedRate = 30000)
|
@Scheduled(cron = "0 0 0/2 * * ? ")
|
||||||
public void distributionTask() {
|
public void distributionTask() {
|
||||||
distributionTask.deliver();
|
distributionTask.deliver(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ public class AAMarketTasks {
|
|||||||
public void birthdayGiftTask() {
|
public void birthdayGiftTask() {
|
||||||
birthdayGiftTask.deliver();
|
birthdayGiftTask.deliver();
|
||||||
}
|
}
|
||||||
|
|
||||||
//会员生日弹窗提醒重置 每年1月1日
|
//会员生日弹窗提醒重置 每年1月1日
|
||||||
@Scheduled(cron = "0 0 0 1 1 ?")
|
@Scheduled(cron = "0 0 0 1 1 ?")
|
||||||
public void birthdayGiftRemindTask() {
|
public void birthdayGiftRemindTask() {
|
||||||
@@ -39,6 +41,7 @@ public class AAMarketTasks {
|
|||||||
//优惠券 过期
|
//优惠券 过期
|
||||||
@Resource
|
@Resource
|
||||||
private CouponTask couponTask;
|
private CouponTask couponTask;
|
||||||
|
|
||||||
//每天每小时的30分 0秒 执行
|
//每天每小时的30分 0秒 执行
|
||||||
@Scheduled(cron = "0 30 * * * ? ")
|
@Scheduled(cron = "0 30 * * * ? ")
|
||||||
public void couponTask() {
|
public void couponTask() {
|
||||||
@@ -48,6 +51,7 @@ public class AAMarketTasks {
|
|||||||
//会员奖励发放
|
//会员奖励发放
|
||||||
@Resource
|
@Resource
|
||||||
private MemberTask memberTask;
|
private MemberTask memberTask;
|
||||||
|
|
||||||
//每天1点 0分 0秒 执行
|
//每天1点 0分 0秒 执行
|
||||||
@Scheduled(cron = "0 0 1 * * ? ")
|
@Scheduled(cron = "0 0 1 * * ? ")
|
||||||
public void memberTask() {
|
public void memberTask() {
|
||||||
@@ -57,6 +61,7 @@ public class AAMarketTasks {
|
|||||||
//满减活动/限时折扣 处理任务状态 定时任务
|
//满减活动/限时折扣 处理任务状态 定时任务
|
||||||
@Resource
|
@Resource
|
||||||
private ActivityStatusTask activityStatusTask;
|
private ActivityStatusTask activityStatusTask;
|
||||||
|
|
||||||
//每天0点 0分 1秒 执行
|
//每天0点 0分 1秒 执行
|
||||||
@Scheduled(cron = "1 0 0 * * ? ")
|
@Scheduled(cron = "1 0 0 * * ? ")
|
||||||
public void activityStatusTask() {
|
public void activityStatusTask() {
|
||||||
@@ -67,6 +72,7 @@ public class AAMarketTasks {
|
|||||||
//月累计 发送条数 累计金额
|
//月累计 发送条数 累计金额
|
||||||
@Resource
|
@Resource
|
||||||
private SmsShopMoneyTask smsShopMoneyTask;
|
private SmsShopMoneyTask smsShopMoneyTask;
|
||||||
|
|
||||||
//每月1号 0点 0分 1秒 执行
|
//每月1号 0点 0分 1秒 执行
|
||||||
@Scheduled(cron = "1 0 0 1 * ?")
|
@Scheduled(cron = "1 0 0 1 * ?")
|
||||||
public void smsShopMoneyTask() {
|
public void smsShopMoneyTask() {
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
package com.czg.task;
|
package com.czg.task;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import com.czg.account.entity.ShopInfo;
|
||||||
import com.czg.account.entity.ShopUser;
|
|
||||||
import com.czg.account.service.ShopInfoService;
|
import com.czg.account.service.ShopInfoService;
|
||||||
import com.czg.account.service.ShopUserService;
|
|
||||||
import com.czg.constant.TableValueConstant;
|
import com.czg.constant.TableValueConstant;
|
||||||
|
import com.czg.constants.SystemConstants;
|
||||||
|
import com.czg.exception.CzgException;
|
||||||
import com.czg.market.entity.MkDistributionFlow;
|
import com.czg.market.entity.MkDistributionFlow;
|
||||||
import com.czg.market.service.MkDistributionFlowService;
|
import com.czg.market.service.MkDistributionFlowService;
|
||||||
import com.czg.market.service.MkDistributionUserService;
|
import com.czg.market.service.MkDistributionUserService;
|
||||||
import com.czg.market.service.OrderInfoService;
|
import com.czg.market.service.OrderInfoService;
|
||||||
import com.czg.order.entity.OrderInfo;
|
import com.czg.order.entity.OrderInfo;
|
||||||
import com.czg.service.market.enums.OrderStatusEnums;
|
import com.czg.service.market.enums.OrderStatusEnums;
|
||||||
import com.czg.utils.FunUtils;
|
|
||||||
import com.mybatisflex.core.query.QueryWrapper;
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -40,8 +39,6 @@ public class DistributionTask {
|
|||||||
private OrderInfoService orderInfoService;
|
private OrderInfoService orderInfoService;
|
||||||
@DubboReference
|
@DubboReference
|
||||||
private ShopInfoService shopInfoService;
|
private ShopInfoService shopInfoService;
|
||||||
@DubboReference
|
|
||||||
private ShopUserService shopUserService;
|
|
||||||
|
|
||||||
List<String> list = List.of(OrderStatusEnums.REFUND.getCode(), OrderStatusEnums.PART_REFUND.getCode());
|
List<String> list = List.of(OrderStatusEnums.REFUND.getCode(), OrderStatusEnums.PART_REFUND.getCode());
|
||||||
|
|
||||||
@@ -51,44 +48,55 @@ public class DistributionTask {
|
|||||||
*/
|
*/
|
||||||
// @Scheduled(cron = "0 0 0 * * ?")
|
// @Scheduled(cron = "0 0 0 * * ?")
|
||||||
// @Scheduled(fixedRate = 30000)
|
// @Scheduled(fixedRate = 30000)
|
||||||
public void deliver() {
|
public void deliver(Long shopId) {
|
||||||
// 1. 订单完成支付时(判断是否分销)产生流水记录。
|
LocalDateTime now = LocalDateTime.now();
|
||||||
// 2. 判断入账时间。
|
List<ShopInfo> shopInfos = shopInfoService.list(QueryWrapper.create()
|
||||||
// 3. 如果是 0 天,再去判断商户余额是否足够。够则入账,不足则不管。
|
.eq(ShopInfo::getIsDeleted, SystemConstants.OneZero.ZERO)
|
||||||
// 4. 流水增加应该入账的时间(订单产生时带入)
|
.isNotNull(ShopInfo::getExpireTime)
|
||||||
// 5. 定时任务 应该是一天执行一次。查询待入账状态和应入账时间小于当前时间的记录,循环处理:并且判断商户余额是否足够,余额不足忽略处理;余额足够变为已入账并扣除商户余额。
|
.lt(ShopInfo::getExpireTime, now)
|
||||||
// 6. 订单产生退款时,去流水表查询该订单的流水记录,如果未入账改为已入账,并插入一条退款扣钱的流水。
|
.gt(ShopInfo::getAmount, BigDecimal.ZERO)
|
||||||
|
.eq(ShopInfo::getId, shopId)
|
||||||
// shopInfo 查余额>0
|
);
|
||||||
// 循环 shopId 查询 如果金额不足 终止
|
if (CollUtil.isEmpty(shopInfos)) {
|
||||||
//
|
log.info("分销延时分账 无符合条件的店铺,无需处理分账");
|
||||||
LocalDateTime localDateTime = DateUtil.date().toLocalDateTime();
|
return;
|
||||||
distributionFlowService.list(new QueryWrapper()
|
}
|
||||||
.eq(MkDistributionFlow::getStatus, TableValueConstant.DistributionFlow.Status.PENDING.getCode()).le(MkDistributionFlow::getDeliverTime, localDateTime)).forEach(item -> {
|
for (ShopInfo shopInfo : shopInfos) {
|
||||||
FunUtils.safeRunVoid(() -> {
|
boolean breakCurrentShopFlow = false;
|
||||||
log.info("开始处理延时分账, id: {}, orderNo: {}, 类型: {}", item.getId(), item.getOrderNo(), item.getType());
|
List<MkDistributionFlow> flowList = distributionFlowService.list(new QueryWrapper()
|
||||||
|
.eq(MkDistributionFlow::getShopId, shopInfo.getId())
|
||||||
|
.eq(MkDistributionFlow::getStatus, TableValueConstant.DistributionFlow.Status.PENDING.getCode())
|
||||||
|
.le(MkDistributionFlow::getDeliverTime, now)
|
||||||
|
.orderBy(MkDistributionFlow::getId, true)
|
||||||
|
);
|
||||||
|
for (MkDistributionFlow item : flowList) {
|
||||||
|
if (breakCurrentShopFlow) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
log.info("分销延时分账, id: {}, orderNo: {}, 类型: {}", item.getId(), item.getOrderNo(), item.getType());
|
||||||
OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper().eq(OrderInfo::getOrderNo, item.getOrderNo()));
|
OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper().eq(OrderInfo::getOrderNo, item.getOrderNo()));
|
||||||
if (orderInfo == null) {
|
if (orderInfo == null) {
|
||||||
item.setStatus(TableValueConstant.DistributionFlow.Status.FAIL.getCode());
|
item.setStatus(TableValueConstant.DistributionFlow.Status.FAIL.getCode());
|
||||||
distributionFlowService.updateById(item);
|
distributionFlowService.updateById(item);
|
||||||
log.warn("订单不存在, 订单号: {}", item.getOrderNo());
|
log.warn("分销延时分账。订单不存在, 订单号: {}", item.getOrderNo());
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
if (list.contains(orderInfo.getStatus())) {
|
if (list.contains(orderInfo.getStatus())) {
|
||||||
log.warn("订单已退款, 订单号: {}", item.getOrderNo());
|
log.warn("分销延时分账。订单已退款, 订单号: {}", item.getOrderNo());
|
||||||
distributionUserService.refund(orderInfo.getId(), orderInfo.getOrderNo());
|
distributionUserService.refund(orderInfo.getId(), orderInfo.getOrderNo());
|
||||||
} else {
|
} else {
|
||||||
item.setStatus(TableValueConstant.DistributionFlow.Status.SUCCESS.getCode());
|
item.setStatus(TableValueConstant.DistributionFlow.Status.SUCCESS.getCode());
|
||||||
ShopUser shopUser = shopUserService.getById(item.getDistributionUserId());
|
distributionUserService.distributionUserAmount(item, orderInfo);
|
||||||
distributionUserService.updateShopInfoAmount(orderInfo.getShopId(), item.getRewardAmount().negate(), orderInfo.getId(), TableValueConstant.DistributionAmountFlow.Type.SUB, "分销扣减");
|
}
|
||||||
distributionUserService.updateIncome(item.getRewardAmount().negate(), item.getRewardAmount(), BigDecimal.ZERO,
|
} catch (CzgException e) {
|
||||||
item.getDistributionUserId(), shopUser.getUserId(), item.getShopUserId(), item.getShopId(), item.getLevel());
|
log.error("店铺{}:{}分销延时分账异常:{}", shopInfo.getId(), shopInfo.getShopName(), e.getMessage());
|
||||||
distributionFlowService.updateById(item);
|
breakCurrentShopFlow = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("店铺{}:{}分销延时分账异常", shopInfo.getId(), shopInfo.getShopName(), e);
|
||||||
|
breakCurrentShopFlow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
package com.czg.controller.pay;
|
package com.czg.controller;
|
||||||
|
|
||||||
import com.czg.annotation.Debounce;
|
import com.czg.annotation.Debounce;
|
||||||
import com.czg.order.dto.MkDistributionPayDTO;
|
import com.czg.order.dto.MkDistributionPayDTO;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
import com.czg.service.order.service.DistributionPayService;
|
import com.czg.service.order.service.DistributionPayService;
|
||||||
import com.czg.system.service.SysParamsService;
|
|
||||||
import com.czg.utils.AssertUtil;
|
import com.czg.utils.AssertUtil;
|
||||||
import com.czg.utils.ServletUtil;
|
import com.czg.utils.ServletUtil;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.apache.dubbo.config.annotation.DubboReference;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -26,16 +27,6 @@ import java.util.Map;
|
|||||||
public class DistributionPayController {
|
public class DistributionPayController {
|
||||||
@Resource
|
@Resource
|
||||||
private DistributionPayService payService;
|
private DistributionPayService payService;
|
||||||
@DubboReference
|
|
||||||
private SysParamsService paramsService;
|
|
||||||
|
|
||||||
|
|
||||||
// @PostMapping("/cashPay")
|
|
||||||
// @Debounce(value = "#payParam.checkOrderPay.orderId")
|
|
||||||
// public CzgResult<Object> cashPayOrder(@RequestHeader Long shopId, @Validated @RequestBody MkDistributionPayDTO payParam) {
|
|
||||||
// payParam.setShopId(shopId);
|
|
||||||
// return payService.cashPayOrder(payParam);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 小程序支付
|
* 小程序支付
|
||||||
@@ -59,26 +50,4 @@ public class DistributionPayController {
|
|||||||
AssertUtil.isBlank(payParam.getCode(), "微信code不为空");
|
AssertUtil.isBlank(payParam.getCode(), "微信code不为空");
|
||||||
return CzgResult.success(payService.mchRecharge(ServletUtil.getClientIP(request), payParam));
|
return CzgResult.success(payService.mchRecharge(ServletUtil.getClientIP(request), payParam));
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 正扫
|
|
||||||
// */
|
|
||||||
// @PostMapping("/scanPay")
|
|
||||||
// @Debounce(value = "#payParam.checkOrderPay.orderId")
|
|
||||||
// public CzgResult<Map<String, Object>> scanPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody MkDistributionPayDTO payParam) {
|
|
||||||
// payParam.setShopId(shopId);
|
|
||||||
// return payService.scanPayOrder(ServletUtil.getClientIP(request), payParam);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 反扫
|
|
||||||
// * authCode 必填 扫描码
|
|
||||||
// */
|
|
||||||
// @PostMapping("/microPay")
|
|
||||||
// @Debounce(value = "#payParam.checkOrderPay.orderId")
|
|
||||||
// public CzgResult<Map<String, Object>> microPayOrder(@RequestHeader Long shopId, @Validated @RequestBody MkDistributionPayDTO payParam) {
|
|
||||||
// payParam.setShopId(shopId);
|
|
||||||
// return payService.microPayOrder(payParam);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -50,6 +50,8 @@ public class NotifyController {
|
|||||||
@Resource
|
@Resource
|
||||||
private MkShopConsumeDiscountRecordService consumeDiscountRecordService;
|
private MkShopConsumeDiscountRecordService consumeDiscountRecordService;
|
||||||
|
|
||||||
|
|
||||||
|
//新客立减清除数据 测试用
|
||||||
@RequestMapping("clear")
|
@RequestMapping("clear")
|
||||||
public String clear(@RequestParam Integer shopId) {
|
public String clear(@RequestParam Integer shopId) {
|
||||||
consumeDiscountRecordService.remove(new QueryWrapper().eq(MkShopConsumeDiscountRecord::getShopId, shopId));
|
consumeDiscountRecordService.remove(new QueryWrapper().eq(MkShopConsumeDiscountRecord::getShopId, shopId));
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.czg.controller.pay;
|
package com.czg.controller;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.core.util.URLUtil;
|
import cn.hutool.core.util.URLUtil;
|
||||||
@@ -10,7 +10,7 @@ import com.czg.order.entity.OrderInfo;
|
|||||||
import com.czg.order.service.OrderInfoCustomService;
|
import com.czg.order.service.OrderInfoCustomService;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
import com.czg.service.order.dto.OrderPayParamDTO;
|
import com.czg.service.order.dto.OrderPayParamDTO;
|
||||||
import com.czg.service.order.service.OrderPayService;
|
import com.czg.service.order.service.PayService;
|
||||||
import com.czg.system.service.SysParamsService;
|
import com.czg.system.service.SysParamsService;
|
||||||
import com.czg.utils.AssertUtil;
|
import com.czg.utils.AssertUtil;
|
||||||
import com.czg.utils.ServletUtil;
|
import com.czg.utils.ServletUtil;
|
||||||
@@ -35,7 +35,7 @@ import java.util.Map;
|
|||||||
@RequestMapping("/pay")
|
@RequestMapping("/pay")
|
||||||
public class OrderPayController {
|
public class OrderPayController {
|
||||||
@Resource
|
@Resource
|
||||||
private OrderPayService orderPayService;
|
private PayService payService;
|
||||||
@Resource
|
@Resource
|
||||||
private OrderInfoCustomService orderInfoCustomService;
|
private OrderInfoCustomService orderInfoCustomService;
|
||||||
@Resource
|
@Resource
|
||||||
@@ -47,14 +47,14 @@ public class OrderPayController {
|
|||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Object> creditPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Object> creditPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
return orderPayService.creditPayOrder(payParam);
|
return payService.creditPayOrder(payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/cashPay")
|
@PostMapping("/cashPay")
|
||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Object> cashPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Object> cashPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
return orderPayService.cashPayOrder(payParam);
|
return payService.cashPayOrder(payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,7 +66,7 @@ public class OrderPayController {
|
|||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Map<String, Object>> rechargePayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> rechargePayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
return orderPayService.rechargePayOrder(ServletUtil.getClientIP(request), payParam);
|
return payService.rechargePayOrder(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,7 +83,7 @@ public class OrderPayController {
|
|||||||
public CzgResult<Object> vipPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Object> vipPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
AssertUtil.isBlank(payParam.getPayType(), "支付类型不可为空");
|
AssertUtil.isBlank(payParam.getPayType(), "支付类型不可为空");
|
||||||
return orderPayService.vipPayOrder(payParam);
|
return payService.vipPayOrder(payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,7 +93,7 @@ public class OrderPayController {
|
|||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Map<String, Object>> h5PayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> h5PayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
return orderPayService.h5PayOrder(ServletUtil.getClientIP(request, ""), payParam);
|
return payService.h5PayOrder(ServletUtil.getClientIP(request, ""), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,7 +106,7 @@ public class OrderPayController {
|
|||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Map<String, Object>> jsPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> jsPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
return orderPayService.jsPayOrder(ServletUtil.getClientIP(request), payParam);
|
return payService.jsPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,7 +118,7 @@ public class OrderPayController {
|
|||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Map<String, Object>> ltPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> ltPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
return orderPayService.ltPayOrder(ServletUtil.getClientIP(request), payParam);
|
return payService.ltPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,7 +128,7 @@ public class OrderPayController {
|
|||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Map<String, Object>> scanPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> scanPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
return orderPayService.scanPayOrder(ServletUtil.getClientIP(request), payParam);
|
return payService.scanPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,7 +139,7 @@ public class OrderPayController {
|
|||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Map<String, Object>> microPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> microPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||||
payParam.setShopId(shopId);
|
payParam.setShopId(shopId);
|
||||||
return orderPayService.microPayOrder(payParam);
|
return payService.microPayOrder(payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,7 +174,7 @@ public class OrderPayController {
|
|||||||
@PostMapping("/shopPayApi/js2Pay")
|
@PostMapping("/shopPayApi/js2Pay")
|
||||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||||
public CzgResult<Map<String, Object>> js2PayOrder(HttpServletRequest request, @RequestBody OrderPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> js2PayOrder(HttpServletRequest request, @RequestBody OrderPayParamDTO payParam) {
|
||||||
return orderPayService.js2PayOrder(ServletUtil.getClientIP(request), payParam);
|
return payService.js2PayOrder(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,7 +21,7 @@ public class StatisticTaskController {
|
|||||||
private StatisticTask statisticTask;
|
private StatisticTask statisticTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础统计
|
* 基础统计 预留重置统计
|
||||||
*
|
*
|
||||||
* @param date 日期yyyy-MM-dd
|
* @param date 日期yyyy-MM-dd
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.czg.controller.pay;
|
package com.czg.controller;
|
||||||
|
|
||||||
import com.czg.annotation.Debounce;
|
import com.czg.annotation.Debounce;
|
||||||
import com.czg.entity.resp.CzgBaseResp;
|
import com.czg.entity.resp.CzgBaseResp;
|
||||||
@@ -7,7 +7,6 @@ import com.czg.service.order.dto.VipMemberPayParamDTO;
|
|||||||
import com.czg.service.order.dto.VipPayParamDTO;
|
import com.czg.service.order.dto.VipPayParamDTO;
|
||||||
import com.czg.service.order.dto.VipRefundDTO;
|
import com.czg.service.order.dto.VipRefundDTO;
|
||||||
import com.czg.service.order.service.PayService;
|
import com.czg.service.order.service.PayService;
|
||||||
import com.czg.service.order.service.ShopUserPayService;
|
|
||||||
import com.czg.utils.AssertUtil;
|
import com.czg.utils.AssertUtil;
|
||||||
import com.czg.utils.ServletUtil;
|
import com.czg.utils.ServletUtil;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@@ -29,8 +28,6 @@ import java.util.Map;
|
|||||||
public class VipPayController {
|
public class VipPayController {
|
||||||
@Resource
|
@Resource
|
||||||
private PayService payService;
|
private PayService payService;
|
||||||
@Resource
|
|
||||||
private ShopUserPayService shopUserPayService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 现金充值
|
* 现金充值
|
||||||
@@ -42,7 +39,7 @@ public class VipPayController {
|
|||||||
public CzgResult<Object> cashPayVip(@Validated @RequestBody VipPayParamDTO payParam) {
|
public CzgResult<Object> cashPayVip(@Validated @RequestBody VipPayParamDTO payParam) {
|
||||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||||
return shopUserPayService.cashPayVip(payParam);
|
return payService.cashPayVip(payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,7 +52,7 @@ public class VipPayController {
|
|||||||
public CzgResult<Map<String, Object>> jsPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> jsPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
||||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||||
return shopUserPayService.jsPayVip(ServletUtil.getClientIP(request), payParam);
|
return payService.jsPayVip(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,7 +65,7 @@ public class VipPayController {
|
|||||||
public CzgResult<Map<String, Object>> ltPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> ltPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
||||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||||
return shopUserPayService.ltPayVip(ServletUtil.getClientIP(request), payParam);
|
return payService.ltPayVip(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +81,7 @@ public class VipPayController {
|
|||||||
return CzgResult.failure("充值失败 未指定充值金额");
|
return CzgResult.failure("充值失败 未指定充值金额");
|
||||||
}
|
}
|
||||||
rechargeDTO.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
rechargeDTO.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||||
return shopUserPayService.recharge(ServletUtil.getClientIP(request), rechargeDTO, rechargeDTO.getShopUserId());
|
return payService.recharge(ServletUtil.getClientIP(request), rechargeDTO, rechargeDTO.getShopUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,7 +95,7 @@ public class VipPayController {
|
|||||||
public CzgResult<Map<String, Object>> ltPayMember(HttpServletRequest request, @Validated @RequestBody VipMemberPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> ltPayMember(HttpServletRequest request, @Validated @RequestBody VipMemberPayParamDTO payParam) {
|
||||||
AssertUtil.isNull(payParam.getShopUserId(), "购买失败 未指定店铺用户Id");
|
AssertUtil.isNull(payParam.getShopUserId(), "购买失败 未指定店铺用户Id");
|
||||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||||
return shopUserPayService.ltPayMember(ServletUtil.getClientIP(request), payParam);
|
return payService.ltPayMember(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -111,7 +108,7 @@ public class VipPayController {
|
|||||||
public CzgResult<Map<String, Object>> scanPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> scanPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
||||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(request, "platformType"));
|
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(request, "platformType"));
|
||||||
return shopUserPayService.scanPayVip(ServletUtil.getClientIP(request), payParam);
|
return payService.scanPayVip(ServletUtil.getClientIP(request), payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,7 +121,7 @@ public class VipPayController {
|
|||||||
public CzgResult<Map<String, Object>> microPayVip(@Validated @RequestBody VipPayParamDTO payParam) {
|
public CzgResult<Map<String, Object>> microPayVip(@Validated @RequestBody VipPayParamDTO payParam) {
|
||||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||||
return shopUserPayService.microPayVip(payParam);
|
return payService.microPayVip(payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,7 +132,7 @@ public class VipPayController {
|
|||||||
@PostMapping("/refundVipBefore")
|
@PostMapping("/refundVipBefore")
|
||||||
@Debounce(value = "#payParam.flowId")
|
@Debounce(value = "#payParam.flowId")
|
||||||
public CzgResult<Map<String, BigDecimal>> refundVipBefore(@Validated @RequestBody VipRefundDTO payParam) {
|
public CzgResult<Map<String, BigDecimal>> refundVipBefore(@Validated @RequestBody VipRefundDTO payParam) {
|
||||||
return shopUserPayService.refundVipBefore(payParam);
|
return payService.refundVipBefore(payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,7 +155,7 @@ public class VipPayController {
|
|||||||
return CzgResult.failure("退款金额过大");
|
return CzgResult.failure("退款金额过大");
|
||||||
}
|
}
|
||||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(request, "platformType"));
|
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(request, "platformType"));
|
||||||
return shopUserPayService.refundVip(payParam);
|
return payService.refundVip(payParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,7 +9,7 @@ import com.czg.order.vo.HistoryOrderVo;
|
|||||||
import com.czg.order.vo.OrderInfoVo;
|
import com.czg.order.vo.OrderInfoVo;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
import com.czg.sa.StpKit;
|
import com.czg.sa.StpKit;
|
||||||
import com.czg.service.order.service.OrderPayService;
|
import com.czg.service.order.service.PayService;
|
||||||
import com.czg.utils.AssertUtil;
|
import com.czg.utils.AssertUtil;
|
||||||
import com.czg.utils.ServletUtil;
|
import com.czg.utils.ServletUtil;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
@@ -31,7 +31,7 @@ public class AdminOrderController {
|
|||||||
@Resource
|
@Resource
|
||||||
private OrderInfoCustomService orderInfoService;
|
private OrderInfoCustomService orderInfoService;
|
||||||
@Resource
|
@Resource
|
||||||
private OrderPayService orderPayService;
|
private PayService payService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单列表
|
* 订单列表
|
||||||
@@ -94,7 +94,7 @@ public class AdminOrderController {
|
|||||||
@PostMapping("/refundOrder")
|
@PostMapping("/refundOrder")
|
||||||
@Debounce(value = "#refundDTO.orderId")
|
@Debounce(value = "#refundDTO.orderId")
|
||||||
public CzgResult<Object> refundOrder(@Validated @RequestBody OrderInfoRefundDTO refundDTO) {
|
public CzgResult<Object> refundOrder(@Validated @RequestBody OrderInfoRefundDTO refundDTO) {
|
||||||
return orderPayService.refundOrderBefore(refundDTO);
|
return payService.refundOrderBefore(refundDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.czg.controller.admin;
|
package com.czg.controller.admin;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.czg.EntryManager;
|
import com.czg.EntryManager;
|
||||||
import com.czg.annotation.Debounce;
|
import com.czg.annotation.Debounce;
|
||||||
import com.czg.dto.req.AggregateMerchantDto;
|
import com.czg.dto.req.AggregateMerchantDto;
|
||||||
@@ -31,25 +30,6 @@ public class EntryManagerController {
|
|||||||
@Resource
|
@Resource
|
||||||
private EntryManagerTask entryManagerTask;
|
private EntryManagerTask entryManagerTask;
|
||||||
|
|
||||||
/**
|
|
||||||
* ocr识别填充
|
|
||||||
* 阿里 ocr识别图片
|
|
||||||
* 本接口支持:PNG、JPG、JPEG、BMP、GIF、TIFF、WebP、PDF。
|
|
||||||
* 图片长宽需要大于 15 像素,小于 8192 像素。
|
|
||||||
* 长宽比需要小于 50。长宽均大于 500px。
|
|
||||||
* 图片二进制文件不能超过 10MB。
|
|
||||||
* 图片过大会影响接口响应速度,建议使用小于 1.5M 图片进行识别,
|
|
||||||
*
|
|
||||||
* @param url 图片地址
|
|
||||||
* @param type IdCard 身份证
|
|
||||||
* BankCard 银行卡
|
|
||||||
* BusinessLicense 营业执照
|
|
||||||
*/
|
|
||||||
@GetMapping("getInfoByImg")
|
|
||||||
public CzgResult<JSONObject> getInfoByImg(String url, String type) throws Exception {
|
|
||||||
return CzgResult.success(shopDirectMerchantService.getInfoByImg(url, type));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询银行支行列表
|
* 查询银行支行列表
|
||||||
*
|
*
|
||||||
@@ -76,7 +56,7 @@ public class EntryManagerController {
|
|||||||
* 进件状态是INIT 待处理 AUDIT 审核中 SIGN 待签约
|
* 进件状态是INIT 待处理 AUDIT 审核中 SIGN 待签约
|
||||||
* 3分钟内只能查一次
|
* 3分钟内只能查一次
|
||||||
*/
|
*/
|
||||||
@GetMapping("queryEntry")
|
@GetMapping
|
||||||
@Debounce(value = "#shopId", interval = 1000 * 60 * 3)
|
@Debounce(value = "#shopId", interval = 1000 * 60 * 3)
|
||||||
public CzgResult<Boolean> queryEntry(Long shopId) {
|
public CzgResult<Boolean> queryEntry(Long shopId) {
|
||||||
entryManagerTask.entryManager(shopId);
|
entryManagerTask.entryManager(shopId);
|
||||||
|
|||||||
@@ -75,11 +75,9 @@ public class EntryManagerMqListener {
|
|||||||
ShopDirectMerchant merchant = new ShopDirectMerchant();
|
ShopDirectMerchant merchant = new ShopDirectMerchant();
|
||||||
merchant.setShopId(entry.getShopId());
|
merchant.setShopId(entry.getShopId());
|
||||||
|
|
||||||
merchant.setWechatApplyId(resp.getWechatApplyId());
|
|
||||||
merchant.setWechatStatus(resp.getWechatStatus());
|
merchant.setWechatStatus(resp.getWechatStatus());
|
||||||
merchant.setWechatErrorMsg(resp.getWechatErrorMsg());
|
merchant.setWechatErrorMsg(resp.getWechatErrorMsg());
|
||||||
|
|
||||||
merchant.setAlipayOrderId(resp.getAlipayOrderId());
|
|
||||||
merchant.setAlipayStatus(resp.getAlipayStatus());
|
merchant.setAlipayStatus(resp.getAlipayStatus());
|
||||||
merchant.setAlipayErrorMsg(resp.getAlipayErrorMsg());
|
merchant.setAlipayErrorMsg(resp.getAlipayErrorMsg());
|
||||||
shopDirectMerchantService.updateById(merchant);
|
shopDirectMerchantService.updateById(merchant);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import com.czg.order.entity.MqLog;
|
|||||||
import com.czg.order.service.MqLogService;
|
import com.czg.order.service.MqLogService;
|
||||||
import com.czg.order.service.OrderInfoCustomService;
|
import com.czg.order.service.OrderInfoCustomService;
|
||||||
import com.czg.order.service.OrderInfoRpcService;
|
import com.czg.order.service.OrderInfoRpcService;
|
||||||
import com.czg.service.order.utils.FunUtil;
|
import com.czg.service.RedisService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
@@ -31,7 +31,7 @@ public class OrderMqListener {
|
|||||||
@Resource
|
@Resource
|
||||||
private OrderInfoCustomService orderInfoCustomService;
|
private OrderInfoCustomService orderInfoCustomService;
|
||||||
@Resource
|
@Resource
|
||||||
private FunUtil funUtil;
|
private RedisService redisService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单上菜
|
* 订单上菜
|
||||||
@@ -44,7 +44,7 @@ public class OrderMqListener {
|
|||||||
info = info.replace("UP_ORDER_DETAIL:", "");
|
info = info.replace("UP_ORDER_DETAIL:", "");
|
||||||
log.info("接收到修改菜品状态mq, info: {}", info);
|
log.info("接收到修改菜品状态mq, info: {}", info);
|
||||||
String finalInfo = info;
|
String finalInfo = info;
|
||||||
funUtil.debounce("UP_ORDER_DETAIL:" + info, 5, () -> {
|
redisService.debounce("UP_ORDER_DETAIL:" + info, 5, () -> {
|
||||||
orderInfoCustomService.updateOrderDetailStatus(Long.valueOf(finalInfo));
|
orderInfoCustomService.updateOrderDetailStatus(Long.valueOf(finalInfo));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import com.czg.config.RabbitConstants;
|
|||||||
import com.czg.config.RedisCst;
|
import com.czg.config.RedisCst;
|
||||||
import com.czg.order.entity.MqLog;
|
import com.czg.order.entity.MqLog;
|
||||||
import com.czg.order.service.MqLogService;
|
import com.czg.order.service.MqLogService;
|
||||||
import com.czg.service.RedisService;
|
|
||||||
import com.czg.service.order.print.PrinterHandler;
|
import com.czg.service.order.print.PrinterHandler;
|
||||||
|
import com.czg.service.order.utils.FunUtil;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -27,7 +28,7 @@ public class PrintMqListener {
|
|||||||
@Resource
|
@Resource
|
||||||
private MqLogService mqLogService;
|
private MqLogService mqLogService;
|
||||||
@Resource
|
@Resource
|
||||||
private RedisService redisService;
|
private FunUtil funUtil;
|
||||||
@Lazy
|
@Lazy
|
||||||
@Resource
|
@Resource
|
||||||
private PrinterHandler printerHandler;
|
private PrinterHandler printerHandler;
|
||||||
@@ -58,7 +59,7 @@ public class PrintMqListener {
|
|||||||
throw new RuntimeException("订单打印失败,未传递orderId");
|
throw new RuntimeException("订单打印失败,未传递orderId");
|
||||||
}
|
}
|
||||||
Boolean printOrder = jsonObject.getBoolean("printOrder");
|
Boolean printOrder = jsonObject.getBoolean("printOrder");
|
||||||
redisService.runFunAndCheckKey(() -> {
|
funUtil.runFunAndCheckKey(() -> {
|
||||||
printerHandler.handler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER);
|
printerHandler.handler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER);
|
||||||
return null;
|
return null;
|
||||||
}, RedisCst.getLockKey("orderPrint", orderId));
|
}, RedisCst.getLockKey("orderPrint", orderId));
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ public class EntryManagerTask {
|
|||||||
for (ShopDirectMerchant shopDirectMerchant : list) {
|
for (ShopDirectMerchant shopDirectMerchant : list) {
|
||||||
String wechatMerchantId = "";
|
String wechatMerchantId = "";
|
||||||
String alipayMerchantId = "";
|
String alipayMerchantId = "";
|
||||||
if (PayCst.EntryStatus.NEED_QUERY_LIST.contains(shopDirectMerchant.getWechatStatus()) && StrUtil.isNotBlank(shopDirectMerchant.getWechatApplyId())) {
|
if (PayCst.EntryStatus.NEED_QUERY_LIST.contains(shopDirectMerchant.getWechatStatus())) {
|
||||||
QueryStatusResp wechatStatus = EntryManager.queryWechatEntryStatus(shopDirectMerchant.getWechatApplyId());
|
QueryStatusResp wechatStatus = EntryManager.queryWechatEntryStatus(shopDirectMerchant.getMerchantCode());
|
||||||
shopDirectMerchant.setWechatStatus(wechatStatus.getStatus());
|
shopDirectMerchant.setWechatStatus(wechatStatus.getStatus());
|
||||||
shopDirectMerchant.setWechatErrorMsg(wechatStatus.getFailReason());
|
shopDirectMerchant.setWechatErrorMsg(wechatStatus.getFailReason());
|
||||||
shopDirectMerchant.setWechatSignUrl(wechatStatus.getSignUrl());
|
shopDirectMerchant.setWechatSignUrl(wechatStatus.getSignUrl());
|
||||||
@@ -69,8 +69,8 @@ public class EntryManagerTask {
|
|||||||
wechatMerchantId = wechatStatus.getThirdMerchantId();
|
wechatMerchantId = wechatStatus.getThirdMerchantId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (PayCst.EntryStatus.NEED_QUERY_LIST.contains(shopDirectMerchant.getAlipayStatus()) && StrUtil.isNotBlank(shopDirectMerchant.getAlipayOrderId())) {
|
if (PayCst.EntryStatus.NEED_QUERY_LIST.contains(shopDirectMerchant.getAlipayStatus())) {
|
||||||
QueryStatusResp alipayStatus = EntryManager.queryAlipayEntryStatus(shopDirectMerchant.getAlipayOrderId());
|
QueryStatusResp alipayStatus = EntryManager.queryAlipayEntryStatus(shopDirectMerchant.getMerchantCode());
|
||||||
shopDirectMerchant.setAlipayStatus(alipayStatus.getStatus());
|
shopDirectMerchant.setAlipayStatus(alipayStatus.getStatus());
|
||||||
shopDirectMerchant.setAlipayErrorMsg(alipayStatus.getFailReason());
|
shopDirectMerchant.setAlipayErrorMsg(alipayStatus.getFailReason());
|
||||||
shopDirectMerchant.setAlipaySignUrl(alipayStatus.getSignUrl());
|
shopDirectMerchant.setAlipaySignUrl(alipayStatus.getSignUrl());
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class OTimeTask {
|
|||||||
@Resource
|
@Resource
|
||||||
private CashierCartService cartService;
|
private CashierCartService cartService;
|
||||||
@Resource
|
@Resource
|
||||||
private OrderPaymentService orderPaymentService;
|
private OrderPaymentService paymentService;
|
||||||
@Resource
|
@Resource
|
||||||
private GbOrderService gbOrderService;
|
private GbOrderService gbOrderService;
|
||||||
@Resource
|
@Resource
|
||||||
@@ -118,7 +118,7 @@ public class OTimeTask {
|
|||||||
|
|
||||||
LocalDateTime tenMinutesAgo = LocalDateTime.now().minusMinutes(10);
|
LocalDateTime tenMinutesAgo = LocalDateTime.now().minusMinutes(10);
|
||||||
LocalDateTime thirdDayAgo = LocalDateTime.now().minusDays(3);
|
LocalDateTime thirdDayAgo = LocalDateTime.now().minusDays(3);
|
||||||
List<OrderPayment> list = orderPaymentService.list(QueryWrapper.create()
|
List<OrderPayment> list = paymentService.list(QueryWrapper.create()
|
||||||
.gt(OrderPayment::getUpdateTime, thirdDayAgo)
|
.gt(OrderPayment::getUpdateTime, thirdDayAgo)
|
||||||
.lt(OrderPayment::getUpdateTime, tenMinutesAgo)
|
.lt(OrderPayment::getUpdateTime, tenMinutesAgo)
|
||||||
.in(OrderPayment::getSourceType, ware)
|
.in(OrderPayment::getSourceType, ware)
|
||||||
|
|||||||
@@ -25,7 +25,23 @@ spring:
|
|||||||
port: 5672
|
port: 5672
|
||||||
username: chaozg
|
username: chaozg
|
||||||
password: chaozg123
|
password: chaozg123
|
||||||
|
# 关键优化:解决MissedHeartbeatException 心跳超时问题
|
||||||
|
connection-timeout: 10000 # 连接超时时间(10秒,避免连接建立过慢)
|
||||||
|
requested-heartbeat: 30 # 心跳间隔调整为30秒(原60秒过长,降低超时概率;过短易误触发)
|
||||||
|
# 自动重连配置(Spring AMQP 自带,关键兜底)
|
||||||
|
publisher-returns: true
|
||||||
|
template:
|
||||||
|
retry:
|
||||||
|
enabled: true # 开启消息发送重试
|
||||||
|
max-attempts: 3 # 最大重试次数
|
||||||
|
initial-interval: 3000 # 首次重试间隔2秒
|
||||||
|
multiplier: 1.5 # 重试间隔倍增因子
|
||||||
|
listener:
|
||||||
|
simple:
|
||||||
|
retry:
|
||||||
|
enabled: true # 开启消费者重试
|
||||||
|
max-attempts: 3 # 消费者最大重试次数
|
||||||
|
acknowledge-mode: auto # 确认模式(可根据业务改为manual)
|
||||||
dubbo:
|
dubbo:
|
||||||
application:
|
application:
|
||||||
name: order-server
|
name: order-server
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class FilteredNacosRegistry extends NacosRegistry {
|
|||||||
public void register(URL url) {
|
public void register(URL url) {
|
||||||
// 1. 获取原始注册的方法列表
|
// 1. 获取原始注册的方法列表
|
||||||
String originalMethods = url.getParameter("methods");
|
String originalMethods = url.getParameter("methods");
|
||||||
log.info("【过滤提示】服务 {} 注册方法:{}", url.getServiceInterface(), originalMethods);
|
// log.info("【过滤提示】服务 {} 注册方法:{}", url.getServiceInterface(), originalMethods);
|
||||||
if (originalMethods != null && !originalMethods.isEmpty()) {
|
if (originalMethods != null && !originalMethods.isEmpty()) {
|
||||||
// 2. 过滤黑名单中的方法名
|
// 2. 过滤黑名单中的方法名
|
||||||
List<String> filteredMethods = Arrays.stream(originalMethods.split(","))
|
List<String> filteredMethods = Arrays.stream(originalMethods.split(","))
|
||||||
@@ -67,12 +67,12 @@ public class FilteredNacosRegistry extends NacosRegistry {
|
|||||||
// 3. 处理过滤后的结果
|
// 3. 处理过滤后的结果
|
||||||
if (filteredMethods.isEmpty()) {
|
if (filteredMethods.isEmpty()) {
|
||||||
// 若所有方法都被过滤,直接终止注册(可选:根据业务决定是否保留服务注册)
|
// 若所有方法都被过滤,直接终止注册(可选:根据业务决定是否保留服务注册)
|
||||||
log.info("【过滤提示】服务 {} 所有方法均被过滤,终止注册", url.getServiceInterface());
|
// log.info("【过滤提示】服务 {} 所有方法均被过滤,终止注册", url.getServiceInterface());
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// 替换 URL 中的 methods 参数为过滤后的列表
|
// 替换 URL 中的 methods 参数为过滤后的列表
|
||||||
url = url.addParameter("methods", String.join(",", filteredMethods));
|
url = url.addParameter("methods", String.join(",", filteredMethods));
|
||||||
log.info("【过滤提示】服务 {} 注册方法:{}", url.getServiceInterface(), filteredMethods);
|
// log.info("【过滤提示】服务 {} 注册方法:{}", url.getServiceInterface(), filteredMethods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.czg.config;
|
package com.czg.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.mybatisflex.core.audit.AuditManager;
|
import com.mybatisflex.core.audit.AuditManager;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -17,8 +18,24 @@ public class MybatisFlexConfig {
|
|||||||
//设置 SQL 审计收集器
|
//设置 SQL 审计收集器
|
||||||
AuditManager.setMessageCollector(auditMessage ->
|
AuditManager.setMessageCollector(auditMessage ->
|
||||||
log.info("[sql] time: {}, size: {}, sql:\n{}",
|
log.info("[sql] time: {}, size: {}, sql:\n{}",
|
||||||
auditMessage.getElapsedTime(), auditMessage.getQueryCount(), auditMessage.getFullSql())
|
auditMessage.getElapsedTime(), auditMessage.getQueryCount(), compressSql(auditMessage.getFullSql())));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 精简SQL:去除多余换行、制表符、连续空格,保留语法必需空格
|
||||||
|
*
|
||||||
|
* @param originalSql 原始带换行/空格的SQL
|
||||||
|
* @return 精简后的SQL
|
||||||
|
*/
|
||||||
|
public static String compressSql(String originalSql) {
|
||||||
|
if (StrUtil.isBlank(originalSql)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// 1. 替换所有换行、制表符为单个空格
|
||||||
|
String tempSql = originalSql.replaceAll("\\r\\n|\\r|\\n|\\t", " ");
|
||||||
|
// 2. 替换多个连续空格为单个空格
|
||||||
|
tempSql = tempSql.replaceAll("\\s+", " ");
|
||||||
|
// 3. 去除首尾空格
|
||||||
|
return tempSql.trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,15 @@ import jakarta.annotation.Resource;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author GYJoker
|
* @author GYJoker
|
||||||
@@ -650,4 +651,106 @@ public class RedisService {
|
|||||||
}
|
}
|
||||||
return JSON.parseArray(jsonStr, type);
|
return JSON.parseArray(jsonStr, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int retryCount = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行任务并保证锁唯一
|
||||||
|
*
|
||||||
|
* @param supplier 业务逻辑
|
||||||
|
* @param lockKey Redis锁的Key
|
||||||
|
* @return 业务逻辑返回值
|
||||||
|
*/
|
||||||
|
public <T> T runFunAndCheckKey(Supplier<T> supplier, String lockKey) {
|
||||||
|
String lockValue = String.valueOf(System.nanoTime() + Thread.currentThread().threadId());
|
||||||
|
try {
|
||||||
|
// 尝试获取锁,超时时间 5 秒,防止死锁
|
||||||
|
boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
|
||||||
|
int count = 0;
|
||||||
|
// 初始等待 10ms
|
||||||
|
int retryDelay = 10;
|
||||||
|
|
||||||
|
while (!lock) {
|
||||||
|
// 最多重试 10 次,大约 10 秒
|
||||||
|
if (count++ > 50) {
|
||||||
|
throw new RuntimeException("系统繁忙, 稍后再试");
|
||||||
|
}
|
||||||
|
Thread.sleep(retryDelay);
|
||||||
|
// 指数退避,最大等待 200ms
|
||||||
|
retryDelay = Math.min(retryDelay * 2, 200);
|
||||||
|
lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行任务
|
||||||
|
return supplier.get();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new RuntimeException("线程被中断", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("执行出错:{}", e.getMessage(), e);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
// 释放锁(使用 Lua 脚本确保原子性)
|
||||||
|
unlock(lockKey, lockValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 Lua 脚本确保释放锁的原子性
|
||||||
|
*
|
||||||
|
* @param lockKey 锁的 Key
|
||||||
|
* @param lockValue 当前线程的锁值
|
||||||
|
*/
|
||||||
|
private void unlock(String lockKey, String lockValue) {
|
||||||
|
String luaScript =
|
||||||
|
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
|
||||||
|
"return redis.call('del', KEYS[1]) " +
|
||||||
|
"else return 0 end";
|
||||||
|
redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class),
|
||||||
|
Collections.singletonList(lockKey), lockValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, R> R runFunAndRetry(
|
||||||
|
Supplier<R> function,
|
||||||
|
Function<R, Boolean> check, Consumer<R> errFun) {
|
||||||
|
R result = function.get();
|
||||||
|
boolean flag = check.apply(result);
|
||||||
|
|
||||||
|
while (flag && retryCount-- > 0) {
|
||||||
|
result = function.get();
|
||||||
|
flag = check.apply(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
errFun.accept(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防抖函数:在指定秒数内相同 Key 的任务只会执行一次
|
||||||
|
*
|
||||||
|
* @param key 防抖使用的 Redis Key
|
||||||
|
* @param seconds 防抖时间(秒)
|
||||||
|
* @param task 要执行的业务逻辑
|
||||||
|
* @return true 执行了任务;false 在防抖期内被拦截
|
||||||
|
*/
|
||||||
|
public boolean debounce(String key, long seconds, Runnable task) {
|
||||||
|
try {
|
||||||
|
Boolean success = redisTemplate.opsForValue().setIfAbsent(
|
||||||
|
key, "1", seconds, TimeUnit.SECONDS
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(success)) {
|
||||||
|
task.run();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("防抖函数执行失败 key={} err={}", key, e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,4 +285,13 @@ public class ShopInfoEditDTO {
|
|||||||
*/
|
*/
|
||||||
private Integer isCountStick;
|
private Integer isCountStick;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业id
|
||||||
|
*/
|
||||||
|
private String weworkId;
|
||||||
|
/**
|
||||||
|
* 企业接入链接
|
||||||
|
*/
|
||||||
|
private String weworkUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.czg.account.entity;
|
||||||
|
|
||||||
|
import com.mybatisflex.annotation.Column;
|
||||||
|
import com.mybatisflex.annotation.Id;
|
||||||
|
import com.mybatisflex.annotation.KeyType;
|
||||||
|
import com.mybatisflex.annotation.Table;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 悬浮窗配置 实体类。
|
||||||
|
*
|
||||||
|
* @author ww
|
||||||
|
* @since 2025-12-29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Table("tb_quick_menu")
|
||||||
|
public class QuickMenu implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id(keyType = KeyType.Auto)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 店铺Id
|
||||||
|
*/
|
||||||
|
private Long shopId;
|
||||||
|
/**
|
||||||
|
* 菜单图标
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜单Id
|
||||||
|
*/
|
||||||
|
@NotNull(message = "关联菜单不能为空")
|
||||||
|
private Long menuId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*/
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 1-启用 0-禁用
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Column(onInsertValue = "now()")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Column(onInsertValue = "now()", onUpdateValue = "now()")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -135,5 +135,13 @@ public class ShopConfig implements Serializable {
|
|||||||
|
|
||||||
private String dingAppKey;
|
private String dingAppKey;
|
||||||
private String dingAppSecret;
|
private String dingAppSecret;
|
||||||
|
/**
|
||||||
|
* 企业id
|
||||||
|
*/
|
||||||
|
private String weworkId;
|
||||||
|
/**
|
||||||
|
* 企业接入链接
|
||||||
|
*/
|
||||||
|
private String weworkUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,4 +371,15 @@ public class ShopInfo implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业id
|
||||||
|
*/
|
||||||
|
@Column(ignore = true)
|
||||||
|
private String weworkId;
|
||||||
|
/**
|
||||||
|
* 企业接入链接
|
||||||
|
*/
|
||||||
|
@Column(ignore = true)
|
||||||
|
private String weworkUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.czg.account.service;
|
||||||
|
|
||||||
|
import com.mybatisflex.core.service.IService;
|
||||||
|
import com.czg.account.entity.QuickMenu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 悬浮窗配置 服务层。
|
||||||
|
*
|
||||||
|
* @author ww
|
||||||
|
* @since 2025-12-29
|
||||||
|
*/
|
||||||
|
public interface QuickMenuService extends IService<QuickMenu> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,10 +7,12 @@ import com.czg.exception.CzgException;
|
|||||||
import com.czg.market.dto.MkDistributionUserDTO;
|
import com.czg.market.dto.MkDistributionUserDTO;
|
||||||
import com.czg.market.dto.MkDistributionWithdrawFlowDTO;
|
import com.czg.market.dto.MkDistributionWithdrawFlowDTO;
|
||||||
import com.czg.market.entity.MkDistributionConfig;
|
import com.czg.market.entity.MkDistributionConfig;
|
||||||
|
import com.czg.market.entity.MkDistributionFlow;
|
||||||
import com.czg.market.entity.MkDistributionUser;
|
import com.czg.market.entity.MkDistributionUser;
|
||||||
import com.czg.market.vo.DistributionCenterShopVO;
|
import com.czg.market.vo.DistributionCenterShopVO;
|
||||||
import com.czg.market.vo.InviteUserVO;
|
import com.czg.market.vo.InviteUserVO;
|
||||||
import com.czg.order.dto.MkDistributionPayDTO;
|
import com.czg.order.dto.MkDistributionPayDTO;
|
||||||
|
import com.czg.order.entity.OrderInfo;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import com.mybatisflex.core.service.IService;
|
import com.mybatisflex.core.service.IService;
|
||||||
|
|
||||||
@@ -123,6 +125,8 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
|||||||
|
|
||||||
void refund(Long orderId, String orderNo);
|
void refund(Long orderId, String orderNo);
|
||||||
|
|
||||||
|
void distributionUserAmount(MkDistributionFlow item, OrderInfo orderInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发放分销奖励
|
* 发放分销奖励
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.czg.order.dto;
|
|||||||
import com.czg.utils.AssertUtil;
|
import com.czg.utils.AssertUtil;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@@ -14,7 +13,6 @@ import java.math.BigDecimal;
|
|||||||
* @author ww
|
* @author ww
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
|
||||||
public class LtPayOtherDTO {
|
public class LtPayOtherDTO {
|
||||||
/**
|
/**
|
||||||
* 积分商品id/团购商品id
|
* 积分商品id/团购商品id
|
||||||
|
|||||||
@@ -1,267 +0,0 @@
|
|||||||
|
|
||||||
package com.czg.order.dto;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.annotation.JSONField;
|
|
||||||
|
|
||||||
import java.io.Serial;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单表 实体类。
|
|
||||||
*
|
|
||||||
* @author ww
|
|
||||||
* @since 2025-02-13
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class OrderInfoDTO implements Serializable {
|
|
||||||
|
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单编号
|
|
||||||
* pc 收银机客户端 PC+雪花ID
|
|
||||||
* wechat 微信小程序 WX+雪花ID
|
|
||||||
* alipay 支付宝小程序 ALI+雪花ID
|
|
||||||
* admin-pc PC管理端 WEB+雪花ID
|
|
||||||
* admin-app APP管理端 APP+雪花ID
|
|
||||||
*/
|
|
||||||
private String orderNo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 店铺Id
|
|
||||||
*/
|
|
||||||
private Long shopId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户Id user_info表的id
|
|
||||||
*/
|
|
||||||
private Long userId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 退单金额
|
|
||||||
*/
|
|
||||||
private BigDecimal refundAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单原金额 不含折扣价格
|
|
||||||
*/
|
|
||||||
private BigDecimal originAmount;
|
|
||||||
/**
|
|
||||||
* 抹零金额 减免多少钱
|
|
||||||
*/
|
|
||||||
private BigDecimal roundAmount;
|
|
||||||
/**
|
|
||||||
* 优惠总金额
|
|
||||||
*/
|
|
||||||
private BigDecimal discountAllAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单金额 (扣除各类折扣)
|
|
||||||
*/
|
|
||||||
private BigDecimal orderAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实际支付金额
|
|
||||||
*/
|
|
||||||
private BigDecimal payAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 积分抵扣金额
|
|
||||||
*/
|
|
||||||
private BigDecimal pointsDiscountAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用的积分数量
|
|
||||||
*/
|
|
||||||
private Integer pointsNum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商品优惠券抵扣金额
|
|
||||||
*/
|
|
||||||
private BigDecimal productCouponDiscountAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户使用的卡券
|
|
||||||
*/
|
|
||||||
private String couponInfoList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 满减活动抵扣金额
|
|
||||||
*/
|
|
||||||
private BigDecimal discountActAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 折扣金额
|
|
||||||
*/
|
|
||||||
private BigDecimal discountAmount;
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 折扣比例
|
|
||||||
// */
|
|
||||||
// private BigDecimal discountRatio;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打包费
|
|
||||||
*/
|
|
||||||
private BigDecimal packFee;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 台桌Id
|
|
||||||
*/
|
|
||||||
private String tableCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 台桌名称
|
|
||||||
*/
|
|
||||||
private String tableName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单类型-
|
|
||||||
* cash收银(除小程序以外 都属于收银)
|
|
||||||
* miniapp小程序
|
|
||||||
*/
|
|
||||||
private String orderType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 平台类型 pc 收银机客户端 wechat 微信小程序 alipay 支付宝小程序 admin-pc PC管理端 admin-app APP管理端
|
|
||||||
*/
|
|
||||||
private String platformType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用餐模式 堂食 dine-in 外带 take-out 外卖 take-away
|
|
||||||
*/
|
|
||||||
private String dineMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付模式:
|
|
||||||
* 后付费 after-pay
|
|
||||||
* 先付费 before-pay
|
|
||||||
* 无桌码 no-table
|
|
||||||
*/
|
|
||||||
private String payMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付类型
|
|
||||||
* 主扫 main-scan
|
|
||||||
* 被扫 back-scan
|
|
||||||
* 微信小程序 wechat-mini
|
|
||||||
* 支付宝小程序 alipay-mini
|
|
||||||
* 会员支付 vip-pay
|
|
||||||
* 现金支付 cash-pay
|
|
||||||
*/
|
|
||||||
private String payType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 状态: unpaid-待支付;in-production 制作中;wait_out 待取餐;;done-订单完成;refunding-申请退单;refund-退单;part_refund 部分退单;cancelled-取消订单
|
|
||||||
*/
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 折扣信息 json
|
|
||||||
*/
|
|
||||||
private String discountInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 限时折扣信息 json
|
|
||||||
*/
|
|
||||||
private String limitRate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否支持退款,1支持退单, 0不支持退单
|
|
||||||
*/
|
|
||||||
private Integer refundAble;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付时间
|
|
||||||
*/
|
|
||||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private LocalDateTime paidTime;
|
|
||||||
|
|
||||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private LocalDateTime createTime;
|
|
||||||
|
|
||||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private LocalDateTime updateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付订单号
|
|
||||||
* tb_order_payment.id
|
|
||||||
* tb_shop_user_flow.id
|
|
||||||
*/
|
|
||||||
private Long payOrderId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 交易日期
|
|
||||||
*/
|
|
||||||
private String tradeDay;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 备注
|
|
||||||
*/
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取餐码
|
|
||||||
*/
|
|
||||||
private String takeCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 员工id
|
|
||||||
*/
|
|
||||||
private Long staffId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当前订单下单次数
|
|
||||||
*/
|
|
||||||
private Integer placeNum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用餐人数
|
|
||||||
*/
|
|
||||||
private Integer seatNum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 餐位费
|
|
||||||
*/
|
|
||||||
private BigDecimal seatAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 退款备注
|
|
||||||
*/
|
|
||||||
private String refundRemark;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否使用了霸王餐
|
|
||||||
*/
|
|
||||||
private Integer isFreeDine;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否等叫 0 否 1 等叫
|
|
||||||
*/
|
|
||||||
private Integer isWaitCall;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 挂账人id
|
|
||||||
*/
|
|
||||||
private Long creditBuyerId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否回收站 0-否,1回收站
|
|
||||||
*/
|
|
||||||
private Integer isDel;
|
|
||||||
private String failMsg;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.czg.order.entity;
|
package com.czg.order.entity;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.czg.order.dto.LimitRateDTO;
|
import com.czg.order.dto.LimitRateDTO;
|
||||||
import com.mybatisflex.annotation.Column;
|
import com.mybatisflex.annotation.Column;
|
||||||
import com.mybatisflex.annotation.Id;
|
import com.mybatisflex.annotation.Id;
|
||||||
@@ -298,8 +300,10 @@ public class OrderInfo implements Serializable {
|
|||||||
private Integer isDel;
|
private Integer isDel;
|
||||||
|
|
||||||
private String failMsg;
|
private String failMsg;
|
||||||
|
/**
|
||||||
|
* 打印状态 Json格式
|
||||||
|
*/
|
||||||
|
private String printStatus;
|
||||||
|
|
||||||
|
|
||||||
public String getRefundRemark() {
|
public String getRefundRemark() {
|
||||||
@@ -342,4 +346,41 @@ public class OrderInfo implements Serializable {
|
|||||||
// 如果需要加上抹零金额,可以取消下面这行注释
|
// 如果需要加上抹零金额,可以取消下面这行注释
|
||||||
// .add(this.getRoundAmount() != null ? this.getRoundAmount() : BigDecimal.ZERO);
|
// .add(this.getRoundAmount() != null ? this.getRoundAmount() : BigDecimal.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JSONArray getPrintStatusAsArray() {
|
||||||
|
if (StrUtil.isBlank(printStatus)) {
|
||||||
|
return new JSONArray();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSONArray.parseArray(printStatus.trim());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new JSONArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void upPrintStatus(JSONObject printJson, boolean isPrintSuccess) {
|
||||||
|
String currentDeviceId = printJson.getString("id");
|
||||||
|
JSONArray oldPrintStatusArray = getPrintStatusAsArray();
|
||||||
|
// 3. 初始化新的打印状态JSON数组(用于存储处理后的结果)
|
||||||
|
JSONArray newPrintStatusArray = new JSONArray();
|
||||||
|
// 场景1:打印成功 - 移除原有数组中与当前设备ID一致的记录,保留其余记录
|
||||||
|
if (oldPrintStatusArray != null && !oldPrintStatusArray.isEmpty()) {
|
||||||
|
for (int i = 0; i < oldPrintStatusArray.size(); i++) {
|
||||||
|
JSONObject deviceObj = oldPrintStatusArray.getJSONObject(i);
|
||||||
|
String deviceId = deviceObj.getString("id");
|
||||||
|
// 仅保留非当前设备ID的记录
|
||||||
|
if (currentDeviceId != null && !currentDeviceId.equals(deviceId)) {
|
||||||
|
newPrintStatusArray.add(deviceObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isPrintSuccess) {
|
||||||
|
newPrintStatusArray.add(printJson);
|
||||||
|
}
|
||||||
|
if (!newPrintStatusArray.isEmpty()) {
|
||||||
|
printStatus = newPrintStatusArray.toJSONString();
|
||||||
|
} else {
|
||||||
|
printStatus = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,6 @@ public class ShopDirectMerchant implements Serializable {
|
|||||||
* 营业执照编号
|
* 营业执照编号
|
||||||
*/
|
*/
|
||||||
private String licenceNo;
|
private String licenceNo;
|
||||||
/**
|
|
||||||
* 支付宝账号
|
|
||||||
*/
|
|
||||||
private String alipayAccount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商户编号(在当前系统唯一)
|
* 商户编号(在当前系统唯一)
|
||||||
@@ -84,7 +80,6 @@ public class ShopDirectMerchant implements Serializable {
|
|||||||
|
|
||||||
private String errorMsg;
|
private String errorMsg;
|
||||||
|
|
||||||
private String wechatApplyId;
|
|
||||||
/**
|
/**
|
||||||
* 微信状态
|
* 微信状态
|
||||||
*/
|
*/
|
||||||
@@ -99,8 +94,6 @@ public class ShopDirectMerchant implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String wechatSignUrl;
|
private String wechatSignUrl;
|
||||||
|
|
||||||
private String alipayOrderId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付宝状态
|
* 支付宝状态
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import com.czg.order.entity.PrintMachineLog;
|
|||||||
* @since 2025-03-11
|
* @since 2025-03-11
|
||||||
*/
|
*/
|
||||||
public interface PrintMachineLogService extends IService<PrintMachineLog> {
|
public interface PrintMachineLogService extends IService<PrintMachineLog> {
|
||||||
void save(PrintMachine config, String bizType, String printContent, Object respJson);
|
void save(Long orderId, PrintMachine config, String bizType, String printContent, String respJson);
|
||||||
|
|
||||||
|
void save(PrintMachine config, String bizType, String printContent, String respJson);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,6 @@ public class OrderDetailSmallVO implements Serializable {
|
|||||||
private LocalDateTime startOrderTime;
|
private LocalDateTime startOrderTime;
|
||||||
private LocalDateTime dishOutTime;
|
private LocalDateTime dishOutTime;
|
||||||
private LocalDateTime foodServeTime;
|
private LocalDateTime foodServeTime;
|
||||||
|
private Integer isTemporary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,11 @@ public class OrderInfoVo implements Serializable {
|
|||||||
* 备注
|
* 备注
|
||||||
*/
|
*/
|
||||||
private String remark;
|
private String remark;
|
||||||
|
/**
|
||||||
|
* 打印状态 Json格式
|
||||||
|
* [{"id":"124","name":"111","time":"2025-12-29 11:05:18"},{"id":"111","name":"标签","time":"2025-12-29 11:05:30"}]
|
||||||
|
*/
|
||||||
|
private String printStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否使用了霸王餐
|
* 是否使用了霸王餐
|
||||||
|
|||||||
@@ -37,10 +37,6 @@ public class SysCategoryInfo implements Serializable {
|
|||||||
@Id(keyType = KeyType.Auto)
|
@Id(keyType = KeyType.Auto)
|
||||||
private BigInteger id;
|
private BigInteger id;
|
||||||
|
|
||||||
/**
|
|
||||||
* 一级类目code
|
|
||||||
*/
|
|
||||||
private String firstCategoryCode;
|
|
||||||
/**
|
/**
|
||||||
* 一级类目
|
* 一级类目
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,11 +30,6 @@
|
|||||||
<groupId>com.alipay.sdk</groupId>
|
<groupId>com.alipay.sdk</groupId>
|
||||||
<artifactId>alipay-sdk-java-v3</artifactId>
|
<artifactId>alipay-sdk-java-v3</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.aliyun</groupId>
|
|
||||||
<artifactId>ocr_api20210707</artifactId>
|
|
||||||
<version>3.1.2</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -9,7 +9,6 @@ import com.czg.dto.resp.EntryThirdRespDto;
|
|||||||
import com.czg.dto.resp.QueryStatusResp;
|
import com.czg.dto.resp.QueryStatusResp;
|
||||||
import com.czg.exception.CzgException;
|
import com.czg.exception.CzgException;
|
||||||
import com.czg.third.alipay.AlipayEntryManager;
|
import com.czg.third.alipay.AlipayEntryManager;
|
||||||
import com.czg.third.alipay.AlipayIsvEntryManager;
|
|
||||||
import com.czg.third.wechat.WechatEntryManager;
|
import com.czg.third.wechat.WechatEntryManager;
|
||||||
import com.czg.utils.AssertUtil;
|
import com.czg.utils.AssertUtil;
|
||||||
import com.czg.utils.AsyncTaskExecutor;
|
import com.czg.utils.AsyncTaskExecutor;
|
||||||
@@ -41,7 +40,7 @@ public class EntryManager {
|
|||||||
/**
|
/**
|
||||||
* 查询微信进件状态
|
* 查询微信进件状态
|
||||||
*
|
*
|
||||||
* @param merchantCode 商户编号, 进件时返回的批次号 {@link EntryRespDto#wechatApplyId}
|
* @param merchantCode 商户编号
|
||||||
* @return 进件状态
|
* @return 进件状态
|
||||||
*/
|
*/
|
||||||
public static QueryStatusResp queryWechatEntryStatus(String merchantCode) {
|
public static QueryStatusResp queryWechatEntryStatus(String merchantCode) {
|
||||||
@@ -51,11 +50,11 @@ public class EntryManager {
|
|||||||
/**
|
/**
|
||||||
* 查询支付宝进件状态
|
* 查询支付宝进件状态
|
||||||
*
|
*
|
||||||
* @param batchNo 商户编号, 进件时返回的批次号 {@link EntryRespDto#alipayOrderId}
|
* @param merchantCode 商户编号
|
||||||
* @return 进件状态
|
* @return 进件状态
|
||||||
*/
|
*/
|
||||||
public static QueryStatusResp queryAlipayEntryStatus(String batchNo) {
|
public static QueryStatusResp queryAlipayEntryStatus(String merchantCode) {
|
||||||
return AlipayIsvEntryManager.queryMerchantBatchStatus(null, batchNo);
|
return AlipayEntryManager.queryMerchantEntryStatus(null, merchantCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,7 +77,7 @@ public class EntryManager {
|
|||||||
tasks.add(() -> WechatEntryManager.entryMerchant(null, reqDto));
|
tasks.add(() -> WechatEntryManager.entryMerchant(null, reqDto));
|
||||||
}
|
}
|
||||||
if (ArrayUtil.contains(platform, PayCst.Platform.ALIPAY)) {
|
if (ArrayUtil.contains(platform, PayCst.Platform.ALIPAY)) {
|
||||||
tasks.add(() -> AlipayIsvEntryManager.entryMerchant(null, reqDto));
|
tasks.add(() -> AlipayEntryManager.entryMerchant(null, reqDto));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行所有任务
|
// 执行所有任务
|
||||||
@@ -236,7 +235,6 @@ public class EntryManager {
|
|||||||
AssertUtil.isBlank(baseInfo.getUserType(), "商户类型不能为空");
|
AssertUtil.isBlank(baseInfo.getUserType(), "商户类型不能为空");
|
||||||
AssertUtil.isBlank(baseInfo.getShortName(), "商户简称不能为空");
|
AssertUtil.isBlank(baseInfo.getShortName(), "商户简称不能为空");
|
||||||
AssertUtil.isBlank(baseInfo.getMccCode(), "商户行业编码不能为空");
|
AssertUtil.isBlank(baseInfo.getMccCode(), "商户行业编码不能为空");
|
||||||
AssertUtil.isBlank(baseInfo.getAlipayAccount(), "支付宝账号不能为空");
|
|
||||||
AssertUtil.isBlank(baseInfo.getContactPersonType(), "联系人类型不能为空");
|
AssertUtil.isBlank(baseInfo.getContactPersonType(), "联系人类型不能为空");
|
||||||
if (!PayCst.ContactPersonType.SUPER.equals(baseInfo.getContactPersonType()) && !PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType())) {
|
if (!PayCst.ContactPersonType.SUPER.equals(baseInfo.getContactPersonType()) && !PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType())) {
|
||||||
throw new CzgException("联系人类型错误");
|
throw new CzgException("联系人类型错误");
|
||||||
@@ -369,11 +367,11 @@ public class EntryManager {
|
|||||||
// uploadParamImage(merchantDto);
|
// uploadParamImage(merchantDto);
|
||||||
|
|
||||||
verifyEntryParam(merchantDto);
|
verifyEntryParam(merchantDto);
|
||||||
// uploadParamImage(merchantDto);
|
uploadParamImage(merchantDto);
|
||||||
// System.out.println(merchantDto);
|
System.out.println(merchantDto);
|
||||||
// entryMerchant(merchantDto, PayCst.Platform.WECHAT);
|
// entryMerchant(merchantDto, PayCst.Platform.WECHAT);
|
||||||
entryMerchant(merchantDto, PayCst.Platform.ALIPAY);
|
// entryMerchant(merchantDto, PayCst.Platform.ALIPAY);
|
||||||
// entryMerchant(merchantDto, PayCst.Platform.WECHAT, PayCst.Platform.ALIPAY);
|
entryMerchant(merchantDto, PayCst.Platform.WECHAT, PayCst.Platform.ALIPAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AggregateMerchantDto getTestMerchantEntryData() {
|
private static AggregateMerchantDto getTestMerchantEntryData() {
|
||||||
@@ -384,8 +382,7 @@ public class EntryManager {
|
|||||||
baseInfoDto.setUserType("1");
|
baseInfoDto.setUserType("1");
|
||||||
baseInfoDto.setCompanyChildType("1");
|
baseInfoDto.setCompanyChildType("1");
|
||||||
baseInfoDto.setShortName("测试商户");
|
baseInfoDto.setShortName("测试商户");
|
||||||
baseInfoDto.setAlipayAccount("1157756119@qq.com");
|
baseInfoDto.setMccCode("0741");
|
||||||
baseInfoDto.setMccCode("A0001_B0001");
|
|
||||||
baseInfoDto.setContactPersonType(PayCst.ContactPersonType.SUPER);
|
baseInfoDto.setContactPersonType(PayCst.ContactPersonType.SUPER);
|
||||||
baseInfoDto.setContactName("张三");
|
baseInfoDto.setContactName("张三");
|
||||||
baseInfoDto.setContactPersonId("110101199001011234");
|
baseInfoDto.setContactPersonId("110101199001011234");
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
package com.czg;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.aliyun.ocr_api20210707.models.RecognizeAllTextResponse;
|
|
||||||
import com.aliyun.tea.*;
|
|
||||||
import com.czg.exception.CzgException;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ww
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class OcrUtils {
|
|
||||||
/**
|
|
||||||
* 阿里 ocr识别图片
|
|
||||||
* 本接口支持:PNG、JPG、JPEG、BMP、GIF、TIFF、WebP、PDF。
|
|
||||||
* 图片长宽需要大于 15 像素,小于 8192 像素。
|
|
||||||
* 长宽比需要小于 50。长宽均大于 500px。
|
|
||||||
* 图片二进制文件不能超过 10MB。
|
|
||||||
* 图片过大会影响接口响应速度,建议使用小于 1.5M 图片进行识别,
|
|
||||||
*
|
|
||||||
* @param url 图片地址
|
|
||||||
* @param type IdCard 身份证
|
|
||||||
* BankCard 银行卡
|
|
||||||
* BusinessLicense 营业执照
|
|
||||||
* 目前使用的角色为 czg-oss@1413456038175003.onaliyun.com
|
|
||||||
* 需要 AliyunOCRFullAccess 权限
|
|
||||||
* AliyunBSSContractFullAccess 权限
|
|
||||||
* 文档地址 <a href="https://help.aliyun.com/zh/ocr/developer-reference/api-ocr-api-2021-07-07-recognizealltext?spm=a2c4g.11186623.0.0.543669f32I79Gw#api-detail-35">
|
|
||||||
*/
|
|
||||||
public static JSONObject getInfoByImg(String accessKeyId, String accessKeySecret,
|
|
||||||
String url, String type) throws Exception {
|
|
||||||
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
|
|
||||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
|
|
||||||
.setAccessKeyId(accessKeyId)
|
|
||||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
|
|
||||||
.setAccessKeySecret(accessKeySecret);
|
|
||||||
config.endpoint = "ocr-api.cn-hangzhou.aliyuncs.com";
|
|
||||||
|
|
||||||
com.aliyun.ocr_api20210707.Client client = new com.aliyun.ocr_api20210707.Client(config);
|
|
||||||
com.aliyun.ocr_api20210707.models.RecognizeAllTextRequest recognizeAllTextRequest = new com.aliyun.ocr_api20210707.models.RecognizeAllTextRequest()
|
|
||||||
.setUrl(url).setType(type);
|
|
||||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
|
||||||
try {
|
|
||||||
RecognizeAllTextResponse resp = client.recognizeAllTextWithOptions(recognizeAllTextRequest, runtime);
|
|
||||||
return JSONObject.from(resp.body.data);
|
|
||||||
} catch (TeaException error) {
|
|
||||||
// // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
|
||||||
// // 错误 message
|
|
||||||
// System.out.println(error.getMessage());
|
|
||||||
// // 诊断地址
|
|
||||||
// System.out.println(error.getData().get("Recommend"));
|
|
||||||
// com.aliyun.teautil.Common.assertAsString(error.message);
|
|
||||||
log.error("识别失败, msg: {}", error.getMessage());
|
|
||||||
throw new CzgException(error.getMessage());
|
|
||||||
} catch (Exception error) {
|
|
||||||
// TeaException error = new TeaException(_error.getMessage(), _error);
|
|
||||||
// // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
|
||||||
// // 错误 message
|
|
||||||
// System.out.println(error.getMessage());
|
|
||||||
// // 诊断地址
|
|
||||||
// System.out.println(error.getData().get("Recommend"));
|
|
||||||
// com.aliyun.teautil.Common.assertAsString(error.message);
|
|
||||||
log.error("识别失败, msg: {}", error.getMessage());
|
|
||||||
throw new CzgException(error.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,11 +10,6 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface PayCst {
|
public interface PayCst {
|
||||||
|
|
||||||
/**
|
|
||||||
* 长期有效时间
|
|
||||||
*/
|
|
||||||
String LONG_TERM_DATE = "2099-12-31";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 平台
|
* 平台
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,17 +29,9 @@ public class MerchantBaseInfoDto {
|
|||||||
/**
|
/**
|
||||||
* 【必填】
|
* 【必填】
|
||||||
* 行业编码
|
* 行业编码
|
||||||
* 一级类目code_二级类目code
|
|
||||||
* 【示例值】A0001_B0199
|
|
||||||
*/
|
*/
|
||||||
private String mccCode;
|
private String mccCode;
|
||||||
|
|
||||||
/**
|
|
||||||
* 【必填】
|
|
||||||
* 支付宝账号
|
|
||||||
*/
|
|
||||||
private String alipayAccount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 联系人类型
|
* 联系人类型
|
||||||
* LEGAL: 经营者/法定代表人
|
* LEGAL: 经营者/法定代表人
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.czg.dto.resp;
|
package com.czg.dto.resp;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询进件状态
|
* 查询进件状态
|
||||||
@@ -9,7 +8,6 @@ import lombok.experimental.Accessors;
|
|||||||
* @date 2026/1/7 17:12
|
* @date 2026/1/7 17:12
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
|
||||||
public class QueryStatusResp {
|
public class QueryStatusResp {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.czg.third.alipay;
|
|||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.alipay.api.AlipayApiException;
|
import com.alipay.api.AlipayApiException;
|
||||||
import com.alipay.api.DefaultAlipayClient;
|
import com.alipay.api.DefaultAlipayClient;
|
||||||
import com.alipay.api.FileItem;
|
import com.alipay.api.FileItem;
|
||||||
@@ -345,12 +344,11 @@ public class AlipayEntryManager {
|
|||||||
return entryParams;
|
return entryParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws ApiException {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
// queryBankBranchList("CMB", "陕西省", "西安市");
|
// queryBankBranchList("CMB", "陕西省", "西安市");
|
||||||
// uploadImage(null, "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg");
|
uploadImage(null, "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg");
|
||||||
|
|
||||||
test();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://opendocs.alipay.com/solution/0dec7x?pathHash=caec4753 直付通
|
// https://opendocs.alipay.com/solution/0dec7x?pathHash=caec4753 直付通
|
||||||
@@ -363,7 +361,6 @@ public class AlipayEntryManager {
|
|||||||
alipayConfig.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB");
|
alipayConfig.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB");
|
||||||
alipayConfig.setPrivateKey("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCz3FkdffxZibdwis9W7eOW1dEjGAbSvRDL2ikfeCIW5KZNoIjUqxI0mIoUlLRRKO71QLHZS1Vb2aJp8jeOAqIPa8e76HTneQEzk3FGA8gpraSGvbadHWzvxnmYKsts1TBiEZQL82ySJXhQTJvZ6jyDM7s6wHHUnrH+Qi29QpppQ1sxsoJeCtajUgRg3btD6XbBcyFAX3pzM56Kw9eaIjZoD8WToZOM/Y3sqNL2uo8lLqcIpTrI7Pq5ZOspmBQ+t8v3rS9IdDZZMvd0trzS67AXwHz8rKPBT/lL1A4iHnXCHUvktusX1fPs3/RGY/a7PIddaBLnfY0GcueE16K7QcrXAgMBAAECggEAbSdT2eckp75BWoaTcGEs1tRqeM7TDT/6moyKmnOQ1K3tE31SrSYpBUxxuC3LBNo/sw2RIZtrcTOyMnPyLTgB3DP/4lUf5X51MTTQ8LnI1ypvh+pIki9Sdm3QS33lOOZk149tdpdDk6ozyx/DEcvq74EMpoo2SuAIi5LkKVDrXuehvGA/WeXtpmuPgqRFdIA+JBlA3knHk5XEQY/k2Y31gq5oCwNL9iT9OAZqVkukE6EnvCXE9t2rAV4/snYilaf/UaO+ktgEwSbPBQ8YKlovDAarMBbGtgr6E174A9djlPyR+W/fgx8rlTwSWtieb9MkO8LN3KSxgVs0kY5U8OHg8QKBgQDljJq9kTFHare+W/fAXdUy3tJprfNQCAii6s+GuDfTQiviVQDtWmdtHAN+xU3to7MepvVhwHsqtQnZXKTtZuwwxn82FNl7A5RYD3GVFW+wG6AsGLIdESrWxySoL6Kx8QmNpMEVg8acT/ywzW/RnUXS5vU7GIi8GA0vtyBo24R9KQKBgQDIlf/R9+iNk9oXlbB/k4um9eVvBBS7l5cx4E5Id5Dpp4kGZfPZEa7oDsEUstZZM9mgQLJK/noNWbcf0+BohCR5ux7SC12qIoxwN3k4BzTDqrS8BzFuVVp5PELUsf/uCbRn05iMzpiDUhj3Vde04wvjHYIobfKlZO2HeSWXCpUH/wKBgQC8wSuU6ck90pEY5QMKmZ3wYK1g3PsQOirv3Gmde+nbu7PePsuuYQJfBAQTwCZeXJezgtKP+PjOm2Nn6vhrhpB9YxvD2s0ijET1TG23i5L1myHQYNZFdJJnXgXUjqcX7v5ODMYA7QTqEBPXRnbGRK7fx66rU3dMQ/LD46+wyaFeUQKBgA4QTk53dkuu6SSsLyLSwoDjTsHY5Gc+urAZjQORtoxbXcUgEtfOYJgOqMT9wP+iHgkZYCbX7tDO0IMfxOUvFqueTgvmFhwergAUM6CVCMMLTf689l9JBr3nVrw4+rvC3G5HLLP6rEDQ2cVFtIkPPj8fS4fwJYopKGpOOS9843QbAoGBAMoHH8LqoZ50FLsospx/hJe24Cd8wCgQTXSa/hMqNZ1999JDhftMt7R0ZdB1he2LReACe0K9ntBU4H4u225zZ3wZlyOfoyerAHuLK/ysNlgIIzblZlOxbBJ64Kul8leXzlYy3tOZuZ997KqBcWPCE3LUBBNvM6E3blJUnlmJAVoi");
|
alipayConfig.setPrivateKey("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCz3FkdffxZibdwis9W7eOW1dEjGAbSvRDL2ikfeCIW5KZNoIjUqxI0mIoUlLRRKO71QLHZS1Vb2aJp8jeOAqIPa8e76HTneQEzk3FGA8gpraSGvbadHWzvxnmYKsts1TBiEZQL82ySJXhQTJvZ6jyDM7s6wHHUnrH+Qi29QpppQ1sxsoJeCtajUgRg3btD6XbBcyFAX3pzM56Kw9eaIjZoD8WToZOM/Y3sqNL2uo8lLqcIpTrI7Pq5ZOspmBQ+t8v3rS9IdDZZMvd0trzS67AXwHz8rKPBT/lL1A4iHnXCHUvktusX1fPs3/RGY/a7PIddaBLnfY0GcueE16K7QcrXAgMBAAECggEAbSdT2eckp75BWoaTcGEs1tRqeM7TDT/6moyKmnOQ1K3tE31SrSYpBUxxuC3LBNo/sw2RIZtrcTOyMnPyLTgB3DP/4lUf5X51MTTQ8LnI1ypvh+pIki9Sdm3QS33lOOZk149tdpdDk6ozyx/DEcvq74EMpoo2SuAIi5LkKVDrXuehvGA/WeXtpmuPgqRFdIA+JBlA3knHk5XEQY/k2Y31gq5oCwNL9iT9OAZqVkukE6EnvCXE9t2rAV4/snYilaf/UaO+ktgEwSbPBQ8YKlovDAarMBbGtgr6E174A9djlPyR+W/fgx8rlTwSWtieb9MkO8LN3KSxgVs0kY5U8OHg8QKBgQDljJq9kTFHare+W/fAXdUy3tJprfNQCAii6s+GuDfTQiviVQDtWmdtHAN+xU3to7MepvVhwHsqtQnZXKTtZuwwxn82FNl7A5RYD3GVFW+wG6AsGLIdESrWxySoL6Kx8QmNpMEVg8acT/ywzW/RnUXS5vU7GIi8GA0vtyBo24R9KQKBgQDIlf/R9+iNk9oXlbB/k4um9eVvBBS7l5cx4E5Id5Dpp4kGZfPZEa7oDsEUstZZM9mgQLJK/noNWbcf0+BohCR5ux7SC12qIoxwN3k4BzTDqrS8BzFuVVp5PELUsf/uCbRn05iMzpiDUhj3Vde04wvjHYIobfKlZO2HeSWXCpUH/wKBgQC8wSuU6ck90pEY5QMKmZ3wYK1g3PsQOirv3Gmde+nbu7PePsuuYQJfBAQTwCZeXJezgtKP+PjOm2Nn6vhrhpB9YxvD2s0ijET1TG23i5L1myHQYNZFdJJnXgXUjqcX7v5ODMYA7QTqEBPXRnbGRK7fx66rU3dMQ/LD46+wyaFeUQKBgA4QTk53dkuu6SSsLyLSwoDjTsHY5Gc+urAZjQORtoxbXcUgEtfOYJgOqMT9wP+iHgkZYCbX7tDO0IMfxOUvFqueTgvmFhwergAUM6CVCMMLTf689l9JBr3nVrw4+rvC3G5HLLP6rEDQ2cVFtIkPPj8fS4fwJYopKGpOOS9843QbAoGBAMoHH8LqoZ50FLsospx/hJe24Cd8wCgQTXSa/hMqNZ1999JDhftMt7R0ZdB1he2LReACe0K9ntBU4H4u225zZ3wZlyOfoyerAHuLK/ysNlgIIzblZlOxbBJ64Kul8leXzlYy3tOZuZ997KqBcWPCE3LUBBNvM6E3blJUnlmJAVoi");
|
||||||
defaultClient.setAlipayConfig(alipayConfig);
|
defaultClient.setAlipayConfig(alipayConfig);
|
||||||
log.info("dd: {}", JSONObject.toJSONString(alipayConfig));
|
|
||||||
AlipayOpenAgentApi api = new AlipayOpenAgentApi();
|
AlipayOpenAgentApi api = new AlipayOpenAgentApi();
|
||||||
AlipayOpenAgentCreateModel data = new AlipayOpenAgentCreateModel();
|
AlipayOpenAgentCreateModel data = new AlipayOpenAgentCreateModel();
|
||||||
ContactModel contactInfo = new ContactModel();
|
ContactModel contactInfo = new ContactModel();
|
||||||
|
|||||||
@@ -1,239 +0,0 @@
|
|||||||
package com.czg.third.alipay;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.alipay.v3.ApiException;
|
|
||||||
import com.alipay.v3.api.*;
|
|
||||||
import com.alipay.v3.model.*;
|
|
||||||
import com.czg.PayCst;
|
|
||||||
import com.czg.dto.req.*;
|
|
||||||
import com.czg.dto.resp.EntryThirdRespDto;
|
|
||||||
import com.czg.dto.resp.QueryStatusResp;
|
|
||||||
import com.czg.exception.CzgException;
|
|
||||||
import com.czg.third.alipay.dto.config.AlipayConfigDto;
|
|
||||||
import com.czg.utils.UploadFileUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付宝服务商进件管理
|
|
||||||
* <a href="https://opendocs.alipay.com/open-v3/b4c46445_alipay.open.agent.create?scene=common&pathHash=d7084b4b">...</a>
|
|
||||||
* @author yjjie
|
|
||||||
* @date 2026/1/8 13:34
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class AlipayIsvEntryManager {
|
|
||||||
|
|
||||||
private static final String ERR_MESSAGE_KEY = "message";
|
|
||||||
|
|
||||||
public static QueryStatusResp queryMerchantBatchStatus(AlipayConfigDto configDto, String batchNo) {
|
|
||||||
QueryStatusResp respDto = new QueryStatusResp()
|
|
||||||
.setPlatform(PayCst.Platform.ALIPAY);
|
|
||||||
AlipayClient.setApiClient(configDto);
|
|
||||||
|
|
||||||
try {
|
|
||||||
AlipayOpenAgentOrderApi api = new AlipayOpenAgentOrderApi();
|
|
||||||
AlipayOpenAgentOrderQueryResponseModel response = api.query(batchNo);
|
|
||||||
|
|
||||||
log.info("支付宝查询进件状态: 响应={}", response);
|
|
||||||
respDto.setApplyId(batchNo);
|
|
||||||
|
|
||||||
switch (response.getOrderStatus()) {
|
|
||||||
case "MERCHANT_INFO_HOLD" -> {
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
|
||||||
respDto.setFailReason("三方异常,请重新提交");
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
case "MERCHANT_CONFIRM_TIME_OUT" -> {
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
|
||||||
respDto.setFailReason("商户确认超时,请重新提交");
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
case "MERCHANT_AUDITING" -> {
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.AUDIT);
|
|
||||||
respDto.setFailReason("");
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
case "MERCHANT_CONFIRM" -> {
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.SIGN);
|
|
||||||
respDto.setFailReason("");
|
|
||||||
respDto.setSignUrl(response.getConfirmUrl());
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
case "MERCHANT_APPLY_ORDER_CANCELED" -> {
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
|
||||||
respDto.setFailReason(response.getRejectReason());
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
case "MERCHANT_CONFIRM_SUCCESS" -> {
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.FINISH);
|
|
||||||
respDto.setFailReason("");
|
|
||||||
respDto.setThirdMerchantId(response.getMerchantPid());
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
case null -> {
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
|
||||||
respDto.setFailReason("查询失败");
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
default -> {
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (ApiException e) {
|
|
||||||
String body = e.getResponseBody();
|
|
||||||
log.error("支付宝查询进件状态异常: {}", body);
|
|
||||||
JSONObject object = JSONObject.parseObject(body);
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
|
||||||
respDto.setFailReason(object.getString(ERR_MESSAGE_KEY));
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建商户
|
|
||||||
* @param configDto 配置信息
|
|
||||||
* @param reqDto 请求信息
|
|
||||||
*/
|
|
||||||
public static EntryThirdRespDto entryMerchant(AlipayConfigDto configDto, AggregateMerchantDto reqDto) {
|
|
||||||
AlipayClient.setApiClient(configDto);
|
|
||||||
EntryThirdRespDto respDto = new EntryThirdRespDto()
|
|
||||||
.setPlatform(PayCst.Platform.ALIPAY);
|
|
||||||
try {
|
|
||||||
String batchNo = createRequest(reqDto);
|
|
||||||
|
|
||||||
AlipayOpenAgentFacetofaceSignModel signModel = buildFaceToFaceModel(reqDto, batchNo);
|
|
||||||
File businessLicensePic = UploadFileUtil.getFileByUrl(reqDto.getBusinessLicenceInfo().getLicensePic().getUrl());
|
|
||||||
File shopScenePic = UploadFileUtil.getFileByUrl(reqDto.getStoreInfo().getInsidePic().getUrl());
|
|
||||||
File shopSignBoardPic = UploadFileUtil.getFileByUrl(reqDto.getStoreInfo().getDoorPic().getUrl());
|
|
||||||
|
|
||||||
// 构造请求参数以调用接口
|
|
||||||
AlipayOpenAgentFacetofaceApi api = new AlipayOpenAgentFacetofaceApi();
|
|
||||||
Object response = api.sign(null, businessLicensePic, signModel, shopScenePic, shopSignBoardPic, null);
|
|
||||||
log.info("支付宝开启代商户签约: 响应={}", JSONObject.toJSONString(response));
|
|
||||||
|
|
||||||
try {
|
|
||||||
String orderNo = confirmRequest(batchNo);
|
|
||||||
respDto.setEntryId(orderNo);
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.INIT);
|
|
||||||
respDto.setErrorMsg("");
|
|
||||||
return respDto;
|
|
||||||
} catch (CzgException e) {
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
|
||||||
respDto.setErrorMsg(e.getMessage());
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
} catch (ApiException e) {
|
|
||||||
String body = e.getResponseBody();
|
|
||||||
log.error("支付宝开启代商户签约,创建应用事务异常: {}", body);
|
|
||||||
JSONObject object = JSONObject.parseObject(body);
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
|
||||||
respDto.setErrorMsg(object.getString(ERR_MESSAGE_KEY));
|
|
||||||
return respDto;
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("上传图片出错", e);
|
|
||||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
|
||||||
respDto.setErrorMsg("上传图片出错");
|
|
||||||
return respDto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开启代商户签约、创建应用事务
|
|
||||||
* @param reqDto 请求信息
|
|
||||||
* @return 请求ID
|
|
||||||
*/
|
|
||||||
public static String createRequest(AggregateMerchantDto reqDto) {
|
|
||||||
AlipayOpenAgentApi api = new AlipayOpenAgentApi();
|
|
||||||
AlipayOpenAgentCreateModel openModel = new AlipayOpenAgentCreateModel();
|
|
||||||
|
|
||||||
MerchantBaseInfoDto info = reqDto.getMerchantBaseInfo();
|
|
||||||
LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
|
|
||||||
String contactPersonType = info.getContactPersonType();
|
|
||||||
boolean isSuper = PayCst.ContactPersonType.SUPER.equals(contactPersonType);
|
|
||||||
|
|
||||||
ContactModel contactModel = new ContactModel();
|
|
||||||
// 联系人名称
|
|
||||||
contactModel.setContactName(isSuper ? info.getContactName() : legalPersonInfo.getLegalPersonName());
|
|
||||||
// 联系人手机号码
|
|
||||||
contactModel.setContactMobile(isSuper ? info.getContactPhone() : legalPersonInfo.getLegalPersonPhone());
|
|
||||||
// 联系人邮箱
|
|
||||||
contactModel.setContactEmail(isSuper ? info.getContactEmail() : legalPersonInfo.getLegalPersonEmail());
|
|
||||||
openModel.setContactInfo(contactModel);
|
|
||||||
|
|
||||||
openModel.setAccount(reqDto.getMerchantBaseInfo().getAlipayAccount());
|
|
||||||
|
|
||||||
try {
|
|
||||||
AlipayOpenAgentCreateResponseModel responseModel = api.create(openModel);
|
|
||||||
log.info("支付宝开启代商户签约,开启事务: 结果={}, batchNo={}", responseModel.getBatchStatus(), responseModel.getBatchNo());
|
|
||||||
return responseModel.getBatchNo();
|
|
||||||
} catch (ApiException e) {
|
|
||||||
String body = e.getResponseBody();
|
|
||||||
log.error("支付宝开启代商户签约,开启事务异常: {}", body);
|
|
||||||
JSONObject object = JSONObject.parseObject(body);
|
|
||||||
throw new CzgException("支付宝开启代商户签约,开启事务异常: " + object.getString(ERR_MESSAGE_KEY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String confirmRequest(String batchNo) {
|
|
||||||
AlipayClient.setApiClient(null);
|
|
||||||
// 构造请求参数以调用接口
|
|
||||||
AlipayOpenAgentCommonsignApi api = new AlipayOpenAgentCommonsignApi();
|
|
||||||
AlipayOpenAgentCommonsignConfirmModel data = new AlipayOpenAgentCommonsignConfirmModel();
|
|
||||||
|
|
||||||
// 设置ISV 代商户操作事务编号
|
|
||||||
data.setBatchNo(batchNo);
|
|
||||||
try {
|
|
||||||
AlipayOpenAgentCommonsignConfirmResponseModel response = api.confirm(data);
|
|
||||||
log.info("支付宝开启代商户签约,确认事务: 响应={}", response);
|
|
||||||
return response.getOrderNo();
|
|
||||||
} catch (ApiException e) {
|
|
||||||
String body = e.getResponseBody();
|
|
||||||
log.error("支付宝开启代商户签约,确认事务异常: {}", body);
|
|
||||||
JSONObject object = JSONObject.parseObject(body);
|
|
||||||
throw new CzgException(object.getString(ERR_MESSAGE_KEY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建 当面付参数
|
|
||||||
*/
|
|
||||||
public static AlipayOpenAgentFacetofaceSignModel buildFaceToFaceModel(AggregateMerchantDto reqDto, String batchNo) {
|
|
||||||
AlipayOpenAgentFacetofaceSignModel signModel = new AlipayOpenAgentFacetofaceSignModel();
|
|
||||||
signModel.setBatchNo(batchNo);
|
|
||||||
|
|
||||||
MerchantBaseInfoDto baseInfo = reqDto.getMerchantBaseInfo();
|
|
||||||
LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
|
|
||||||
BusinessLicenceInfoDto licenceInfo = reqDto.getBusinessLicenceInfo();
|
|
||||||
StoreInfoDto storeInfo = reqDto.getStoreInfo();
|
|
||||||
|
|
||||||
signModel.setMccCode(baseInfo.getMccCode());
|
|
||||||
signModel.setRate("0.38");
|
|
||||||
signModel.setSignAndAuth(true);
|
|
||||||
|
|
||||||
signModel.setBusinessLicenseNo(licenceInfo.getLicenceNo());
|
|
||||||
signModel.setBusinessLicenseMobile(legalPersonInfo.getLegalPersonPhone());
|
|
||||||
signModel.setLongTerm(PayCst.LONG_TERM_DATE.equals(licenceInfo.getLicenceEndDate()));
|
|
||||||
signModel.setDateLimitation(licenceInfo.getLicenceStartDate());
|
|
||||||
|
|
||||||
signModel.setShopName(baseInfo.getShortName());
|
|
||||||
|
|
||||||
// 设置店铺地址
|
|
||||||
SignAddressInfo shopAddress = new SignAddressInfo();
|
|
||||||
shopAddress.setCountryCode("156");
|
|
||||||
shopAddress.setDistrictCode(storeInfo.getMercAreaCode());
|
|
||||||
shopAddress.setDetailAddress(storeInfo.getBusinessAddress());
|
|
||||||
shopAddress.setProvinceCode(storeInfo.getMercProvCode());
|
|
||||||
shopAddress.setCityCode(storeInfo.getMercCityCode());
|
|
||||||
signModel.setShopAddress(shopAddress);
|
|
||||||
|
|
||||||
return signModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
// confirmRequest("2026010815384505500018243");
|
|
||||||
queryMerchantBatchStatus(null, "2026010815384505500018243");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
package com.czg.third.alipay;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alipay.api.AlipayApiException;
|
||||||
|
import com.alipay.api.AlipayConfig;
|
||||||
|
import com.alipay.api.DefaultAlipayClient;
|
||||||
|
import com.alipay.api.domain.*;
|
||||||
|
import com.alipay.api.request.AntMerchantExpandIndirectZftSimplecreateRequest;
|
||||||
|
import com.alipay.api.response.AntMerchantExpandIndirectZftSimplecreateResponse;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2026/1/5 13:46
|
||||||
|
*/
|
||||||
|
public class AlipayReqUtils {
|
||||||
|
public static void main(String[] args) throws AlipayApiException {
|
||||||
|
// DefaultAlipayClient defaultAlipayClient = AlipayClient.getDefaultClient(null);
|
||||||
|
// AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
|
||||||
|
DefaultAlipayClient defaultAlipayClient = new DefaultAlipayClient(getAlipayConfig());
|
||||||
|
|
||||||
|
// 构造请求参数以调用接口
|
||||||
|
AntMerchantExpandIndirectZftSimplecreateRequest request = new AntMerchantExpandIndirectZftSimplecreateRequest();
|
||||||
|
AntMerchantExpandIndirectZftSimplecreateModel model = new AntMerchantExpandIndirectZftSimplecreateModel();
|
||||||
|
|
||||||
|
// 设置商户编号
|
||||||
|
model.setExternalId("1052900599901941");
|
||||||
|
|
||||||
|
// 设置签约支付宝账户
|
||||||
|
model.setBindingAlipayLogonId("18434286340");
|
||||||
|
|
||||||
|
// 设置商户别名
|
||||||
|
model.setAliasName("一点点");
|
||||||
|
|
||||||
|
// 设置商户客服电话
|
||||||
|
// model.setServicePhone("0571-85022088");
|
||||||
|
|
||||||
|
// 设置商户联系人信息
|
||||||
|
ContactInfo contactInfos = new ContactInfo();
|
||||||
|
contactInfos.setIdCardNo("142725199902176419");
|
||||||
|
// contactInfos.setPhone("0571-85022088");
|
||||||
|
contactInfos.setName("王伟");
|
||||||
|
contactInfos.setMobile("18434286340");
|
||||||
|
contactInfos.setEmail("18434286340");
|
||||||
|
model.setContactInfos(contactInfos);
|
||||||
|
|
||||||
|
// 设置进件的二级商户名称
|
||||||
|
model.setName("王伟");
|
||||||
|
|
||||||
|
// 设置默认结算规则
|
||||||
|
DefaultSettleRule defaultSettleRule = new DefaultSettleRule();
|
||||||
|
defaultSettleRule.setDefaultSettleType("alipayAccount");
|
||||||
|
defaultSettleRule.setDefaultSettleTarget("18434286340");
|
||||||
|
model.setDefaultSettleRule(defaultSettleRule);
|
||||||
|
|
||||||
|
// 设置结算支付宝账号
|
||||||
|
model.setAlipayLogonId("18434286340");
|
||||||
|
|
||||||
|
// 设置结算银行卡信息
|
||||||
|
SettleCardInfo bizCards = new SettleCardInfo();
|
||||||
|
bizCards.setAccountInstName("招商银行");
|
||||||
|
bizCards.setBankCode("103290003044");
|
||||||
|
bizCards.setAccountType("DC");
|
||||||
|
bizCards.setUsageType("01");
|
||||||
|
bizCards.setAccountHolderName("王伟");
|
||||||
|
bizCards.setAccountInstCity("杭州市");
|
||||||
|
bizCards.setAccountInstId("CMB");
|
||||||
|
bizCards.setAccountNo("6214831259609102");
|
||||||
|
bizCards.setAccountBranchName("招商银行杭州高新支行");
|
||||||
|
bizCards.setAccountInstProvince("浙江省");
|
||||||
|
model.setBizCards(bizCards);
|
||||||
|
|
||||||
|
// 设置授权函
|
||||||
|
model.setLicenseAuthLetterImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||||
|
|
||||||
|
// 设置开票资料信息
|
||||||
|
// MerchantInvoiceInfo invoiceInfo = new MerchantInvoiceInfo();
|
||||||
|
// invoiceInfo.setMailTelephone("057162288888");
|
||||||
|
// invoiceInfo.setTaxPayerQualification("01");
|
||||||
|
// invoiceInfo.setAddress("浙江省杭州市西湖区西溪路蚂蚁金服");
|
||||||
|
// invoiceInfo.setAcceptElectronic(false);
|
||||||
|
// invoiceInfo.setTelephone("057162288888");
|
||||||
|
// invoiceInfo.setTitle("蚂蚁金服(杭州)信息技术有限公司");
|
||||||
|
// invoiceInfo.setMailName("张三");
|
||||||
|
// invoiceInfo.setAutoInvoice(true);
|
||||||
|
// invoiceInfo.setTaxPayerValid("19981011");
|
||||||
|
// invoiceInfo.setTaxNo("51010482542598631219");
|
||||||
|
// invoiceInfo.setBankName("中国银行");
|
||||||
|
// AddressInfo mailAddress = new AddressInfo();
|
||||||
|
// mailAddress.setAddress("万塘路18号黄龙时代广场B座");
|
||||||
|
// mailAddress.setDistrictCode("371002");
|
||||||
|
// mailAddress.setLatitude("60.270001");
|
||||||
|
// mailAddress.setCityCode("371000");
|
||||||
|
// mailAddress.setPoiid("B0FFIVU189");
|
||||||
|
// mailAddress.setProvinceCode("370000");
|
||||||
|
// mailAddress.setLongitude("120.760001");
|
||||||
|
// invoiceInfo.setMailAddress(mailAddress);
|
||||||
|
// invoiceInfo.setBankAccount("1234567812345678123");
|
||||||
|
// model.setInvoiceInfo(invoiceInfo);
|
||||||
|
|
||||||
|
// 设置商户使用服务
|
||||||
|
List<String> service = new ArrayList<String>();
|
||||||
|
service.add("当面付");
|
||||||
|
model.setService(service);
|
||||||
|
|
||||||
|
// 设置经营地址
|
||||||
|
AddressInfo businessAddress = new AddressInfo();
|
||||||
|
businessAddress.setAddress("万塘路18号黄龙时代广场B座");
|
||||||
|
businessAddress.setDistrictCode("371002");
|
||||||
|
businessAddress.setLatitude("60.270001");
|
||||||
|
businessAddress.setCityCode("371000");
|
||||||
|
businessAddress.setPoiid("B0FFIVU189");
|
||||||
|
businessAddress.setProvinceCode("370000");
|
||||||
|
businessAddress.setType("BUSINESS_ADDRESS");
|
||||||
|
businessAddress.setLongitude("120.760001");
|
||||||
|
model.setBusinessAddress(businessAddress);
|
||||||
|
|
||||||
|
// 设置门头照
|
||||||
|
model.setOutDoorImages("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||||
|
|
||||||
|
// 设置内景照
|
||||||
|
model.setInDoorImages("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||||
|
|
||||||
|
// 设置商户站点信息
|
||||||
|
// SiteInfo sites = new SiteInfo();
|
||||||
|
// sites.setIcpOrgName("支付宝(中国)网络技术有限公司");
|
||||||
|
// sites.setSiteType("01");
|
||||||
|
// sites.setSiteDomain("www.alipay.com");
|
||||||
|
// sites.setScreenshotImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||||
|
// sites.setRemark("备注说明");
|
||||||
|
// sites.setAuthLetterImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||||
|
// sites.setSiteName("XXX网站");
|
||||||
|
// sites.setMarket("豌豆荚");
|
||||||
|
// sites.setPassword("测试密码");
|
||||||
|
// sites.setDownload("https://itunes.apple.com/cn/app/id333206289?mt=8");
|
||||||
|
// sites.setTinyAppId("2021004105652035");
|
||||||
|
// sites.setSiteUrl("https://open.alipay.com");
|
||||||
|
// sites.setIcpServiceName("支付宝");
|
||||||
|
// sites.setRemarkImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||||
|
// sites.setAccount("测试账号");
|
||||||
|
// sites.setIcpNo("沪ICP备15027489号-2");
|
||||||
|
// sites.setStatus("ONLINE");
|
||||||
|
// model.setSites(sites);
|
||||||
|
|
||||||
|
// 设置商户类别码 mcc
|
||||||
|
model.setMcc("B0007");
|
||||||
|
|
||||||
|
// 设置商户行业资质图片
|
||||||
|
List<IndustryQualificationInfo> qualifications = new ArrayList<IndustryQualificationInfo>();
|
||||||
|
IndustryQualificationInfo qualifications0 = new IndustryQualificationInfo();
|
||||||
|
qualifications0.setIndustryQualificationImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||||
|
qualifications0.setIndustryQualificationType("323");
|
||||||
|
qualifications.add(qualifications0);
|
||||||
|
model.setQualifications(qualifications);
|
||||||
|
|
||||||
|
// 设置补充证件号
|
||||||
|
model.setAdditionalCertNo("9133010608210550XR");
|
||||||
|
|
||||||
|
// 设置补充证件类型
|
||||||
|
model.setAdditionalCertType("201");
|
||||||
|
|
||||||
|
// 设置补充证件图片
|
||||||
|
model.setAdditionalCertImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||||
|
|
||||||
|
// uid参数未来计划废弃,存量商户可继续使用,新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。
|
||||||
|
// model.setInfoSourceUid("2088111122223333");
|
||||||
|
|
||||||
|
// 设置(平替原来的info_source_uid字段
|
||||||
|
// model.setInfoSourceOpenId("074a1CcTG1LelxKe4xQC0zgNdId0nxi95b5lsNpazWYoCo5");
|
||||||
|
|
||||||
|
// uid参数未来计划废弃,存量商户可继续使用,新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。
|
||||||
|
// model.setOverseaSettleAccount("2088111122223333");
|
||||||
|
|
||||||
|
// 设置(平替原来的oversea_settle_open_id字段
|
||||||
|
// model.setOverseaSettleOpenId("074a1CcTG1LelxKe4xQC0zgNdId0nxi95b5lsNpazWYoCo5");
|
||||||
|
|
||||||
|
// 设置二级商户与服务商的签约时间
|
||||||
|
model.setSignTimeWithIsv("2015-04-15");
|
||||||
|
|
||||||
|
// 设置代扣产品信息
|
||||||
|
ZFTWithholdingInfo zftWithholdingInfo = new ZFTWithholdingInfo();
|
||||||
|
zftWithholdingInfo.setWithholdingServiceFeatureName("GENERAL_WITHHOLDING_P");
|
||||||
|
zftWithholdingInfo.setSignScene("DEFAULT");
|
||||||
|
model.setZftWithholdingInfo(zftWithholdingInfo);
|
||||||
|
|
||||||
|
// 设置交易场景
|
||||||
|
List<String> tradeScene = new ArrayList<String>();
|
||||||
|
tradeScene.add("TINY_APP");
|
||||||
|
model.setTradeScene(tradeScene);
|
||||||
|
|
||||||
|
request.setBizModel(model);
|
||||||
|
// 第三方代调用模式下请设置app_auth_token
|
||||||
|
// request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
|
||||||
|
|
||||||
|
AntMerchantExpandIndirectZftSimplecreateResponse response = defaultAlipayClient.execute(request);
|
||||||
|
System.out.println(response.getBody());
|
||||||
|
|
||||||
|
if (response.isSuccess()) {
|
||||||
|
System.out.println("调用成功");
|
||||||
|
} else {
|
||||||
|
System.out.println("调用失败");
|
||||||
|
// sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
|
||||||
|
// String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
|
||||||
|
// System.out.println(diagnosisUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AlipayConfig getAlipayConfig() {
|
||||||
|
String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD48HaUoV7OH7os+9L01kHgxzwIhJick4OkFq4aHsntsXEJ J3gedhuEZtV8oHKZ30DPW12IJ4S8NXtpr8OWaqrAPFonf4wVaRY1d0yIAea57kfLEn9oOEEy4FzARgMNDkyxC+/3OUdGbLHpTjfVX3gusXsEhUDy1/WewihAkoNYF37+W3W/uVLzeWoPq0EcUbRv/G/t/p6gL69ltsMAiVFG4Q/Yk24YAN6lYgBPNLXUEwQ1Q+T+1omjfavHgvarKOp33z3JOUH+aGOmDsJ5Y9gyGtJzOCipAd8Zcv+T1ygsEzZYO1/gzcbPnfO1ShqStCHzssuw8FBVx2JdfQKXKMMNAgMBAAECggEAVTrO/pg5Q00titU1Jspsh67u6OOs9H605Ws2dI7yB8VmtAGlaJh7V1t14FN2qSP8poHbhhAxq9aLyGV7C3a9u09udnN+3J28EtYjh7VO732bavWMVXxdJjQWzWWrCb9JlpxFrlkYBA6W4w/6ob0sAqCVQ7jzwbEa0R4cde8ztOa5nysKSfr4YTSs0gqvoiC6fmg8eiRJraEQBoYz9VkKFtOhhh/4w5FhVcYQ2gQvZ3kK3QVuD1eJIQKlCtz8qaox9lXKDiZT4SCmnKshdUL0u5TYIcYeBjZmhJz0Q50KHcpZrCs5y7I0+vRBH3hU+TKSQt7ureymwhbwWMHScLV2gQKBgQD+58SHXhr5M8NGagAmTdsgmCnNv2kOYMd4STyPMY10SVwCv1Bk808ZuP+7e558J1b5/OuDLI5dLq6xrZ/1wLv1G++XqxI00hlFuWS5mUGJVcXotT1mw20rVeUILc7Qe3mLvbMGgfyKf4A7Qa5SSZ4bDeDTJYaFxyiQ281hMzDuPQKBgQD6AiL/Na2/uPH4CG6juwpjYvYVUcjK+7gbRwf3wWsWMpk90Z4ju2iUiP5c1J/oK9P+1T3PIr6M4Xjza8JJj+r9KC/PVB0gBv6vVM96cDpKUEy/UMpcn/T81vqj/Z+WEOODU8Ms6NiTTm+u9ldvpCjbu0u8M+9c0JeIyadJvSTFEQKBgQCsxmFyM3nq8YfpgU2qqNjfBeRH3faSVUy+nj1a/YZYjKS+A/i1BCnYUImeBVNN6chNV342ggvY4xxruDiU9Vcw8wd58O09Oi8BEIFSP6upL6cebUI6Fjo3xlegLJRiwV6INkNTJOYM5hD/mSxUACwXQFfkJipBINXBIgraWD1RLQKBgQCj49axWq0F6+WjZVOyPaD3uh37p9trRUxRhWTxw3fB23WdktaKMgbCqHOmwzP4bRLSEVQtf2dOz1gMqu14b8HqJvgAf/F/11YJ9hz09LEhmjZVjE68HZfqT7uK2W5OX8/lfXmK7TFcj6SjG5YB96lZMhTZ0WnufEd6QkdKDZYXIQKBgQD9GDTcIMbFwbEaKHnfZaTD3f876EGRgsgrCxwdEk7LBCRPwWo7yI929M4psIlpNwNeiyjBkBunWIVkpznp6qPtJqagIPUYesU4f5v6/okq5wcpaNKSkWbIvWVLaLGOiA1aeGJtbpMpyClbSr52puHpRRdvAiIEQ74yYh0JX8q96g==";
|
||||||
|
String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB";
|
||||||
|
AlipayConfig alipayConfig = new AlipayConfig();
|
||||||
|
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
|
||||||
|
alipayConfig.setAppId("2021004174605036");
|
||||||
|
alipayConfig.setPrivateKey(privateKey);
|
||||||
|
alipayConfig.setFormat("json");
|
||||||
|
alipayConfig.setAlipayPublicKey(alipayPublicKey);
|
||||||
|
alipayConfig.setCharset("UTF-8");
|
||||||
|
alipayConfig.setSignType("RSA2");
|
||||||
|
return alipayConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -34,15 +34,10 @@ public class AlipayConfigDto {
|
|||||||
|
|
||||||
public static AlipayConfigDto getDefaultConfig() {
|
public static AlipayConfigDto getDefaultConfig() {
|
||||||
return new AlipayConfigDto()
|
return new AlipayConfigDto()
|
||||||
.setAppId("2021006121646825")
|
.setAppId("2021004174605036")
|
||||||
.setPrivateKey("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCz3FkdffxZibdwis9W7eOW1dEjGAbSvRDL2ikfeCIW5KZNoIjUqxI0mIoUlLRRKO71QLHZS1Vb2aJp8jeOAqIPa8e76HTneQEzk3FGA8gpraSGvbadHWzvxnmYKsts1TBiEZQL82ySJXhQTJvZ6jyDM7s6wHHUnrH+Qi29QpppQ1sxsoJeCtajUgRg3btD6XbBcyFAX3pzM56Kw9eaIjZoD8WToZOM/Y3sqNL2uo8lLqcIpTrI7Pq5ZOspmBQ+t8v3rS9IdDZZMvd0trzS67AXwHz8rKPBT/lL1A4iHnXCHUvktusX1fPs3/RGY/a7PIddaBLnfY0GcueE16K7QcrXAgMBAAECggEAbSdT2eckp75BWoaTcGEs1tRqeM7TDT/6moyKmnOQ1K3tE31SrSYpBUxxuC3LBNo/sw2RIZtrcTOyMnPyLTgB3DP/4lUf5X51MTTQ8LnI1ypvh+pIki9Sdm3QS33lOOZk149tdpdDk6ozyx/DEcvq74EMpoo2SuAIi5LkKVDrXuehvGA/WeXtpmuPgqRFdIA+JBlA3knHk5XEQY/k2Y31gq5oCwNL9iT9OAZqVkukE6EnvCXE9t2rAV4/snYilaf/UaO+ktgEwSbPBQ8YKlovDAarMBbGtgr6E174A9djlPyR+W/fgx8rlTwSWtieb9MkO8LN3KSxgVs0kY5U8OHg8QKBgQDljJq9kTFHare+W/fAXdUy3tJprfNQCAii6s+GuDfTQiviVQDtWmdtHAN+xU3to7MepvVhwHsqtQnZXKTtZuwwxn82FNl7A5RYD3GVFW+wG6AsGLIdESrWxySoL6Kx8QmNpMEVg8acT/ywzW/RnUXS5vU7GIi8GA0vtyBo24R9KQKBgQDIlf/R9+iNk9oXlbB/k4um9eVvBBS7l5cx4E5Id5Dpp4kGZfPZEa7oDsEUstZZM9mgQLJK/noNWbcf0+BohCR5ux7SC12qIoxwN3k4BzTDqrS8BzFuVVp5PELUsf/uCbRn05iMzpiDUhj3Vde04wvjHYIobfKlZO2HeSWXCpUH/wKBgQC8wSuU6ck90pEY5QMKmZ3wYK1g3PsQOirv3Gmde+nbu7PePsuuYQJfBAQTwCZeXJezgtKP+PjOm2Nn6vhrhpB9YxvD2s0ijET1TG23i5L1myHQYNZFdJJnXgXUjqcX7v5ODMYA7QTqEBPXRnbGRK7fx66rU3dMQ/LD46+wyaFeUQKBgA4QTk53dkuu6SSsLyLSwoDjTsHY5Gc+urAZjQORtoxbXcUgEtfOYJgOqMT9wP+iHgkZYCbX7tDO0IMfxOUvFqueTgvmFhwergAUM6CVCMMLTf689l9JBr3nVrw4+rvC3G5HLLP6rEDQ2cVFtIkPPj8fS4fwJYopKGpOOS9843QbAoGBAMoHH8LqoZ50FLsospx/hJe24Cd8wCgQTXSa/hMqNZ1999JDhftMt7R0ZdB1he2LReACe0K9ntBU4H4u225zZ3wZlyOfoyerAHuLK/ysNlgIIzblZlOxbBJ64Kul8leXzlYy3tOZuZ997KqBcWPCE3LUBBNvM6E3blJUnlmJAVoi")
|
.setPrivateKey("MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD48HaUoV7OH7os+9L01kHgxzwIhJick4OkFq4aHsntsXEJ J3gedhuEZtV8oHKZ30DPW12IJ4S8NXtpr8OWaqrAPFonf4wVaRY1d0yIAea57kfLEn9oOEEy4FzARgMNDkyxC+/3OUdGbLHpTjfVX3gusXsEhUDy1/WewihAkoNYF37+W3W/uVLzeWoPq0EcUbRv/G/t/p6gL69ltsMAiVFG4Q/Yk24YAN6lYgBPNLXUEwQ1Q+T+1omjfavHgvarKOp33z3JOUH+aGOmDsJ5Y9gyGtJzOCipAd8Zcv+T1ygsEzZYO1/gzcbPnfO1ShqStCHzssuw8FBVx2JdfQKXKMMNAgMBAAECggEAVTrO/pg5Q00titU1Jspsh67u6OOs9H605Ws2dI7yB8VmtAGlaJh7V1t14FN2qSP8poHbhhAxq9aLyGV7C3a9u09udnN+3J28EtYjh7VO732bavWMVXxdJjQWzWWrCb9JlpxFrlkYBA6W4w/6ob0sAqCVQ7jzwbEa0R4cde8ztOa5nysKSfr4YTSs0gqvoiC6fmg8eiRJraEQBoYz9VkKFtOhhh/4w5FhVcYQ2gQvZ3kK3QVuD1eJIQKlCtz8qaox9lXKDiZT4SCmnKshdUL0u5TYIcYeBjZmhJz0Q50KHcpZrCs5y7I0+vRBH3hU+TKSQt7ureymwhbwWMHScLV2gQKBgQD+58SHXhr5M8NGagAmTdsgmCnNv2kOYMd4STyPMY10SVwCv1Bk808ZuP+7e558J1b5/OuDLI5dLq6xrZ/1wLv1G++XqxI00hlFuWS5mUGJVcXotT1mw20rVeUILc7Qe3mLvbMGgfyKf4A7Qa5SSZ4bDeDTJYaFxyiQ281hMzDuPQKBgQD6AiL/Na2/uPH4CG6juwpjYvYVUcjK+7gbRwf3wWsWMpk90Z4ju2iUiP5c1J/oK9P+1T3PIr6M4Xjza8JJj+r9KC/PVB0gBv6vVM96cDpKUEy/UMpcn/T81vqj/Z+WEOODU8Ms6NiTTm+u9ldvpCjbu0u8M+9c0JeIyadJvSTFEQKBgQCsxmFyM3nq8YfpgU2qqNjfBeRH3faSVUy+nj1a/YZYjKS+A/i1BCnYUImeBVNN6chNV342ggvY4xxruDiU9Vcw8wd58O09Oi8BEIFSP6upL6cebUI6Fjo3xlegLJRiwV6INkNTJOYM5hD/mSxUACwXQFfkJipBINXBIgraWD1RLQKBgQCj49axWq0F6+WjZVOyPaD3uh37p9trRUxRhWTxw3fB23WdktaKMgbCqHOmwzP4bRLSEVQtf2dOz1gMqu14b8HqJvgAf/F/11YJ9hz09LEhmjZVjE68HZfqT7uK2W5OX8/lfXmK7TFcj6SjG5YB96lZMhTZ0WnufEd6QkdKDZYXIQKBgQD9GDTcIMbFwbEaKHnfZaTD3f876EGRgsgrCxwdEk7LBCRPwWo7yI929M4psIlpNwNeiyjBkBunWIVkpznp6qPtJqagIPUYesU4f5v6/okq5wcpaNKSkWbIvWVLaLGOiA1aeGJtbpMpyClbSr52puHpRRdvAiIEQ74yYh0JX8q96g==")
|
||||||
.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB")
|
.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB")
|
||||||
.setDomain("https://openapi.alipay.com");
|
.setDomain("https://openapi.alipay.com/gateway.do");
|
||||||
// return new AlipayConfigDto()
|
|
||||||
// .setAppId("2021004174605036")
|
|
||||||
// .setPrivateKey("MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD48HaUoV7OH7os+9L01kHgxzwIhJick4OkFq4aHsntsXEJ J3gedhuEZtV8oHKZ30DPW12IJ4S8NXtpr8OWaqrAPFonf4wVaRY1d0yIAea57kfLEn9oOEEy4FzARgMNDkyxC+/3OUdGbLHpTjfVX3gusXsEhUDy1/WewihAkoNYF37+W3W/uVLzeWoPq0EcUbRv/G/t/p6gL69ltsMAiVFG4Q/Yk24YAN6lYgBPNLXUEwQ1Q+T+1omjfavHgvarKOp33z3JOUH+aGOmDsJ5Y9gyGtJzOCipAd8Zcv+T1ygsEzZYO1/gzcbPnfO1ShqStCHzssuw8FBVx2JdfQKXKMMNAgMBAAECggEAVTrO/pg5Q00titU1Jspsh67u6OOs9H605Ws2dI7yB8VmtAGlaJh7V1t14FN2qSP8poHbhhAxq9aLyGV7C3a9u09udnN+3J28EtYjh7VO732bavWMVXxdJjQWzWWrCb9JlpxFrlkYBA6W4w/6ob0sAqCVQ7jzwbEa0R4cde8ztOa5nysKSfr4YTSs0gqvoiC6fmg8eiRJraEQBoYz9VkKFtOhhh/4w5FhVcYQ2gQvZ3kK3QVuD1eJIQKlCtz8qaox9lXKDiZT4SCmnKshdUL0u5TYIcYeBjZmhJz0Q50KHcpZrCs5y7I0+vRBH3hU+TKSQt7ureymwhbwWMHScLV2gQKBgQD+58SHXhr5M8NGagAmTdsgmCnNv2kOYMd4STyPMY10SVwCv1Bk808ZuP+7e558J1b5/OuDLI5dLq6xrZ/1wLv1G++XqxI00hlFuWS5mUGJVcXotT1mw20rVeUILc7Qe3mLvbMGgfyKf4A7Qa5SSZ4bDeDTJYaFxyiQ281hMzDuPQKBgQD6AiL/Na2/uPH4CG6juwpjYvYVUcjK+7gbRwf3wWsWMpk90Z4ju2iUiP5c1J/oK9P+1T3PIr6M4Xjza8JJj+r9KC/PVB0gBv6vVM96cDpKUEy/UMpcn/T81vqj/Z+WEOODU8Ms6NiTTm+u9ldvpCjbu0u8M+9c0JeIyadJvSTFEQKBgQCsxmFyM3nq8YfpgU2qqNjfBeRH3faSVUy+nj1a/YZYjKS+A/i1BCnYUImeBVNN6chNV342ggvY4xxruDiU9Vcw8wd58O09Oi8BEIFSP6upL6cebUI6Fjo3xlegLJRiwV6INkNTJOYM5hD/mSxUACwXQFfkJipBINXBIgraWD1RLQKBgQCj49axWq0F6+WjZVOyPaD3uh37p9trRUxRhWTxw3fB23WdktaKMgbCqHOmwzP4bRLSEVQtf2dOz1gMqu14b8HqJvgAf/F/11YJ9hz09LEhmjZVjE68HZfqT7uK2W5OX8/lfXmK7TFcj6SjG5YB96lZMhTZ0WnufEd6QkdKDZYXIQKBgQD9GDTcIMbFwbEaKHnfZaTD3f876EGRgsgrCxwdEk7LBCRPwWo7yI929M4psIlpNwNeiyjBkBunWIVkpznp6qPtJqagIPUYesU4f5v6/okq5wcpaNKSkWbIvWVLaLGOiA1aeGJtbpMpyClbSr52puHpRRdvAiIEQ74yYh0JX8q96g==")
|
|
||||||
// .setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB")
|
|
||||||
// .setDomain("https://openapi.alipay.com/gateway.do");
|
|
||||||
// return new AlipayConfigDto()
|
// return new AlipayConfigDto()
|
||||||
// .setAppId("2021004145625815")
|
// .setAppId("2021004145625815")
|
||||||
// .setPrivateKey("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCAjDBuS8K/IJb9ui+KuNm/sTUdEiaji4BNpZ92avO1N5JpNlGmac6ec4p3tNFT950sBLcQkClcUpQxUHQzAT6DYNNXOKyvfI/EmcqwCw6PaMNLs/8cV//J2WWZBUhLaOsjKurpm9/3W5MnTh4BGxIfBoeBMA8f8K3BgKdmyKtvIEV2h2cyjsMskdn+g6oNZcmWcms0pvpPHyH46mRaGFhpp0v19wX3WsamGldh1L2VntmaDN3C2XbSrXv90XYp5bEUqwTbLwXpMAlzTibF56d/iqv9oYi8cpAKougUFLOymnbutLNs2tLrEDSFwHcmG2/wbZHybZyYcIgFgv4arf+tAgMBAAECggEAf7hKKlw1y6Z6vvAtalxNZUuRZSfyog3p1bwYWxTavZPQcZ7Zs0lvVDmiO1u5m/7q96BbryY9IhCeUv0H5uF2lhwu/3s9AEL3qTPQkeb6eXxyhhX6A9RfPdM1Qbtg4CQHdHKg4qjP9znSVHwmDZ0y/QaEvdPdQzPjv92u9c2tn4N4x6XyBYcU5gzxiJNnIugCmBgcJo/3H2fgV+XXEhORPvy5of9b4oATHEaLS/8dAS2wuOjhzaGS4MXp3VkXn3XaYjwSzaL03qYWA+xm+aO5sJv8bmqZW7sNVck5o3sPo7cQ4VkBFVzyrRdmJcxcSRJ9MsB9JsrhoKI8pgaXrVie4QKBgQDU2vai0lpBIK/0jzRpPNoqdT8lnafnnWni8nU4kfAh+gCLi+HBPhQRT0kv4unQc2q2/gALE7sgZVO00JGY5a3R0orsojPoUSZlpypGW7GGqKy576NHn0nw4o/PdfysT92VWgt1hlfTf6qfCDhfE9APU+RGvlSWXcT8nxVel3iUaQKBgQCamoJN6+4v+chJvL2nqV8NVVRLp0vDIHxs1QOtKwUodx8Qp1D6CJYtavCXn8aNUFVNQJPJ7TQPpJjXP2rI4SN01weDwx+I+wh8PBGHV6/234R+6TvFgY1PrYgCdfNP4i/E7B4uyEhAxdU73PB8qkqRAeJGok05p7oG71KCOBiYpQKBgEZfGflcuDAeAW5GRhqg3rP4zWa/R7qgZVh9tll8jjp9b96y4XFE99d9MgId8BVVgyt6sEL5Q/2C4ni+F9TH4n6jMADp42VkJuCmsqhOOlP9whU67+2G8Sgtj0QUivPg964f9ffl8XVgGOW5DwIIB9p5btggptCLscufQK5kP545AoGADBvf6tR4wl8w9b2HqTMV08iEIqzGvVC1Dh0c/Zop/EJgN4CzUfIMOSBwGaAVAApzs+pD6QPgGP2OTwWTioo/qa4R05sbxDHNN1XJFa2jhZV6HiqMWOrNs5jm1zJ/zRjtHuJTdtyO9CvKiLbESy9XScY4/8lEfSiK5HIoJzTXkFUCgYAkYkvkW6psJpWj05XWq44UN0n6QOU/Igl35Um/iuOMVhsTmIt09STQVTuzJzfH82+sCqoRsD1blE5unKNUC1DK77aNKTv3Z0dxN9R7FAyfZRiYQXTrbBPBqWjay6FCNxn8e8UsJN4Z6FIV2LGlQI114krSap1MALKLVvnld0NaUQ==")
|
// .setPrivateKey("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCAjDBuS8K/IJb9ui+KuNm/sTUdEiaji4BNpZ92avO1N5JpNlGmac6ec4p3tNFT950sBLcQkClcUpQxUHQzAT6DYNNXOKyvfI/EmcqwCw6PaMNLs/8cV//J2WWZBUhLaOsjKurpm9/3W5MnTh4BGxIfBoeBMA8f8K3BgKdmyKtvIEV2h2cyjsMskdn+g6oNZcmWcms0pvpPHyH46mRaGFhpp0v19wX3WsamGldh1L2VntmaDN3C2XbSrXv90XYp5bEUqwTbLwXpMAlzTibF56d/iqv9oYi8cpAKougUFLOymnbutLNs2tLrEDSFwHcmG2/wbZHybZyYcIgFgv4arf+tAgMBAAECggEAf7hKKlw1y6Z6vvAtalxNZUuRZSfyog3p1bwYWxTavZPQcZ7Zs0lvVDmiO1u5m/7q96BbryY9IhCeUv0H5uF2lhwu/3s9AEL3qTPQkeb6eXxyhhX6A9RfPdM1Qbtg4CQHdHKg4qjP9znSVHwmDZ0y/QaEvdPdQzPjv92u9c2tn4N4x6XyBYcU5gzxiJNnIugCmBgcJo/3H2fgV+XXEhORPvy5of9b4oATHEaLS/8dAS2wuOjhzaGS4MXp3VkXn3XaYjwSzaL03qYWA+xm+aO5sJv8bmqZW7sNVck5o3sPo7cQ4VkBFVzyrRdmJcxcSRJ9MsB9JsrhoKI8pgaXrVie4QKBgQDU2vai0lpBIK/0jzRpPNoqdT8lnafnnWni8nU4kfAh+gCLi+HBPhQRT0kv4unQc2q2/gALE7sgZVO00JGY5a3R0orsojPoUSZlpypGW7GGqKy576NHn0nw4o/PdfysT92VWgt1hlfTf6qfCDhfE9APU+RGvlSWXcT8nxVel3iUaQKBgQCamoJN6+4v+chJvL2nqV8NVVRLp0vDIHxs1QOtKwUodx8Qp1D6CJYtavCXn8aNUFVNQJPJ7TQPpJjXP2rI4SN01weDwx+I+wh8PBGHV6/234R+6TvFgY1PrYgCdfNP4i/E7B4uyEhAxdU73PB8qkqRAeJGok05p7oG71KCOBiYpQKBgEZfGflcuDAeAW5GRhqg3rP4zWa/R7qgZVh9tll8jjp9b96y4XFE99d9MgId8BVVgyt6sEL5Q/2C4ni+F9TH4n6jMADp42VkJuCmsqhOOlP9whU67+2G8Sgtj0QUivPg964f9ffl8XVgGOW5DwIIB9p5btggptCLscufQK5kP545AoGADBvf6tR4wl8w9b2HqTMV08iEIqzGvVC1Dh0c/Zop/EJgN4CzUfIMOSBwGaAVAApzs+pD6QPgGP2OTwWTioo/qa4R05sbxDHNN1XJFa2jhZV6HiqMWOrNs5jm1zJ/zRjtHuJTdtyO9CvKiLbESy9XScY4/8lEfSiK5HIoJzTXkFUCgYAkYkvkW6psJpWj05XWq44UN0n6QOU/Igl35Um/iuOMVhsTmIt09STQVTuzJzfH82+sCqoRsD1blE5unKNUC1DK77aNKTv3Z0dxN9R7FAyfZRiYQXTrbBPBqWjay6FCNxn8e8UsJN4Z6FIV2LGlQI114krSap1MALKLVvnld0NaUQ==")
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.czg.third.alipay.dto.entry;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 经营地址
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2026/1/4 11:20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AlipayAddressReqDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 城市编码
|
||||||
|
* 蚂蚁店铺请按照蚂蚁店铺地区码 表格中填写。
|
||||||
|
* 直付通商户请按照直付通商户地区码 表格中内容填写。
|
||||||
|
*/
|
||||||
|
@JSONField(name = "city_code")
|
||||||
|
private String cityCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 区县编码
|
||||||
|
*/
|
||||||
|
@JSONField(name = "district_code")
|
||||||
|
private String districtCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 详细地址
|
||||||
|
*/
|
||||||
|
@JSONField(name = "address")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 省份编码
|
||||||
|
*/
|
||||||
|
@JSONField(name = "province_code")
|
||||||
|
private String provinceCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package com.czg.third.alipay.dto.entry;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结算银行卡信息
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2026/1/4 11:14
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AlipayBizCardsReqDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 开户支行名
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account_branch_name")
|
||||||
|
private String accountBranchName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 卡户名
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account_holder_name")
|
||||||
|
private String accountHolderName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 开户行所在地-省
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account_inst_province")
|
||||||
|
private String accountInstProvince;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 开户行所在地-市
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account_inst_city")
|
||||||
|
private String accountInstCity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 开户行简称缩写
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account_inst_id")
|
||||||
|
private String accountInstId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 银行名称
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account_inst_name")
|
||||||
|
private String accountInstName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 银行卡号
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account_no")
|
||||||
|
private String accountNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 银行卡类型
|
||||||
|
* 【枚举值】
|
||||||
|
* 借记卡: DC
|
||||||
|
* 信用卡: CC
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account_type")
|
||||||
|
private String accountType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 账号使用类型
|
||||||
|
* 【枚举值】
|
||||||
|
* 对公: 01
|
||||||
|
* 对私: 02
|
||||||
|
*/
|
||||||
|
@JSONField(name = "usage_type")
|
||||||
|
private String usageType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 联行号
|
||||||
|
*/
|
||||||
|
@JSONField(name = "bank_code")
|
||||||
|
private String bankCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.czg.third.alipay.dto.entry;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户联系人信息
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2026/1/4 11:02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AlipayContactInfoReqDto {
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 联系人名字
|
||||||
|
*/
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* email | mobile | phone 三选一
|
||||||
|
* 电子邮箱
|
||||||
|
*/
|
||||||
|
@JSONField(name = "email")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* email | mobile | phone 三选一
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
@JSONField(name = "mobile")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* email | mobile | phone 三选一
|
||||||
|
* 电话
|
||||||
|
*/
|
||||||
|
@JSONField(name = "phone")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 身份证号
|
||||||
|
*/
|
||||||
|
@JSONField(name = "id_card_no")
|
||||||
|
private String idCardNo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
package com.czg.third.alipay.dto.entry;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台商提交二级商户资料进行进件,完成二级商户入驻
|
||||||
|
* <a href="https://opendocs.alipay.com/solution/9434dd99_ant.merchant.expand.indirect.zft.simplecreate?scene=bf5951260023430e944c2e9afdf7f9e2&pathHash=d3136936">...</a>
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2025/12/29 14:19
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AlipayEntryReqDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 商户编号,由一级商户定义,保证在一级商户下唯一即可
|
||||||
|
*/
|
||||||
|
@JSONField(name = "external_id")
|
||||||
|
private String externalId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 商户别名。支付宝收银台及账单中的商户名称会展示此处设置的别名。如果涉及支付宝APP内的支付,支付结果页也会展示该别名;如果涉及线下当面付场景,请填写线下店铺名称
|
||||||
|
*/
|
||||||
|
@JSONField(name = "alias_name")
|
||||||
|
private String aliasName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 商户联系人信息。在本业务中,ContactInfo对象中联系人姓名、手机号必填,其他选填
|
||||||
|
*/
|
||||||
|
@JSONField(name = "contact_infos")
|
||||||
|
private AlipayContactInfoReqDto contactInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 默认结算规则。当调用收单接口,settle_info中设置默认结算规则(defaultSettle)时,交易资金将结算至此处设置的默认结算目标账户中。其详细描述及收单接口传参示例参考功能包文档
|
||||||
|
*/
|
||||||
|
@JSONField(name = "default_settle_rule")
|
||||||
|
private AlipaySettleRuleReqDto defaultSettleRule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 商户使用服务
|
||||||
|
* 可选值有:当面付、jsapi支付、app支付、wap支付、电脑支付、预授权支付、商户代扣、小程序支付、订单码支付。其值会影响其他字段必填性,详见其他字段描述
|
||||||
|
* 当面付: 当面付
|
||||||
|
* jsapi支付: jsapi支付
|
||||||
|
* app支付: app支付
|
||||||
|
* wap支付: wap支付
|
||||||
|
* 电脑支付: 电脑支付
|
||||||
|
* 预授权支付: 预授权支付
|
||||||
|
* 商户代扣: 商户代扣
|
||||||
|
* 小程序支付: 小程序支付
|
||||||
|
* 订单码支付: 订单码支付
|
||||||
|
*/
|
||||||
|
@JSONField(name = "service")
|
||||||
|
private List<String> service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 商户证件编号
|
||||||
|
* 按商户类型merchant_type的说明提供对应的证件编号
|
||||||
|
*/
|
||||||
|
@JSONField(name = "cert_no")
|
||||||
|
private String certNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 商户类别码 mcc
|
||||||
|
* <a href="https://mdn.alipayobjects.com/huamei_fctrxv/afts/file/A*3TMHRZ8ppa4AAAAAAAAAAAAADs2DAQ/%E8%BF%9B%E4%BB%B6MCC%E4%B8%8E%E8%B5%84%E8%B4%A8%E8%A6%81%E6%B1%82202212.xlsx">...</a>
|
||||||
|
* 可查看 进件MCC与资质要求 202212.xlsx,特殊行业要按照MCC说明中的资质一栏上传辅助资质,辅助资质要在 qualifications 中上传,会有人工审核。
|
||||||
|
* 【示例值】B0007
|
||||||
|
*/
|
||||||
|
@JSONField(name = "mcc")
|
||||||
|
private String mcc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 结算支付宝账号
|
||||||
|
* 结算账号使用支付宝账号时必填,本字段指定交易资金结算的具体支付宝账号,与binding_alipay_logon_id同主体的支付宝账号即可
|
||||||
|
*/
|
||||||
|
@JSONField(name = "alipay_logon_id")
|
||||||
|
private String alipayLogonId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 法人名称
|
||||||
|
* 非个人商户类型必填
|
||||||
|
*/
|
||||||
|
@JSONField(name = "legal_name")
|
||||||
|
private String legalName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 法人证件编号
|
||||||
|
* 法人证件编号,非个人商户类型必填
|
||||||
|
*/
|
||||||
|
@JSONField(name = "legal_cert_no")
|
||||||
|
private String legalCertNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 商户证件图
|
||||||
|
* 目前只有当商户类型是个人商户且使用当面付服务时才需填写
|
||||||
|
*/
|
||||||
|
@JSONField(name = "cert_image_back")
|
||||||
|
private String certImageBack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 商户证件图片
|
||||||
|
* 本业务接口中,如果是特殊行业必填;使用当面付服务时,非个人必填,个人结算到卡时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key。
|
||||||
|
*/
|
||||||
|
@JSONField(name = "cert_image")
|
||||||
|
private String certImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 进件的二级商户名称
|
||||||
|
* 一般情况下要与证件的名称相同。个体工商户类型可以放宽到法人名称
|
||||||
|
*/
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 法人证件类型
|
||||||
|
* 默认可不填,认为legal_cert_no是大陆身份证。类型包括:100 大陆身份证;105 港澳居民往来内地通行证;106 台湾同胞往来大陆通行证;108 外国人居留证
|
||||||
|
* 【枚举值】
|
||||||
|
* 大陆身份证: 100
|
||||||
|
* 港澳居民往来内地通行证: 105
|
||||||
|
* 台湾同胞往来大陆通行证: 106
|
||||||
|
* 外国人居留证: 108
|
||||||
|
*/
|
||||||
|
@JSONField(name = "legal_cert_type")
|
||||||
|
private String legalCertType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 商户类型
|
||||||
|
* 01:企业;cert_type填写201(营业执照);cert_no填写营业执照号;
|
||||||
|
* 02:事业单位:cert_type填写218(事业单位法人证书);cert_no填写事业单位法人证书编号;
|
||||||
|
* 03:民办非企业组织:cert_type填写204(民办非企业登记证书);cert_no填写民办非企业登记证书编号;
|
||||||
|
* 04:社会团体:cert_type填写206(社会团体法人登记证书);cert_no填写社会团体法人登记证书编号;
|
||||||
|
* 05:党政及国家机关:cert_type填写219(党政机关批准设立文件/行政执法主体资格证);cert_no填写党政机关批准设立文件/行政执法主体资格证编号;
|
||||||
|
* 06:个人商户:cert_type填写100(个人身份证);cert_no填写个人身份证号码;
|
||||||
|
* 07:个体工商户:cert_type填写201(营业执照);cert_no填写营业执照编号;
|
||||||
|
*/
|
||||||
|
@JSONField(name = "merchant_type")
|
||||||
|
private String merchantType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 商户证件类型
|
||||||
|
* 按商户类型merchant_type的说明提供对应的证件类型。
|
||||||
|
* 营业执照: 201
|
||||||
|
* 事业单位法人证书: 218
|
||||||
|
* 民办非企业登记证书: 204
|
||||||
|
* 社会团体法人登记证书: 206
|
||||||
|
* 党政机关批准设立文件/行政执法主体资格证: 219
|
||||||
|
* 个人身份证: 100
|
||||||
|
*/
|
||||||
|
@JSONField(name = "cert_type")
|
||||||
|
private String certType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 证件名称
|
||||||
|
* 目前只有个体工商户商户类型要求填入本字段,填写值为个体工商户营业执照上的名称
|
||||||
|
*/
|
||||||
|
@JSONField(name = "cert_name")
|
||||||
|
private String certName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 结算银行卡信息
|
||||||
|
* 结算银行卡信息,结算账号使用银行卡时必填。本业务当前只允许传入一张结算卡。个人类型商户不允许结算到银行卡
|
||||||
|
* 【必选条件】结算银行卡信息,结算账号使用银行卡时必填。本业务当前只允许传入一张结算卡。个人类型商户不允许结算到银行卡
|
||||||
|
*/
|
||||||
|
@JSONField(name = "biz_cards")
|
||||||
|
private AlipayBizCardsReqDto bizCards;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 经营地址
|
||||||
|
* 使用当面付服务时必填。地址对象中省、市、区、地址必填,其余选填
|
||||||
|
*/
|
||||||
|
@JSONField(name = "business_address")
|
||||||
|
private AlipayAddressReqDto businessAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 门头照
|
||||||
|
* 使用当面付服务时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key
|
||||||
|
*/
|
||||||
|
@JSONField(name = "out_door_images")
|
||||||
|
private String outDoorImages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 内景照
|
||||||
|
* 使用当面付服务时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key
|
||||||
|
*/
|
||||||
|
@JSONField(name = "in_door_images")
|
||||||
|
private String inDoorImages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 授权函
|
||||||
|
* <a href="https://opendocs.alipay.com/open/direct-payment/cg5mkp#%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99">《说明函》模板参考</a>
|
||||||
|
* 当商户名与结算卡户名不一致。《说明函》模板参考。涉及外籍法人(这种情况上传任意能证明身份的图片)时必填,
|
||||||
|
* 其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key。(商户类型为个体工商户时,本字段仅需上传营业执照非授权函)
|
||||||
|
*/
|
||||||
|
@JSONField(name = "license_auth_letter_image")
|
||||||
|
private String licenseAuthLetterImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 商户站点信息
|
||||||
|
* 包括网站、app、小程序。商户使用服务包含电脑支付、wap支付时,必须填充一个类型为01(网站)的SiteInfo对象,site_type/site_url/site_name必填;
|
||||||
|
* 当包含app支付时,必须至少填充类型为02(APP)或06(支付宝小程序)中一种类型的SiteInfo对象,site_type/site_name必填;当包含jsapi支付时,必须填充一个类型为06(支付宝小程序)的SiteInfo对象;
|
||||||
|
*/
|
||||||
|
@JSONField(name = "sites")
|
||||||
|
private AlipaySitesReqDto sites;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 商户行业资质图片
|
||||||
|
* 当商户的经营类目选择了特殊行业时该字段必填,需要特殊行业资质文件。每项行业资质信息中,industry_qualification_type和industry_qualification_image均必填。
|
||||||
|
*/
|
||||||
|
@JSONField(name = "qualifications")
|
||||||
|
private List<AlipayQualificationsReqDto> qualifications;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 交易场景
|
||||||
|
* 【枚举值】
|
||||||
|
* 小程序支付场景: TINY_APP
|
||||||
|
* H5场景: WAP
|
||||||
|
* 线下当面付场景: OFFLINE
|
||||||
|
* APP支付场景: APP
|
||||||
|
* 网站支付场景: PC
|
||||||
|
*/
|
||||||
|
@JSONField(name = "trade_scene")
|
||||||
|
private List<String> tradeScene;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.czg.third.alipay.dto.entry;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片上传
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2026/1/4 13:46
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class AlipayImageUploadReqDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 图片格式
|
||||||
|
* 支持格式:bmp、jpg、jpeg、png、gif.
|
||||||
|
*/
|
||||||
|
@JSONField(name = "image_type")
|
||||||
|
private String imageType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 图片二进制字节流
|
||||||
|
* 最大为10M
|
||||||
|
*/
|
||||||
|
@JSONField(name = "image_content")
|
||||||
|
private byte[] imageContent;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.czg.third.alipay.dto.entry;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户行业资质
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2026/1/4 11:40
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AlipayQualificationsReqDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 商户行业资质类型 具体选值参见 <a href="https://gw.alipayobjects.com/os/bmw-prod/7aa3a36b-2bc2-4d57-815f-08edd55ef67e.xlsx">文档</a>
|
||||||
|
* 【枚举值】
|
||||||
|
* 金融许可证: 323
|
||||||
|
* 【示例值】323
|
||||||
|
*/
|
||||||
|
@JSONField(name = "industry_qualification_type")
|
||||||
|
private String industryQualificationType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 商户行业资质图片
|
||||||
|
*/
|
||||||
|
@JSONField(name = "industry_qualification_image")
|
||||||
|
private String industryQualificationImage;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.czg.third.alipay.dto.entry;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结算规则
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2026/1/4 11:06
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AlipaySettleRuleReqDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 默认结算类型
|
||||||
|
* 可选值有bankCard/alipayAccount。bankCard表示结算到银行卡;alipayAccount表示结算到支付宝账号
|
||||||
|
*/
|
||||||
|
@JSONField(name = "default_settle_type")
|
||||||
|
private String defaultSettleType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 默认结算目标
|
||||||
|
* 当默认结算类型为bankCard时填写银行卡卡号,其值需在进件填写的结算银行卡范围内;当默认结算类型为alipayAccount时填写支付宝账号登录号,其值需在进件填写的结算支付宝账号范围内。
|
||||||
|
*/
|
||||||
|
@JSONField(name = "default_settle_target")
|
||||||
|
private String defaultSettleTarget;
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package com.czg.third.alipay.dto.entry;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2026/1/4 11:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AlipaySitesReqDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【必填】
|
||||||
|
* 网站类型
|
||||||
|
* 【枚举值】
|
||||||
|
* 网站: 01
|
||||||
|
* APP: 02
|
||||||
|
* 服务窗: 03
|
||||||
|
* 公众号: 04
|
||||||
|
* 其他: 05
|
||||||
|
* 支付宝小程序: 06
|
||||||
|
* 手机网站/H5: 07
|
||||||
|
*/
|
||||||
|
@JSONField(name = "site_type")
|
||||||
|
private String siteType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 站点地址
|
||||||
|
* 当传入service,且包含jsapi支付时,sites的site_type=06, site_url必填
|
||||||
|
*/
|
||||||
|
@JSONField(name = "site_url")
|
||||||
|
private String siteUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 站点名称
|
||||||
|
* 当传入service,且包含jsapi支付、小程序支付时,sites的site_type=06, site_name必填
|
||||||
|
*/
|
||||||
|
@JSONField(name = "site_name")
|
||||||
|
private String siteName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 截图照片
|
||||||
|
* 当传入交易场景trade_scene,且当传入trade_scene=WAP、trade_scene=APP、trade_scene=PC时该参数必传
|
||||||
|
*/
|
||||||
|
@JSONField(name = "screenshot_image")
|
||||||
|
private String screenshotImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 小程序appId
|
||||||
|
* 当传入service,且包含jsapi支付时,sites的site_type=06, tiny_app_id必填。
|
||||||
|
*/
|
||||||
|
@JSONField(name = "tiny_app_id")
|
||||||
|
private String tinyAppId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 测试账号
|
||||||
|
*/
|
||||||
|
@JSONField(name = "account")
|
||||||
|
private String account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 测试账号密码
|
||||||
|
*/
|
||||||
|
@JSONField(name = "password")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 上架状态
|
||||||
|
* 【枚举值】
|
||||||
|
* 已上线: ONLINE
|
||||||
|
* 已上线-内部: ONLINE_INNER
|
||||||
|
* 未上线: OFFLINE
|
||||||
|
*/
|
||||||
|
@JSONField(name = "status")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 授权函照片
|
||||||
|
*/
|
||||||
|
@JSONField(name = "auth_letter_image")
|
||||||
|
private String authLetterImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 备注说明
|
||||||
|
*/
|
||||||
|
@JSONField(name = "remark")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 备注说明图片
|
||||||
|
*/
|
||||||
|
@JSONField(name = "remark_image")
|
||||||
|
private String remarkImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 网站域名
|
||||||
|
*/
|
||||||
|
@JSONField(name = "site_domain")
|
||||||
|
private String siteDomain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* ICP备案主体信息服务名称
|
||||||
|
*/
|
||||||
|
@JSONField(name = "icp_service_name")
|
||||||
|
private String icpServiceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* ICP备案/许可证号
|
||||||
|
*/
|
||||||
|
@JSONField(name = "icp_no")
|
||||||
|
private String icpNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* ICP备案主体主办单位名称
|
||||||
|
*/
|
||||||
|
@JSONField(name = "icp_org_name")
|
||||||
|
private String icpOrgName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 下载地址
|
||||||
|
*/
|
||||||
|
@JSONField(name = "download")
|
||||||
|
private String download;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【选填】
|
||||||
|
* 应用市场
|
||||||
|
* 【示例值】豌豆荚
|
||||||
|
*/
|
||||||
|
@JSONField(name = "market")
|
||||||
|
private String market;
|
||||||
|
}
|
||||||
@@ -42,15 +42,15 @@ public class WechatEntryManager {
|
|||||||
* 查询商户进件状态
|
* 查询商户进件状态
|
||||||
*
|
*
|
||||||
* @param configDto 配置信息
|
* @param configDto 配置信息
|
||||||
* @param applyId 自系统的商户编号
|
* @param merchantCode 自系统的商户编号
|
||||||
* @return 进件状态
|
* @return 进件状态
|
||||||
*/
|
*/
|
||||||
public static QueryStatusResp queryMerchantEntryStatus(WechatPayConfigDto configDto, String applyId) {
|
public static QueryStatusResp queryMerchantEntryStatus(WechatPayConfigDto configDto, String merchantCode) {
|
||||||
QueryStatusResp queryStatusResp = new QueryStatusResp();
|
QueryStatusResp queryStatusResp = new QueryStatusResp();
|
||||||
queryStatusResp.setPlatform(PayCst.Platform.WECHAT);
|
queryStatusResp.setPlatform(PayCst.Platform.WECHAT);
|
||||||
queryStatusResp.setMerchantCode(applyId);
|
queryStatusResp.setMerchantCode(merchantCode);
|
||||||
|
|
||||||
String resp = WechatReqUtils.getReq(configDto, "/v3/applyment4sub/applyment/applyment_id/" + applyId, Map.of());
|
String resp = WechatReqUtils.getReq(configDto, "/v3/applyment4sub/applyment/business_code/" + merchantCode, Map.of());
|
||||||
JSONObject object = JSONObject.parseObject(resp);
|
JSONObject object = JSONObject.parseObject(resp);
|
||||||
JSONObject data = object.getJSONObject("data");
|
JSONObject data = object.getJSONObject("data");
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
|
|||||||
@@ -2,14 +2,10 @@ package com.czg.utils;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
import java.net.http.HttpResponse;
|
import java.net.http.HttpResponse;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,21 +33,6 @@ public class UploadFileUtil {
|
|||||||
return "png";
|
return "png";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据图片URL获取图片文件
|
|
||||||
*
|
|
||||||
* @param url 图片URL
|
|
||||||
* @return 图片文件
|
|
||||||
*/
|
|
||||||
public static File getFileByUrl(String url) throws IOException {
|
|
||||||
byte[] bytes = downloadImage(url);
|
|
||||||
|
|
||||||
Path tempFile = Files.createTempFile("image_", "." + extractImageExtension(url));
|
|
||||||
Files.write(tempFile, bytes);
|
|
||||||
|
|
||||||
return tempFile.toFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载图片
|
* 下载图片
|
||||||
* @param url 图片地址
|
* @param url 图片地址
|
||||||
|
|||||||
@@ -13,13 +13,11 @@ import com.czg.entity.CzgBaseRespParams;
|
|||||||
import com.czg.entity.req.*;
|
import com.czg.entity.req.*;
|
||||||
import com.czg.entity.resp.*;
|
import com.czg.entity.resp.*;
|
||||||
import com.czg.enums.CzgPayEnum;
|
import com.czg.enums.CzgPayEnum;
|
||||||
import com.czg.resp.CzgRespCode;
|
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
import com.czg.utils.AssertUtil;
|
import com.czg.utils.AssertUtil;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -37,10 +35,9 @@ public class CzgPayUtils {
|
|||||||
* @param domain 域名
|
* @param domain 域名
|
||||||
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
* CzgResult<CzgH5PayResp>
|
|
||||||
*/
|
*/
|
||||||
public static CzgResult<Map<String, Object>> h5Pay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgH5PayReq bizData) {
|
public static CzgResult<CzgH5PayResp> h5Pay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgH5PayReq bizData) {
|
||||||
return execPayResult(sendCzg(domain.concat(CzgPayEnum.H5PAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgH5PayResp.class));
|
return sendCzg(domain.concat(CzgPayEnum.H5PAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgH5PayResp.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,10 +46,9 @@ public class CzgPayUtils {
|
|||||||
* @param domain 域名
|
* @param domain 域名
|
||||||
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
* CzgResult<CzgJsPayResp>
|
|
||||||
*/
|
*/
|
||||||
public static CzgResult<Map<String, Object>> jsPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgJsPayReq bizData) {
|
public static CzgResult<CzgJsPayResp> jsPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgJsPayReq bizData) {
|
||||||
return execPayResult(sendCzg(domain.concat(CzgPayEnum.JSPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgJsPayResp.class));
|
return sendCzg(domain.concat(CzgPayEnum.JSPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgJsPayResp.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,10 +57,9 @@ public class CzgPayUtils {
|
|||||||
* @param domain 域名
|
* @param domain 域名
|
||||||
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
* CzgResult<CzgLtPayResp>
|
|
||||||
*/
|
*/
|
||||||
public static CzgResult<Map<String, Object>> ltPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgLtPayReq bizData) {
|
public static CzgResult<CzgLtPayResp> ltPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgLtPayReq bizData) {
|
||||||
return execPayResult(sendCzg(domain.concat(CzgPayEnum.LTPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgLtPayResp.class));
|
return sendCzg(domain.concat(CzgPayEnum.LTPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgLtPayResp.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,10 +68,9 @@ public class CzgPayUtils {
|
|||||||
* @param domain 域名
|
* @param domain 域名
|
||||||
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
* CzgResult<CzgScanPayResp>
|
|
||||||
*/
|
*/
|
||||||
public static CzgResult<Map<String, Object>> scanPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgScanPayReq bizData) {
|
public static CzgResult<CzgScanPayResp> scanPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgScanPayReq bizData) {
|
||||||
return execPayResult(sendCzg(domain.concat(CzgPayEnum.SCANPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgScanPayResp.class));
|
return sendCzg(domain.concat(CzgPayEnum.SCANPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgScanPayResp.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,10 +79,9 @@ public class CzgPayUtils {
|
|||||||
* @param domain 域名
|
* @param domain 域名
|
||||||
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
* CzgResult<CzgMicroPayResp>
|
|
||||||
*/
|
*/
|
||||||
public static CzgResult<Map<String, Object>> microPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgMicroPayReq bizData) {
|
public static CzgResult<CzgMicroPayResp> microPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgMicroPayReq bizData) {
|
||||||
return execPayResult(sendCzg(domain.concat(CzgPayEnum.MICROPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgMicroPayResp.class));
|
return sendCzg(domain.concat(CzgPayEnum.MICROPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgMicroPayResp.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -236,41 +229,51 @@ public class CzgPayUtils {
|
|||||||
}
|
}
|
||||||
return sortParam;
|
return sortParam;
|
||||||
}
|
}
|
||||||
private static CzgResult<Map<String, Object>> execPayResult(CzgResult<? extends CzgBaseResp> res) {
|
|
||||||
CzgResult<Map<String, Object>> result = CzgResult.success();
|
|
||||||
if (res.getCode() != 200 || res.getData() == null) {
|
|
||||||
result.setCode(500);
|
|
||||||
result.setMsg(res.getMsg());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CzgBaseResp data = res.getData();
|
|
||||||
|
|
||||||
Map<String, Object> map = new HashMap<>();
|
// public static void main(String[] args) {
|
||||||
switch (data) {
|
//// String appId = "66691a6afdf641f0bf1dc701";
|
||||||
case CzgMicroPayResp ignored -> {
|
// String appId = "66e3dd399a7621f45a6293c1";
|
||||||
if ("TRADE_SUCCESS".equals(data.getState())) {
|
//// String appSecret = "jikd52TefZcSPI5hRWrfPSpQcXZrbqshbnLmqH6UattqspIDEzjbGvZmfwTW58RMf1XuPhN4zE1GbIjKy3b1oabgOx5n79faT93Si6i7g2IPSQJAln2NNsCSNynHIJ8";
|
||||||
return result;
|
// String appSecret = "2p7TCixkN3FuhTqJyr23GNAfrqAqUt84T1IOSunCEEqFBP9gVkSO8CqrfNwNAJqLYuWmQou7lbwdW0Lb4zJVkBEdV7CPq3VhnbGDRIpQXpBNPOjJbor1IFGuLLOA7oll";
|
||||||
} else if ("TRADE_AWAIT".equals(data.getState())) {
|
// CzgJsPayReq bizData = new CzgJsPayReq("20250428150248328893", 100L,
|
||||||
result.setCode(CzgRespCode.WAIT_PAY.getCode());
|
// "订单支付", "or1l867cx6JFbLgmppwtG46AUhwg","1.80.211.145", "http://store.sxczgkj.com/h5/#/pages/user-order/user-order", "", "");
|
||||||
result.setMsg("等待用户付款");
|
// bizData.setCurrency("cny");
|
||||||
} else {
|
// bizData.setPayType("WECHAT");
|
||||||
result.setCode(CzgRespCode.FAILURE.getCode());
|
// bizData.setSubAppid("wxd88fffa983758a30");
|
||||||
}
|
//
|
||||||
}
|
// bizData.setSubject("订单支付");
|
||||||
case CzgH5PayResp h5PayResp ->
|
//// bizData.setStoreId("S2409148611");
|
||||||
map = JSONObject.parseObject(JSONObject.toJSONString(h5PayResp.getPayInfo()));
|
// bizData.setStoreId("S2406120331");
|
||||||
case CzgJsPayResp jsPayResp ->
|
//
|
||||||
map = JSONObject.parseObject(JSONObject.toJSONString(jsPayResp.getPayInfo()));
|
// CzgBaseReqParams params = CzgBaseReqParams.getInstance(appId, appSecret, bizData);
|
||||||
case CzgLtPayResp ltPayResp ->
|
// params.setVersion("1.0");
|
||||||
map = JSONObject.parseObject(JSONObject.toJSONString(ltPayResp.getPayInfo()));
|
// params.setReqId("57143686759273485473");
|
||||||
case CzgScanPayResp scanPayResp ->
|
// params.setReqTime("20250428150248");
|
||||||
map = JSONObject.parseObject(JSONObject.toJSONString(scanPayResp.getPayInfo()));
|
// params.setSignType("MD5");
|
||||||
default -> throw new IllegalStateException("Unexpected value: " + data);
|
// CzgResult<CzgH5PayResp> czgH5PayRespCzgResult = sendCzg("https://paymentapi.sxczgkj.cn/api/open/payment/jspay", params, CzgH5PayResp.class);
|
||||||
}
|
// System.out.println(czgH5PayRespCzgResult);
|
||||||
|
// }
|
||||||
|
|
||||||
result.setData(map);
|
|
||||||
|
|
||||||
return result;
|
// public static void main(String[] args) {
|
||||||
}
|
// CzgResult<Object> result = CzgResult.success();
|
||||||
|
// CzgBaseRespParams respParams = new CzgBaseRespParams();
|
||||||
|
// respParams.setCode("000000");
|
||||||
|
// respParams.setMsg("成功");
|
||||||
|
// respParams.setSign("6c0f1e11b0d3a16298c2dfeee8c1491a");
|
||||||
|
// respParams.setBizData("{\"amount\":500,\"currency\":\"cny\",\"ifCode\":\"lklspay\",\"mchOrderNo\":\"WX1889977729515615615\",\"mercNo\":\"B240612563201\",\"note\":\"成功\",\"payOrderId\":\"202502151890598483156443138V6W\",\"payType\":\"WECHAT\",\"settlementType\":\"D1\",\"state\":\"TRADE_SUCCESS\",\"storeId\":\"S2406125309\",\"subject\":\"超掌柜\",\"tradeFee\":2}");
|
||||||
|
// respParams.setTimestamp("20250215110620");
|
||||||
|
// log.info("超掌柜交易请求响应,{}", respParams);
|
||||||
|
//
|
||||||
|
// result.setCode("000000".equals(respParams.getCode()) ? 200 : Integer.parseInt(respParams.getCode()));
|
||||||
|
// result.setMsg(respParams.getMsg());
|
||||||
|
// if ("000000".equals(respParams.getCode()) && StrUtil.isNotBlank(respParams.getSign())) {
|
||||||
|
// if (validateSign(respParams.getSign(), JSONObject.toJSONString(respParams))) {
|
||||||
|
// log.info("验签失败");
|
||||||
|
// }
|
||||||
|
// result.setData(JSONObject.parseObject(respParams.getBizData(), CzgMicroPayResp.class));
|
||||||
|
// }
|
||||||
|
// System.out.println(JSONObject.toJSONString(result));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.czg.service.account.mapper;
|
||||||
|
|
||||||
|
import com.mybatisflex.core.BaseMapper;
|
||||||
|
import com.czg.account.entity.QuickMenu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 悬浮窗配置 映射层。
|
||||||
|
*
|
||||||
|
* @author ww
|
||||||
|
* @since 2025-12-29
|
||||||
|
*/
|
||||||
|
public interface QuickMenuMapper extends BaseMapper<QuickMenu> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,9 +14,9 @@ import com.czg.config.RedisCst;
|
|||||||
import com.czg.constants.ParamCodeCst;
|
import com.czg.constants.ParamCodeCst;
|
||||||
import com.czg.exception.CzgException;
|
import com.czg.exception.CzgException;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
|
import com.czg.service.RedisService;
|
||||||
import com.czg.service.account.mapper.CallQueueMapper;
|
import com.czg.service.account.mapper.CallQueueMapper;
|
||||||
import com.czg.service.account.mapper.CallTableMapper;
|
import com.czg.service.account.mapper.CallTableMapper;
|
||||||
import com.czg.service.account.util.FunUtil;
|
|
||||||
import com.czg.service.account.util.WechatMiniMsgUtil;
|
import com.czg.service.account.util.WechatMiniMsgUtil;
|
||||||
import com.czg.system.dto.SysParamsDTO;
|
import com.czg.system.dto.SysParamsDTO;
|
||||||
import com.czg.system.service.SysParamsService;
|
import com.czg.system.service.SysParamsService;
|
||||||
@@ -51,10 +51,10 @@ public class CallTableServiceImpl extends ServiceImpl<CallTableMapper, CallTable
|
|||||||
@Resource
|
@Resource
|
||||||
private ShopUserService shopUserService;
|
private ShopUserService shopUserService;
|
||||||
@Resource
|
@Resource
|
||||||
private FunUtil funUtil;
|
|
||||||
@Resource
|
|
||||||
private StringRedisTemplate stringRedisTemplate;
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
@Resource
|
@Resource
|
||||||
|
private RedisService redisService;
|
||||||
|
@Resource
|
||||||
private ShopInfoService shopInfoService;
|
private ShopInfoService shopInfoService;
|
||||||
@Resource
|
@Resource
|
||||||
private CallConfigService callConfigService;
|
private CallConfigService callConfigService;
|
||||||
@@ -228,13 +228,13 @@ public class CallTableServiceImpl extends ServiceImpl<CallTableMapper, CallTable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getCallNumber(Long shopId, CallTable callTable) {
|
private String getCallNumber(Long shopId, CallTable callTable) {
|
||||||
return funUtil.runFunAndCheckKey(() -> {
|
return redisService.runFunAndCheckKey(() -> {
|
||||||
String callNumKey = RedisCst.getTableCallNumKey(shopId, callTable.getId());
|
String callNumKey = RedisCst.getTableCallNumKey(shopId, callTable.getId());
|
||||||
String value = stringRedisTemplate.opsForValue().get(callNumKey);
|
String value = stringRedisTemplate.opsForValue().get(callNumKey);
|
||||||
AtomicReference<String> newVal = new AtomicReference<>("");
|
AtomicReference<String> newVal = new AtomicReference<>("");
|
||||||
// 初始化
|
// 初始化
|
||||||
if (StrUtil.isBlank(value)) {
|
if (StrUtil.isBlank(value)) {
|
||||||
Boolean setFlag = FunUtil.runFunAndRetry(() -> stringRedisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
|
Boolean setFlag = RedisService.runFunAndRetry(() -> stringRedisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
|
||||||
_ -> newVal.set(stringRedisTemplate.opsForValue().get(callNumKey)));
|
_ -> newVal.set(stringRedisTemplate.opsForValue().get(callNumKey)));
|
||||||
|
|
||||||
if (setFlag) {
|
if (setFlag) {
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.czg.service.account.service.impl;
|
||||||
|
|
||||||
|
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||||
|
import com.czg.account.entity.QuickMenu;
|
||||||
|
import com.czg.account.service.QuickMenuService;
|
||||||
|
import com.czg.service.account.mapper.QuickMenuMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 悬浮窗配置 服务层实现。
|
||||||
|
*
|
||||||
|
* @author ww
|
||||||
|
* @since 2025-12-29
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class QuickMenuServiceImpl extends ServiceImpl<QuickMenuMapper, QuickMenu> implements QuickMenuService{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -99,7 +99,7 @@ public class ShopInfoServiceImpl extends ServiceImpl<ShopInfoMapper, ShopInfo> i
|
|||||||
if (shopInfo == null) {
|
if (shopInfo == null) {
|
||||||
throw new CzgException("店铺不存在");
|
throw new CzgException("店铺不存在");
|
||||||
}
|
}
|
||||||
if (shopInfo.getExpireTime() != null && (DateUtil.date().toLocalDateTime().isAfter(shopInfo.getExpireTime()))) {
|
if (shopInfo.getExpireTime() != null && (LocalDateTime.now().isAfter(shopInfo.getExpireTime()))) {
|
||||||
throw new CzgException("店铺已过期,请联系商家");
|
throw new CzgException("店铺已过期,请联系商家");
|
||||||
}
|
}
|
||||||
if (SystemConstants.OneZero.ZERO == shopInfo.getOnSale() || shopInfo.getStatus() != SystemConstants.OneZero.ONE) {
|
if (SystemConstants.OneZero.ZERO == shopInfo.getOnSale() || shopInfo.getStatus() != SystemConstants.OneZero.ONE) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.czg.market.vo.InviteUserVO;
|
|||||||
import com.czg.market.vo.MemberConfigVO;
|
import com.czg.market.vo.MemberConfigVO;
|
||||||
import com.czg.order.entity.OrderInfo;
|
import com.czg.order.entity.OrderInfo;
|
||||||
import com.czg.service.account.mapper.ShopUserMapper;
|
import com.czg.service.account.mapper.ShopUserMapper;
|
||||||
|
import com.czg.utils.FunUtils;
|
||||||
import com.czg.utils.PageUtil;
|
import com.czg.utils.PageUtil;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
@@ -61,6 +62,7 @@ public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> i
|
|||||||
private MemberLevelConfigService memberLevelConfigService;
|
private MemberLevelConfigService memberLevelConfigService;
|
||||||
@DubboReference
|
@DubboReference
|
||||||
private TbMemberConfigService memberConfigService;
|
private TbMemberConfigService memberConfigService;
|
||||||
|
|
||||||
private ShopUser getUserInfo(Long shopUserId) {
|
private ShopUser getUserInfo(Long shopUserId) {
|
||||||
ShopUser shopUser = queryChain().eq(ShopUser::getId, shopUserId).one();
|
ShopUser shopUser = queryChain().eq(ShopUser::getId, shopUserId).one();
|
||||||
if (shopUser == null) {
|
if (shopUser == null) {
|
||||||
@@ -240,9 +242,13 @@ public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> i
|
|||||||
shopUser.setBirthDay(null);
|
shopUser.setBirthDay(null);
|
||||||
}
|
}
|
||||||
shopUser.setNickName(userInfo.getNickName());
|
shopUser.setNickName(userInfo.getNickName());
|
||||||
if (shopUser.getJoinTime() == null) {
|
// if (shopUser.getJoinTime() == null) {
|
||||||
shopUser.setJoinTime(LocalDateTime.now());
|
// shopUser.setJoinTime(LocalDateTime.now());
|
||||||
|
// }
|
||||||
|
boolean b = saveOrUpdate(shopUser);
|
||||||
|
if (b) {
|
||||||
|
FunUtils.transactionSafeRun(() -> memberConfigService.joinMemberByCondition(shopId, userId, shopUser));
|
||||||
}
|
}
|
||||||
return saveOrUpdate(shopUser);
|
return b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.czg.market.entity.MkPointsUser;
|
|||||||
import com.czg.market.entity.MkShopCouponRecord;
|
import com.czg.market.entity.MkShopCouponRecord;
|
||||||
import com.czg.market.service.MkPointsUserService;
|
import com.czg.market.service.MkPointsUserService;
|
||||||
import com.czg.market.service.MkShopCouponRecordService;
|
import com.czg.market.service.MkShopCouponRecordService;
|
||||||
|
import com.czg.market.service.TbMemberConfigService;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
import com.czg.service.RedisService;
|
import com.czg.service.RedisService;
|
||||||
import com.czg.service.account.mapper.ShopConfigMapper;
|
import com.czg.service.account.mapper.ShopConfigMapper;
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
package com.czg.service.account.util;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Administrator
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class FunUtil {
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
public static int retryCount = 5;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行任务并保证锁唯一
|
|
||||||
* @param supplier 业务逻辑
|
|
||||||
* @param lockKey Redis锁的Key
|
|
||||||
* @return 业务逻辑返回值
|
|
||||||
*/
|
|
||||||
public <T> T runFunAndCheckKey(Supplier<T> supplier, String lockKey) {
|
|
||||||
String lockValue = String.valueOf(System.nanoTime() + Thread.currentThread().threadId());
|
|
||||||
try {
|
|
||||||
// 尝试获取锁,超时时间 5 秒,防止死锁
|
|
||||||
boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
|
|
||||||
int count = 0;
|
|
||||||
// 初始等待 10ms
|
|
||||||
int retryDelay = 10;
|
|
||||||
|
|
||||||
while (!lock) {
|
|
||||||
// 最多重试 10 次,大约 10 秒
|
|
||||||
if (count++ > 50) {
|
|
||||||
throw new RuntimeException("系统繁忙, 稍后再试");
|
|
||||||
}
|
|
||||||
Thread.sleep(retryDelay);
|
|
||||||
// 指数退避,最大等待 200ms
|
|
||||||
retryDelay = Math.min(retryDelay * 2, 200);
|
|
||||||
lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行任务
|
|
||||||
return supplier.get();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
throw new RuntimeException("线程被中断", e);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("执行出错:{}", e.getMessage(), e);
|
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
// 释放锁(使用 Lua 脚本确保原子性)
|
|
||||||
unlock(lockKey, lockValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 Lua 脚本确保释放锁的原子性
|
|
||||||
* @param lockKey 锁的 Key
|
|
||||||
* @param lockValue 当前线程的锁值
|
|
||||||
*/
|
|
||||||
private void unlock(String lockKey, String lockValue) {
|
|
||||||
String luaScript =
|
|
||||||
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
|
|
||||||
"return redis.call('del', KEYS[1]) " +
|
|
||||||
"else return 0 end";
|
|
||||||
redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class),
|
|
||||||
Collections.singletonList(lockKey), lockValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T, R> R runFunAndRetry(
|
|
||||||
Supplier<R> function,
|
|
||||||
Function<R, Boolean> check, Consumer<R> errFun) {
|
|
||||||
log.info("工具类开始执行函数");
|
|
||||||
R result = function.get();
|
|
||||||
boolean flag = check.apply(result);
|
|
||||||
|
|
||||||
log.info("执行结果: {}", result);
|
|
||||||
|
|
||||||
while (flag && retryCount-- > 0) {
|
|
||||||
log.info("执行函数失败, 剩余尝试次数{}", retryCount);
|
|
||||||
result = function.get();
|
|
||||||
log.info("执行结果: {}", result);
|
|
||||||
flag = check.apply(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag) {
|
|
||||||
errFun.accept(result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.czg.service.account.mapper.QuickMenuMapper">
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
<if test="amount != null">
|
<if test="amount != null">
|
||||||
AND a.amount >= #{amount}
|
AND a.amount >= #{amount}
|
||||||
</if>
|
</if>
|
||||||
|
group by a.id
|
||||||
ORDER BY a.create_time DESC
|
ORDER BY a.create_time DESC
|
||||||
</select>
|
</select>
|
||||||
<select id="selectVipCard_COUNT" resultType="java.lang.Long">
|
<select id="selectVipCard_COUNT" resultType="java.lang.Long">
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
|
|||||||
private ShopUserService shopUserService;
|
private ShopUserService shopUserService;
|
||||||
@DubboReference
|
@DubboReference
|
||||||
private UserInfoService userInfoService;
|
private UserInfoService userInfoService;
|
||||||
@DubboReference
|
|
||||||
private OrderPaymentService orderPaymentService;
|
|
||||||
@Resource
|
@Resource
|
||||||
private OrderInfoService orderInfoService;
|
private OrderInfoService orderInfoService;
|
||||||
@DubboReference
|
@DubboReference
|
||||||
@@ -706,6 +704,16 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public void distributionUserAmount(MkDistributionFlow item, OrderInfo orderInfo) {
|
||||||
|
ShopUser shopUser = shopUserService.getById(item.getDistributionUserId());
|
||||||
|
updateShopInfoAmount(orderInfo.getShopId(), item.getRewardAmount().negate(), orderInfo.getId(), TableValueConstant.DistributionAmountFlow.Type.SUB, "分销扣减");
|
||||||
|
updateIncome(item.getRewardAmount().negate(), item.getRewardAmount(), BigDecimal.ZERO,
|
||||||
|
item.getDistributionUserId(), shopUser.getUserId(), item.getShopUserId(), item.getShopId(), item.getLevel());
|
||||||
|
distributionFlowService.updateById(item);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void distribute(Long sourceId, String orderNo, BigDecimal amount, Long sourceUserId, Long shopId, String type) {
|
public void distribute(Long sourceId, String orderNo, BigDecimal amount, Long sourceUserId, Long shopId, String type) {
|
||||||
MkDistributionDeliver deliver = new MkDistributionDeliver().setSourceId(sourceId).setOrderNo(orderNo).setShopId(shopId).setType(type).setStatus("success");
|
MkDistributionDeliver deliver = new MkDistributionDeliver().setSourceId(sourceId).setOrderNo(orderNo).setShopId(shopId).setType(type).setStatus("success");
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
|
|||||||
.shopId(pointsUser.getShopId())
|
.shopId(pointsUser.getShopId())
|
||||||
.shopUserId(pointsUser.getShopUserId())
|
.shopUserId(pointsUser.getShopUserId())
|
||||||
.floatType(PointsConstant.SUB.getValue())
|
.floatType(PointsConstant.SUB.getValue())
|
||||||
.floatPoints(floatPoints)
|
.floatPoints(-floatPoints)
|
||||||
.balancePoints(pointsUser.getPointBalance())
|
.balancePoints(pointsUser.getPointBalance())
|
||||||
.sourceId(orderId.toString())
|
.sourceId(orderId.toString())
|
||||||
.content(reason)
|
.content(reason)
|
||||||
|
|||||||
@@ -175,9 +175,9 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
|
|||||||
|
|
||||||
// 标准充值
|
// 标准充值
|
||||||
if (rechargeDetailId != null) {
|
if (rechargeDetailId != null) {
|
||||||
FunUtils.asyncSafeRunVoid(() -> {
|
|
||||||
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getById(rechargeDetailId);
|
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getById(rechargeDetailId);
|
||||||
shopUserMoneyEditDTO.setMoney(rechargeDetail.getAmount());
|
shopUserMoneyEditDTO.setMoney(rechargeDetail.getAmount());
|
||||||
|
FunUtils.asyncSafeRunVoid(() -> {
|
||||||
// 赠送金额
|
// 赠送金额
|
||||||
ShopUserMoneyEditDTO shopUserMoneyEditRewardDTO = new ShopUserMoneyEditDTO()
|
ShopUserMoneyEditDTO shopUserMoneyEditRewardDTO = new ShopUserMoneyEditDTO()
|
||||||
.setId(shopUserId)
|
.setId(shopUserId)
|
||||||
|
|||||||
@@ -361,6 +361,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
|||||||
memberExpFlowService.save(expFlow);
|
memberExpFlowService.save(expFlow);
|
||||||
|
|
||||||
upShopUser.setExperience(shopUser.getExperience() + exp);
|
upShopUser.setExperience(shopUser.getExperience() + exp);
|
||||||
|
shopUser.setExperience(upShopUser.getExperience());
|
||||||
// 修改会员等级
|
// 修改会员等级
|
||||||
MemberLevelConfig nextConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopUser.getMainShopId())
|
MemberLevelConfig nextConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopUser.getMainShopId())
|
||||||
.gt(MemberLevelConfig::getExperienceValue, levelVO.getExperienceValue()).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
|
.gt(MemberLevelConfig::getExperienceValue, levelVO.getExperienceValue()).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
|
||||||
|
|||||||
@@ -20,12 +20,7 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.czg</groupId>
|
<groupId>com.czg</groupId>
|
||||||
<artifactId>czg-pay</artifactId>
|
<artifactId>pay-service</artifactId>
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.czg</groupId>
|
|
||||||
<artifactId>aggregation-pay</artifactId>
|
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ package com.czg.service.order.dto;
|
|||||||
|
|
||||||
import com.czg.dto.req.*;
|
import com.czg.dto.req.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ww
|
* @author ww
|
||||||
*/
|
*/
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
@Data
|
||||||
public class AggregateMerchantVO extends AggregateMerchantDto{
|
public class AggregateMerchantVO extends AggregateMerchantDto{
|
||||||
|
|
||||||
@@ -26,11 +24,6 @@ public class AggregateMerchantVO extends AggregateMerchantDto{
|
|||||||
*/
|
*/
|
||||||
private String wechatStatus;
|
private String wechatStatus;
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付宝账号
|
|
||||||
*/
|
|
||||||
private String alipayAccount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信进件错误信息
|
* 微信进件错误信息
|
||||||
*/
|
*/
|
||||||
@@ -39,8 +32,6 @@ public class AggregateMerchantVO extends AggregateMerchantDto{
|
|||||||
* 微信进件签名地址
|
* 微信进件签名地址
|
||||||
*/
|
*/
|
||||||
private String wechatSignUrl;
|
private String wechatSignUrl;
|
||||||
private String wechatApplyId;
|
|
||||||
private String alipayOrderId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link com.czg.PayCst.EntryStatus}
|
* {@link com.czg.PayCst.EntryStatus}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.czg.service.order.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建订单
|
||||||
|
* @author ww
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CreateOrderDTO {
|
||||||
|
@NotBlank(message = "桌号不能为空")
|
||||||
|
private String tableCode;
|
||||||
|
@NotBlank(message = "用餐模式 堂食 dine-in 外带 take-out 外卖 take-away")
|
||||||
|
private String dineMode;
|
||||||
|
/**
|
||||||
|
* 平台类型
|
||||||
|
* 微信小程序 WX
|
||||||
|
* 支付宝小程序 ALI
|
||||||
|
* 收银机客户端 PC
|
||||||
|
* PC管理端 APC
|
||||||
|
* APP管理端 APP
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "平台类型不能为空")
|
||||||
|
private String platformType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否使用了霸王餐
|
||||||
|
*/
|
||||||
|
private boolean isFreeDine = false;
|
||||||
|
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
// 使用的积分抵扣数量
|
||||||
|
private Integer pointsNum;
|
||||||
|
|
||||||
|
// 使用的优惠券
|
||||||
|
@Valid
|
||||||
|
private List<UserCouponInfoDTO> userCouponInfos = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.czg.service.order.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.DecimalMin;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付接收参数 实体类
|
||||||
|
*
|
||||||
|
* @author ww
|
||||||
|
* @description
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RechargeDTO {
|
||||||
|
@NotNull(message = "店铺不能为空")
|
||||||
|
private Long shopId;
|
||||||
|
private Long shopUserId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充值金额id
|
||||||
|
*/
|
||||||
|
private Long rechargeDetailId;
|
||||||
|
@DecimalMin("0.01")
|
||||||
|
private BigDecimal amount;
|
||||||
|
private Integer allPack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转地址
|
||||||
|
*/
|
||||||
|
private String returnUrl;
|
||||||
|
/**
|
||||||
|
* 平台类型 pc 收银机客户端 wechat 微信小程序 alipay 支付宝小程序 admin-pc PC管理端 admin-app APP管理端
|
||||||
|
*/
|
||||||
|
private String platformType;
|
||||||
|
|
||||||
|
private String openId;
|
||||||
|
|
||||||
|
private String buyerRemark;
|
||||||
|
|
||||||
|
private String payType;
|
||||||
|
|
||||||
|
private Long orderId;
|
||||||
|
private Integer seatNum;
|
||||||
|
/**
|
||||||
|
* 用户端 使用 全打包 或者 全不打包
|
||||||
|
*/
|
||||||
|
private Integer userAllPack;
|
||||||
|
|
||||||
|
public boolean isAllPack() {
|
||||||
|
return allPack != null && allPack == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.czg.service.order.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UserCouponInfoDTO {
|
||||||
|
private Long userCouponId;
|
||||||
|
@Min(1)
|
||||||
|
private Integer num;
|
||||||
|
}
|
||||||
@@ -320,7 +320,7 @@ public interface ShopOrderStatisticMapper extends BaseMapper<ShopOrderStatistic>
|
|||||||
" `order`.shop_id = #{shopId} " +
|
" `order`.shop_id = #{shopId} " +
|
||||||
" and trade_day = #{tradeDay} " +
|
" and trade_day = #{tradeDay} " +
|
||||||
" and paid_time is not null" +
|
" and paid_time is not null" +
|
||||||
" order by detail.product_id, detail.sku_id")
|
" group by detail.product_id, detail.sku_id")
|
||||||
List<ProductCostAmountVO> getOrderDetailProduct(Long shopId, LocalDate tradeDay);
|
List<ProductCostAmountVO> getOrderDetailProduct(Long shopId, LocalDate tradeDay);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
package com.czg.service.order.print;
|
package com.czg.service.order.print;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.text.UnicodeUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.czg.account.dto.HandoverRecordDTO;
|
import com.czg.account.dto.HandoverRecordDTO;
|
||||||
import com.czg.account.entity.HandoverRecord;
|
|
||||||
import com.czg.account.entity.PrintMachine;
|
import com.czg.account.entity.PrintMachine;
|
||||||
import com.czg.account.entity.ShopInfo;
|
import com.czg.account.entity.ShopInfo;
|
||||||
import com.czg.account.service.ShopInfoService;
|
|
||||||
import com.czg.order.entity.OrderDetail;
|
import com.czg.order.entity.OrderDetail;
|
||||||
import com.czg.order.entity.OrderInfo;
|
import com.czg.order.entity.OrderInfo;
|
||||||
import com.czg.service.order.enums.OrderStatusEnums;
|
import com.czg.service.order.enums.OrderStatusEnums;
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
@@ -20,24 +21,21 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.stereotype.Component;
|
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 java.math.BigDecimal;
|
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.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Administrator
|
* @author Administrator
|
||||||
|
* 接口文档 <a href="https://help.feieyun.com/home/doc/zh;nav=1-1">
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||||
@Resource
|
|
||||||
private RestTemplate restTemplate;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ShopInfoService shopInfoService;
|
|
||||||
|
|
||||||
// API 地址
|
// API 地址
|
||||||
private static final String URL = "http://api.feieyun.cn/Api/Open/";
|
private static final String URL = "http://api.feieyun.cn/Api/Open/";
|
||||||
@@ -72,10 +70,8 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
String remark = orderDetail.getRemark();
|
String remark = orderDetail.getRemark();
|
||||||
String content = buildDishPrintData(false, getPickupNum(orderInfo), orderInfo.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
|
String content = buildDishPrintData(false, getPickupNum(orderInfo), orderInfo.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
|
||||||
orderDetail.getProductName(), orderDetail.getSkuName(), orderDetail.getNum(), remark, orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
orderDetail.getProductName(), orderDetail.getSkuName(), orderDetail.getNum(), remark, orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
||||||
Object o = sendPrintRequest(machine.getAddress(), content, null, "1");
|
String o = sendPrintRequest(machine.getAddress(), content, null, "1");
|
||||||
printMachineLogService.save(machine, "新订单", content, o);
|
printMachineLogService.save(orderInfo.getId(), machine, "新订单", content, o);
|
||||||
|
|
||||||
// printMachineLogService.save(machine, "新订单", , );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -84,8 +80,8 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
String remark = orderDetail.getRemark();
|
String remark = orderDetail.getRemark();
|
||||||
String content = buildDishPrintData(true, getPickupNum(orderInfo), orderInfo.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
|
String content = buildDishPrintData(true, getPickupNum(orderInfo), orderInfo.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
|
||||||
orderDetail.getProductName(), orderDetail.getSkuName(), orderDetail.getReturnNum(), remark, orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
orderDetail.getProductName(), orderDetail.getSkuName(), orderDetail.getReturnNum(), remark, orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
||||||
Object o = sendPrintRequest(machine.getAddress(), content, null, "1");
|
String o = sendPrintRequest(machine.getAddress(), content, null, "1");
|
||||||
printMachineLogService.save(machine, "退款单", content, o);
|
printMachineLogService.save(orderInfo.getId(), machine, "退款单", content, o);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,8 +102,8 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
.setRemark(orderInfo.getRemark())
|
.setRemark(orderInfo.getRemark())
|
||||||
.setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());
|
.setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());
|
||||||
String string = buildOrderPrintData(printInfoDTO, detailList);
|
String string = buildOrderPrintData(printInfoDTO, detailList);
|
||||||
Object o = sendPrintRequest(machine.getAddress(), string, null, printerNum);
|
String o = sendPrintRequest(machine.getAddress(), string, null, printerNum);
|
||||||
printMachineLogService.save(machine, "退款单", string, o);
|
printMachineLogService.save(orderInfo.getId(), machine, "结算单", string, o);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,15 +139,15 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String string = buildOrderPrintData(printInfoDTO, detailList);
|
String string = buildOrderPrintData(printInfoDTO, detailList);
|
||||||
Object resp = sendPrintRequest(machine.getAddress(), string, null, printerNum);
|
String resp = sendPrintRequest(machine.getAddress(), string, null, printerNum);
|
||||||
printMachineLogService.save(machine, "结算单", string, resp);
|
printMachineLogService.save(orderInfo.getId(), machine, "结算单", string, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) {
|
protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) {
|
||||||
String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一条新的排号记录\"}";
|
String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一条新的排号记录\"}";
|
||||||
String data = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime);
|
String data = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime);
|
||||||
Object resp = sendPrintRequest(machine.getAddress(), data, voiceJson, "1");
|
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, "1");
|
||||||
printMachineLogService.save(machine, "叫号单", data, resp);
|
printMachineLogService.save(machine, "叫号单", data, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +166,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R> R sendPrintRequest(String address, String metaPrintData, String voiceData, String printerNum) {
|
public String sendPrintRequest(String address, String metaPrintData, String voiceData, String printerNum) {
|
||||||
log.info("飞蛾打印机开始发送打印请求, 设备地址: {}, 元数据: {}", address, metaPrintData);
|
log.info("飞蛾打印机开始发送打印请求, 设备地址: {}, 元数据: {}", address, metaPrintData);
|
||||||
String time = String.valueOf(System.currentTimeMillis() / 1000);
|
String time = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||||
@@ -189,12 +185,68 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
|
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
|
||||||
|
|
||||||
String result = restTemplate.postForObject(URL, requestEntity, String.class);
|
String result = restTemplate.postForObject(URL, requestEntity, String.class);
|
||||||
log.info("打印结果: {}", result);
|
log.info("飞鹅打印结果: {}", result);
|
||||||
return (R) result;
|
return result;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("打印请求失败: {}", e.getMessage());
|
log.error("打印请求失败: {}", e.getMessage());
|
||||||
throw new RuntimeException("飞蛾打印请求失败", e);
|
throw new RuntimeException("飞蛾打印请求失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查飞鹅打印机 打印任务是否已打印
|
||||||
|
*
|
||||||
|
* @param printOrderId 打印订单编号
|
||||||
|
* @return null-未知错误,true-已打印,false-未打印
|
||||||
|
*/
|
||||||
|
public Boolean checkFPrintStatus(String printOrderId) {
|
||||||
|
String time = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
|
Map<String, Object> paramMap = new HashMap<>();
|
||||||
|
paramMap.put("user", USER);
|
||||||
|
paramMap.put("stime", time);
|
||||||
|
paramMap.put("sig", signature(time));
|
||||||
|
paramMap.put("apiname", "Open_queryOrderState");
|
||||||
|
paramMap.put("orderid", printOrderId);
|
||||||
|
Boolean ret;
|
||||||
|
try {
|
||||||
|
String resp = HttpUtil.post(URL, paramMap, 1000 * 5);
|
||||||
|
//成功 {"msg":"ok","ret":0,"data":true,"serverExecutedTime":4}
|
||||||
|
//失败 {"msg":"ok","ret":0,"data":false,"serverExecutedTime":4}
|
||||||
|
JSONObject json = JSONUtil.parseObj(UnicodeUtil.toString(resp));
|
||||||
|
log.info("飞鹅打印机 打印任务状态响应: {}", json);
|
||||||
|
ret = json.getBool("data");
|
||||||
|
} catch (Exception e) {
|
||||||
|
ret = null;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查飞鹅打印机是否在线
|
||||||
|
*
|
||||||
|
* @param sn 设备编号
|
||||||
|
* @return 在线,工作状态正常。/离线。/未知错误
|
||||||
|
*/
|
||||||
|
public String checkOnline(String sn) {
|
||||||
|
String time = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
|
Map<String, Object> paramMap = new HashMap<>();
|
||||||
|
paramMap.put("user", USER);
|
||||||
|
paramMap.put("stime", time);
|
||||||
|
paramMap.put("sig", signature(time));
|
||||||
|
paramMap.put("apiname", "Open_queryPrinterStatus");
|
||||||
|
paramMap.put("sn", sn);
|
||||||
|
String msg;
|
||||||
|
try {
|
||||||
|
String resp = HttpUtil.post(URL, paramMap, 1000 * 5);
|
||||||
|
//成功 开机 {"msg":"ok","ret":0,"data":"在线,工作状态正常。","serverExecutedTime":4}
|
||||||
|
//成功 离线 {"msg":"ok","ret":0,"data":"离线。","serverExecutedTime":7}
|
||||||
|
JSONObject json = JSONUtil.parseObj(UnicodeUtil.toString(resp));
|
||||||
|
log.info("飞鹅打印机状态响应: {}", json);
|
||||||
|
msg = json.getStr("data");
|
||||||
|
} catch (Exception e) {
|
||||||
|
msg = "未知错误";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import lombok.ToString;
|
|||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.dubbo.config.annotation.DubboReference;
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -49,10 +50,9 @@ public abstract class PrinterHandler {
|
|||||||
@Setter
|
@Setter
|
||||||
protected PrinterHandler nextPrinter;
|
protected PrinterHandler nextPrinter;
|
||||||
protected String printerBrand;
|
protected String printerBrand;
|
||||||
// 创建 ThreadLocal 变量
|
|
||||||
private static final ThreadLocal<String> ERR_MSG = ThreadLocal.withInitial(() -> "");
|
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected RestTemplate restTemplate;
|
||||||
@Resource
|
@Resource
|
||||||
protected OrderDetailService orderDetailService;
|
protected OrderDetailService orderDetailService;
|
||||||
@Resource
|
@Resource
|
||||||
@@ -84,7 +84,11 @@ public abstract class PrinterHandler {
|
|||||||
@Getter
|
@Getter
|
||||||
public enum PrintTypeEnum {
|
public enum PrintTypeEnum {
|
||||||
HANDOVER("交班", "handover"),
|
HANDOVER("交班", "handover"),
|
||||||
ORDER("订单", "order"), ONE("菜品", "one"), CALL("叫号", "call"), ONE_AND_ORDER("菜品和结算单同时打印", "oneAndOrder"), PRE_ORDER("预结算单", "preOrder");
|
ORDER("订单", "order"),
|
||||||
|
ONE("菜品", "one"),
|
||||||
|
CALL("叫号", "call"),
|
||||||
|
ONE_AND_ORDER("菜品和结算单同时打印", "oneAndOrder"),
|
||||||
|
PRE_ORDER("预结算单", "preOrder");
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String code;
|
private final String code;
|
||||||
|
|
||||||
@@ -173,10 +177,6 @@ public abstract class PrinterHandler {
|
|||||||
wrapper.like(PrintMachine::getPrintType, printType);
|
wrapper.like(PrintMachine::getPrintType, printType);
|
||||||
}
|
}
|
||||||
List<PrintMachine> list = printMachineService.list(wrapper);
|
List<PrintMachine> list = printMachineService.list(wrapper);
|
||||||
// for (PrintMachine item : list) {
|
|
||||||
// //实际打印以传递的参数为准
|
|
||||||
// item.setPrintMethod(printMethod);
|
|
||||||
// }
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
log.error("店铺未配置打印机,店铺id: {}", shopId);
|
log.error("店铺未配置打印机,店铺id: {}", shopId);
|
||||||
return list;
|
return list;
|
||||||
@@ -188,6 +188,7 @@ public abstract class PrinterHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理打印
|
* 处理打印
|
||||||
|
*
|
||||||
* @param data 传递的数据
|
* @param data 传递的数据
|
||||||
* @param printTypeEnum order returnOrder preOrder one call handover
|
* @param printTypeEnum order returnOrder preOrder one call handover
|
||||||
*/
|
*/
|
||||||
@@ -341,6 +342,7 @@ public abstract class PrinterHandler {
|
|||||||
case PrintTypeEnum.ORDER:
|
case PrintTypeEnum.ORDER:
|
||||||
log.info("准备开始打印订单");
|
log.info("准备开始打印订单");
|
||||||
if (data instanceof OrderInfo orderInfo) {
|
if (data instanceof OrderInfo orderInfo) {
|
||||||
|
redisService.set("order:print:" + orderInfo.getId(),"", 180);
|
||||||
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
|
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
|
||||||
onlyFrontDesk(machine, false, orderInfo, orderDetailList);
|
onlyFrontDesk(machine, false, orderInfo, orderDetailList);
|
||||||
} else {
|
} else {
|
||||||
@@ -350,6 +352,7 @@ public abstract class PrinterHandler {
|
|||||||
case PrintTypeEnum.PRE_ORDER:
|
case PrintTypeEnum.PRE_ORDER:
|
||||||
log.info("准备开始打印预结算订单");
|
log.info("准备开始打印预结算订单");
|
||||||
if (data instanceof OrderInfo orderInfo) {
|
if (data instanceof OrderInfo orderInfo) {
|
||||||
|
redisService.set("order:print:" + orderInfo.getId(),"", 180);
|
||||||
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
|
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
|
||||||
onlyFrontDesk(machine, true, orderInfo, orderDetailList);
|
onlyFrontDesk(machine, true, orderInfo, orderDetailList);
|
||||||
} else {
|
} else {
|
||||||
@@ -359,6 +362,7 @@ public abstract class PrinterHandler {
|
|||||||
case PrintTypeEnum.ONE:
|
case PrintTypeEnum.ONE:
|
||||||
log.info("准备开始打印菜品单");
|
log.info("准备开始打印菜品单");
|
||||||
if (data instanceof OrderInfo orderInfo) {
|
if (data instanceof OrderInfo orderInfo) {
|
||||||
|
redisService.set("order:print:" + orderInfo.getId(),"", 180);
|
||||||
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
|
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
|
||||||
onlyKitchen(machine, orderInfo, orderDetailList);
|
onlyKitchen(machine, orderInfo, orderDetailList);
|
||||||
} else {
|
} else {
|
||||||
@@ -376,6 +380,7 @@ public abstract class PrinterHandler {
|
|||||||
case PrintTypeEnum.ONE_AND_ORDER:
|
case PrintTypeEnum.ONE_AND_ORDER:
|
||||||
log.info("准备开始打印菜品以及结算单");
|
log.info("准备开始打印菜品以及结算单");
|
||||||
if (data instanceof OrderInfo orderInfo) {
|
if (data instanceof OrderInfo orderInfo) {
|
||||||
|
redisService.set("order:print:" + orderInfo.getId(),"", 180);
|
||||||
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
|
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
|
||||||
switch (machine.getPrintMethod()) {
|
switch (machine.getPrintMethod()) {
|
||||||
case "all":
|
case "all":
|
||||||
@@ -448,17 +453,7 @@ public abstract class PrinterHandler {
|
|||||||
log.info("台位费商品,不打印");
|
log.info("台位费商品,不打印");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ProdSku sku = prodSkuService.getById(item.getSkuId());
|
|
||||||
// if (isTemporary == 0 && sku == null) {
|
|
||||||
// log.error("商品不存在, id: {}", item.getSkuId());
|
|
||||||
// return;
|
|
||||||
// } else if (isTemporary == 1) {
|
|
||||||
// sku = new ProdSku();
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// String remark = StrUtil.isNotBlank(sku.getSpecInfo()) ? sku.getSpecInfo() : "";
|
|
||||||
// item.setRemark(remark);
|
|
||||||
if (item.getReturnNum().compareTo(BigDecimal.ZERO) > 0) {
|
if (item.getReturnNum().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
returnDishesPrint(orderInfo, item, machine);
|
returnDishesPrint(orderInfo, item, machine);
|
||||||
}
|
}
|
||||||
@@ -469,7 +464,8 @@ public abstract class PrinterHandler {
|
|||||||
|
|
||||||
// 保存已打印信息
|
// 保存已打印信息
|
||||||
OrderDetail orderDetail = detailMap.get(item.getId());
|
OrderDetail orderDetail = detailMap.get(item.getId());
|
||||||
redisService.set(RedisCst.getPrintOrderDetailKey(orderInfo.getId(), item.getId()), JSONObject.toJSONString(new PrintDetailInfo().setPrint(item.getIsPrint() == 1).setDetailId(item.getId())
|
redisService.set(RedisCst.getPrintOrderDetailKey(orderInfo.getId(), item.getId()),
|
||||||
|
JSONObject.toJSONString(new PrintDetailInfo().setPrint(item.getIsPrint() == 1).setDetailId(item.getId())
|
||||||
.setPrintNum(orderDetail.getNum()).setPrintReturnNum(orderDetail.getReturnNum())), 3600 * 24);
|
.setPrintNum(orderDetail.getNum()).setPrintReturnNum(orderDetail.getReturnNum())), 3600 * 24);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import cn.hutool.json.JSONUtil;
|
|||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.czg.account.dto.HandoverRecordDTO;
|
import com.czg.account.dto.HandoverRecordDTO;
|
||||||
import com.czg.account.entity.HandoverRecord;
|
|
||||||
import com.czg.order.entity.OrderDetail;
|
import com.czg.order.entity.OrderDetail;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -69,10 +68,9 @@ public interface PrinterImpl {
|
|||||||
* @param metaPrintData 打印元数据
|
* @param metaPrintData 打印元数据
|
||||||
* @param voiceData 语音信息
|
* @param voiceData 语音信息
|
||||||
* @param printNum 打印联数
|
* @param printNum 打印联数
|
||||||
* @param <R> 返回数据类型
|
|
||||||
* @return 打印结果
|
* @return 打印结果
|
||||||
*/
|
*/
|
||||||
<R> R sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum);
|
String sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前打印机标签信息
|
* 获取当前打印机标签信息
|
||||||
@@ -560,12 +558,6 @@ public interface PrinterImpl {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
System.out.println("水煮肉片".length());
|
|
||||||
System.out.println(StrUtil.repeat(' ', 8));
|
|
||||||
System.out.println(StrUtil.fillAfter("水煮肉片", ' ', 21));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取填充字符串, 并且换行
|
* 获取填充字符串, 并且换行
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ import cn.hutool.core.date.DateUtil;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.crypto.SecureUtil;
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
import com.czg.account.dto.HandoverRecordDTO;
|
import com.czg.account.dto.HandoverRecordDTO;
|
||||||
import com.czg.account.entity.HandoverRecord;
|
|
||||||
import com.czg.account.entity.PrintMachine;
|
import com.czg.account.entity.PrintMachine;
|
||||||
import com.czg.account.entity.ShopInfo;
|
import com.czg.account.entity.ShopInfo;
|
||||||
import com.czg.account.service.ShopInfoService;
|
|
||||||
import com.czg.order.entity.OrderDetail;
|
import com.czg.order.entity.OrderDetail;
|
||||||
import com.czg.order.entity.OrderInfo;
|
import com.czg.order.entity.OrderInfo;
|
||||||
import com.czg.service.order.enums.OrderStatusEnums;
|
import com.czg.service.order.enums.OrderStatusEnums;
|
||||||
@@ -20,16 +19,14 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.stereotype.Component;
|
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 javax.annotation.Resource;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云享印打印机
|
* 博实结-云享印打印机
|
||||||
*
|
* 接口文档 <a href="https://bsj2.yuque.com/bsj/izhmfn/rr8b5g?#ZbE6s">
|
||||||
* @author Administrator
|
* @author Administrator
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -45,12 +42,6 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
//APPSECRET
|
//APPSECRET
|
||||||
private static final String APP_SECRET = "2022bsjZF544GAH";
|
private static final String APP_SECRET = "2022bsjZF544GAH";
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ShopInfoService shopInfoService;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RestTemplate restTemplate;
|
|
||||||
|
|
||||||
public YxyPrinter() {
|
public YxyPrinter() {
|
||||||
super("云想印");
|
super("云想印");
|
||||||
}
|
}
|
||||||
@@ -75,7 +66,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R> R sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum) {
|
public String sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum) {
|
||||||
log.info("开始请求云享印,请求数据:{}, {}", voiceData, metaPrintData);
|
log.info("开始请求云享印,请求数据:{}, {}", voiceData, metaPrintData);
|
||||||
//设备名称
|
//设备名称
|
||||||
//行为方式 1:只打印数据 2:只播放信息 3:打印数据并播放信息
|
//行为方式 1:只打印数据 2:只播放信息 3:打印数据并播放信息
|
||||||
@@ -87,10 +78,9 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
String time = String.valueOf(System.currentTimeMillis());
|
String time = String.valueOf(System.currentTimeMillis());
|
||||||
String uuid = UUID.randomUUID().toString();
|
String uuid = UUID.randomUUID().toString();
|
||||||
|
|
||||||
Map<String, String> param = getToken(time, uuid);
|
|
||||||
//参数
|
//参数
|
||||||
MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
|
MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
|
||||||
multiValueMap.add("token", param.get("TOKEN"));
|
multiValueMap.add("token", getToken(time, uuid));
|
||||||
multiValueMap.add("devName", address);
|
multiValueMap.add("devName", address);
|
||||||
multiValueMap.add("actWay", 3);
|
multiValueMap.add("actWay", 3);
|
||||||
multiValueMap.add("cn", printNum);
|
multiValueMap.add("cn", printNum);
|
||||||
@@ -108,7 +98,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
httpEntity, String.class);
|
httpEntity, String.class);
|
||||||
|
|
||||||
log.info("请求云享印成功,响应数据: {}", httpResponse);
|
log.info("请求云享印成功,响应数据: {}", httpResponse);
|
||||||
return (R) httpResponse;
|
return httpResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -116,10 +106,8 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
String buildDishPrintData = buildDishPrintData(false, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(),
|
String buildDishPrintData = buildDishPrintData(false, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(),
|
||||||
orderDetail.getNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
orderDetail.getNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
||||||
String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
||||||
// String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
|
||||||
Object resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
|
printMachineLogService.save(orderInfo.getId(), machine, "新订单", buildDishPrintData, resp);
|
||||||
// sendPrintRequest(voiceJson, 3, 1, machine.getAddress(), data);
|
|
||||||
printMachineLogService.save(machine, "新订单", buildDishPrintData, resp);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,10 +115,9 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
protected void returnDishesPrint(OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) {
|
protected void returnDishesPrint(OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) {
|
||||||
String buildDishPrintData = buildDishPrintData(true, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(),
|
String buildDishPrintData = buildDishPrintData(true, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(),
|
||||||
orderDetail.getReturnNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
orderDetail.getReturnNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
||||||
// String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
|
||||||
String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
||||||
Object resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
|
String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
|
||||||
printMachineLogService.save(machine, "退款单", buildDishPrintData, resp);
|
printMachineLogService.save(orderInfo.getId(), machine, "退款单", buildDishPrintData, resp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,18 +128,17 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
.setOrderNo(orderInfo.getOrderNo()).setTradeDate(DateUtil.format(orderInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss")).setOperator("【POS-1】001").setPayAmount(orderInfo.getPayAmount().toPlainString())
|
.setOrderNo(orderInfo.getOrderNo()).setTradeDate(DateUtil.format(orderInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss")).setOperator("【POS-1】001").setPayAmount(orderInfo.getPayAmount().toPlainString())
|
||||||
.setOriginalAmount(orderInfo.getOriginAmount().toPlainString()).setReturn(isReturn(orderInfo))
|
.setOriginalAmount(orderInfo.getOriginAmount().toPlainString()).setReturn(isReturn(orderInfo))
|
||||||
.setBalance(balance).setPayType((ObjectUtil.isEmpty(orderInfo.getPayType()) || ObjectUtil.isNull(orderInfo.getPayType()) ? "" : orderInfo.getPayType())).setIntegral("0")
|
.setBalance(balance).setPayType((ObjectUtil.isEmpty(orderInfo.getPayType()) || ObjectUtil.isNull(orderInfo.getPayType()) ? "" : orderInfo.getPayType())).setIntegral("0")
|
||||||
.setOutNumber(orderInfo.getTakeCode()).setPrintTitle("结算单")
|
.setOutNumber(orderInfo.getTakeCode()).setPrintTitle("退款单")
|
||||||
.setRemark(orderInfo.getRemark()).setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());
|
.setRemark(orderInfo.getRemark()).setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());
|
||||||
|
|
||||||
String data = buildOrderPrintData(printInfoDTO, detailList);
|
String data = buildOrderPrintData(printInfoDTO, detailList);
|
||||||
String voiceJson = "{\"PbizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
String voiceJson = "{\"PbizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
||||||
// String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
|
||||||
String printerNum = "1";
|
String printerNum = "1";
|
||||||
if (StrUtil.isNotBlank(machine.getPrintQty())) {
|
if (StrUtil.isNotBlank(machine.getPrintQty())) {
|
||||||
printerNum = machine.getPrintQty().split("\\^")[1];
|
printerNum = machine.getPrintQty().split("\\^")[1];
|
||||||
}
|
}
|
||||||
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
|
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
|
||||||
printMachineLogService.save(machine, "新订单", data, resp);
|
printMachineLogService.save(orderInfo.getId(), machine, "退款单", data, resp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,23 +169,28 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
|
|
||||||
String data = buildOrderPrintData(printInfoDTO, detailList);
|
String data = buildOrderPrintData(printInfoDTO, detailList);
|
||||||
String voiceJson = "{\"PbizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
String voiceJson = "{\"PbizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
||||||
// String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
|
||||||
String printerNum = "1";
|
String printerNum = "1";
|
||||||
if (StrUtil.isNotBlank(machine.getPrintQty())) {
|
if (StrUtil.isNotBlank(machine.getPrintQty())) {
|
||||||
printerNum = machine.getPrintQty().split("\\^")[1];
|
printerNum = machine.getPrintQty().split("\\^")[1];
|
||||||
}
|
}
|
||||||
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
|
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
|
||||||
// printMachineLogService.save(machine, printType, data, resp);
|
printMachineLogService.save(orderInfo.getId(), machine, "结算单", data, resp);
|
||||||
printMachineLogService.save(machine, "新订单", data, resp);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 叫号单打印
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) {
|
protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) {
|
||||||
String resp = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime);
|
String resp = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime);
|
||||||
sendPrintRequest(machine.getAddress(), resp, null, "1");
|
sendPrintRequest(machine.getAddress(), resp, null, "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交班单打印
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void handoverPrint(PrintMachine machine, HandoverRecordDTO record) {
|
protected void handoverPrint(PrintMachine machine, HandoverRecordDTO record) {
|
||||||
String string = buildHandoverData(record);
|
String string = buildHandoverData(record);
|
||||||
@@ -214,9 +205,9 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
* @param requestId 请求ID,自定义
|
* @param requestId 请求ID,自定义
|
||||||
* @return token信息
|
* @return token信息
|
||||||
*/
|
*/
|
||||||
private static Map<String, String> getToken(String timestamp, String requestId) {
|
private static String getToken(String timestamp, String requestId) {
|
||||||
StringBuilder token = new StringBuilder();
|
StringBuilder token = new StringBuilder();
|
||||||
StringBuilder encode = new StringBuilder();
|
// StringBuilder encode = new StringBuilder();
|
||||||
SortedMap<String, Object> map = new TreeMap<>();
|
SortedMap<String, Object> map = new TreeMap<>();
|
||||||
map.put("appId", APP_ID);
|
map.put("appId", APP_ID);
|
||||||
map.put("timestamp", timestamp);
|
map.put("timestamp", timestamp);
|
||||||
@@ -226,13 +217,38 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
|||||||
String key = next.getKey();
|
String key = next.getKey();
|
||||||
Object value = next.getValue();
|
Object value = next.getValue();
|
||||||
token.append(key).append(value);
|
token.append(key).append(value);
|
||||||
encode.append(key).append("=").append(value).append("&");
|
// encode.append(key).append("=").append(value).append("&");
|
||||||
}
|
}
|
||||||
Map<String, String> finalMap = new HashMap<>();
|
// Map<String, String> finalMap = new HashMap<>();
|
||||||
finalMap.put("ENCODE", encode.toString());
|
// finalMap.put("ENCODE", encode.toString());
|
||||||
finalMap.put("TOKEN", SecureUtil.md5(token + APP_SECRET).toUpperCase());
|
// finalMap.put("TOKEN", SecureUtil.md5(token + APP_SECRET).toUpperCase());
|
||||||
return finalMap;
|
// return finalMap;
|
||||||
|
return SecureUtil.md5(token + APP_SECRET).toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查打印状态
|
||||||
|
*
|
||||||
|
* @param devName 设备名称,(唯一) 对应配置表中的address字段即(IP地址/打印机编号)
|
||||||
|
* @param taskId 打印任务id,用于复查打印状态,云想印=orderId
|
||||||
|
*/
|
||||||
|
public String checkPrintStatus(String devName, String taskId) {
|
||||||
|
String time = String.valueOf(System.currentTimeMillis());
|
||||||
|
String uuid = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
Map<String, Object> paramMap = new HashMap<>();
|
||||||
|
|
||||||
|
paramMap.put("devName", devName);
|
||||||
|
paramMap.put("orderId", taskId);
|
||||||
|
paramMap.put("token", getToken(time, uuid));
|
||||||
|
paramMap.put("appId", APP_ID);
|
||||||
|
paramMap.put("timestamp", time);
|
||||||
|
paramMap.put("requestId", uuid);
|
||||||
|
paramMap.put("userCode", USER_CODE);
|
||||||
|
String s = HttpUtil.get("https://ioe.car900.com/v1/openApi/dev/findOrder.json", paramMap, 1000 * 5);
|
||||||
|
log.info("云想印打印机:{},任务:{}状态:{}", devName, taskId, s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,20 +7,33 @@ import java.util.Map;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分销员支付
|
* 支付
|
||||||
*
|
*
|
||||||
* @author ww
|
* @author ww
|
||||||
*/
|
*/
|
||||||
public interface DistributionPayService {
|
public interface DistributionPayService {
|
||||||
|
/**
|
||||||
|
* 现金支付
|
||||||
|
*/
|
||||||
|
CzgResult<Object> cashPayOrder(MkDistributionPayDTO payParam);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 小程序支付
|
* 小程序支付
|
||||||
*/
|
*/
|
||||||
CzgResult<Map<String, Object>> ltPayOrder(String clintIp, MkDistributionPayDTO payParam);
|
CzgResult<Map<String, Object>> ltPayOrder(String clintIp, MkDistributionPayDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PC扫码支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> scanPayOrder(String clintIp, MkDistributionPayDTO payParam);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 运营端小程序余额充值
|
* 反扫
|
||||||
*/
|
*/
|
||||||
|
CzgResult<Map<String, Object>> microPayOrder(MkDistributionPayDTO payParam);
|
||||||
|
|
||||||
|
|
||||||
Map<String, String> mchRecharge(String clientIP, MkDistributionPayDTO payParam);
|
Map<String, String> mchRecharge(String clientIP, MkDistributionPayDTO payParam);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
package com.czg.service.order.service;
|
|
||||||
|
|
||||||
import com.czg.order.dto.OrderInfoRefundDTO;
|
|
||||||
import com.czg.resp.CzgResult;
|
|
||||||
import com.czg.service.order.dto.OrderPayParamDTO;
|
|
||||||
import lombok.NonNull;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ww
|
|
||||||
*/
|
|
||||||
public interface OrderPayService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 挂账
|
|
||||||
*/
|
|
||||||
CzgResult<Object> creditPayOrder(OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 现金支付
|
|
||||||
*/
|
|
||||||
CzgResult<Object> cashPayOrder(OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 余额支付
|
|
||||||
*/
|
|
||||||
CzgResult<Object> vipPayOrder(OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* h5支付
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> h5PayOrder(String clintIp, OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* js支付
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> jsPayOrder(String clintIp, OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 空订单支付
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> js2PayOrder(@NonNull String clintIp, OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小程序支付
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> ltPayOrder(String clintIp, OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PC扫码支付
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> scanPayOrder(String clintIp, OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 聚合反扫
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> microPayOrder(OrderPayParamDTO payParam);
|
|
||||||
//-----------------------------------------------------------------订单+会员 一起支付-----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 充值并付款
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> rechargePayOrder(String clintIp, OrderPayParamDTO payParam);
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------退款-----------------------------------------------------------------
|
|
||||||
|
|
||||||
//订单退款
|
|
||||||
CzgResult<Object> refundOrderBefore(OrderInfoRefundDTO param);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
package com.czg.service.order.service;
|
package com.czg.service.order.service;
|
||||||
|
|
||||||
import com.czg.entity.req.*;
|
|
||||||
import com.czg.entity.resp.CzgBaseResp;
|
import com.czg.entity.resp.CzgBaseResp;
|
||||||
import com.czg.entity.resp.CzgRefundResp;
|
import com.czg.entity.resp.CzgRefundResp;
|
||||||
import com.czg.order.dto.LtPayOtherDTO;
|
import com.czg.order.dto.LtPayOtherDTO;
|
||||||
|
import com.czg.order.dto.OrderInfoRefundDTO;
|
||||||
import com.czg.order.entity.OrderPayment;
|
import com.czg.order.entity.OrderPayment;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
|
import com.czg.service.order.dto.OrderPayParamDTO;
|
||||||
|
import com.czg.service.order.dto.VipMemberPayParamDTO;
|
||||||
|
import com.czg.service.order.dto.VipPayParamDTO;
|
||||||
|
import com.czg.service.order.dto.VipRefundDTO;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -18,45 +22,129 @@ import java.util.Map;
|
|||||||
* @author ww
|
* @author ww
|
||||||
*/
|
*/
|
||||||
public interface PayService {
|
public interface PayService {
|
||||||
BigDecimal MONEY_RATE = new BigDecimal("100");
|
//-----------------------------------------------------------------订单支付--------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂账
|
||||||
|
*/
|
||||||
|
CzgResult<Object> creditPayOrder(OrderPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 现金支付
|
||||||
|
*/
|
||||||
|
CzgResult<Object> cashPayOrder(OrderPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额支付
|
||||||
|
*/
|
||||||
|
CzgResult<Object> vipPayOrder(OrderPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* h5支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> h5PayOrder(String clintIp, OrderPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* js支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> jsPayOrder(String clintIp, OrderPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空订单支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> js2PayOrder(@NonNull String clintIp, OrderPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> ltPayOrder(String clintIp, OrderPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PC扫码支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> scanPayOrder(String clintIp, OrderPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚合反扫
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> microPayOrder(OrderPayParamDTO payParam);
|
||||||
|
//-----------------------------------------------------------------订单+会员 一起支付-----------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充值并付款
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> rechargePayOrder(String clintIp, OrderPayParamDTO payParam);
|
||||||
|
//-----------------------------------------------------------------会员支付--------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 现金充值
|
||||||
|
*/
|
||||||
|
CzgResult<Object> cashPayVip(VipPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* js支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> jsPayVip(String clintIp, VipPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> ltPayVip(String clintIp, VipPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PC扫码支付
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> scanPayVip(String clintIp, VipPayParamDTO payParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚合反扫
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, Object>> microPayVip(VipPayParamDTO payParam);
|
||||||
|
//-----------------------------------------------------------------会员开通购买 ----------------------------------------------------------
|
||||||
|
|
||||||
|
CzgResult<Map<String, Object>> ltPayMember(String clientIP, VipMemberPayParamDTO payParam);
|
||||||
|
|
||||||
|
CzgResult<Map<String, Object>> recharge(String clientIP, VipPayParamDTO rechargeDTO, Long userId);
|
||||||
|
|
||||||
|
|
||||||
Long initOrderPayment(OrderPayment payment);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------付款 ----------------------------------------------------------
|
|
||||||
CzgResult<Map<String, Object>> h5Pay(@NonNull Long shopId, CzgH5PayReq bizData);
|
|
||||||
CzgResult<Map<String, Object>> jsPay(@NonNull Long shopId, @NonNull String payType, CzgJsPayReq bizData);
|
|
||||||
CzgResult<Map<String, Object>> ltPay(@NonNull Long shopId, String payType, CzgLtPayReq bizData);
|
|
||||||
CzgResult<Map<String, Object>> scanPay(@NonNull Long shopId, CzgScanPayReq bizData);
|
|
||||||
CzgResult<Map<String, Object>> microPay(@NonNull Long shopId, CzgMicroPayReq bizData);
|
|
||||||
//-----------------------------------------------------------------积分商品/拼团 付款 ----------------------------------------------------------
|
//-----------------------------------------------------------------积分商品/拼团 付款 ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param param 支付参数
|
* @param param 支付参数
|
||||||
* @param payType {@link com.czg.constants.PayTypeConstants.SourceType} 常量
|
* @param payType 暂时只有 POINT 积分 和 WARE 拼团商品
|
||||||
* @param detail 操作描述 如 积分商品购买 / 拼团商品购买
|
* @param detail 操作描述 如 积分商品购买 / 拼团商品购买
|
||||||
*/
|
*/
|
||||||
CzgResult<Map<String, Object>> ltPayOther(LtPayOtherDTO param, String payType, String detail);
|
CzgResult<Map<String, Object>> ltPayOther(LtPayOtherDTO param, String payType, String detail);
|
||||||
|
|
||||||
//-----------------------------------------------------------------退款-----------------------------------------------------------------
|
//-----------------------------------------------------------------退款-----------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款前校验
|
||||||
|
*/
|
||||||
|
CzgResult<Map<String, BigDecimal>> refundVipBefore(VipRefundDTO payParam);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款
|
* 会员退款
|
||||||
* 目前订单 会员 使用
|
|
||||||
*/
|
*/
|
||||||
CzgResult<CzgRefundResp> refund(@NonNull Long shopId, CzgRefundReq bizData);
|
CzgResult<Object> refundVip(VipRefundDTO payParam);
|
||||||
|
|
||||||
|
CzgResult<Object> refundOrderBefore(OrderInfoRefundDTO param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单退款
|
||||||
|
*/
|
||||||
|
void refundOrder(Long shopId, Long orderId, Long payOrderId, String refPayOrderNo, String refundReason, BigDecimal refundAmount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一退款接口
|
* 统一退款接口
|
||||||
* 目前 拼团商品 积分商品 套餐推广 使用
|
*
|
||||||
* @param refPayOrderNo 自定义退单号 {@link com.czg.enums.OrderNoPrefixEnum} + 雪花Id
|
* @param refPayOrderNo 自定义退单号 {@link com.czg.enums.OrderNoPrefixEnum} + 雪花Id
|
||||||
*/
|
*/
|
||||||
void unifyRefund(Long shopId, Long sourceId, Long payOrderId, String refPayOrderNo, String refundReason, BigDecimal refundAmount);
|
void unifyRefund(Long shopId, Long sourceId, Long payOrderId, String refPayOrderNo, String refundReason, BigDecimal refundAmount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款补偿使用
|
* 退款补偿使用
|
||||||
* 目前 拼团商品 积分商品 套餐推广 使用
|
|
||||||
* (退款 账户余额不足时 会失败定时任务)
|
|
||||||
*/
|
*/
|
||||||
void unifyRefund(OrderPayment payment, String refPayOrderNo);
|
void unifyRefund(OrderPayment payment, String refPayOrderNo);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
package com.czg.service.order.service;
|
package com.czg.service.order.service;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.czg.dto.req.AggregateMerchantDto;
|
import com.czg.dto.req.AggregateMerchantDto;
|
||||||
import com.czg.service.order.dto.AggregateMerchantVO;
|
import com.czg.service.order.dto.AggregateMerchantVO;
|
||||||
import com.mybatisflex.core.service.IService;
|
import com.mybatisflex.core.service.IService;
|
||||||
@@ -13,22 +12,8 @@ import com.czg.order.entity.ShopDirectMerchant;
|
|||||||
*/
|
*/
|
||||||
public interface ShopDirectMerchantService extends IService<ShopDirectMerchant> {
|
public interface ShopDirectMerchantService extends IService<ShopDirectMerchant> {
|
||||||
|
|
||||||
/**
|
|
||||||
* ocr识别图片
|
|
||||||
* @param url 图片地址
|
|
||||||
* @param type IdCard 身份证
|
|
||||||
* BankCard 银行卡
|
|
||||||
* BusinessLicense 营业执照
|
|
||||||
*/
|
|
||||||
JSONObject getInfoByImg(String url, String type) throws Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取进件信息
|
|
||||||
*/
|
|
||||||
AggregateMerchantVO getEntry(Long shopId);
|
AggregateMerchantVO getEntry(Long shopId);
|
||||||
|
|
||||||
/**
|
|
||||||
* 申请进件
|
|
||||||
*/
|
|
||||||
boolean entryManager(AggregateMerchantDto reqDto);
|
boolean entryManager(AggregateMerchantDto reqDto);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
package com.czg.service.order.service;
|
|
||||||
|
|
||||||
import com.czg.resp.CzgResult;
|
|
||||||
import com.czg.service.order.dto.VipMemberPayParamDTO;
|
|
||||||
import com.czg.service.order.dto.VipPayParamDTO;
|
|
||||||
import com.czg.service.order.dto.VipRefundDTO;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户余额 充值/会员购买开通
|
|
||||||
* @author ww
|
|
||||||
*/
|
|
||||||
public interface ShopUserPayService {
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------会员支付--------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 现金充值
|
|
||||||
*/
|
|
||||||
CzgResult<Object> cashPayVip(VipPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* js支付
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> jsPayVip(String clintIp, VipPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小程序支付
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> ltPayVip(String clintIp, VipPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PC扫码支付
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> scanPayVip(String clintIp, VipPayParamDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 聚合反扫
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, Object>> microPayVip(VipPayParamDTO payParam);
|
|
||||||
//-----------------------------------------------------------------会员开通购买 ----------------------------------------------------------
|
|
||||||
|
|
||||||
CzgResult<Map<String, Object>> ltPayMember(String clientIP, VipMemberPayParamDTO payParam);
|
|
||||||
|
|
||||||
CzgResult<Map<String, Object>> recharge(String clientIP, VipPayParamDTO rechargeDTO, Long userId);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------退款-----------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 退款前校验
|
|
||||||
*/
|
|
||||||
CzgResult<Map<String, BigDecimal>> refundVipBefore(VipRefundDTO payParam);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 会员退款
|
|
||||||
*/
|
|
||||||
CzgResult<Object> refundVip(VipRefundDTO payParam);
|
|
||||||
}
|
|
||||||
@@ -3,16 +3,17 @@ package com.czg.service.order.service.impl;
|
|||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import com.czg.account.entity.ShopUser;
|
import com.czg.account.entity.ShopUser;
|
||||||
import com.czg.account.entity.UserInfo;
|
import com.czg.account.entity.UserInfo;
|
||||||
|
import com.czg.account.service.ShopInfoService;
|
||||||
import com.czg.account.service.ShopUserService;
|
import com.czg.account.service.ShopUserService;
|
||||||
import com.czg.account.service.UserInfoService;
|
import com.czg.account.service.UserInfoService;
|
||||||
import com.czg.constant.TableValueConstant;
|
import com.czg.constant.TableValueConstant;
|
||||||
import com.czg.constants.PayTypeConstants;
|
|
||||||
import com.czg.entity.req.CzgLtPayReq;
|
import com.czg.entity.req.CzgLtPayReq;
|
||||||
import com.czg.exception.CzgException;
|
import com.czg.exception.CzgException;
|
||||||
import com.czg.market.service.MkDistributionConfigService;
|
import com.czg.market.service.MkDistributionConfigService;
|
||||||
import com.czg.market.vo.MkDistributionConfigVO;
|
import com.czg.market.vo.MkDistributionConfigVO;
|
||||||
import com.czg.order.dto.MkDistributionPayDTO;
|
import com.czg.order.dto.MkDistributionPayDTO;
|
||||||
import com.czg.order.entity.OrderPayment;
|
import com.czg.order.entity.OrderPayment;
|
||||||
|
import com.czg.constants.PayTypeConstants;
|
||||||
import com.czg.order.service.OrderPaymentService;
|
import com.czg.order.service.OrderPaymentService;
|
||||||
import com.czg.resp.CzgResult;
|
import com.czg.resp.CzgResult;
|
||||||
import com.czg.service.market.service.impl.WxServiceImpl;
|
import com.czg.service.market.service.impl.WxServiceImpl;
|
||||||
@@ -35,7 +36,7 @@ public class DistributionPayServiceImpl implements DistributionPayService {
|
|||||||
private final BigDecimal MONEY_RATE = new BigDecimal("100");
|
private final BigDecimal MONEY_RATE = new BigDecimal("100");
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private OrderPaymentService orderPaymentService;
|
private OrderPaymentService paymentService;
|
||||||
@Resource
|
@Resource
|
||||||
private MkDistributionConfigService configService;
|
private MkDistributionConfigService configService;
|
||||||
@Resource
|
@Resource
|
||||||
@@ -43,6 +44,8 @@ public class DistributionPayServiceImpl implements DistributionPayService {
|
|||||||
@Resource
|
@Resource
|
||||||
private PayServiceImpl payService;
|
private PayServiceImpl payService;
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private ShopInfoService shopInfoService;
|
||||||
@DubboReference
|
@DubboReference
|
||||||
private ShopUserService shopUserService;
|
private ShopUserService shopUserService;
|
||||||
@DubboReference
|
@DubboReference
|
||||||
@@ -71,7 +74,7 @@ public class DistributionPayServiceImpl implements DistributionPayService {
|
|||||||
.setPayType(PayTypeConstants.PayType.PAY)
|
.setPayType(PayTypeConstants.PayType.PAY)
|
||||||
.setOrderNo(payParam.getPlatformType() + IdUtil.getSnowflakeNextId())
|
.setOrderNo(payParam.getPlatformType() + IdUtil.getSnowflakeNextId())
|
||||||
.setAmount(isRecharge ? payParam.getAmount() : detail.getPayAmount());
|
.setAmount(isRecharge ? payParam.getAmount() : detail.getPayAmount());
|
||||||
orderPaymentService.save(orderPayment);
|
paymentService.save(orderPayment);
|
||||||
|
|
||||||
InitInfo initInfo = new InitInfo().setConfig(detail);
|
InitInfo initInfo = new InitInfo().setConfig(detail);
|
||||||
if (isRecharge) {
|
if (isRecharge) {
|
||||||
@@ -86,6 +89,11 @@ public class DistributionPayServiceImpl implements DistributionPayService {
|
|||||||
return initInfo;
|
return initInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<Object> cashPayOrder(MkDistributionPayDTO payParam) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CzgResult<Map<String, Object>> ltPayOrder(String clintIp, MkDistributionPayDTO payParam) {
|
public CzgResult<Map<String, Object>> ltPayOrder(String clintIp, MkDistributionPayDTO payParam) {
|
||||||
InitInfo initInfo = initPayment(payParam.getUserId(), payParam, false);
|
InitInfo initInfo = initPayment(payParam.getUserId(), payParam, false);
|
||||||
@@ -98,4 +106,14 @@ public class DistributionPayServiceImpl implements DistributionPayService {
|
|||||||
InitInfo initInfo = initPayment(payParam.getUserId() == null ? payParam.getShopId() : payParam.getUserId(), payParam, true);
|
InitInfo initInfo = initPayment(payParam.getUserId() == null ? payParam.getShopId() : payParam.getUserId(), payParam, true);
|
||||||
return wxService.v3Pay(initInfo.openId, payParam.getAmount(), "商户运营余额充值", initInfo.payment.getOrderNo(), initInfo.payment.getSourceType());
|
return wxService.v3Pay(initInfo.openId, payParam.getAmount(), "商户运营余额充值", initInfo.payment.getOrderNo(), initInfo.payment.getSourceType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<Map<String, Object>> scanPayOrder(String clintIp, MkDistributionPayDTO payParam) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<Map<String, Object>> microPayOrder(MkDistributionPayDTO payParam) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1516,6 +1516,9 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean printOrder(Long shopId, OrderInfoPrintDTO orderInfoPrintDTO) {
|
public Boolean printOrder(Long shopId, OrderInfoPrintDTO orderInfoPrintDTO) {
|
||||||
|
if (redisService.hasKey("order:print:" + orderInfoPrintDTO.getId())) {
|
||||||
|
throw new CzgException("网络打印机正在尝试打印中。如需重打,请稍后再试!");
|
||||||
|
}
|
||||||
OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getId, orderInfoPrintDTO.getId()));
|
OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getId, orderInfoPrintDTO.getId()));
|
||||||
if (orderInfo == null) {
|
if (orderInfo == null) {
|
||||||
throw new CzgException("订单信息不存在");
|
throw new CzgException("订单信息不存在");
|
||||||
|
|||||||
@@ -1,561 +0,0 @@
|
|||||||
package com.czg.service.order.service.impl;
|
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.convert.Convert;
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.hutool.crypto.SecureUtil;
|
|
||||||
import cn.hutool.crypto.digest.MD5;
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
|
|
||||||
import com.czg.account.entity.ShopInfo;
|
|
||||||
import com.czg.account.entity.ShopUser;
|
|
||||||
import com.czg.account.entity.UserInfo;
|
|
||||||
import com.czg.account.service.ShopInfoService;
|
|
||||||
import com.czg.account.service.ShopUserService;
|
|
||||||
import com.czg.account.service.UserInfoService;
|
|
||||||
import com.czg.config.RabbitPublisher;
|
|
||||||
import com.czg.config.RedisCst;
|
|
||||||
import com.czg.constants.PayTypeConstants;
|
|
||||||
import com.czg.entity.req.*;
|
|
||||||
import com.czg.entity.resp.CzgRefundResp;
|
|
||||||
import com.czg.enums.ShopUserFlowBizEnum;
|
|
||||||
import com.czg.exception.CzgException;
|
|
||||||
import com.czg.exception.PaySuccessException;
|
|
||||||
import com.czg.market.entity.MkShopRechargeDetail;
|
|
||||||
import com.czg.market.enums.PointsConstant;
|
|
||||||
import com.czg.market.service.*;
|
|
||||||
import com.czg.market.vo.MkShopRechargeVO;
|
|
||||||
import com.czg.order.dto.CheckOrderPay;
|
|
||||||
import com.czg.order.dto.OrderInfoRefundDTO;
|
|
||||||
import com.czg.order.entity.OrderDetail;
|
|
||||||
import com.czg.order.entity.OrderInfo;
|
|
||||||
import com.czg.order.entity.OrderPayment;
|
|
||||||
import com.czg.order.enums.PayEnums;
|
|
||||||
import com.czg.order.service.CreditBuyerOrderService;
|
|
||||||
import com.czg.order.service.OrderDetailService;
|
|
||||||
import com.czg.order.service.OrderInfoCustomService;
|
|
||||||
import com.czg.order.service.OrderPaymentService;
|
|
||||||
import com.czg.resp.CzgResult;
|
|
||||||
import com.czg.service.RedisService;
|
|
||||||
import com.czg.service.order.dto.OrderPayParamDTO;
|
|
||||||
import com.czg.service.order.enums.OrderStatusEnums;
|
|
||||||
import com.czg.service.order.service.OrderPayService;
|
|
||||||
import com.czg.service.order.service.PayService;
|
|
||||||
import com.czg.utils.AssertUtil;
|
|
||||||
import com.czg.utils.CzgRandomUtils;
|
|
||||||
import com.czg.utils.FunUtils;
|
|
||||||
import com.mybatisflex.core.query.QueryWrapper;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.dubbo.config.annotation.DubboReference;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class OrderPayServiceImpl implements OrderPayService {
|
|
||||||
@Resource
|
|
||||||
private PayService payService;
|
|
||||||
@Resource
|
|
||||||
private OrderPaymentService paymentService;
|
|
||||||
@DubboReference
|
|
||||||
private ShopUserService shopUserService;
|
|
||||||
@DubboReference
|
|
||||||
private UserInfoService userInfoService;
|
|
||||||
@DubboReference
|
|
||||||
private ShopInfoService shopInfoService;
|
|
||||||
@Resource
|
|
||||||
private OrderInfoCustomService orderInfoCustomService;
|
|
||||||
@Resource
|
|
||||||
private OrderInfoService orderInfoService;
|
|
||||||
@Resource
|
|
||||||
private CreditBuyerOrderService buyerOrderService;
|
|
||||||
@Resource
|
|
||||||
private RedisService redisService;
|
|
||||||
@Resource
|
|
||||||
private RabbitPublisher rabbitPublisher;
|
|
||||||
@Resource
|
|
||||||
private MkShopRechargeService shopRechargeService;
|
|
||||||
@Resource
|
|
||||||
private MkShopRechargeDetailService shopRechargeDetailService;
|
|
||||||
@Resource
|
|
||||||
private OrderDetailService orderDetailService;
|
|
||||||
@Resource
|
|
||||||
private MkDistributionUserService distributionUserService;
|
|
||||||
@Resource
|
|
||||||
private MkShopConsumerCouponService consumerCouponService;
|
|
||||||
@Resource
|
|
||||||
private MkPointsUserService mkPointsUserService;
|
|
||||||
@Resource
|
|
||||||
private MkConsumeCashbackService consumeCashbackService;
|
|
||||||
@Resource
|
|
||||||
private MkPointsConfigService pointsConfigService;
|
|
||||||
|
|
||||||
private OrderInfo checkPay(CheckOrderPay checkOrderPay) {
|
|
||||||
OrderInfo orderInfo = orderInfoCustomService.checkOrderPay(checkOrderPay);
|
|
||||||
if (orderInfo.getOrderAmount().compareTo(BigDecimal.ZERO) == 0) {
|
|
||||||
//发送打票信息
|
|
||||||
//orderId_0_0 订单ID_先付后付(1先付0后付)_订单状态 0未完成 1完成
|
|
||||||
//orderInfo.getId() + "_" + (!"after-pay".equals(orderInfo.getPayMode()) ? 1 : 0) + "_0"
|
|
||||||
rabbitPublisher.sendOrderPrintMsg(orderInfo.getId() + "_" + (!"after-pay".equals(orderInfo.getPayMode()) ? 1 : 0) + "_1", orderInfo.getIsPrint() == 1);
|
|
||||||
redisService.del(RedisCst.classKeyExpired.EXPIRED_ORDER + orderInfo.getId());
|
|
||||||
throw new PaySuccessException("支付成功");
|
|
||||||
}
|
|
||||||
return orderInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Object> creditPayOrder(OrderPayParamDTO payParam) {
|
|
||||||
AssertUtil.isNull(payParam.getCreditBuyerId(), "请选择挂账人后支付");
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
orderInfo.setCreditBuyerId(payParam.getCreditBuyerId());
|
|
||||||
orderInfoCustomService.upOrderInfo(orderInfo, orderInfo.getOrderAmount(),
|
|
||||||
LocalDateTime.now(), null, PayEnums.CREDIT_PAY);
|
|
||||||
//挂账后续逻辑
|
|
||||||
buyerOrderService.save(payParam.getCreditBuyerId().toString(), orderInfo.getId());
|
|
||||||
return CzgResult.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Object> cashPayOrder(OrderPayParamDTO payParam) {
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
orderInfoCustomService.upOrderInfo(orderInfo, orderInfo.getOrderAmount(),
|
|
||||||
LocalDateTime.now(), null, PayEnums.CASH_PAY);
|
|
||||||
return CzgResult.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Object> vipPayOrder(OrderPayParamDTO payParam) {
|
|
||||||
ShopInfo shopInfo = shopInfoService.getById(payParam.getShopId());
|
|
||||||
AssertUtil.isNull(shopInfo, "店铺不存在");
|
|
||||||
if (!shopInfo.getIsAccountPay().equals(1)) {
|
|
||||||
return CzgResult.failure("支付失败,店铺暂未开启会员余额支付。");
|
|
||||||
}
|
|
||||||
ShopUser shopUser = new ShopUser();
|
|
||||||
if ("scanCode".equals(payParam.getPayType())) {
|
|
||||||
AssertUtil.isBlank(payParam.getAuthCode(), "会员码不能为空");
|
|
||||||
Object o = redisService.get(RedisCst.SHOP_USER_DYNAMIC_CODE + payParam.getShopId() + ":" + payParam.getAuthCode());
|
|
||||||
AssertUtil.isNull(o, "会员码已失效");
|
|
||||||
shopUser = shopUserService.getById(o.toString());
|
|
||||||
} else {
|
|
||||||
if ("userPay".equals(payParam.getPayType())) {
|
|
||||||
AssertUtil.isNull(payParam.getShopUserId(), "请选择付款人后重试");
|
|
||||||
shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
} else if ("accountPay".equals(payParam.getPayType())) {
|
|
||||||
shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
AssertUtil.isNull(shopUser, "会员不存在");
|
|
||||||
UserInfo userInfo = userInfoService.getById(shopUser.getUserId());
|
|
||||||
AssertUtil.isNull(userInfo, "用户信息不存在");
|
|
||||||
if (userInfo.getUsePayPwd() == 1) {
|
|
||||||
AssertUtil.isBlank(payParam.getPwd(), "支付密码不能为空");
|
|
||||||
if (userInfo.getPayPwd() == null || !userInfo.getPayPwd().equals(MD5.create().digestHex((payParam.getPwd())))) {
|
|
||||||
return CzgResult.failure("支付密码错误");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (shopUser == null || shopUser.getId() == null) {
|
|
||||||
AssertUtil.isNull(shopUser, "会员不存在");
|
|
||||||
}
|
|
||||||
payParam.getCheckOrderPay().setUserId(shopUser.getUserId());
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
if (shopInfo.getIsHeadShop().equals(1)) {
|
|
||||||
if (!shopUser.getMainShopId().equals(orderInfo.getShopId())) {
|
|
||||||
return CzgResult.failure("违规操作,请确认店铺后重试");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
boolean exists = shopInfoService.exists(QueryWrapper.create()
|
|
||||||
.eq(ShopInfo::getMainId, shopInfo.getMainId())
|
|
||||||
.eq(ShopInfo::getId, orderInfo.getShopId()));
|
|
||||||
if (!exists) {
|
|
||||||
return CzgResult.failure("违规操作,请确认店铺后重试");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (shopUser.getAmount().compareTo(orderInfo.getOrderAmount()) < 0) {
|
|
||||||
return CzgResult.failure("会员余额不足");
|
|
||||||
}
|
|
||||||
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
|
|
||||||
.setId(shopUser.getId())
|
|
||||||
.setMoney(orderInfo.getOrderAmount())
|
|
||||||
.setType(0)
|
|
||||||
.setBizEnum(ShopUserFlowBizEnum.ORDER_PAY)
|
|
||||||
.setRelationId(orderInfo.getId());
|
|
||||||
//更新会员余额 并生成流水
|
|
||||||
if (payParam.getCheckOrderPay() != null && StrUtil.isNotBlank(payParam.getCheckOrderPay().getRemark())) {
|
|
||||||
orderInfo.setRemark(payParam.getCheckOrderPay().getRemark());
|
|
||||||
}
|
|
||||||
|
|
||||||
Long flowId = shopUserService.updateMoney(shopUserMoneyEditDTO);
|
|
||||||
orderInfoCustomService.upOrderInfo(orderInfo, orderInfo.getOrderAmount(),
|
|
||||||
LocalDateTime.now(), flowId, PayEnums.VIP_PAY);
|
|
||||||
return CzgResult.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CzgResult<Map<String, Object>> rechargePayOrder(String clintIp, OrderPayParamDTO payParam) {
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
ShopInfo shopInfo = shopInfoService.getById(payParam.getShopId());
|
|
||||||
AssertUtil.isNull(shopInfo, "店铺不存在");
|
|
||||||
AssertUtil.isNull(payParam.getShopUserId(), "请选择付款人后重试");
|
|
||||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
AssertUtil.isNull(shopUser, "支付失败 该店铺用户不存在");
|
|
||||||
AssertUtil.isBlank(payParam.getPayType(), "支付方式不能为空");
|
|
||||||
UserInfo userInfo = userInfoService.getById(shopUser.getUserId());
|
|
||||||
AssertUtil.isNull(payParam.getRechargeId(), "请选择充值配置后重试");
|
|
||||||
AssertUtil.isNull(payParam.getRechargeDetailId(), "请选择充值配置后重试");
|
|
||||||
//查询活动Id 获取金额字段
|
|
||||||
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getOne(
|
|
||||||
new QueryWrapper().eq(MkShopRechargeDetail::getId, payParam.getRechargeDetailId())
|
|
||||||
.eq(MkShopRechargeDetail::getShopRechargeId, payParam.getRechargeId()));
|
|
||||||
AssertUtil.isNull(rechargeDetail, "充值配置不存在");
|
|
||||||
if (orderInfo.getOrderAmount().compareTo(rechargeDetail.getAmount()) >= 0) {
|
|
||||||
log.info("充值金额小于订单金额,充值金额:{} 订单金额:{}", rechargeDetail.getAmount(), orderInfo.getOrderAmount());
|
|
||||||
return CzgResult.failure("支付失败 充值金额必须大雨订单金额");
|
|
||||||
}
|
|
||||||
String payOrderNo = orderInfo.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
Long paymentId = payService.initOrderPayment(new OrderPayment(payParam.getShopId(), shopUser.getId(), PayTypeConstants.SourceType.MEMBER_IN, PayTypeConstants.PayType.PAY, payOrderNo,
|
|
||||||
"", rechargeDetail.getAmount(), rechargeDetail.getId()));
|
|
||||||
upOrderPayInfo(orderInfo.getId(), PayEnums.VIP_PAY, paymentId,
|
|
||||||
payParam.getCheckOrderPay() == null ? null : payParam.getCheckOrderPay().getRemark());
|
|
||||||
return payService.ltPay(payParam.getShopId(), payParam.getPayType(), new CzgLtPayReq(payOrderNo, rechargeDetail.getAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
payParam.getPayType(), "充值并支付", "wechatPay".equals(payParam.getPayType()) ? userInfo.getWechatOpenId() : userInfo.getAlipayOpenId(),
|
|
||||||
clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Map<String, Object>> h5PayOrder(@NonNull String clintIp, OrderPayParamDTO payParam) {
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
String payOrderNo = orderInfo.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
Long paymentId = payService.initOrderPayment(new OrderPayment(payParam.getShopId(), orderInfo.getId(),
|
|
||||||
PayTypeConstants.SourceType.ORDER, PayTypeConstants.PayType.PAY, payOrderNo, "", orderInfo.getOrderAmount()));
|
|
||||||
upOrderPayInfo(orderInfo.getId(), PayEnums.H5_PAY, paymentId,
|
|
||||||
payParam.getCheckOrderPay() == null ? null : payParam.getCheckOrderPay().getRemark());
|
|
||||||
return payService.h5Pay(payParam.getShopId(), new CzgH5PayReq(payOrderNo, orderInfo.getOrderAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
"点餐支付", clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Map<String, Object>> jsPayOrder(@NonNull String clintIp, OrderPayParamDTO payParam) {
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
AssertUtil.isBlank(payParam.getPayType(), "支付方式不能为空");
|
|
||||||
AssertUtil.isBlank(payParam.getOpenId(), "用户小程序ID不能为空");
|
|
||||||
String payOrderNo = orderInfo.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
Long paymentId = payService.initOrderPayment(new OrderPayment(payParam.getShopId(), orderInfo.getId(),
|
|
||||||
PayTypeConstants.SourceType.ORDER, PayTypeConstants.PayType.PAY, payOrderNo, "", orderInfo.getOrderAmount()));
|
|
||||||
upOrderPayInfo(orderInfo.getId(), "aliPay".equals(payParam.getPayType()) ? PayEnums.ALIPAY_MINI : PayEnums.WECHAT_MINI, paymentId,
|
|
||||||
payParam.getCheckOrderPay() == null ? null : payParam.getCheckOrderPay().getRemark());
|
|
||||||
return payService.jsPay(payParam.getShopId(), payParam.getPayType(), new CzgJsPayReq(payOrderNo, orderInfo.getOrderAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
"点餐支付", payParam.getOpenId(), clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Map<String, Object>> js2PayOrder(@NonNull String clintIp, OrderPayParamDTO payParam) {
|
|
||||||
AssertUtil.isBlank(payParam.getPayType(), "支付方式不能为空");
|
|
||||||
AssertUtil.isBlank(payParam.getOpenId(), "用户小程序ID不能为空");
|
|
||||||
OrderInfo orderInfo;
|
|
||||||
if (payParam.getCheckOrderPay().getOrderId() == null) {
|
|
||||||
if (payParam.getCheckOrderPay().getOrderAmount() == null || payParam.getCheckOrderPay().getOrderAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
|
||||||
throw new CzgException("支付金额不合法");
|
|
||||||
}
|
|
||||||
orderInfo = orderInfoCustomService.createPayOrder(payParam.getShopId(), payParam.getCheckOrderPay().getOrderAmount(),
|
|
||||||
payParam.getCheckOrderPay().getRemark());
|
|
||||||
} else {
|
|
||||||
orderInfo = orderInfoService.getById(payParam.getCheckOrderPay().getOrderId());
|
|
||||||
}
|
|
||||||
String payOrderNo = orderInfo.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
Long paymentId = payService.initOrderPayment(new OrderPayment(payParam.getShopId(), orderInfo.getId(),
|
|
||||||
PayTypeConstants.SourceType.ORDER, PayTypeConstants.PayType.PAY, payOrderNo, "", orderInfo.getOrderAmount()));
|
|
||||||
upOrderPayInfo(orderInfo.getId(), "aliPay".equals(payParam.getPayType()) ? PayEnums.ALIPAY_MINI : PayEnums.WECHAT_MINI, paymentId,
|
|
||||||
payParam.getCheckOrderPay() == null ? null : payParam.getCheckOrderPay().getRemark());
|
|
||||||
return payService.jsPay(payParam.getShopId(), payParam.getPayType(), new CzgJsPayReq(payOrderNo, orderInfo.getOrderAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
"点餐支付", payParam.getOpenId(), clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Map<String, Object>> ltPayOrder(@NonNull String clintIp, OrderPayParamDTO payParam) {
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
AssertUtil.isBlank(payParam.getPayType(), "支付方式不能为空");
|
|
||||||
AssertUtil.isBlank(payParam.getOpenId(), "用户小程序ID不能为空");
|
|
||||||
String payOrderNo = orderInfo.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
Long paymentId = payService.initOrderPayment(new OrderPayment(payParam.getShopId(), orderInfo.getId(),
|
|
||||||
PayTypeConstants.SourceType.ORDER, PayTypeConstants.PayType.PAY, payOrderNo, "", orderInfo.getOrderAmount()));
|
|
||||||
upOrderPayInfo(orderInfo.getId(), "aliPay".equals(payParam.getPayType()) ? PayEnums.ALIPAY_MINI : PayEnums.WECHAT_MINI, paymentId,
|
|
||||||
payParam.getCheckOrderPay() == null ? null : payParam.getCheckOrderPay().getRemark());
|
|
||||||
return payService.ltPay(payParam.getShopId(), payParam.getPayType(), new CzgLtPayReq(payOrderNo, orderInfo.getOrderAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
payParam.getPayType(), "点餐支付", payParam.getOpenId(), clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Map<String, Object>> scanPayOrder(@NonNull String clintIp, OrderPayParamDTO payParam) {
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
MkShopRechargeVO rechargeVO = shopRechargeService.detail(payParam.getShopId());
|
|
||||||
if (payParam.getRechargeDetailId() == null && rechargeVO.getIsCustom() == 0) {
|
|
||||||
throw new CzgException("未开启自定义充值金额");
|
|
||||||
}
|
|
||||||
Long mainShopId = shopInfoService.getMainIdByShopId(payParam.getShopId());
|
|
||||||
BigDecimal amount = shopRechargeService.checkRecharge(mainShopId, payParam.getShopId(), shopUser.getUserId(), payParam.getRechargeDetailId(), payParam.getAmount());
|
|
||||||
payParam.setAmount(amount);
|
|
||||||
String payOrderNo = orderInfo.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
Long paymentId = payService.initOrderPayment(new OrderPayment(payParam.getShopId(), orderInfo.getId(),
|
|
||||||
PayTypeConstants.SourceType.ORDER, PayTypeConstants.PayType.PAY, payOrderNo, "", orderInfo.getOrderAmount()));
|
|
||||||
upOrderPayInfo(orderInfo.getId(), PayEnums.MAIN_SCAN, paymentId,
|
|
||||||
payParam.getCheckOrderPay() == null ? null : payParam.getCheckOrderPay().getRemark());
|
|
||||||
return payService.scanPay(payParam.getShopId(), new CzgScanPayReq(payOrderNo, orderInfo.getOrderAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
"点餐支付", clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(noRollbackFor = PaySuccessException.class)
|
|
||||||
public CzgResult<Map<String, Object>> microPayOrder(OrderPayParamDTO payParam) {
|
|
||||||
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
|
|
||||||
AssertUtil.isBlank(payParam.getAuthCode(), "扫描码不能为空");
|
|
||||||
|
|
||||||
|
|
||||||
if (payParam.getShopUserId() != null) {
|
|
||||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
MkShopRechargeVO rechargeVO = shopRechargeService.detail(payParam.getShopId());
|
|
||||||
if (payParam.getRechargeDetailId() == null && rechargeVO.getIsCustom() == 0) {
|
|
||||||
throw new CzgException("未开启自定义充值金额");
|
|
||||||
}
|
|
||||||
Long mainShopId = shopInfoService.getMainIdByShopId(payParam.getShopId());
|
|
||||||
BigDecimal amount = shopRechargeService.checkRecharge(mainShopId, payParam.getShopId(), shopUser.getUserId(), payParam.getRechargeDetailId(), payParam.getAmount());
|
|
||||||
payParam.setAmount(amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
String payOrderNo = orderInfo.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
Long paymentId = payService.initOrderPayment(new OrderPayment(payParam.getShopId(), orderInfo.getId(),
|
|
||||||
PayTypeConstants.SourceType.ORDER, PayTypeConstants.PayType.PAY, payOrderNo, payParam.getAuthCode(), orderInfo.getOrderAmount()));
|
|
||||||
CzgResult<Map<String, Object>> mapCzgResult = payService.microPay(payParam.getShopId(), new CzgMicroPayReq(payOrderNo, orderInfo.getOrderAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
"点餐支付", payParam.getAuthCode(), payParam.getBuyerRemark(), ""));
|
|
||||||
if (mapCzgResult.getCode() == 200) {
|
|
||||||
orderInfoCustomService.upOrderInfo(orderInfo, orderInfo.getOrderAmount(),
|
|
||||||
LocalDateTime.now(), paymentId, PayEnums.BACK_SCAN);
|
|
||||||
} else {
|
|
||||||
upOrderPayInfo(orderInfo.getId(), PayEnums.BACK_SCAN, paymentId,
|
|
||||||
payParam.getCheckOrderPay() == null ? null : payParam.getCheckOrderPay().getRemark());
|
|
||||||
}
|
|
||||||
return mapCzgResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public CzgResult<Object> refundOrderBefore(OrderInfoRefundDTO param) {
|
|
||||||
OrderInfo orderInfo = orderInfoService.getById(param.getOrderId());
|
|
||||||
if (orderInfo.getStatus().equals(OrderStatusEnums.CANCELLED.getCode())) {
|
|
||||||
throw new CzgException("订单已过期不可退单");
|
|
||||||
}
|
|
||||||
boolean isFirstRefund = true;
|
|
||||||
if (orderInfo.getRefundAmount().compareTo(BigDecimal.ZERO) != 0) {
|
|
||||||
isFirstRefund = false;
|
|
||||||
}
|
|
||||||
ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId());
|
|
||||||
Map<String, BigDecimal> returnProMap = new HashMap<>();
|
|
||||||
boolean isPay = true;
|
|
||||||
String refPayOrderNo = "REFO" + IdUtil.getSnowflakeNextId();
|
|
||||||
if (orderInfo.getStatus().equals(OrderStatusEnums.UNPAID.getCode())) {
|
|
||||||
isPay = false;
|
|
||||||
refPayOrderNo = "";
|
|
||||||
}
|
|
||||||
if (isPay) {
|
|
||||||
if (shopInfo.getIsReturnPwd().equals(1)) {
|
|
||||||
AssertUtil.isBlank(shopInfo.getOperationPwd(), "请设置操作密码后使用");
|
|
||||||
if (!SecureUtil.md5(param.getPwd()).equals(shopInfo.getOperationPwd())) {
|
|
||||||
throw new CzgException("操作密码错误");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
orderInfo.setRefundAmount(orderInfo.getRefundAmount().add(param.getRefundAmount()));
|
|
||||||
if (orderInfo.getRefundAmount().compareTo(orderInfo.getPayAmount()) > 0) {
|
|
||||||
throw new CzgException("退单失败,可退金额不足");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CollUtil.isNotEmpty(param.getRefundDetails())) {
|
|
||||||
for (OrderDetail refundDetail : param.getRefundDetails()) {
|
|
||||||
AssertUtil.isNull(refundDetail.getNum(), "退单数量不能为空");
|
|
||||||
//退款数量
|
|
||||||
BigDecimal refNum = refundDetail.getNum();
|
|
||||||
OrderDetail orderDetail = orderDetailService.getById(refundDetail.getId());
|
|
||||||
//可退数量=订单数量-退单数量-退菜数量
|
|
||||||
BigDecimal returnNum = orderDetail.getNum().subtract(orderDetail.getRefundNum()).subtract(orderDetail.getReturnNum());
|
|
||||||
if (returnNum.compareTo(BigDecimal.ZERO) <= 0 || returnNum.compareTo(refundDetail.getNum()) < 0) {
|
|
||||||
throw new CzgException("退单失败," + orderDetail.getProductName() + "可退数量不足");
|
|
||||||
}
|
|
||||||
refundDetail.setReturnAmount(refundDetail.getNum().multiply(orderDetail.getUnitPrice()).setScale(2, RoundingMode.UP));
|
|
||||||
if (isPay) {
|
|
||||||
orderDetail.setRefundNum(orderDetail.getRefundNum().add(refNum));
|
|
||||||
if (orderDetail.getNum().compareTo(orderDetail.getRefundNum().add(orderDetail.getReturnNum())) == 0) {
|
|
||||||
orderDetail.setStatus(OrderStatusEnums.REFUND.getCode());
|
|
||||||
} else {
|
|
||||||
orderDetail.setStatus(OrderStatusEnums.PART_REFUND.getCode());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
orderDetail.setReturnNum(orderDetail.getReturnNum().add(refNum));
|
|
||||||
if (orderDetail.getPackNumber().compareTo(BigDecimal.ZERO) > 0 && orderDetail.getPackNumber().compareTo(orderDetail.getNum().subtract(orderDetail.getReturnNum())) > 0) {
|
|
||||||
orderDetail.setPackNumber(orderDetail.getNum().subtract(orderDetail.getReturnNum()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
orderDetail.setRefundNo(refPayOrderNo);
|
|
||||||
orderDetail.setRefundRemark(orderDetail.getRefundRemark() + param.getRefundReason());
|
|
||||||
// if (isPay) {
|
|
||||||
orderDetail.setReturnAmount(orderDetail.getReturnAmount().add(refundDetail.getReturnAmount()));
|
|
||||||
if (orderDetail.getReturnAmount().compareTo(orderDetail.getPayAmount()) > 0) {
|
|
||||||
orderDetail.setReturnAmount(orderDetail.getPayAmount());
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
orderDetailService.updateById(orderDetail);
|
|
||||||
if (orderDetail.getProductId() != null && orderDetail.getProductId() > 0) {
|
|
||||||
returnProMap.put(Convert.toStr(orderDetail.getProductId()), refundDetail.getNum());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
long count = orderDetailService.queryChain()
|
|
||||||
.eq(OrderDetail::getOrderId, orderInfo.getId())
|
|
||||||
.ne(OrderDetail::getStatus, OrderStatusEnums.REFUND.getCode()).count();
|
|
||||||
if (count > 0 && isPay) {
|
|
||||||
orderInfo.setStatus(OrderStatusEnums.PART_REFUND.getCode());
|
|
||||||
} else if (isPay) {
|
|
||||||
orderInfo.setStatus(OrderStatusEnums.REFUND.getCode());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
orderInfo.setStatus(OrderStatusEnums.REFUND.getCode());
|
|
||||||
List<OrderDetail> orderDetails = orderDetailService.queryChain()
|
|
||||||
.select(OrderDetail::getId, OrderDetail::getProductId, OrderDetail::getNum, OrderDetail::getReturnNum, OrderDetail::getPackAmount, OrderDetail::getReturnNum)
|
|
||||||
.eq(OrderDetail::getOrderId, orderInfo.getId())
|
|
||||||
.list();
|
|
||||||
for (OrderDetail orderDetail : orderDetails) {
|
|
||||||
if (isPay) {
|
|
||||||
if (orderDetail.getProductId() != null && orderDetail.getProductId() > 0) {
|
|
||||||
returnProMap.put(Convert.toStr(orderDetail.getProductId()), orderDetail.getNum().subtract(orderDetail.getReturnNum()).subtract(orderDetail.getRefundNum()));
|
|
||||||
}
|
|
||||||
orderDetail.setReturnAmount(orderDetail.getPayAmount());
|
|
||||||
orderDetail.setRefundNum(orderDetail.getNum().subtract(orderDetail.getReturnNum()));
|
|
||||||
orderDetail.setStatus(OrderStatusEnums.REFUND.getCode());
|
|
||||||
} else {
|
|
||||||
if (orderDetail.getProductId() != null && orderDetail.getProductId() > 0) {
|
|
||||||
returnProMap.put(Convert.toStr(orderDetail.getProductId()), orderDetail.getNum().subtract(orderDetail.getReturnNum()));
|
|
||||||
}
|
|
||||||
orderDetail.setReturnNum(orderDetail.getNum());
|
|
||||||
orderDetail.setStatus(OrderStatusEnums.CANCELLED.getCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
orderDetailService.updateBatch(orderDetails);
|
|
||||||
}
|
|
||||||
//总退款金额
|
|
||||||
//TODO 退款 券 未处理
|
|
||||||
if (isPay) {
|
|
||||||
orderInfo.setRefundType("cash");
|
|
||||||
//非现金退款
|
|
||||||
if (!param.isCash()) {
|
|
||||||
if (orderInfo.getPayType().equals(PayEnums.VIP_PAY.getValue())) {
|
|
||||||
ShopUser shopUser = shopUserService.getShopUserInfo(orderInfo.getShopId(), orderInfo.getUserId());
|
|
||||||
//会员支付 退钱
|
|
||||||
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
|
|
||||||
.setId(shopUser.getId())
|
|
||||||
.setMoney(param.getRefundAmount())
|
|
||||||
.setType(1)
|
|
||||||
.setRelationId(orderInfo.getId())
|
|
||||||
.setBizEnum(ShopUserFlowBizEnum.ORDER_REFUND);
|
|
||||||
shopUserService.updateMoney(shopUserMoneyEditDTO);
|
|
||||||
} else if (orderInfo.getPayType().equals(PayEnums.CREDIT_PAY.getValue())) {
|
|
||||||
AssertUtil.isNull(orderInfo.getCreditBuyerId(), "挂账单退款失败,未查询到挂账人");
|
|
||||||
buyerOrderService.partRefund(orderInfo.getCreditBuyerId().toString(), orderInfo.getId(), param.getRefundAmount());
|
|
||||||
} else if (!orderInfo.getPayType().equals(PayEnums.CASH_PAY.getValue())) {
|
|
||||||
//退款 param.getRefundAmount()
|
|
||||||
if (orderInfo.getPayOrderId() == null) {
|
|
||||||
throw new CzgException("退款失败,支付记录不存在");
|
|
||||||
}
|
|
||||||
refundOrder(orderInfo.getShopId(), orderInfo.getId(), orderInfo.getPayOrderId(),
|
|
||||||
refPayOrderNo, StrUtil.isBlank(param.getRefundReason()) ? "退款" : param.getRefundReason(), param.getRefundAmount());
|
|
||||||
}
|
|
||||||
orderInfo.setRefundType("payBack");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
orderInfo.setOrderAmount(orderInfo.getOrderAmount().subtract(param.getRefundAmount()));
|
|
||||||
}
|
|
||||||
orderInfo.setRefundRemark(orderInfo.getRefundRemark() + param.getRefundReason());
|
|
||||||
orderInfoService.updateById(orderInfo);
|
|
||||||
//退款后续
|
|
||||||
//退款返还库存
|
|
||||||
if (!returnProMap.isEmpty()) {
|
|
||||||
rabbitPublisher.sendOrderRefundMsg(JSONObject.toJSONString(Map.of("orderId", orderInfo.getId(), "returnProMap", returnProMap)));
|
|
||||||
}
|
|
||||||
refundOrderAfter(orderInfo.getId(), orderInfo.getShopId(), orderInfo.getUserId(), orderInfo.getOrderNo(),
|
|
||||||
orderInfo.getPointsNum(), isFirstRefund, orderInfo.getStatus().equals(OrderStatusEnums.REFUND.getCode()));
|
|
||||||
return CzgResult.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refundOrder(@NonNull Long shopId, @NonNull Long orderId, @NonNull Long payOrderId, @NonNull String refPayOrderNo,
|
|
||||||
@NonNull String refundReason, @NonNull BigDecimal refundAmount) {
|
|
||||||
OrderPayment payment = paymentService.getById(payOrderId);
|
|
||||||
AssertUtil.isNull(payment, "退款失败支付记录不存在");
|
|
||||||
Long refundId = payService.initOrderPayment(new OrderPayment(shopId, orderId, PayTypeConstants.SourceType.ORDER, PayTypeConstants.PayType.REFUND, refPayOrderNo, null, refundAmount, payment.getId()));
|
|
||||||
CzgResult<CzgRefundResp> refund = payService.refund(shopId, new CzgRefundReq(refPayOrderNo, refundReason, refundAmount.multiply(PayService.MONEY_RATE).longValue(), payment.getOrderNo(), ""));
|
|
||||||
if (refund.getCode() != 200 || refund.getData() == null || !"SUCCESS".equals(refund.getData().getState())) {
|
|
||||||
if (refund.getData() != null && refund.getData().getNote() != null) {
|
|
||||||
throw new CzgException(refund.getData().getNote());
|
|
||||||
}
|
|
||||||
throw new CzgException(refund.getMsg());
|
|
||||||
} else {
|
|
||||||
paymentService.updateChain()
|
|
||||||
.eq(OrderPayment::getId, refundId)
|
|
||||||
.set(OrderPayment::getPayTime, refund.getData().getRefundTime())
|
|
||||||
.set(OrderPayment::getTradeNumber, refund.getData().getRefundOrderId())
|
|
||||||
.set(OrderPayment::getRespJson, JSONObject.toJSONString(refund.getData()))
|
|
||||||
.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//触发订单退款时 后续处理
|
|
||||||
@Async
|
|
||||||
public void refundOrderAfter(@NonNull Long orderId, @NonNull Long shopId, Long userId, String orderNo,
|
|
||||||
Integer pointsNum, boolean isFirstRefund, boolean isAllRefund) {
|
|
||||||
if (isFirstRefund) {
|
|
||||||
// 退款分销还原
|
|
||||||
FunUtils.safeRunVoid(() -> distributionUserService.refund(orderId, orderNo),
|
|
||||||
"订单id:{} 退款,分销处理失败", orderId);
|
|
||||||
if (userId == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FunUtils.safeRunVoid(() -> consumerCouponService.removeConsumerCoupon(shopId, userId, orderId),
|
|
||||||
"订单id:{} 退款,消费赠券回撤处理失败", orderId);
|
|
||||||
FunUtils.safeRunVoid(() -> consumeCashbackService.removeCashback(shopId, userId, orderId, orderNo),
|
|
||||||
"订单id:{} 退款,消费返现扣除处理失败", orderId);
|
|
||||||
FunUtils.safeRunVoid(() -> pointsConfigService.removeConsumeAwardPoints(shopId, userId, orderId, orderNo),
|
|
||||||
"订单id:{} 退款,赠送积分扣除失败", orderId);
|
|
||||||
}
|
|
||||||
if (isAllRefund && userId != null && pointsNum != null && pointsNum > 0) {
|
|
||||||
FunUtils.safeRunVoid(() -> mkPointsUserService.alterPoints(userId, null, shopId, PointsConstant.ADD,
|
|
||||||
pointsNum, orderId, StrUtil.format("订单退款返还{}积分", pointsNum)),
|
|
||||||
"订单id:{} 退款,赠送积分扣除失败", orderId);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void upOrderPayInfo(@NonNull Long orderId, @NonNull PayEnums payType, @NotBlank Long paymentId, String remark) {
|
|
||||||
if (paymentId == null) {
|
|
||||||
throw new CzgException("未获取到支付记录");
|
|
||||||
}
|
|
||||||
orderInfoCustomService.updatePayOrderId(orderId, paymentId, payType.getValue(), remark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,10 +22,10 @@ public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, Ord
|
|||||||
@Override
|
@Override
|
||||||
public BigDecimal countMemberInAmount(Long shopId, Long shopUserId) {
|
public BigDecimal countMemberInAmount(Long shopId, Long shopUserId) {
|
||||||
return getOneAs(QueryWrapper.create().select("IFNULL(sum(amount), 0) as total_amount")
|
return getOneAs(QueryWrapper.create().select("IFNULL(sum(amount), 0) as total_amount")
|
||||||
.eq(OrderPayment::getShopId, 143)
|
.eq(OrderPayment::getShopId, shopId)
|
||||||
.eq(OrderPayment::getSourceType, PayTypeConstants.SourceType.MEMBER_IN)
|
.eq(OrderPayment::getSourceType, PayTypeConstants.SourceType.MEMBER_IN)
|
||||||
.eq(OrderPayment::getPayType, PayTypeConstants.PayType.PAY)
|
.eq(OrderPayment::getPayType, PayTypeConstants.PayType.PAY)
|
||||||
.eq(OrderPayment::getSourceId, 127452)
|
.eq(OrderPayment::getSourceId, shopUserId)
|
||||||
.eq(OrderPayment::getPayStatus, PayTypeConstants.PayStatus.SUCCESS), BigDecimal.class);
|
.eq(OrderPayment::getPayStatus, PayTypeConstants.PayStatus.SUCCESS), BigDecimal.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,32 +2,36 @@ package com.czg.service.order.service.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.map.MapProxy;
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
|
||||||
import cn.hutool.core.text.UnicodeUtil;
|
|
||||||
import cn.hutool.core.thread.ThreadUtil;
|
import cn.hutool.core.thread.ThreadUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.crypto.SecureUtil;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import cn.hutool.http.HttpUtil;
|
|
||||||
import cn.hutool.json.JSONObject;
|
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import com.czg.account.entity.PrintMachine;
|
import com.czg.account.entity.PrintMachine;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.czg.config.RedisCst;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.czg.market.service.OrderInfoService;
|
||||||
import com.mybatisflex.core.query.QueryWrapper;
|
import com.czg.order.entity.OrderInfo;
|
||||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
|
||||||
import com.czg.order.entity.PrintMachineLog;
|
import com.czg.order.entity.PrintMachineLog;
|
||||||
import com.czg.order.service.PrintMachineLogService;
|
import com.czg.order.service.PrintMachineLogService;
|
||||||
|
import com.czg.service.RedisService;
|
||||||
import com.czg.service.order.mapper.PrintMachineLogMapper;
|
import com.czg.service.order.mapper.PrintMachineLogMapper;
|
||||||
|
import com.czg.service.order.print.FeiPrinter;
|
||||||
|
import com.czg.service.order.print.YxyPrinter;
|
||||||
|
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.*;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 店铺小票打印记录ServiceImpl
|
* 店铺小票打印记录ServiceImpl
|
||||||
@@ -39,138 +43,46 @@ import java.util.*;
|
|||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMapper, PrintMachineLog> implements PrintMachineLogService {
|
public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMapper, PrintMachineLog> implements PrintMachineLogService {
|
||||||
//请求地址
|
|
||||||
private static final String URL_STR = "https://ioe.car900.com/v1/openApi/dev/customPrint.json";
|
|
||||||
//APPID
|
|
||||||
private static final String APP_ID = "ZF544";
|
|
||||||
//USERCODE
|
|
||||||
private static final String USER_CODE = "ZF544";
|
|
||||||
//APPSECRET
|
|
||||||
private static final String APP_SECRET = "2022bsjZF544GAH";
|
|
||||||
|
|
||||||
public static final String URL = "http://api.feieyun.cn/Api/Open/";//不需要修改
|
@Resource
|
||||||
|
private OrderInfoService orderInfoService;
|
||||||
|
@Lazy
|
||||||
|
@Resource
|
||||||
|
private YxyPrinter yxyPrinter;
|
||||||
|
@Lazy
|
||||||
|
@Resource
|
||||||
|
private FeiPrinter feiPrinter;
|
||||||
|
@Resource
|
||||||
|
private RedisService redisService;
|
||||||
|
|
||||||
public static final String USER = "chaozhanggui2022@163.com";//*必填*:账号名
|
Map<Integer, String> yxxStatusMap = Map.of(
|
||||||
public static final String UKEY = "UfWkhXxSkeSSscsU";//*必填*: 飞鹅云后台注册账号后生成的UKEY 【备注:这不是填打印机的KEY】
|
0, "离线(设备上线后自动补打)",
|
||||||
public static final String SN = "960238952";//*必填*:打印机编号,必须要在管理后台里添加打印机或调用API接口添加之后,才能调用API
|
1, "在线",
|
||||||
/**
|
2, "获取失败",
|
||||||
* 获取TOKEN值
|
3, "未激活",
|
||||||
*
|
4, "设备已禁用");
|
||||||
* @param timestamp 时间戳,13位
|
|
||||||
* @param requestId 请求ID,自定义
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static Map<String, String> getToken(String timestamp, String requestId) {
|
|
||||||
StringBuilder token = new StringBuilder();
|
|
||||||
StringBuilder encode = new StringBuilder();
|
|
||||||
SortedMap<String, Object> map = new TreeMap<>();
|
|
||||||
map.put("appId", APP_ID);
|
|
||||||
map.put("timestamp", timestamp);
|
|
||||||
map.put("requestId", requestId);
|
|
||||||
map.put("userCode", USER_CODE);
|
|
||||||
for (Map.Entry<String, Object> next : map.entrySet()) {
|
|
||||||
String key = next.getKey();
|
|
||||||
Object value = next.getValue();
|
|
||||||
token.append(key).append(value);
|
|
||||||
encode.append(key).append("=").append(value).append("&");
|
|
||||||
}
|
|
||||||
System.out.println("token" + token);
|
|
||||||
Map<String, String> finalMap = new HashMap<>();
|
|
||||||
finalMap.put("ENCODE", encode.toString());
|
|
||||||
System.out.println("+++++++++++++++" + token + APP_SECRET);
|
|
||||||
finalMap.put("TOKEN", SecureUtil.md5(token + APP_SECRET).toUpperCase());
|
|
||||||
return finalMap;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 检查打印状态
|
|
||||||
*
|
|
||||||
* @param devName 设备名称,(唯一) 对应配置表中的address字段即(IP地址/打印机编号)
|
|
||||||
* @param taskId 打印任务id,用于复查打印状态,云想印=orderId
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String checkPrintStatus(String devName, String taskId) {
|
|
||||||
String time = String.valueOf(System.currentTimeMillis());
|
|
||||||
String uuid = UUID.randomUUID().toString();
|
|
||||||
|
|
||||||
Map<String, String> param = getToken(time, uuid);
|
@Async
|
||||||
String token = param.get("TOKEN");
|
@Override
|
||||||
Map<String, Object> paramMap = new HashMap<>();
|
public void save(PrintMachine config, String bizType, String printContent, String respJson) {
|
||||||
|
if (config == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
save(null, config, bizType, printContent, respJson);
|
||||||
|
}
|
||||||
|
|
||||||
paramMap.put("devName", devName);
|
|
||||||
paramMap.put("orderId", taskId);
|
|
||||||
paramMap.put("token", token);
|
|
||||||
paramMap.put("appId", APP_ID);
|
|
||||||
paramMap.put("timestamp", time);
|
|
||||||
paramMap.put("requestId", uuid);
|
|
||||||
paramMap.put("userCode", USER_CODE);
|
|
||||||
|
|
||||||
return HttpUtil.get("https://ioe.car900.com/v1/openApi/dev/findOrder.json", paramMap, 1000 * 5);
|
|
||||||
}
|
|
||||||
private static String signature(String USER, String UKEY, String STIME) {
|
|
||||||
return DigestUtils.sha1Hex(USER + UKEY + STIME);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 检查飞鹅打印机打印任务是否已打印
|
|
||||||
*
|
|
||||||
* @param printOrderId 打印订单编号
|
|
||||||
* @return null-未知错误,true-已打印,false-未打印
|
|
||||||
*/
|
|
||||||
public static Boolean checkFPrintStatus(String printOrderId) {
|
|
||||||
String STIME = String.valueOf(System.currentTimeMillis() / 1000);
|
|
||||||
Map<String, Object> paramMap = new HashMap<>();
|
|
||||||
paramMap.put("user", USER);
|
|
||||||
paramMap.put("stime", STIME);
|
|
||||||
paramMap.put("sig", signature(USER, UKEY, STIME));
|
|
||||||
paramMap.put("apiname", "Open_queryOrderState");
|
|
||||||
paramMap.put("orderid", printOrderId);
|
|
||||||
Boolean ret;
|
|
||||||
try {
|
|
||||||
String resp = HttpUtil.post(URL, paramMap, 1000 * 5);
|
|
||||||
//成功 {"msg":"ok","ret":0,"data":true,"serverExecutedTime":4}
|
|
||||||
//失败 {"msg":"ok","ret":0,"data":false,"serverExecutedTime":4}
|
|
||||||
JSONObject json = JSONUtil.parseObj(UnicodeUtil.toString(resp));
|
|
||||||
ret = json.getBool("data");
|
|
||||||
} catch (Exception e) {
|
|
||||||
ret = null;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 检查飞鹅打印机是否在线
|
|
||||||
*
|
|
||||||
* @param sn 设备编号
|
|
||||||
* @return 在线,工作状态正常。/离线。/未知错误
|
|
||||||
*/
|
|
||||||
public static String checkOnline(String sn) {
|
|
||||||
String STIME = String.valueOf(System.currentTimeMillis() / 1000);
|
|
||||||
Map<String, Object> paramMap = new HashMap<>();
|
|
||||||
paramMap.put("user", USER);
|
|
||||||
paramMap.put("stime", STIME);
|
|
||||||
paramMap.put("sig", signature(USER, UKEY, STIME));
|
|
||||||
paramMap.put("apiname", "Open_queryPrinterStatus");
|
|
||||||
paramMap.put("sn", sn);
|
|
||||||
String msg;
|
|
||||||
try {
|
|
||||||
String resp = HttpUtil.post(URL, paramMap, 1000 * 5);
|
|
||||||
//成功 开机 {"msg":"ok","ret":0,"data":"在线,工作状态正常。","serverExecutedTime":4}
|
|
||||||
//成功 离线 {"msg":"ok","ret":0,"data":"离线。","serverExecutedTime":7}
|
|
||||||
JSONObject json = JSONUtil.parseObj(UnicodeUtil.toString(resp));
|
|
||||||
msg = json.getStr("data");
|
|
||||||
} catch (Exception e) {
|
|
||||||
msg = "未知错误";
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 保存打印记录
|
* 保存打印记录
|
||||||
*
|
*
|
||||||
|
* @param orderId 订单Id
|
||||||
* @param config 打印机配置
|
* @param config 打印机配置
|
||||||
* @param bizType 业务类型
|
* @param bizType 业务类型
|
||||||
* @param printContent 打印内容
|
* @param printContent 打印内容
|
||||||
* @param respJson 打印机响应结果
|
* @param respJson 打印机响应结果
|
||||||
*/
|
*/
|
||||||
@Async
|
@Async
|
||||||
public void save(PrintMachine config, String bizType, String printContent, Object respJson) {
|
@Override
|
||||||
|
public void save(Long orderId, PrintMachine config, String bizType, String printContent, String respJson) {
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -179,51 +91,41 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
|
|||||||
int failFlag = 0;
|
int failFlag = 0;
|
||||||
String respCode = "0";
|
String respCode = "0";
|
||||||
String respMsg = "打印中";
|
String respMsg = "打印中";
|
||||||
|
JSONObject resp = JSONObject.parseObject(respJson);
|
||||||
Map<Integer, String> yxxStatusMap = MapUtil.builder(0, "离线(设备上线后自动补打)").put(1, "在线").put(2, "获取失败").put(3, "未激活").put(4, "设备已禁用").build();
|
|
||||||
// 云想印
|
// 云想印
|
||||||
if ("云享印".equals(config.getContentType())) {
|
if ("云想印".equals(config.getContentType())) {
|
||||||
cn.hutool.json.JSONObject resp = JSONUtil.parseObj(respJson);
|
int code = resp.getIntValue("code");
|
||||||
int code = resp.getInt("code");
|
JSONObject respData = resp.getJSONObject("data");
|
||||||
cn.hutool.json.JSONObject data = resp.getJSONObject("data").getJSONObject("data");
|
JSONObject data = respData.getJSONObject("data");
|
||||||
//设备状态,0: 离线, 1: 在线, 2: 获取失败, 3:未激活, 4:设备已禁用
|
//设备状态,0: 离线, 1: 在线, 2: 获取失败, 3:未激活, 4:设备已禁用
|
||||||
int status = data.getInt("status");
|
int status = data.getIntValue("status");
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
failFlag = 1;
|
failFlag = 1;
|
||||||
respCode = code + "";
|
respCode = code + "";
|
||||||
respMsg = resp.getStr("msg");
|
respMsg = resp.getString("msg");
|
||||||
} else if (status != 1) {
|
} else if (status != 1) {
|
||||||
failFlag = 1;
|
failFlag = 1;
|
||||||
respCode = code + "";
|
respCode = code + "";
|
||||||
|
|
||||||
respMsg = status + "_" + yxxStatusMap.get(status);
|
respMsg = status + "_" + yxxStatusMap.get(status);
|
||||||
}
|
}
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
String taskId = resp.getJSONObject("data").getStr("orderId");
|
entity.setTaskId(respData.getString("orderId"));
|
||||||
entity.setTaskId(taskId);
|
|
||||||
}
|
}
|
||||||
// 飞鹅云打印机暂时没有适配,先return不做打印记录
|
// 飞鹅云打印机暂时没有适配,先return不做打印记录
|
||||||
} else if ("飞鹅".equals(config.getContentType())) {
|
} else if ("飞鹅".equals(config.getContentType())) {
|
||||||
cn.hutool.json.JSONObject resp = JSONUtil.parseObj(respJson);
|
int ret = resp.getIntValue("ret");
|
||||||
int ret = resp.getInt("ret");
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
failFlag = 1;
|
failFlag = 1;
|
||||||
respCode = ret + "";
|
respCode = ret + "";
|
||||||
respMsg = resp.getStr("msg");
|
respMsg = resp.getString("msg");
|
||||||
} else {
|
} else {
|
||||||
String printOrderId = resp.getStr("data");
|
entity.setTaskId(resp.getString("data"));
|
||||||
entity.setTaskId(printOrderId);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 其他打印机暂时没有适配,先return不做打印记录
|
// 其他打印机暂时没有适配,先return不做打印记录
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entity.setBizType(bizType);
|
entity.setBizType(bizType);
|
||||||
// entity.setCreateUserId(config.getCurrentUserId());
|
|
||||||
// entity.setCreateUserName(config.getCurrentUserName());
|
|
||||||
// if (StrUtil.isNotBlank(config.getCurrentUserNickName())) {
|
|
||||||
// entity.setCreateUserName(StrUtil.concat(true, config.getCurrentUserNickName(), " | ", config.getCurrentUserName()));
|
|
||||||
// }
|
|
||||||
entity.setPrintContent(printContent);
|
entity.setPrintContent(printContent);
|
||||||
entity.setCreateTime(DateUtil.date().toLocalDateTime());
|
entity.setCreateTime(DateUtil.date().toLocalDateTime());
|
||||||
if (failFlag == 0) {
|
if (failFlag == 0) {
|
||||||
@@ -233,66 +135,213 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
|
|||||||
entity.setRespCode(respCode);
|
entity.setRespCode(respCode);
|
||||||
entity.setRespMsg(respMsg);
|
entity.setRespMsg(respMsg);
|
||||||
super.save(entity);
|
super.save(entity);
|
||||||
|
ThreadUtil.execAsync(() -> checkPrintStatus(orderId, config, entity));
|
||||||
|
}
|
||||||
|
|
||||||
// 云想印
|
/**
|
||||||
if ("云享印".equals(config.getContentType())) {
|
* 类级别成员变量:基于虚拟线程的固定大小(5)定时线程池
|
||||||
// 延迟3ms,复查打印状态 (用户可以根据设备信息查询到当前设备的在线情况(注:该接口只能提供参考,设备的离线状态是在设备离线3分钟后才会生效))
|
* // Java 21+ 虚拟线程工厂,支持命名
|
||||||
ThreadUtil.safeSleep(1000 * 5);
|
*/
|
||||||
String jsonStr = checkPrintStatus(config.getAddress(), entity.getTaskId());
|
private final ScheduledExecutorService virtualThreadScheduler = Executors.newScheduledThreadPool(
|
||||||
cn.hutool.json.JSONObject resp = JSONUtil.parseObj(jsonStr);
|
5,
|
||||||
int code = resp.getInt("code");
|
Thread.ofVirtual().name("print-query-vt-", 0).factory()
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印机状态查询(解决 retryFuture 爆红问题 + 虚拟线程 + 轮询重试)
|
||||||
|
*
|
||||||
|
* @param orderId 订单Id
|
||||||
|
* @param config 打印机配置
|
||||||
|
* @param entity 打印日志实体
|
||||||
|
*/
|
||||||
|
public void checkPrintStatus(Long orderId, PrintMachine config, PrintMachineLog entity) {
|
||||||
|
// 最大重试次数
|
||||||
|
int maxRetryTimes = 5;
|
||||||
|
AtomicInteger executedTimes = new AtomicInteger(0);
|
||||||
|
|
||||||
|
// 原子引用包装ScheduledFuture,用于后续取消轮询
|
||||||
|
AtomicReference<ScheduledFuture<?>> retryFutureRef = new AtomicReference<>();
|
||||||
|
|
||||||
|
// 核心查询任务(修正后,逻辑内聚)
|
||||||
|
Runnable printQueryTask = () -> {
|
||||||
|
int currentTimes = executedTimes.incrementAndGet();
|
||||||
|
boolean isPrintSuccess = false;
|
||||||
|
boolean isLastTask = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 云想印打印机状态查询
|
||||||
|
if ("云想印".equals(config.getContentType())) {
|
||||||
|
String jsonStr = yxyPrinter.checkPrintStatus(config.getAddress(), entity.getTaskId());
|
||||||
|
log.info("云想印打印状态查询结果(第{}次,虚拟线程:{}):{}",
|
||||||
|
currentTimes, Thread.currentThread().getName(), jsonStr);
|
||||||
|
JSONObject resp = JSONObject.parseObject(jsonStr);
|
||||||
|
int code = resp.getIntValue("code");
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
cn.hutool.json.JSONObject data = resp.getJSONObject("data");
|
JSONObject data = resp.getJSONObject("data");
|
||||||
boolean status = data.containsKey("status");
|
if (data.containsKey("status")) {
|
||||||
if (!status) {
|
isPrintSuccess = data.getBooleanValue("status", false);
|
||||||
return;
|
updatePrintLogEntity(entity, isPrintSuccess);
|
||||||
}
|
}
|
||||||
boolean success = data.getBool("status", false);
|
|
||||||
if (entity.getFailFlag() == 0 && success) {
|
|
||||||
entity.setFailFlag(0);
|
|
||||||
entity.setRespMsg("打印成功");
|
|
||||||
entity.setPrintTime(entity.getCreateTime());
|
|
||||||
} else if (entity.getFailFlag() == 1 && success) {
|
|
||||||
entity.setFailFlag(0);
|
|
||||||
entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
|
||||||
entity.setRespMsg("打印成功");
|
|
||||||
// 如果设备在线 and 休眠5秒后查询结果是未打印,即视为设备已离线,云端3分钟后才会同步到离线信息
|
|
||||||
} else if (entity.getFailFlag() == 0 && !success) {
|
|
||||||
entity.setFailFlag(1);
|
|
||||||
entity.setPrintTime(null);
|
|
||||||
entity.setRespMsg("0_离线(设备上线后自动补打)");
|
|
||||||
} else {
|
|
||||||
entity.setFailFlag(1);
|
|
||||||
entity.setPrintTime(null);
|
|
||||||
entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", entity.getRespMsg()));
|
|
||||||
}
|
}
|
||||||
super.updateById(entity);
|
|
||||||
}
|
}
|
||||||
// 飞鹅云打印机
|
// 2. 飞鹅云打印机状态查询
|
||||||
} else if ("飞鹅".equals(config.getContentType())) {
|
else if ("飞鹅".equals(config.getContentType())) {
|
||||||
ThreadUtil.safeSleep(1000 * 5);
|
Boolean success = feiPrinter.checkFPrintStatus(entity.getTaskId());
|
||||||
Boolean success = checkFPrintStatus(entity.getTaskId());
|
|
||||||
if (success == null) {
|
if (success == null) {
|
||||||
entity.setFailFlag(1);
|
entity.setFailFlag(1);
|
||||||
entity.setRespMsg("打印失败,未知错误");
|
entity.setRespMsg("打印失败,未知错误");
|
||||||
|
entity.setPrintTime(null);
|
||||||
} else if (success) {
|
} else if (success) {
|
||||||
entity.setFailFlag(0);
|
isPrintSuccess = true;
|
||||||
entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
updatePrintLogEntity(entity, true);
|
||||||
entity.setRespMsg("打印成功");
|
|
||||||
} else {
|
} else {
|
||||||
String msg = checkOnline(entity.getAddress());
|
String msg = feiPrinter.checkOnline(entity.getAddress());
|
||||||
if (msg.indexOf("在线,工作状态正常") > 0) {
|
if (msg.indexOf("在线,工作状态正常") > 0) {
|
||||||
entity.setFailFlag(0);
|
isPrintSuccess = true;
|
||||||
entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
updatePrintLogEntity(entity, true);
|
||||||
entity.setRespMsg("打印成功");
|
|
||||||
} else {
|
} else {
|
||||||
|
isPrintSuccess = false;
|
||||||
entity.setFailFlag(1);
|
entity.setFailFlag(1);
|
||||||
entity.setPrintTime(null);
|
entity.setPrintTime(null);
|
||||||
entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", msg));
|
entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.updateById(entity);
|
} else {
|
||||||
|
log.info("打印类型为其他类型,终止打印状态查询轮询任务");
|
||||||
|
ScheduledFuture<?> future = retryFutureRef.get();
|
||||||
|
if (future != null && !future.isCancelled()) {
|
||||||
|
boolean cancelSuccess = future.cancel(false); // 取消后续轮询(不中断当前任务)
|
||||||
|
log.info("其他打印类型,取消轮询任务:{}", cancelSuccess ? "成功" : "失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. 打印成功:取消后续轮询任务
|
||||||
|
if (isPrintSuccess) {
|
||||||
|
isLastTask = true;
|
||||||
|
ScheduledFuture<?> future = retryFutureRef.get();
|
||||||
|
if (future != null && !future.isCancelled()) {
|
||||||
|
future.cancel(false); // 不中断当前任务,仅取消后续任务
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 达到最大重试次数:取消后续轮询任务
|
||||||
|
if (currentTimes >= maxRetryTimes) {
|
||||||
|
isLastTask = true;
|
||||||
|
ScheduledFuture<?> future = retryFutureRef.get();
|
||||||
|
if (future != null && !future.isCancelled()) {
|
||||||
|
future.cancel(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("第{}次打印机状态查询异常(虚拟线程:{})",
|
||||||
|
currentTimes, Thread.currentThread().getName(), e);
|
||||||
|
// 异常时达到最大重试次数,同样取消任务
|
||||||
|
if (currentTimes >= maxRetryTimes) {
|
||||||
|
ScheduledFuture<?> future = retryFutureRef.get();
|
||||||
|
if (future != null && !future.isCancelled()) {
|
||||||
|
boolean cancelSuccess = future.cancel(false);
|
||||||
|
log.info("查询异常且达到最大重试次数,取消轮询任务:{}", cancelSuccess ? "成功" : "失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
//仅当是最后一次任务时,才执行更新操作
|
||||||
|
if (isLastTask) {
|
||||||
|
super.updateById(entity);
|
||||||
|
updateOrderEntity(orderId, config, isPrintSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 修正:统一使用scheduleAtFixedRate,避免任务重复执行
|
||||||
|
// 首次延迟10秒执行,后续每隔30秒执行一次(符合原逻辑的首次查询延迟,后续轮询间隔)
|
||||||
|
ScheduledFuture<?> retryFuture = virtualThreadScheduler.scheduleAtFixedRate(
|
||||||
|
printQueryTask,
|
||||||
|
10,
|
||||||
|
30,
|
||||||
|
TimeUnit.SECONDS
|
||||||
|
);
|
||||||
|
|
||||||
|
// 修正:先赋值AtomicReference,再让任务可能执行,避免线程安全隐患
|
||||||
|
retryFutureRef.set(retryFuture);
|
||||||
|
// 修正:关闭钩子仅注册一次(通过静态代码块或类初始化时注册,避免重复注册)
|
||||||
|
registerShutdownHookOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新状态
|
||||||
|
*/
|
||||||
|
private void updateOrderEntity(Long orderId, PrintMachine config, boolean isPrintSuccess) {
|
||||||
|
redisService.runFunAndCheckKey(() -> {
|
||||||
|
OrderInfo orderInfo = orderInfoService.getOne(query().select(OrderInfo::getPrintStatus).eq(OrderInfo::getId, orderId));
|
||||||
|
if (orderInfo == null) {
|
||||||
|
orderInfo = new OrderInfo();
|
||||||
|
}
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("id", config.getId());
|
||||||
|
jsonObject.put("name", config.getName());
|
||||||
|
jsonObject.put("time", LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
|
||||||
|
orderInfo.upPrintStatus(jsonObject, isPrintSuccess);
|
||||||
|
orderInfoService.update(orderInfo, query().eq(OrderInfo::getId, orderId));
|
||||||
|
return orderInfo;
|
||||||
|
}, RedisCst.getLockKey("UP_ORDER_PRINT", orderId));
|
||||||
|
redisService.del("order:print:" + orderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一更新打印日志实体
|
||||||
|
*
|
||||||
|
* @param entity 打印日志实体
|
||||||
|
* @param isPrintSuccess 是否打印成功
|
||||||
|
*/
|
||||||
|
private void updatePrintLogEntity(PrintMachineLog entity, boolean isPrintSuccess) {
|
||||||
|
if (isPrintSuccess) {
|
||||||
|
entity.setFailFlag(0);
|
||||||
|
entity.setRespMsg("打印成功");
|
||||||
|
entity.setPrintTime(entity.getFailFlag() == 0 ? entity.getCreateTime() : DateUtil.date().toLocalDateTime());
|
||||||
|
} else {
|
||||||
|
entity.setFailFlag(1);
|
||||||
|
entity.setPrintTime(null);
|
||||||
|
if (entity.getFailFlag() == 0) {
|
||||||
|
entity.setRespMsg("0_离线(设备上线后自动补打)");
|
||||||
|
} else {
|
||||||
|
entity.setRespMsg(entity.getRespMsg());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 静态标识,确保关闭钩子仅注册一次
|
||||||
|
private static volatile boolean shutdownHookRegistered = false;
|
||||||
|
// 锁对象,保证线程安全
|
||||||
|
private static final Object HOOK_LOCK = new Object();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一注册JVM关闭钩子(仅执行一次)
|
||||||
|
*/
|
||||||
|
private void registerShutdownHookOnce() {
|
||||||
|
if (!shutdownHookRegistered) {
|
||||||
|
synchronized (HOOK_LOCK) {
|
||||||
|
// 双重校验锁,避免多线程下重复注册
|
||||||
|
if (!shutdownHookRegistered) {
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
|
if (virtualThreadScheduler != null && !virtualThreadScheduler.isShutdown()) {
|
||||||
|
virtualThreadScheduler.shutdown();
|
||||||
|
try {
|
||||||
|
if (!virtualThreadScheduler.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||||
|
log.warn("虚拟线程调度器10秒内未关闭,强制关闭...");
|
||||||
|
virtualThreadScheduler.shutdownNow();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("等待虚拟线程调度器终止时被中断,强制关闭", e);
|
||||||
|
virtualThreadScheduler.shutdownNow();
|
||||||
|
Thread.currentThread().interrupt(); // 保留中断状态
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "PrinterScheduler-ShutdownHook"));
|
||||||
|
shutdownHookRegistered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package com.czg.service.order.service.impl;
|
package com.czg.service.order.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
|
import cn.hutool.core.io.unit.DataSizeUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.czg.EntryManager;
|
import com.czg.EntryManager;
|
||||||
import com.czg.OcrUtils;
|
|
||||||
import com.czg.PayCst;
|
import com.czg.PayCst;
|
||||||
import com.czg.config.RabbitPublisher;
|
import com.czg.config.RabbitPublisher;
|
||||||
import com.czg.constants.ParamCodeCst;
|
|
||||||
import com.czg.dto.req.*;
|
import com.czg.dto.req.*;
|
||||||
import com.czg.order.entity.ShopDirectMerchant;
|
|
||||||
import com.czg.service.order.dto.AggregateMerchantVO;
|
import com.czg.service.order.dto.AggregateMerchantVO;
|
||||||
import com.czg.service.order.mapper.ShopDirectMerchantMapper;
|
|
||||||
import com.czg.service.order.service.ShopDirectMerchantService;
|
|
||||||
import com.czg.system.service.SysParamsService;
|
|
||||||
import com.czg.utils.FunUtils;
|
import com.czg.utils.FunUtils;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||||
|
import com.czg.order.entity.ShopDirectMerchant;
|
||||||
|
import com.czg.service.order.service.ShopDirectMerchantService;
|
||||||
|
import com.czg.service.order.mapper.ShopDirectMerchantMapper;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.dubbo.config.annotation.DubboReference;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,21 +35,11 @@ public class ShopDirectMerchantServiceImpl extends ServiceImpl<ShopDirectMerchan
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private RabbitPublisher rabbitPublisher;
|
private RabbitPublisher rabbitPublisher;
|
||||||
@DubboReference
|
|
||||||
private SysParamsService sysParamsService;
|
|
||||||
|
|
||||||
|
|
||||||
// 全局原子计数器,按天重置(避免数值过大)
|
// 全局原子计数器,按天重置(避免数值过大)
|
||||||
private static final AtomicLong COUNTER = new AtomicLong(0);
|
private static final AtomicLong COUNTER = new AtomicLong(0);
|
||||||
// 记录上一次的日期,用于重置计数器
|
// 记录上一次的日期,用于重置计数器
|
||||||
private static String LAST_DATE = DateUtil.format(new Date(), "yyyyMMdd");
|
private static String LAST_DATE = DateUtil.format(new Date(), "yyyyMMdd");
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSONObject getInfoByImg(String url, String type) throws Exception {
|
|
||||||
Map<String, String> aliOssKeys = sysParamsService.getParamsByMap("ali_oss_key_set", ParamCodeCst.ALI_OSS_KEY_SET);
|
|
||||||
return OcrUtils.getInfoByImg(aliOssKeys.get(ParamCodeCst.AliYun.ALI_SMS_KEY), aliOssKeys.get(ParamCodeCst.AliYun.ALI_SMS_SECRET), url, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AggregateMerchantVO getEntry(Long shopId) {
|
public AggregateMerchantVO getEntry(Long shopId) {
|
||||||
ShopDirectMerchant merchant = getById(shopId);
|
ShopDirectMerchant merchant = getById(shopId);
|
||||||
@@ -129,14 +119,11 @@ public class ShopDirectMerchantServiceImpl extends ServiceImpl<ShopDirectMerchan
|
|||||||
vo.setSettlementInfo(JSONObject.parseObject(entity.getSettlementInfo(), SettlementInfoDto.class));
|
vo.setSettlementInfo(JSONObject.parseObject(entity.getSettlementInfo(), SettlementInfoDto.class));
|
||||||
|
|
||||||
// 设置其他字段
|
// 设置其他字段
|
||||||
vo.setAlipayAccount(entity.getAlipayAccount());
|
|
||||||
vo.setCreateTime(entity.getCreateTime());
|
vo.setCreateTime(entity.getCreateTime());
|
||||||
vo.setUpdateTime(entity.getUpdateTime());
|
vo.setUpdateTime(entity.getUpdateTime());
|
||||||
vo.setWechatApplyId(entity.getWechatApplyId());
|
|
||||||
vo.setWechatStatus(entity.getWechatStatus());
|
vo.setWechatStatus(entity.getWechatStatus());
|
||||||
vo.setWechatErrorMsg(entity.getWechatErrorMsg());
|
vo.setWechatErrorMsg(entity.getWechatErrorMsg());
|
||||||
vo.setWechatSignUrl(entity.getWechatSignUrl());
|
vo.setWechatSignUrl(entity.getWechatSignUrl());
|
||||||
vo.setAlipayOrderId(entity.getAlipayOrderId());
|
|
||||||
vo.setAlipayStatus(entity.getAlipayStatus());
|
vo.setAlipayStatus(entity.getAlipayStatus());
|
||||||
vo.setAlipayErrorMsg(entity.getAlipayErrorMsg());
|
vo.setAlipayErrorMsg(entity.getAlipayErrorMsg());
|
||||||
vo.setAlipaySignUrl(entity.getAlipaySignUrl());
|
vo.setAlipaySignUrl(entity.getAlipaySignUrl());
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
|
|||||||
*/
|
*/
|
||||||
private BigDecimal getProductCostAmount(Long shopId, LocalDate day) {
|
private BigDecimal getProductCostAmount(Long shopId, LocalDate day) {
|
||||||
BigDecimal productCostAmount = BigDecimal.ZERO;
|
BigDecimal productCostAmount = BigDecimal.ZERO;
|
||||||
////获取orderDetail信息 productId skuId 数量
|
//获取orderDetail信息 productId skuId 数量
|
||||||
List<ProductCostAmountVO> orderDetailProduct = mapper.getOrderDetailProduct(shopId, day);
|
List<ProductCostAmountVO> orderDetailProduct = mapper.getOrderDetailProduct(shopId, day);
|
||||||
orderDetailProduct = orderDetailProduct.stream()
|
orderDetailProduct = orderDetailProduct.stream()
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -167,44 +164,99 @@ public class ShopProdStatisticServiceImpl extends ServiceImpl<ShopProdStatisticM
|
|||||||
* @return 合并后的数据
|
* @return 合并后的数据
|
||||||
*/
|
*/
|
||||||
private List<ShopProdStatistic> mergeProdStatistic(List<ShopProdStatistic> realTimeDataByDay, List<ShopProdStatistic> dateRange) {
|
private List<ShopProdStatistic> mergeProdStatistic(List<ShopProdStatistic> realTimeDataByDay, List<ShopProdStatistic> dateRange) {
|
||||||
if (realTimeDataByDay == null) {
|
// 1. 使用防御性编程,确保非空列表
|
||||||
realTimeDataByDay = new ArrayList<>();
|
List<ShopProdStatistic> realTimeData = Optional.ofNullable(realTimeDataByDay).orElseGet(ArrayList::new);
|
||||||
}
|
List<ShopProdStatistic> rangeData = Optional.ofNullable(dateRange).orElseGet(ArrayList::new);
|
||||||
if (dateRange == null) {
|
|
||||||
dateRange = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stream.concat(realTimeDataByDay.stream(), dateRange.stream())
|
calculateValidData(realTimeData);
|
||||||
|
calculateValidData(rangeData);
|
||||||
|
|
||||||
|
return Stream.concat(realTimeData.stream(), rangeData.stream())
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
ShopProdStatistic::getProdId,
|
ShopProdStatistic::getProdId,
|
||||||
Function.identity(),
|
Function.identity(),
|
||||||
(stat1, stat2) -> {
|
this::mergeStatistics
|
||||||
// 创建合并后的对象
|
|
||||||
ShopProdStatistic merged = new ShopProdStatistic();
|
|
||||||
merged.setId(stat1.getId());
|
|
||||||
merged.setShopId(stat1.getShopId());
|
|
||||||
merged.setProdId(stat1.getProdId());
|
|
||||||
merged.setProductName(stat1.getProductName());
|
|
||||||
|
|
||||||
// 安全处理BigDecimal相加,处理null值
|
|
||||||
merged.setSaleCount(safeAdd(stat1.getSaleCount(), stat2.getSaleCount()));
|
|
||||||
merged.setSaleAmount(safeAdd(stat1.getSaleAmount(), stat2.getSaleAmount()));
|
|
||||||
merged.setRefundCount(safeAdd(stat1.getRefundCount(), stat2.getRefundCount()));
|
|
||||||
merged.setRefundAmount(safeAdd(stat1.getRefundAmount(), stat2.getRefundAmount()));
|
|
||||||
|
|
||||||
return merged;
|
|
||||||
}
|
|
||||||
))
|
))
|
||||||
.values()
|
.values()
|
||||||
.stream()
|
.stream()
|
||||||
|
.peek(this::recalculateValidData)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算有效销售数据
|
||||||
|
*/
|
||||||
|
private void calculateValidData(List<ShopProdStatistic> statistics) {
|
||||||
|
if (statistics == null || statistics.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
statistics.forEach(stat -> {
|
||||||
|
if (stat != null) {
|
||||||
|
stat.setValidSaleCount(safeSubtract(stat.getSaleCount(), stat.getRefundCount()));
|
||||||
|
stat.setValidSaleAmount(safeSubtract(stat.getValidSaleAmount(), stat.getRefundAmount()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并两个统计对象
|
||||||
|
*/
|
||||||
|
private ShopProdStatistic mergeStatistics(ShopProdStatistic stat1, ShopProdStatistic stat2) {
|
||||||
|
// 使用第一个非空对象作为基准
|
||||||
|
ShopProdStatistic baseStat = Optional.ofNullable(stat1).orElse(stat2);
|
||||||
|
ShopProdStatistic otherStat = stat1 == null ? null : stat2;
|
||||||
|
|
||||||
|
if (otherStat == null) {
|
||||||
|
return baseStat;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShopProdStatistic merged = new ShopProdStatistic();
|
||||||
|
|
||||||
|
// 设置基本信息(优先使用非空值)
|
||||||
|
merged.setId(baseStat.getId());
|
||||||
|
merged.setShopId(baseStat.getShopId());
|
||||||
|
merged.setProdId(baseStat.getProdId());
|
||||||
|
merged.setProductName(
|
||||||
|
Optional.ofNullable(baseStat.getProductName())
|
||||||
|
.orElse(otherStat.getProductName())
|
||||||
|
);
|
||||||
|
|
||||||
|
// 合并数值字段
|
||||||
|
merged.setSaleCount(safeAdd(baseStat.getSaleCount(), otherStat.getSaleCount()));
|
||||||
|
merged.setSaleAmount(safeAdd(baseStat.getSaleAmount(), otherStat.getSaleAmount()));
|
||||||
|
merged.setRefundCount(safeAdd(baseStat.getRefundCount(), otherStat.getRefundCount()));
|
||||||
|
merged.setRefundAmount(safeAdd(baseStat.getRefundAmount(), otherStat.getRefundAmount()));
|
||||||
|
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新计算合并后的有效数据
|
||||||
|
*/
|
||||||
|
private void recalculateValidData(ShopProdStatistic stat) {
|
||||||
|
if (stat != null) {
|
||||||
|
stat.setValidSaleCount(safeSubtract(stat.getSaleCount(), stat.getRefundCount()));
|
||||||
|
stat.setValidSaleAmount(safeSubtract(stat.getSaleAmount(), stat.getRefundAmount()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全的BigDecimal加法(处理null值)
|
||||||
|
*/
|
||||||
private BigDecimal safeAdd(BigDecimal num1, BigDecimal num2) {
|
private BigDecimal safeAdd(BigDecimal num1, BigDecimal num2) {
|
||||||
BigDecimal safeNum1 = num1 != null ? num1 : BigDecimal.ZERO;
|
BigDecimal safeNum1 = Optional.ofNullable(num1).orElse(BigDecimal.ZERO);
|
||||||
BigDecimal safeNum2 = num2 != null ? num2 : BigDecimal.ZERO;
|
BigDecimal safeNum2 = Optional.ofNullable(num2).orElse(BigDecimal.ZERO);
|
||||||
return safeNum1.add(safeNum2);
|
return safeNum1.add(safeNum2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全的BigDecimal减法(处理null值)
|
||||||
|
*/
|
||||||
|
private BigDecimal safeSubtract(BigDecimal num1, BigDecimal num2) {
|
||||||
|
BigDecimal safeNum1 = Optional.ofNullable(num1).orElse(BigDecimal.ZERO);
|
||||||
|
BigDecimal safeNum2 = Optional.ofNullable(num2).orElse(BigDecimal.ZERO);
|
||||||
|
return safeNum1.subtract(safeNum2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,360 +0,0 @@
|
|||||||
package com.czg.service.order.service.impl;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
|
||||||
import cn.hutool.crypto.SecureUtil;
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
|
|
||||||
import com.czg.account.entity.*;
|
|
||||||
import com.czg.account.service.*;
|
|
||||||
import com.czg.constants.PayTypeConstants;
|
|
||||||
import com.czg.entity.req.*;
|
|
||||||
import com.czg.entity.resp.CzgRefundResp;
|
|
||||||
import com.czg.enums.ShopUserFlowBizEnum;
|
|
||||||
import com.czg.exception.CzgException;
|
|
||||||
import com.czg.market.dto.MemberOrderDTO;
|
|
||||||
import com.czg.market.entity.MemberOrder;
|
|
||||||
import com.czg.market.entity.MkShopCouponRecord;
|
|
||||||
import com.czg.market.service.MemberOrderService;
|
|
||||||
import com.czg.market.service.MkShopCouponRecordService;
|
|
||||||
import com.czg.market.service.MkShopRechargeService;
|
|
||||||
import com.czg.market.vo.MkShopRechargeVO;
|
|
||||||
import com.czg.order.dto.CheckOrderPay;
|
|
||||||
import com.czg.order.dto.LtPayOtherDTO;
|
|
||||||
import com.czg.order.entity.OrderInfo;
|
|
||||||
import com.czg.order.entity.OrderPayment;
|
|
||||||
import com.czg.order.service.OrderInfoCustomService;
|
|
||||||
import com.czg.order.service.OrderPaymentService;
|
|
||||||
import com.czg.resp.CzgResult;
|
|
||||||
import com.czg.service.order.dto.VipMemberPayParamDTO;
|
|
||||||
import com.czg.service.order.dto.VipPayParamDTO;
|
|
||||||
import com.czg.service.order.dto.VipRefundDTO;
|
|
||||||
import com.czg.service.order.service.PayService;
|
|
||||||
import com.czg.service.order.service.ShopUserPayService;
|
|
||||||
import com.czg.utils.AssertUtil;
|
|
||||||
import com.czg.utils.CzgRandomUtils;
|
|
||||||
import com.mybatisflex.core.query.QueryWrapper;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.apache.dubbo.config.annotation.DubboReference;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ww
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class ShopUserServiceImpl implements ShopUserPayService {
|
|
||||||
@Resource
|
|
||||||
private PayService payService;
|
|
||||||
|
|
||||||
@DubboReference
|
|
||||||
private ShopUserService shopUserService;
|
|
||||||
@DubboReference
|
|
||||||
private UserInfoService userInfoService;
|
|
||||||
@DubboReference
|
|
||||||
private ShopInfoService shopInfoService;
|
|
||||||
@DubboReference
|
|
||||||
private FreeDineConfigService freeConfigService;
|
|
||||||
@Resource
|
|
||||||
private OrderInfoCustomService orderInfoCustomService;
|
|
||||||
@DubboReference
|
|
||||||
private MemberOrderService memberOrderService;
|
|
||||||
@Resource
|
|
||||||
private MkShopRechargeService shopRechargeService;
|
|
||||||
@DubboReference
|
|
||||||
private ShopUserFlowService userFlowService;
|
|
||||||
@Resource
|
|
||||||
private MkShopCouponRecordService recordService;
|
|
||||||
@Resource
|
|
||||||
private OrderPaymentService paymentService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 会员充值 校验
|
|
||||||
*
|
|
||||||
* @return 是否是霸王餐充值
|
|
||||||
*/
|
|
||||||
private boolean checkPayVip(VipPayParamDTO payParam) {
|
|
||||||
if (payParam.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
|
||||||
throw new CzgException("充值金额不正确");
|
|
||||||
}
|
|
||||||
if (payParam.getOrderId() != null) {
|
|
||||||
FreeDineConfig freeConfig = freeConfigService.getById(shopInfoService.getMainIdByShopId(payParam.getShopId()));
|
|
||||||
AssertUtil.isNull(freeConfig, "该店铺未启用霸王餐");
|
|
||||||
if (!freeConfig.getEnable()) {
|
|
||||||
throw new CzgException("该店铺未启用霸王餐");
|
|
||||||
}
|
|
||||||
CheckOrderPay checkOrderPay = payParam.getCheckOrderPay();
|
|
||||||
OrderInfo orderInfo = orderInfoCustomService.checkOrderPay(checkOrderPay.setFreeDine(true).setWithCoupon(freeConfig.getWithCoupon()).setWithPoints(freeConfig.getWithPoints()));
|
|
||||||
payParam.setAmount(orderInfo.getOrderAmount().multiply(BigDecimal.valueOf(freeConfig.getRechargeTimes())));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public CzgResult<Object> cashPayVip(VipPayParamDTO payParam) {
|
|
||||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
|
|
||||||
ShopInfo shopInfo = shopInfoService.getById(payParam.getShopId());
|
|
||||||
AssertUtil.isNull(shopInfo, "店铺不存在");
|
|
||||||
if (shopInfo.getIsMemberInPwd().equals(1)) {
|
|
||||||
AssertUtil.isBlank(shopInfo.getOperationPwd(), "请设置操作密码后使用");
|
|
||||||
AssertUtil.isBlank(payParam.getPwd(), "请输入操作密码后充值");
|
|
||||||
if (!shopInfo.getOperationPwd().equals(SecureUtil.md5(payParam.getPwd()))) {
|
|
||||||
return CzgResult.failure("支付密码错误");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if (shopUser.getIsVip().equals(0)) {
|
|
||||||
// //更新会员
|
|
||||||
// ShopUser updateInfo = new ShopUser();
|
|
||||||
// updateInfo.setIsVip(1);
|
|
||||||
// updateInfo.setJoinTime(LocalDateTime.now());
|
|
||||||
// updateInfo.setId(payParam.getShopUserId());
|
|
||||||
// shopUserService.updateById(updateInfo);
|
|
||||||
// }
|
|
||||||
shopRechargeService.recharge(shopUser.getMainShopId(), shopUser.getId(), payParam.getRechargeDetailId(),
|
|
||||||
payParam.getAmount(), null, "cash", ShopUserFlowBizEnum.CASH_IN, true);
|
|
||||||
return CzgResult.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public CzgResult<Map<String, Object>> jsPayVip(String clintIp, VipPayParamDTO payParam) {
|
|
||||||
boolean isFree = checkPayVip(payParam);
|
|
||||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
|
|
||||||
AssertUtil.isBlank(payParam.getOpenId(), "用户小程序ID不能为空");
|
|
||||||
AssertUtil.isBlank(payParam.getPayType(), "支付方式不能为空");
|
|
||||||
String payOrderNo = payParam.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
String payType = isFree ? PayTypeConstants.SourceType.FREE : PayTypeConstants.SourceType.MEMBER_IN;
|
|
||||||
payService.initOrderPayment(new OrderPayment(payParam.getShopId(), shopUser.getId(), payType, PayTypeConstants.PayType.PAY, payOrderNo,
|
|
||||||
"", payParam.getAmount(), isFree ? payParam.getOrderId() : payParam.getActivateId()));
|
|
||||||
return payService.jsPay(payParam.getShopId(), payParam.getPayType(), new CzgJsPayReq(payOrderNo, payParam.getAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
"会员充值", payParam.getOpenId(), clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public CzgResult<Map<String, Object>> ltPayMember(String clientIP, VipMemberPayParamDTO payParam) {
|
|
||||||
ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getMainShopId, shopInfoService.getMainIdByShopId(payParam.getShopId())).eq(ShopUser::getId, payParam.getShopUserId()));
|
|
||||||
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
|
|
||||||
MemberOrder memberOrder = memberOrderService.createMemberOrder(new MemberOrderDTO().setName(payParam.getName())
|
|
||||||
.setNum(1).setNickName(payParam.getNickName()).setOrderType(payParam.getOrderType())
|
|
||||||
.setPlatformType(payParam.getPlatformType()).setSex(payParam.getSex()).setUserId(shopUser.getUserId())
|
|
||||||
.setShopId(payParam.getShopId()).setBirthDay(payParam.getBirthDay()));
|
|
||||||
AssertUtil.isBlank(payParam.getOpenId(), "用户小程序ID不能为空");
|
|
||||||
AssertUtil.isBlank(payParam.getPayType(), "支付方式不能为空");
|
|
||||||
|
|
||||||
LtPayOtherDTO payParam1 = new LtPayOtherDTO()
|
|
||||||
.setOpenId(payParam.getOpenId())
|
|
||||||
.setPayType(payParam.getPayType())
|
|
||||||
.setShopId(payParam.getShopId())
|
|
||||||
.setRecordId(shopUser.getId())
|
|
||||||
.setPrice(memberOrder.getAmount())
|
|
||||||
.setIp(clientIP);
|
|
||||||
return payService.ltPayOther(payParam1, PayTypeConstants.SourceType.MEMBER_PAY, "会员充值");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public CzgResult<Map<String, Object>> ltPayVip(String clintIp, VipPayParamDTO payParam) {
|
|
||||||
// 霸王餐校验
|
|
||||||
boolean isFree = checkPayVip(payParam);
|
|
||||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
|
|
||||||
AssertUtil.isBlank(payParam.getOpenId(), "用户小程序ID不能为空");
|
|
||||||
AssertUtil.isBlank(payParam.getPayType(), "支付方式不能为空");
|
|
||||||
|
|
||||||
MkShopRechargeVO rechargeVO = shopRechargeService.detail(payParam.getShopId());
|
|
||||||
if (payParam.getRechargeDetailId() == null && rechargeVO.getIsCustom() == 0) {
|
|
||||||
throw new CzgException("未开启自定义充值金额");
|
|
||||||
}
|
|
||||||
Long mainShopId = shopInfoService.getMainIdByShopId(payParam.getShopId());
|
|
||||||
if (isFree) {
|
|
||||||
BigDecimal amount = shopRechargeService.checkRecharge(mainShopId, payParam.getShopId(), shopUser.getUserId(), payParam.getRechargeDetailId(), payParam.getAmount());
|
|
||||||
payParam.setAmount(amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
String payType = isFree ? PayTypeConstants.SourceType.FREE : PayTypeConstants.SourceType.MEMBER_IN;
|
|
||||||
LtPayOtherDTO payParam1 = new LtPayOtherDTO()
|
|
||||||
.setOpenId(payParam.getOpenId())
|
|
||||||
.setPayType(payParam.getPayType())
|
|
||||||
.setShopId(payParam.getShopId())
|
|
||||||
.setRecordId(shopUser.getId())
|
|
||||||
.setPrice(payParam.getAmount())
|
|
||||||
.setIp(clintIp);
|
|
||||||
return payService.ltPayOther(payParam1, payType, "会员充值");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CzgResult<Map<String, Object>> recharge(String clientIP, VipPayParamDTO rechargeDTO, Long shopUserId) {
|
|
||||||
boolean isFree = checkPayVip(rechargeDTO);
|
|
||||||
Long mainShopId = shopInfoService.getMainIdByShopId(rechargeDTO.getShopId());
|
|
||||||
|
|
||||||
ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getMainShopId, mainShopId)
|
|
||||||
.eq(ShopUser::getId, shopUserId));
|
|
||||||
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
|
|
||||||
MkShopRechargeVO rechargeVO = shopRechargeService.detail(rechargeDTO.getShopId());
|
|
||||||
if (rechargeDTO.getRechargeDetailId() == null && rechargeVO.getIsCustom() == 0) {
|
|
||||||
throw new CzgException("未开启自定义充值金额");
|
|
||||||
}
|
|
||||||
UserInfo userInfo = userInfoService.getById(shopUser.getUserId());
|
|
||||||
BigDecimal amount = shopRechargeService.checkRecharge(mainShopId, rechargeDTO.getShopId(), shopUser.getUserId(), rechargeDTO.getRechargeDetailId(), rechargeDTO.getAmount());
|
|
||||||
String payType = isFree ? PayTypeConstants.SourceType.FREE : PayTypeConstants.SourceType.MEMBER_IN;
|
|
||||||
|
|
||||||
LtPayOtherDTO payParam = new LtPayOtherDTO()
|
|
||||||
.setOpenId("wechatPay".equals(rechargeDTO.getPayType()) ? userInfo.getWechatOpenId() : userInfo.getAlipayOpenId())
|
|
||||||
.setPayType(rechargeDTO.getPayType())
|
|
||||||
.setShopId(rechargeDTO.getShopId())
|
|
||||||
.setRecordId(shopUser.getId())
|
|
||||||
.setPrice(amount)
|
|
||||||
.setIp(clientIP);
|
|
||||||
return payService.ltPayOther(payParam, payType, "会员充值");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public CzgResult<Map<String, Object>> scanPayVip(String clintIp, VipPayParamDTO payParam) {
|
|
||||||
boolean isFree = checkPayVip(payParam);
|
|
||||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
|
|
||||||
String payOrderNo = payParam.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
String payType = isFree ? PayTypeConstants.SourceType.FREE : PayTypeConstants.SourceType.MEMBER_IN;
|
|
||||||
payService.initOrderPayment(new OrderPayment(payParam.getShopId(), shopUser.getId(), payType, PayTypeConstants.PayType.PAY, payOrderNo,
|
|
||||||
"", payParam.getAmount(), isFree ? payParam.getOrderId() : payParam.getActivateId()));
|
|
||||||
return payService.scanPay(payParam.getShopId(), new CzgScanPayReq(payOrderNo, payParam.getAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
"会员充值", clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public CzgResult<Map<String, Object>> microPayVip(VipPayParamDTO payParam) {
|
|
||||||
boolean isFree = checkPayVip(payParam);
|
|
||||||
AssertUtil.isBlank(payParam.getAuthCode(), "扫描码不能为空");
|
|
||||||
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
|
|
||||||
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
|
|
||||||
String payOrderNo = payParam.getPlatformType() + CzgRandomUtils.snowflake();
|
|
||||||
String payType = isFree ? PayTypeConstants.SourceType.FREE : PayTypeConstants.SourceType.MEMBER_IN;
|
|
||||||
payService.initOrderPayment(new OrderPayment(payParam.getShopId(), shopUser.getId(), payType, PayTypeConstants.PayType.PAY, payOrderNo,
|
|
||||||
payParam.getAuthCode(), payParam.getAmount(), isFree ? payParam.getOrderId() : payParam.getActivateId()));
|
|
||||||
CzgResult<Map<String, Object>> mapCzgResult = payService.microPay(payParam.getShopId(), new CzgMicroPayReq(payOrderNo, payParam.getAmount().multiply(PayService.MONEY_RATE).longValue(),
|
|
||||||
"会员充值", payParam.getAuthCode(), payParam.getBuyerRemark(), ""));
|
|
||||||
mapCzgResult.setData(Map.of("payOrderNo", payOrderNo));
|
|
||||||
return mapCzgResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CzgResult<Map<String, BigDecimal>> refundVipBefore(VipRefundDTO payParam) {
|
|
||||||
Map<String, BigDecimal> resultMap = new HashMap<>(5);
|
|
||||||
ShopUser shopUser = shopUserService.getShopUserInfo(payParam.getShopId(), payParam.getUserId());
|
|
||||||
AssertUtil.isNull(shopUser, "该店铺用户不存在");
|
|
||||||
ShopUserFlow inFlow = userFlowService.getById(payParam.getFlowId());
|
|
||||||
AssertUtil.isNull(inFlow, "充值记录不存在");
|
|
||||||
QueryWrapper queryWrapper = new QueryWrapper();
|
|
||||||
queryWrapper.eq(ShopUserFlow::getRelationId, payParam.getFlowId());
|
|
||||||
queryWrapper.eq(ShopUserFlow::getBizCode, ShopUserFlowBizEnum.AWARD_IN.getCode());
|
|
||||||
ShopUserFlow giftFlow = userFlowService.getOne(queryWrapper);
|
|
||||||
resultMap.put("amount", shopUser.getAmount());
|
|
||||||
resultMap.put("inAmount", inFlow.getAmount());
|
|
||||||
resultMap.put("inRefundAmount", inFlow.getRefundAmount());
|
|
||||||
resultMap.put("giftAmount", giftFlow == null ? BigDecimal.ZERO : giftFlow.getAmount());
|
|
||||||
resultMap.put("giftRefundAmount", giftFlow == null ? BigDecimal.ZERO : giftFlow.getRefundAmount());
|
|
||||||
return CzgResult.success(resultMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public CzgResult<Object> refundVip(VipRefundDTO refPayParam) {
|
|
||||||
ShopInfo shopInfo = shopInfoService.getById(refPayParam.getShopId());
|
|
||||||
if (shopInfo.getIsReturnPwd().equals(1)) {
|
|
||||||
AssertUtil.isBlank(shopInfo.getOperationPwd(), "请设置操作密码后使用");
|
|
||||||
if (!SecureUtil.md5(refPayParam.getPwd()).equals(shopInfo.getOperationPwd())) {
|
|
||||||
throw new CzgException("操作密码错误");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ShopUser shopUser = shopUserService.getShopUserInfo(refPayParam.getShopId(), refPayParam.getUserId());
|
|
||||||
ShopUserFlow inFlow = userFlowService.getById(refPayParam.getFlowId());
|
|
||||||
AssertUtil.isNull(inFlow, "充值记录不存在");
|
|
||||||
if ("cashIn".equals(inFlow.getBizCode()) || "adminIn".equals(inFlow.getBizCode())) {
|
|
||||||
refPayParam.setCashRefund(true);
|
|
||||||
}
|
|
||||||
QueryWrapper queryWrapper = new QueryWrapper();
|
|
||||||
queryWrapper.eq(ShopUserFlow::getRelationId, refPayParam.getFlowId());
|
|
||||||
queryWrapper.eq(ShopUserFlow::getBizCode, ShopUserFlowBizEnum.AWARD_IN.getCode());
|
|
||||||
ShopUserFlow giftFlow = userFlowService.getOne(queryWrapper);
|
|
||||||
if ((inFlow.getAmount().subtract(inFlow.getRefundAmount())).compareTo(refPayParam.getRefAmount()) < 0) {
|
|
||||||
return CzgResult.failure("退款失败,退款金额不可大于可退金额");
|
|
||||||
}
|
|
||||||
//用户余额减去赠送金额 小于 退款金额 则需要勾选 超额退款
|
|
||||||
if (giftFlow != null) {
|
|
||||||
if (shopUser.getAmount().subtract(giftFlow.getAmount().subtract(giftFlow.getRefundAmount())).compareTo(refPayParam.getRefAmount()) < 0 && !refPayParam.isOutOfRange()) {
|
|
||||||
return CzgResult.failure("超额退款,请勾选 超额退款后重试");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (shopUser.getAmount().compareTo(refPayParam.getRefAmount()) < 0 && !refPayParam.isOutOfRange()) {
|
|
||||||
return CzgResult.failure("超额退款,请勾选 超额退款后重试");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Long refPaymentId = null;
|
|
||||||
if (!refPayParam.isCashRefund()) {
|
|
||||||
OrderPayment payment;
|
|
||||||
if (inFlow.getRelationId() != null) {
|
|
||||||
payment = paymentService.getById(inFlow.getRelationId());
|
|
||||||
} else {
|
|
||||||
return CzgResult.failure("退款失败,该充值记录不存在");
|
|
||||||
}
|
|
||||||
String refPayOrderNo = "REFVIP" + IdUtil.getSnowflakeNextId();
|
|
||||||
refPaymentId = payService.initOrderPayment(new OrderPayment(refPayParam.getShopId(), shopUser.getId(),
|
|
||||||
PayTypeConstants.SourceType.MEMBER_IN, PayTypeConstants.PayType.REFUND, refPayOrderNo, null, refPayParam.getRefAmount()));
|
|
||||||
CzgResult<CzgRefundResp> refund = payService.refund(refPayParam.getShopId(), new CzgRefundReq(refPayOrderNo, refPayParam.getRemark(),
|
|
||||||
refPayParam.getRefAmount().multiply(PayService.MONEY_RATE).longValue(), payment.getOrderNo(), ""));
|
|
||||||
if (refund.getCode() != 200 || refund.getData() == null || !"SUCCESS".equals(refund.getData().getState())) {
|
|
||||||
throw new CzgException(refund.getMsg());
|
|
||||||
} else {
|
|
||||||
paymentService.updateChain()
|
|
||||||
.eq(OrderPayment::getId, refPaymentId)
|
|
||||||
.set(OrderPayment::getPayTime, refund.getData().getRefundTime())
|
|
||||||
.set(OrderPayment::getTradeNumber, refund.getData().getRefundOrderId())
|
|
||||||
.set(OrderPayment::getPayStatus, PayTypeConstants.PayStatus.SUCCESS)
|
|
||||||
.set(OrderPayment::getRespJson, JSONObject.toJSONString(refund.getData()))
|
|
||||||
.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
|
|
||||||
.setId(shopUser.getId())
|
|
||||||
.setMoney(refPayParam.getRefAmount())
|
|
||||||
.setType(0)
|
|
||||||
.setRemark("退款")
|
|
||||||
.setBizEnum(refPayParam.isCashRefund() ? ShopUserFlowBizEnum.RECHARGE_CASH_REFUND : ShopUserFlowBizEnum.RECHARGE_REFUND)
|
|
||||||
.setRelationId(refPaymentId)
|
|
||||||
.setRechargeId(inFlow.getId());
|
|
||||||
//更新会员余额 并生成流水
|
|
||||||
shopUserService.updateMoney(shopUserMoneyEditDTO);
|
|
||||||
userFlowService.updateRefund(inFlow.getId(), refPayParam.getRefAmount());
|
|
||||||
if (giftFlow != null && (giftFlow.getAmount().subtract(giftFlow.getRefundAmount())).compareTo(BigDecimal.ZERO) > 0) {
|
|
||||||
ShopUserMoneyEditDTO giftFlowEdit = new ShopUserMoneyEditDTO()
|
|
||||||
.setId(shopUser.getId())
|
|
||||||
.setMoney(giftFlow.getAmount())
|
|
||||||
.setType(0)
|
|
||||||
.setRemark("退款")
|
|
||||||
.setBizEnum(ShopUserFlowBizEnum.RECHARGE_REFUND)
|
|
||||||
.setRelationId(refPaymentId)
|
|
||||||
.setRechargeId(giftFlow.getId());
|
|
||||||
//更新会员余额 并生成流水
|
|
||||||
shopUserService.updateMoney(giftFlowEdit);
|
|
||||||
userFlowService.updateRefund(giftFlow.getId(), giftFlow.getAmount());
|
|
||||||
}
|
|
||||||
//移除优惠券
|
|
||||||
recordService.remove(QueryWrapper.create()
|
|
||||||
.eq(MkShopCouponRecord::getSourceFlowId, inFlow.getId())
|
|
||||||
.eq(MkShopCouponRecord::getSource, "activate")
|
|
||||||
.eq(MkShopCouponRecord::getStatus, 0));
|
|
||||||
return CzgResult.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
package com.czg.service.order.utils;
|
|
||||||
|
|
||||||
import cn.hutool.core.lang.func.Func0;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Administrator
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class FunUtil {
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
public static int retryCount = 5;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行任务并保证锁唯一
|
|
||||||
* @param supplier 业务逻辑
|
|
||||||
* @param lockKey Redis锁的Key
|
|
||||||
* @return 业务逻辑返回值
|
|
||||||
*/
|
|
||||||
public <T> T runFunAndCheckKey(Supplier<T> supplier, String lockKey) {
|
|
||||||
String lockValue = String.valueOf(System.nanoTime() + Thread.currentThread().threadId());
|
|
||||||
try {
|
|
||||||
// 尝试获取锁,超时时间 5 秒,防止死锁
|
|
||||||
boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
|
|
||||||
int count = 0;
|
|
||||||
// 初始等待 10ms
|
|
||||||
int retryDelay = 10;
|
|
||||||
|
|
||||||
while (!lock) {
|
|
||||||
// 最多重试 10 次,大约 10 秒
|
|
||||||
if (count++ > 50) {
|
|
||||||
throw new RuntimeException("系统繁忙, 稍后再试");
|
|
||||||
}
|
|
||||||
Thread.sleep(retryDelay);
|
|
||||||
// 指数退避,最大等待 200ms
|
|
||||||
retryDelay = Math.min(retryDelay * 2, 200);
|
|
||||||
lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行任务
|
|
||||||
return supplier.get();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
throw new RuntimeException("线程被中断", e);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("执行出错:{}", e.getMessage(), e);
|
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
// 释放锁(使用 Lua 脚本确保原子性)
|
|
||||||
unlock(lockKey, lockValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 Lua 脚本确保释放锁的原子性
|
|
||||||
* @param lockKey 锁的 Key
|
|
||||||
* @param lockValue 当前线程的锁值
|
|
||||||
*/
|
|
||||||
private void unlock(String lockKey, String lockValue) {
|
|
||||||
String luaScript =
|
|
||||||
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
|
|
||||||
"return redis.call('del', KEYS[1]) " +
|
|
||||||
"else return 0 end";
|
|
||||||
redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class),
|
|
||||||
Collections.singletonList(lockKey), lockValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T, R> R runFunAndRetry(
|
|
||||||
Supplier<R> function,
|
|
||||||
Function<R, Boolean> check, Consumer<R> errFun) {
|
|
||||||
log.info("工具类开始执行函数");
|
|
||||||
R result = function.get();
|
|
||||||
boolean flag = check.apply(result);
|
|
||||||
|
|
||||||
log.info("执行结果: {}", result);
|
|
||||||
|
|
||||||
while (flag && retryCount-- > 0) {
|
|
||||||
log.info("执行函数失败, 剩余尝试次数{}", retryCount);
|
|
||||||
result = function.get();
|
|
||||||
log.info("执行结果: {}", result);
|
|
||||||
flag = check.apply(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag) {
|
|
||||||
errFun.accept(result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 防抖函数:在指定秒数内相同 Key 的任务只会执行一次
|
|
||||||
* @param key 防抖使用的 Redis Key
|
|
||||||
* @param seconds 防抖时间(秒)
|
|
||||||
* @param task 要执行的业务逻辑
|
|
||||||
* @return true 执行了任务;false 在防抖期内被拦截
|
|
||||||
*/
|
|
||||||
public boolean debounce(String key, long seconds, Runnable task) {
|
|
||||||
try {
|
|
||||||
Boolean success = redisTemplate.opsForValue().setIfAbsent(
|
|
||||||
key, "1", seconds, TimeUnit.SECONDS
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Boolean.TRUE.equals(success)) {
|
|
||||||
task.run();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("防抖函数执行失败 key={} err={}", key, e.getMessage(), e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
36
cash-service/pay-service/pom.xml
Normal file
36
cash-service/pay-service/pom.xml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?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">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.czg</groupId>
|
||||||
|
<artifactId>cash-service</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>pay-service</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.javen205</groupId>
|
||||||
|
<artifactId>IJPay-All</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.czg</groupId>
|
||||||
|
<artifactId>czg-pay</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.czg</groupId>
|
||||||
|
<artifactId>aggregation-pay</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.czg.service;
|
||||||
|
|
||||||
|
import com.czg.entity.notify.CzgPayNotifyDTO;
|
||||||
|
import com.czg.entity.notify.CzgRefundNotifyDTO;
|
||||||
|
import com.czg.entity.req.*;
|
||||||
|
import com.czg.entity.resp.*;
|
||||||
|
import com.czg.resp.CzgResult;
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ww
|
||||||
|
* @description
|
||||||
|
*/
|
||||||
|
public interface CzgPayService {
|
||||||
|
/**
|
||||||
|
* h5支付
|
||||||
|
*
|
||||||
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
|
*/
|
||||||
|
CzgResult<CzgH5PayResp> h5Pay(@NonNull String appId, @NonNull String appSecret, CzgH5PayReq bizData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* js支付
|
||||||
|
*
|
||||||
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
|
*/
|
||||||
|
CzgResult<CzgJsPayResp> jsPay(@NonNull String appId, @NonNull String appSecret, CzgJsPayReq bizData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序支付
|
||||||
|
*
|
||||||
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
|
*/
|
||||||
|
CzgResult<CzgLtPayResp> ltPay(@NonNull String appId, @NonNull String appSecret, CzgLtPayReq bizData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PC扫码支付
|
||||||
|
*
|
||||||
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
|
*/
|
||||||
|
CzgResult<CzgScanPayResp> scanPay(@NonNull String appId, @NonNull String appSecret, CzgScanPayReq bizData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚合反扫
|
||||||
|
*
|
||||||
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
|
*/
|
||||||
|
CzgResult<CzgMicroPayResp> microPay(@NonNull String appId, @NonNull String appSecret, CzgMicroPayReq bizData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单查询
|
||||||
|
*
|
||||||
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
|
* @param payOrderId 平台订单号
|
||||||
|
* @param mchOrderNo 商户订单号
|
||||||
|
*/
|
||||||
|
CzgResult<CzgBaseResp> queryPayOrder(@NonNull String appId, @NonNull String appSecret,
|
||||||
|
String payOrderId, String mchOrderNo);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单退款
|
||||||
|
*
|
||||||
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
|
*/
|
||||||
|
CzgResult<CzgRefundResp> refundOrder(@NonNull String appId, @NonNull String appSecret, CzgRefundReq bizData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款订单查询
|
||||||
|
*
|
||||||
|
* @param appId 应用id tb_shop_merchant 表中的 app_id
|
||||||
|
* @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
|
||||||
|
* @param mchRefundNo 商户退款订单号 二选一
|
||||||
|
* @param refundOrderId 平台退款订单号 二选一
|
||||||
|
*/
|
||||||
|
CzgResult<CzgRefundResp> queryRefundOrder(@NonNull String appId, @NonNull String appSecret,
|
||||||
|
String mchRefundNo, String refundOrderId);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package com.czg.service.Impl;
|
||||||
|
|
||||||
|
import com.czg.CzgPayUtils;
|
||||||
|
import com.czg.constants.ParamCodeCst;
|
||||||
|
import com.czg.entity.req.*;
|
||||||
|
import com.czg.entity.resp.*;
|
||||||
|
import com.czg.resp.CzgResult;
|
||||||
|
import com.czg.service.CzgPayService;
|
||||||
|
import com.czg.system.service.SysParamsService;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ww
|
||||||
|
* @description 1
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class CzgPayServiceImpl implements CzgPayService {
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private SysParamsService sysParamsService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<CzgH5PayResp> h5Pay(@NonNull String appId, @NonNull String appSecret, CzgH5PayReq bizData) {
|
||||||
|
return CzgPayUtils.h5Pay(sysParamsService.getSysParamValue(ParamCodeCst.System.PAY_CZG_DOMAIN), appId, appSecret, bizData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<CzgJsPayResp> jsPay(@NonNull String appId, @NonNull String appSecret, CzgJsPayReq bizData) {
|
||||||
|
return CzgPayUtils.jsPay(sysParamsService.getSysParamValue(ParamCodeCst.System.PAY_CZG_DOMAIN), appId, appSecret, bizData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<CzgLtPayResp> ltPay(@NonNull String appId, @NonNull String appSecret, CzgLtPayReq bizData) {
|
||||||
|
return CzgPayUtils.ltPay(sysParamsService.getSysParamValue(ParamCodeCst.System.PAY_CZG_DOMAIN), appId, appSecret, bizData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<CzgScanPayResp> scanPay(@NonNull String appId, @NonNull String appSecret, CzgScanPayReq bizData) {
|
||||||
|
return CzgPayUtils.scanPay(sysParamsService.getSysParamValue(ParamCodeCst.System.PAY_CZG_DOMAIN), appId, appSecret, bizData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<CzgMicroPayResp> microPay(@NonNull String appId, @NonNull String appSecret, CzgMicroPayReq bizData) {
|
||||||
|
return CzgPayUtils.microPay(sysParamsService.getSysParamValue(ParamCodeCst.System.PAY_CZG_DOMAIN), appId, appSecret, bizData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<CzgBaseResp> queryPayOrder(@NonNull String appId, @NonNull String appSecret, String payOrderId, String mchOrderNo) {
|
||||||
|
return CzgPayUtils.queryPayOrder(sysParamsService.getSysParamValue(ParamCodeCst.System.PAY_CZG_DOMAIN), appId, appSecret, payOrderId, mchOrderNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<CzgRefundResp> refundOrder(@NonNull String appId, @NonNull String appSecret, CzgRefundReq bizData) {
|
||||||
|
return CzgPayUtils.refundOrder(sysParamsService.getSysParamValue(ParamCodeCst.System.PAY_CZG_DOMAIN), appId, appSecret, bizData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CzgResult<CzgRefundResp> queryRefundOrder(@NonNull String appId, @NonNull String appSecret, String mchRefundNo, String refundOrderId) {
|
||||||
|
return CzgPayUtils.queryRefundOrder(sysParamsService.getSysParamValue(ParamCodeCst.System.PAY_CZG_DOMAIN), appId, appSecret, mchRefundNo, refundOrderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
<module>product-service</module>
|
<module>product-service</module>
|
||||||
<module>system-service</module>
|
<module>system-service</module>
|
||||||
<module>code-generator</module>
|
<module>code-generator</module>
|
||||||
|
<module>pay-service</module>
|
||||||
<module>market-service</module>
|
<module>market-service</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user