From c6231ce4d2dfa2615b9c8a033e2ffaa86cc7eddc Mon Sep 17 00:00:00 2001 From: dzc <2388224167@qq.com> Date: Thu, 8 May 2025 09:51:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E7=AC=AC=E4=B8=89=E6=96=B9=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=B5=81=E6=B0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hard/api/dto/async/OfflineOrder.java | 5 +- .../hard/api/dto/hard/HardOfflinePayDto.java | 12 ++++ .../hard/api/vo/order/HardOrderVo.java | 7 +++ .../controller/hard/HardApiController.java | 2 +- .../controller/order/HardOrderController.java | 11 ++++ .../hard/mapper/order/HardOrderMapper.java | 15 +++++ .../hard/service/HardOrderSyncService.java | 4 ++ .../impl/order/HardOrderSyncServiceImpl.java | 57 +++++++++++++++++- .../impl/third/HardThirdPayServiceImpl.java | 6 +- .../mapper/order/HardOrderMapper.xml | 8 ++- .../impl/pay/ThirdPayApiServiceImpl.java | 4 ++ .../src/main/resources/application.yml | 4 +- .../src/main/resources/doc/第三方支付文档.wps | Bin 130560 -> 130048 bytes .../java/com/bsd/pjcloud/admin/PayTest.java | 14 +++++ 14 files changed, 137 insertions(+), 12 deletions(-) create mode 100644 pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/dto/hard/HardOfflinePayDto.java diff --git a/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/dto/async/OfflineOrder.java b/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/dto/async/OfflineOrder.java index 91b75025..d21281bb 100644 --- a/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/dto/async/OfflineOrder.java +++ b/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/dto/async/OfflineOrder.java @@ -7,6 +7,7 @@ import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.time.LocalDateTime; import java.util.Date; import java.util.List; @@ -70,10 +71,10 @@ public class OfflineOrder { private Double weight; @Schema(description = "支付时间") - private String payTime; + private LocalDateTime payTime; @Schema(description = "创建时间") - private Date createTime; + private LocalDateTime createTime; @Schema(description = "购物车列表") private List carList; diff --git a/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/dto/hard/HardOfflinePayDto.java b/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/dto/hard/HardOfflinePayDto.java new file mode 100644 index 00000000..41b2fba5 --- /dev/null +++ b/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/dto/hard/HardOfflinePayDto.java @@ -0,0 +1,12 @@ +package com.bsd.pjcloud.hard.api.dto.hard; + +import lombok.Data; + +import java.util.List; + +@Data +public class HardOfflinePayDto { + + private List orderIds; + +} diff --git a/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/vo/order/HardOrderVo.java b/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/vo/order/HardOrderVo.java index 2f01ab08..129ba706 100644 --- a/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/vo/order/HardOrderVo.java +++ b/pjcloud-hardware/pjcloud-hardware-api/src/main/java/com/bsd/pjcloud/hard/api/vo/order/HardOrderVo.java @@ -51,4 +51,11 @@ public class HardOrderVo extends HardOrderEntity implements BaseUserInterface, B * 预约二维码信息 */ private String reserveCode; + + /** + * 退款相关 + */ + private Long afterSaleId; + + private String afterSaleNo; } diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/hard/HardApiController.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/hard/HardApiController.java index cbb3446c..fc55a87d 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/hard/HardApiController.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/hard/HardApiController.java @@ -96,7 +96,7 @@ public class HardApiController { @PostMapping("/sync-offline-order") @Operation(summary = "同步离线订单") - @Idempotent(expireTime = 10, info = "正在处理中,请勿重复操作") + @Idempotent(expireTime = 1, info = "正在处理中,请勿重复操作") public R> syncOfflineOrder(@Valid @RequestBody SyncOfflineReqVo dto) { return R.ok(hardOrderSyncService.syncOfflineOrder(dto)); } diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/order/HardOrderController.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/order/HardOrderController.java index f81378aa..e16c81f1 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/order/HardOrderController.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/order/HardOrderController.java @@ -28,6 +28,7 @@ import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum; import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum; import com.bsd.pjcloud.hard.api.dto.app.HardAppCreateOrderScancode; import com.bsd.pjcloud.hard.api.dto.hard.CurrentUserHardTypeInfoDto; +import com.bsd.pjcloud.hard.api.dto.hard.HardOfflinePayDto; import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto; import com.bsd.pjcloud.hard.api.dto.order.HardOrderPreferencesDto; import com.bsd.pjcloud.hard.api.dto.order.app.HardAppCreateOrderDto; @@ -37,6 +38,7 @@ import com.bsd.pjcloud.hard.api.vo.order.excel.HardOrderExcelVo; import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper; import com.bsd.pjcloud.hard.service.HardManagerService; import com.bsd.pjcloud.hard.service.HardOrderService; +import com.bsd.pjcloud.hard.service.HardOrderSyncService; import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum; import com.bsd.pjcloud.wallet.api.feign.RemoteMchService; import com.bsd.pjcloud.wallet.api.vo.MchManageVo; @@ -73,6 +75,7 @@ public class HardOrderController { private final HardOrderService hardwareOrderService; private final HardManagerService hardManagerService; + private final HardOrderSyncService hardOrderSyncService; private final HardOrderMapper hardOrderMapper; @@ -227,6 +230,14 @@ public class HardOrderController { return R.ok(hardwareOrderService.join(id)); } + @Operation(summary = "离线订单手动支付", description = "离线订单手动支付") + @PostMapping("/offline-pay") + @PreAuthorize("@pms.hasPermission('hard_hardwareOrder_offlinePay')") + public R offlinePay(@RequestBody HardOfflinePayDto dto) { + hardOrderSyncService.offlinePay(dto.getOrderIds()); + return R.ok(); + } + @GetMapping("/export") @PreAuthorize("@pms.hasPermission('hard_hardwareOrder_export')") public void export(HttpServletResponse response, HardOrderDto dto) throws IOException { diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/mapper/order/HardOrderMapper.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/mapper/order/HardOrderMapper.java index 20535d00..e78b43f1 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/mapper/order/HardOrderMapper.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/mapper/order/HardOrderMapper.java @@ -4,8 +4,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum; import com.bsd.pjcloud.common.data.datascope.DataScope; import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum; import com.bsd.pjcloud.hard.api.dto.order.HardChartLatitudeVo; import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto; import com.bsd.pjcloud.hard.api.dto.order.HardOrderSumAndCountDto; @@ -89,6 +91,19 @@ public interface HardOrderMapper extends PjcloudBaseMapper { return selectJoinOne(HardOrderVo.class, wrapper); } + /** + * 查询离线订单 + */ + default List getOfflineOrderList(List orderIds) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper() + .in(HardOrderEntity::getId, orderIds) + .eq(HardOrderEntity::getOrderStatus, HardOrderStatusEnum.OFFLINE_CREATE.getType()) + .eq(HardOrderEntity::getIsOfflineOrder, YesNoEnum.YES.getCode()) + .orderByDesc(HardOrderEntity::getCreateTime) + .orderByDesc(HardOrderEntity::getId); + return selectList(wrapper); + } + default List list(HardOrderDto dto) { return selectListByScope(commonWrapper(dto), DataScope.of()); } diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/HardOrderSyncService.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/HardOrderSyncService.java index 843c4022..745cc5d3 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/HardOrderSyncService.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/HardOrderSyncService.java @@ -14,4 +14,8 @@ public interface HardOrderSyncService { */ List syncOfflineOrder(@Valid SyncOfflineReqVo dto); + /** + * 离线订单手动支付 + */ + void offlinePay(List orderIds); } diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderSyncServiceImpl.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderSyncServiceImpl.java index ec838985..45c7748b 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderSyncServiceImpl.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderSyncServiceImpl.java @@ -5,6 +5,8 @@ import cn.hutool.extra.spring.SpringUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.hard.api.constant.HardTypeEnum; import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum; import com.bsd.pjcloud.hard.api.dto.async.OfflineCar; import com.bsd.pjcloud.hard.api.dto.async.OfflineOrder; @@ -12,11 +14,15 @@ import com.bsd.pjcloud.hard.api.dto.async.SyncOfflineReqVo; import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity; import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity; import com.bsd.pjcloud.hard.api.entity.order.HardParentCarEntity; +import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper; import com.bsd.pjcloud.hard.service.HardCarService; import com.bsd.pjcloud.hard.service.HardOrderSyncService; import com.bsd.pjcloud.hard.service.HardOrderService; import com.bsd.pjcloud.hard.service.HardParentCarService; +import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum; +import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity; import com.bsd.pjcloud.wallet.api.feign.RemoteMchService; +import com.bsd.pjcloud.wallet.api.feign.RemoteWalletService; import com.bsd.pjcloud.wallet.api.feign.RemoteWalletSettingService; import com.bsd.pjcloud.wallet.api.vo.MchManageVo; import com.bsd.pjcloud.wallet.api.vo.WalletSettingVo; @@ -27,7 +33,9 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** * 订单同步 @@ -40,12 +48,16 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { static private final String TAG = "订单同步"; - private final RemoteMchService remoteMchService; - private final RemoteWalletSettingService walletSettingService; private final HardCarService hardCarService; private final HardParentCarService hardParentCarService; private final HardOrderService orderService; + private final HardOrderMapper hardOrderMapper; + + private final RemoteMchService remoteMchService; + private final RemoteWalletSettingService walletSettingService; + private final RemoteWalletService walletService; + @Override @Transactional(rollbackFor = Exception.class) public List syncOfflineOrder(SyncOfflineReqVo body) { @@ -58,7 +70,7 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { if (ObjectUtil.isNotEmpty(setting) && ObjectUtil.isNotEmpty(setting.getOffLineOrderApplyEnable())) { offLineOrderApplyEnable = ObjectUtil.equals(setting.getOffLineOrderApplyEnable(), YesNoEnum.YES.getCode()); } - List createIdList = List.of(); + List createIdList = new ArrayList<>(); List list = body.getList(); for (OfflineOrder i : list) { if (ObjectUtil.isEmpty(i.getCarList())) { @@ -75,6 +87,19 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { HardOrderEntity order = parseOrder(i, body.getHardwareId(), body.getMerchantId(), merchant.getDeptId()); HardParentCarEntity parentCar = parseParentCar(i, body.getMerchantId()); List carList = i.getCarList().stream().map(this::parseCar).toList(); + + // 查询钱包 + WalletManageEntity wallet = null; + if (ObjectUtil.isNotEmpty(merchant.getDefaultWalletTypeId())) { + wallet = walletService.getWallet(order.getUserId(), WalletTypeEnum.EAT).getData(); + } else { + wallet = walletService.getWalletByWalletTypeId(order.getUserId(), merchant.getDefaultWalletTypeId()).getData(); + } + if (ObjectUtil.isEmpty(wallet)) { + log.error("|{}|同步安卓机离线订单,钱包不存在order:{}", TAG, JSON.toJSONString(i)); + continue; + } + order.setWalletId(wallet.getId()); if (!ObjectUtil.isAllNotEmpty(order, parentCar, carList)) { log.error("|{}|同步安卓机离线订单,order、parentCar、carList任意一个为空order:{}", TAG, JSON.toJSONString(i)); continue; @@ -85,6 +110,31 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { return createIdList; } + /** + * 离线订单手动支付 + */ + @Override + public void offlinePay(List orderIds) { + // 查询离线订单 + List list = hardOrderMapper.getOfflineOrderList(orderIds); + if (ObjectUtil.isEmpty(list)) return; + for (HardOrderEntity v : list) { + getSelf().offlinePay(v); + } + } + + /** + * 离线订单手动支付 + */ + @Transactional(rollbackFor = Exception.class) + public void offlinePay(HardOrderEntity order) { + // 支付 + orderService.fastReduceBalance(order); + // 标记离线支付成功 + HardOrderEntity updateObj = HardOrderEntity.builder().id(order.getId()).offlinePaySuccess(YesNoEnum.YES.getCode()).build(); + orderService.updateById(updateObj); + } + // 同步安卓机单个离线订单 TODO 允许把金额扣为负数 @Transactional(rollbackFor = Exception.class) public Boolean createOfflineOrder(HardOrderEntity order, HardParentCarEntity parentCar, List list, OfflineOrder offlineOrder, boolean offLineOrderApplyEnable) { @@ -144,6 +194,7 @@ public class HardOrderSyncServiceImpl implements HardOrderSyncService { HardParentCarEntity res = new HardParentCarEntity(); res.setUserId(order.getUserCode()); res.setMerchantId(merchantId); + res.setHardType(order.getSysType().getType()); res.setOrderStatus(HardOrderStatusEnum.OFFLINE_CREATE.getType()); return res; } diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/third/HardThirdPayServiceImpl.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/third/HardThirdPayServiceImpl.java index 6e1a915f..5ba579d5 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/third/HardThirdPayServiceImpl.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/third/HardThirdPayServiceImpl.java @@ -275,11 +275,11 @@ public class HardThirdPayServiceImpl implements HardThirdPayService { PayWaterVo item = new PayWaterVo(); item.setUserId(v.getUserId()); item.setName(v.getUsername()); - item.setSignPhone(""); + item.setSignPhone(v.getUserMobile()); item.setPlatformOrderId(String.valueOf(v.getId())); - item.setPlatformRefundId(String.valueOf(v.getPayRefundId())); + item.setPlatformRefundId(String.valueOf(v.getAfterSaleId())); item.setThirdOrderId(v.getOrderNo()); - item.setThirdRefundId(""); + item.setThirdRefundId(String.valueOf(v.getAfterSaleNo())); item.setOrderStatus(v.getOrderStatus()); item.setOrderPrice(v.getPayPrice()); item.setRefundPrice(v.getRefundPrice()); diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/resources/mapper/order/HardOrderMapper.xml b/pjcloud-hardware/pjcloud-hardware-biz/src/main/resources/mapper/order/HardOrderMapper.xml index 16788db4..6cdd74fb 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/resources/mapper/order/HardOrderMapper.xml +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/resources/mapper/order/HardOrderMapper.xml @@ -100,6 +100,9 @@ and a.merchant_id = #{dto.merchantId} + + and a.is_offline_order = #{dto.isOfflineOrder} + @@ -180,9 +183,12 @@ m.name as hardName, m.type as hardType, - m.dept_id as hardTypeDeptId + m.dept_id as hardTypeDeptId, + s.id as afterSaleId, + s.no as afterSaleNo from hard_order a left join hard_manager m on m.id = a.hard_id + left join hard_after_sale s on s.order_id = a.id diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/impl/pay/ThirdPayApiServiceImpl.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/impl/pay/ThirdPayApiServiceImpl.java index b9272d4c..2fac513b 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/impl/pay/ThirdPayApiServiceImpl.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/impl/pay/ThirdPayApiServiceImpl.java @@ -253,6 +253,10 @@ public class ThirdPayApiServiceImpl implements ThirdPayApiService { payLogService.save(logObj); return baseVo; } + // 加密一下手机号 + for (PayWaterVo item : pageList.getData()) { + item.setSignPhone(LbRetailSignUtils.sm4Encrypt(item.getSignPhone(), keySetting.getFieldKey())); + } return pageList; } catch (Exception e) { log.error("|{}|流水查询,json|{}|headers|{}|", TAG, json, headers, e); diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/application.yml b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/application.yml index 28a2f134..4c777952 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/application.yml +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/application.yml @@ -89,8 +89,8 @@ zy: # callback-recognition-url: /third/third-ks/callback/recognition # callback-sku-url: /third/third-ks/callback/sku lb: - # base-url: https://elss-sit.nbcb.com.cn - base-url: https://elss-sit.nbcb.com.cn/h5/thirdApp + base-url: https://elss-sit.nbcb.com.cn + # base-url: https://elss-sit.nbcb.com.cn/h5/thirdApp app-id: 7da62b1a9ade473c917f573c5748081e app-secret: 8ffl6b+OKTmdVAt9Qo+2F/HQQMdt/d8GFia0zUOt9l= company-number: 202504673472 diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/doc/第三方支付文档.wps b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/doc/第三方支付文档.wps index 3341d2e9994e81a3f7b69312f09200d4f9024032..862ba59c4f18470e3056ab2b1e883fa6622eab25 100644 GIT binary patch delta 8852 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 D#qOS0 delta 9262 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