From 51a951d8631ca3fb89c20bace7558ddf4bfb5655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=8C=E5=85=88=E8=88=9C?= <2499071264@qq.com> Date: Wed, 29 Jul 2026 10:11:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=AF=E5=88=86=E5=95=86=E5=9F=8E-?= =?UTF-8?q?=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../h5/index/PointsMallH5IndexController.java | 20 +- .../annotation/MallTokenRequired.java | 11 + .../PointsMallBridgeController.java | 110 +++-- .../mallbridge/dto/FinalStatementDTO.java | 14 + .../mallbridge/dto/GetInvoiceInfoDTO.java | 15 + .../mallbridge/dto/InvoiceInfoDTO.java | 23 + .../mallbridge/dto/MallInvoiceApplyDTO.java | 29 ++ .../mallbridge/dto/MallTokenDTO.java | 1 + .../mallbridge/dto/MallTokenRefreshDTO.java | 1 + .../dto/OrderPayFinishNoticeDTO.java | 14 + .../mallbridge/dto/PictureQueryDTO.java | 15 + .../mallbridge/dto/QueryInvoiceInfoDTO.java | 11 + .../dto/UnReconciledMsgNoticeDTO.java | 15 + .../interceptor/MallTokenInterceptor.java | 52 +++ .../mallbridge/model/MallOutboundResult.java | 4 + .../model/MallPictureOutboundResult.java | 57 +++ .../service/PointsMallBridgeService.java | 11 + .../impl/PointsMallBridgeServiceImpl.java | 440 +++++++++++++++--- .../PointsMallOrderSubController.java | 86 ++++ .../order/service/PointsMallOrderService.java | 10 + .../impl/PointsMallOrderServiceImpl.java | 48 +- .../platform/zhghh5/points-mall/index.html | 29 +- 22 files changed, 923 insertions(+), 93 deletions(-) create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/annotation/MallTokenRequired.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/FinalStatementDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/GetInvoiceInfoDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/InvoiceInfoDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallInvoiceApplyDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/OrderPayFinishNoticeDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/PictureQueryDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/QueryInvoiceInfoDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/UnReconciledMsgNoticeDTO.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/interceptor/MallTokenInterceptor.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/model/MallPictureOutboundResult.java create mode 100644 src/main/java/com/budwk/app/zhgh/pointsmall/order/controller/PointsMallOrderSubController.java diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/h5/index/PointsMallH5IndexController.java b/src/main/java/com/budwk/app/zhgh/pointsmall/h5/index/PointsMallH5IndexController.java index 6ece8aa1..ccc0aabf 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/h5/index/PointsMallH5IndexController.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/h5/index/PointsMallH5IndexController.java @@ -1,7 +1,9 @@ package com.budwk.app.zhgh.pointsmall.h5.index; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.stp.StpUtil; import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.pointsmall.points.service.PointsMallUserPointsService; import com.budwk.app.zhgh.pointsmall.supplier.service.PointsMallSupplierService; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -13,10 +15,12 @@ import org.nutz.mvc.annotation.Param; @Ok("json:full") @At("/platform/h5/points-mall") public class PointsMallH5IndexController { - @Inject private PointsMallSupplierService pointsMallSupplierService; + @Inject + private PointsMallUserPointsService pointsMallUserPointsService; + @At("") @Ok("beetl:/platform/zhghh5/points-mall/index.html") @SaCheckPermission("h5.points.mall") @@ -28,4 +32,18 @@ public class PointsMallH5IndexController { public Result supplierList(@Param("mallType") Integer mallType) { return Result.success(pointsMallSupplierService.listByMallType(mallType)); } + + @At("/me/points") + @SaCheckPermission("h5.points.mall") + public Result points() { + return Result.success(pointsMallUserPointsService.availablePoints(currentUserId())); + } + + private String currentUserId() { + try { + return StpUtil.getLoginIdAsString(); + } catch (Exception e) { + return ""; + } + } } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/annotation/MallTokenRequired.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/annotation/MallTokenRequired.java new file mode 100644 index 00000000..ad3ae293 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/annotation/MallTokenRequired.java @@ -0,0 +1,11 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface MallTokenRequired { +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/controller/PointsMallBridgeController.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/controller/PointsMallBridgeController.java index b2149d14..76e1c289 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/controller/PointsMallBridgeController.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/controller/PointsMallBridgeController.java @@ -1,24 +1,29 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.controller; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.pointsmall.mallbridge.annotation.MallTokenRequired; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.*; +import com.budwk.app.zhgh.pointsmall.mallbridge.interceptor.MallTokenInterceptor; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundPointsResult; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallOutboundResult; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallPictureOutboundResult; import com.budwk.app.zhgh.pointsmall.mallbridge.service.PointsMallBridgeService; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.json.Json; +import org.nutz.mvc.adaptor.JsonAdaptor; +import org.nutz.mvc.annotation.AdaptBy; import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.By; +import org.nutz.mvc.annotation.Filters; import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; import org.nutz.mvc.annotation.POST; -import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; - @IocBean @Ok("json:full") @At("/open") +@AdaptBy(type = JsonAdaptor.class) public class PointsMallBridgeController { @Inject @@ -26,9 +31,9 @@ public class PointsMallBridgeController { @POST @At("/connect/token") - public MallInboundResult getToken(HttpServletRequest request) { + public MallInboundResult getToken(@Param("..") MallTokenDTO dto) { try { - return pointsMallBridgeService.getToken(readBody(request, MallTokenDTO.class)); + return pointsMallBridgeService.getToken(dto); } catch (Exception e) { return MallInboundResult.fail(401, e.getMessage()); } @@ -36,9 +41,9 @@ public class PointsMallBridgeController { @POST @At("/connect/refreshToken") - public MallInboundResult refreshToken(HttpServletRequest request) { + public MallInboundResult refreshToken(@Param("..") MallTokenRefreshDTO dto) { try { - return pointsMallBridgeService.refreshToken(readBody(request, MallTokenRefreshDTO.class)); + return pointsMallBridgeService.refreshToken(dto); } catch (Exception e) { return MallInboundResult.fail(401, e.getMessage()); } @@ -46,9 +51,11 @@ public class PointsMallBridgeController { @POST @At("/pointOrder/queryPoints") - public MallInboundPointsResult queryPoints(HttpServletRequest request) { + @MallTokenRequired + @Filters(@By(type = MallTokenInterceptor.class)) + public MallInboundPointsResult queryPoints(@Param("..") MallPointQueryDTO dto) { try { - return pointsMallBridgeService.queryPoints(readBody(request, MallPointQueryDTO.class)); + return pointsMallBridgeService.queryPoints(dto); } catch (Exception e) { return MallInboundPointsResult.fail(401, e.getMessage()); } @@ -56,38 +63,88 @@ public class PointsMallBridgeController { @POST @At("/pointOrder/pendingOrderInfo") - public MallInboundResult receivePending(HttpServletRequest request) { - return inbound(() -> pointsMallBridgeService.receivePending(readBody(request, MallPendingOrderDTO.class))); + @MallTokenRequired + @Filters(@By(type = MallTokenInterceptor.class)) + public MallInboundResult receivePending(@Param("..") MallPendingOrderDTO dto) { + return inbound(() -> pointsMallBridgeService.receivePending(dto)); } @POST @At("/pointOrder/confirmPurchase") - public MallInboundResult confirmPurchase(HttpServletRequest request) { - return inbound(() -> pointsMallBridgeService.confirmPurchase(readBody(request, MallPurchaseConfirmDTO.class))); + @MallTokenRequired + @Filters(@By(type = MallTokenInterceptor.class)) + public MallInboundResult confirmPurchase(@Param("..") MallPurchaseConfirmDTO dto) { + return inbound(() -> pointsMallBridgeService.confirmPurchase(dto)); } @POST @At("/pointOrder/purchaseResult") - public MallInboundResult purchaseResult(HttpServletRequest request) { - return inbound(() -> pointsMallBridgeService.purchaseResult(readBody(request, MallPurchaseResultDTO.class))); + @MallTokenRequired + @Filters(@By(type = MallTokenInterceptor.class)) + public MallInboundResult purchaseResult(@Param("..") MallPurchaseResultDTO dto) { + return inbound(() -> pointsMallBridgeService.purchaseResult(dto)); } @POST @At("/pointOrder/pushOrderInfoMsg") - public MallInboundResult receiveEvent(HttpServletRequest request) { - return inbound(() -> pointsMallBridgeService.receiveEvent(readBody(request, MallOrderEventDTO.class))); + @MallTokenRequired + @Filters(@By(type = MallTokenInterceptor.class)) + public MallInboundResult receiveEvent(@Param("..") MallOrderEventDTO dto) { + return inbound(() -> pointsMallBridgeService.receiveEvent(dto)); } @POST @At("/pointOrder/queryOrderInfo") - public MallOutboundResult queryOrderInfo(HttpServletRequest request) { + public MallOutboundResult queryOrderInfo(@Param("..") MallOrderQueryDTO dto) { try { - return pointsMallBridgeService.queryOrderInfo(readBody(request, MallOrderQueryDTO.class)); + return pointsMallBridgeService.queryOrderInfo(dto); } catch (Exception e) { return MallOutboundResult.fail(401, e.getMessage()); } } + @POST + @At("/pointOrder/applyForInvoices") + public MallOutboundResult applyInvoice(@Param("..") MallInvoiceApplyDTO dto) { + try { + return pointsMallBridgeService.applyInvoice(dto); + } catch (Exception e) { + return MallOutboundResult.fail(401, e.getMessage()); + } + } + + @POST + @At("/pointOrder/queryInvoicesInfo") + public Result queryInvoicesInfo(@Param("..") QueryInvoiceInfoDTO dto) { + try { + return Result.success(pointsMallBridgeService.queryInvoicesInfo(dto)); + } catch (Exception e) { + return Result.error(401, e.getMessage()); + } + } + + @POST + @At("/pointOrder/queryFileBase64Info") + public MallPictureOutboundResult queryFileBase64Info(@Param("..") PictureQueryDTO dto) { + try { + return pointsMallBridgeService.queryFileBase64Info(dto); + } catch (Exception e) { + return MallPictureOutboundResult.fail(401, e.getMessage()); + } + } + + @POST + @At("/pointOrder/unReconciledMsg") + public MallInboundResult unReconciledMsg(@Param("..") UnReconciledMsgNoticeDTO dto) { + return inbound(() -> pointsMallBridgeService.unReconciledMsg(dto)); + } + + @POST + @At("/pointOrder/payCompletion") + public MallInboundResult payCompletion(@Param("..") OrderPayFinishNoticeDTO dto) { + return inbound(() -> pointsMallBridgeService.payCompletion(dto)); + } + private MallInboundResult inbound(InboundCall call) { try { return call.get(); @@ -96,17 +153,6 @@ public class PointsMallBridgeController { } } - private T readBody(HttpServletRequest request, Class type) throws IOException { - StringBuilder body = new StringBuilder(); - try (BufferedReader reader = request.getReader()) { - String line; - while ((line = reader.readLine()) != null) { - body.append(line); - } - } - return Json.fromJson(type, body.toString()); - } - private interface InboundCall { MallInboundResult get() throws Exception; } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/FinalStatementDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/FinalStatementDTO.java new file mode 100644 index 00000000..0c0738db --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/FinalStatementDTO.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.dto; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class FinalStatementDTO { + private String settlementId; + private String invoiceIds; + private String orderIds; + private String payDate; + private BigDecimal totalFee; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/GetInvoiceInfoDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/GetInvoiceInfoDTO.java new file mode 100644 index 00000000..96285515 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/GetInvoiceInfoDTO.java @@ -0,0 +1,15 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class GetInvoiceInfoDTO { + private Integer bSuccess; + private String settlementId; + private String sucOrderIds; + private String failOrderIds; + private String failMsg; + private List invoiceInfos; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/InvoiceInfoDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/InvoiceInfoDTO.java new file mode 100644 index 00000000..657ea471 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/InvoiceInfoDTO.java @@ -0,0 +1,23 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.dto; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@Data +public class InvoiceInfoDTO { + private String invoiceId; + private String invoiceCode; + private LocalDate invoiceDate; + private BigDecimal invoiceNakeAmount; + private BigDecimal invoiceTaxRate; + private BigDecimal invoiceTaxAmount; + private BigDecimal invoiceAmount; + private Integer invoiceType; + private String url; + private String imageEncode; + private String fileType; + private String checkCode; + private String invoiceAddress; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallInvoiceApplyDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallInvoiceApplyDTO.java new file mode 100644 index 00000000..55edcda9 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallInvoiceApplyDTO.java @@ -0,0 +1,29 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.dto; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class MallInvoiceApplyDTO { + private String supplierId; + private String token; + private String settlementId; + private String orderIds; + private Integer orderNum; + private BigDecimal orderTotalPrice; + private String invoiceDate; + private String invoiceTitle; + private String invoiceCode; + private String invoiceAddress; + private String invoiceContact; + private BigDecimal invoiceNakedPrice; + private BigDecimal invoiceTaxPrice; + private String invoiceType; + private String invoiceContent; + private String remark; + private String bankAccount; + private String registeredAddress; + private String bankName; + private Long timestamp; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallTokenDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallTokenDTO.java index 9dbaee8a..5fde506d 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallTokenDTO.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallTokenDTO.java @@ -7,6 +7,7 @@ public class MallTokenDTO { private String supplierId; private String clientId; private String clientSecret; + private String sendSha256; private String code; private String timestamp; } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallTokenRefreshDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallTokenRefreshDTO.java index da2768d6..6bf0fc03 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallTokenRefreshDTO.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallTokenRefreshDTO.java @@ -8,5 +8,6 @@ public class MallTokenRefreshDTO { private String refreshToken; private String clientId; private String clientSecret; + private String sendSha256; private String timestamp; } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/OrderPayFinishNoticeDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/OrderPayFinishNoticeDTO.java new file mode 100644 index 00000000..25f9a522 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/OrderPayFinishNoticeDTO.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class OrderPayFinishNoticeDTO { + private String supplierId; + private String token; + private String expReportNumber; + private List expFinalInfos; + private Long timestamp; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/PictureQueryDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/PictureQueryDTO.java new file mode 100644 index 00000000..8c0c2440 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/PictureQueryDTO.java @@ -0,0 +1,15 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class PictureQueryDTO { + private String supplierId; + private String token; + private String queryType; + private String idNumber; + private List fileIdList; + private Long timestamp; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/QueryInvoiceInfoDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/QueryInvoiceInfoDTO.java new file mode 100644 index 00000000..293d8696 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/QueryInvoiceInfoDTO.java @@ -0,0 +1,11 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.dto; + +import lombok.Data; + +@Data +public class QueryInvoiceInfoDTO { + private String supplierId; + private String token; + private String settlementId; + private Long timestamp; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/UnReconciledMsgNoticeDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/UnReconciledMsgNoticeDTO.java new file mode 100644 index 00000000..d2e26696 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/UnReconciledMsgNoticeDTO.java @@ -0,0 +1,15 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.dto; + +import lombok.Data; + +@Data +public class UnReconciledMsgNoticeDTO { + private String uniqueSeqNo; + private String supplierId; + private String token; + private String orderIds; + private String unReconciledMsg; + private String unReconciledType; + private String startDate; + private String endDate; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/interceptor/MallTokenInterceptor.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/interceptor/MallTokenInterceptor.java new file mode 100644 index 00000000..5d250743 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/interceptor/MallTokenInterceptor.java @@ -0,0 +1,52 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.interceptor; + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.zhgh.pointsmall.mallbridge.annotation.MallTokenRequired; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; +import com.budwk.app.zhgh.pointsmall.mallbridge.models.PointsMallSupplierTokenStore; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.json.JsonFormat; +import org.nutz.mvc.ActionContext; +import org.nutz.mvc.ActionFilter; +import org.nutz.mvc.Mvcs; +import org.nutz.mvc.View; +import org.nutz.mvc.view.UTF8JsonView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Date; + +public class MallTokenInterceptor implements ActionFilter { + + @Override + public View match(ActionContext actionContext) { + if (actionContext.getMethod() == null || !actionContext.getMethod().isAnnotationPresent(MallTokenRequired.class)) { + return null; + } + + String accessToken = actionContext.getRequest().getHeader("token"); + if (StrUtil.isBlank(accessToken)) { + return fail(401, "缺少accessToken参数"); + } + + Dao dao = Mvcs.getIoc().get(Dao.class); + PointsMallSupplierTokenStore tokenStore = dao.fetch(PointsMallSupplierTokenStore.class, + Cnd.where("accessToken", "=", accessToken).and("isValid", "=", true)); + if (tokenStore == null || tokenStore.getAccessExpireTime() == null || tokenStore.getAccessExpireTime().before(new Date())) { + return fail(401, "无效的accessToken"); + } + + return null; + } + + private View fail(int code, String message) { + return new View() { + @Override + public void render(HttpServletRequest req, HttpServletResponse resp, Object obj) throws Throwable { + resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + new UTF8JsonView(JsonFormat.compact()).render(req, resp, MallInboundResult.fail(code, message)); + } + }; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/model/MallOutboundResult.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/model/MallOutboundResult.java index cad2758b..4b8aa182 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/model/MallOutboundResult.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/model/MallOutboundResult.java @@ -11,6 +11,10 @@ public class MallOutboundResult { private String message; private List orderInfo; + public static MallOutboundResult success() { + return success(null); + } + public static MallOutboundResult success(List orderInfo) { MallOutboundResult result = new MallOutboundResult(); result.setResultCode(0); diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/model/MallPictureOutboundResult.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/model/MallPictureOutboundResult.java new file mode 100644 index 00000000..c5f5bdc0 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/model/MallPictureOutboundResult.java @@ -0,0 +1,57 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.model; + +import java.util.Map; + +public class MallPictureOutboundResult { + private int resultCode; + private String message; + private String fileType; + private Map imageEncodeMap; + + public static MallPictureOutboundResult success(Map imageEncodeMap) { + MallPictureOutboundResult result = new MallPictureOutboundResult(); + result.resultCode = 0; + result.message = "成功"; + result.imageEncodeMap = imageEncodeMap; + return result; + } + + public static MallPictureOutboundResult fail(int code, String message) { + MallPictureOutboundResult result = new MallPictureOutboundResult(); + result.resultCode = code; + result.message = message; + return result; + } + + public int getResultCode() { + return resultCode; + } + + public void setResultCode(int resultCode) { + this.resultCode = resultCode; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getFileType() { + return fileType; + } + + public void setFileType(String fileType) { + this.fileType = fileType; + } + + public Map getImageEncodeMap() { + return imageEncodeMap; + } + + public void setImageEncodeMap(Map imageEncodeMap) { + this.imageEncodeMap = imageEncodeMap; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/PointsMallBridgeService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/PointsMallBridgeService.java index c655d91e..334da01a 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/PointsMallBridgeService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/PointsMallBridgeService.java @@ -5,6 +5,7 @@ import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundPointsResult; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundTokenResult; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallOutboundResult; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallPictureOutboundResult; public interface PointsMallBridgeService { MallInboundTokenResult getToken(MallTokenDTO dto); @@ -22,4 +23,14 @@ public interface PointsMallBridgeService { MallInboundResult receiveEvent(MallOrderEventDTO dto); MallOutboundResult queryOrderInfo(MallOrderQueryDTO dto); + + MallOutboundResult applyInvoice(MallInvoiceApplyDTO dto); + + GetInvoiceInfoDTO queryInvoicesInfo(QueryInvoiceInfoDTO dto); + + MallPictureOutboundResult queryFileBase64Info(PictureQueryDTO dto); + + MallInboundResult unReconciledMsg(UnReconciledMsgNoticeDTO dto); + + MallInboundResult payCompletion(OrderPayFinishNoticeDTO dto); } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/impl/PointsMallBridgeServiceImpl.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/impl/PointsMallBridgeServiceImpl.java index 68fac3fe..e689328c 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/impl/PointsMallBridgeServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/impl/PointsMallBridgeServiceImpl.java @@ -1,22 +1,44 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.service.impl; -import cn.hutool.core.date.DateUtil; import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.json.JSONUtil; -import com.budwk.app.zhgh.pointsmall.mallbridge.dto.*; +import com.budwk.app.zhgh.pointsmall.invoice.models.PointsMallInvoiceInfo; +import com.budwk.app.zhgh.pointsmall.invoice.models.PointsMallInvoiceMain; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.FinalStatementDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.GetInvoiceInfoDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.InvoiceInfoDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallInvoiceApplyDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderEventDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderQueryDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallPendingOrderDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallPointQueryDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallPurchaseConfirmDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallPurchaseResultDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallTokenDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallTokenRefreshDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderInfoDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderPayFinishNoticeDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderProInfoDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.PictureQueryDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.QueryInvoiceInfoDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.UnReconciledMsgNoticeDTO; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundPointsResult; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundTokenResult; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallOutboundResult; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallPictureOutboundResult; import com.budwk.app.zhgh.pointsmall.mallbridge.models.PointsMallSupplierTokenStore; import com.budwk.app.zhgh.pointsmall.mallbridge.service.PointsMallBridgeService; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSubProduct; import com.budwk.app.zhgh.pointsmall.points.service.PointsMallUserPointsService; +import com.budwk.app.zhgh.pointsmall.reconciliation.models.PointsMallReconciliationRecord; import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; +import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.Sqls; @@ -28,7 +50,16 @@ import org.nutz.trans.Atom; import org.nutz.trans.Trans; import java.math.BigDecimal; -import java.util.*; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; import java.util.stream.Collectors; @IocBean(args = {"refer:dao"}) @@ -36,6 +67,16 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { private static final long ACCESS_EXPIRE_SECONDS = 3600; private static final long REFRESH_EXPIRE_SECONDS = 86400L * 7; + private static final int ORDER_PENDING_PAY = 0; + private static final int ORDER_FINISH_PAY = 1; + private static final int ORDER_IN_PROGRESS = 2; + private static final int ORDER_CANCELLED = 3; + private static final int ORDER_RECEIVED = 4; + private static final int ORDER_COMPLETED = 5; + private static final int ORDER_EXCHANGE = 6; + private static final int ORDER_REFUNDED = 7; + private static final int ORDER_ABOLISH = 8; + private final Dao dao; @Inject @@ -47,18 +88,18 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { @Override public MallInboundTokenResult getToken(MallTokenDTO dto) { - PointsMallSupplier supplier = checkedSupplier(dto.getSupplierId(), dto.getClientId(), dto.getClientSecret(), dto.getTimestamp()); + PointsMallSupplier supplier = checkedSupplier(dto.getSupplierId(), dto.getClientId(), dto.getClientSecret(), dto.getSendSha256(), dto.getTimestamp()); invalidateOldToken(supplier.getSupplierId(), supplier.getClientId()); return createToken(supplier); } @Override public MallInboundTokenResult refreshToken(MallTokenRefreshDTO dto) { - PointsMallSupplier supplier = checkedSupplier(dto.getSupplierId(), dto.getClientId(), dto.getClientSecret(), dto.getTimestamp()); + PointsMallSupplier supplier = checkedSupplier(dto.getSupplierId(), dto.getClientId(), dto.getClientSecret(), dto.getSendSha256(), dto.getTimestamp()); PointsMallSupplierTokenStore store = dao.fetch(PointsMallSupplierTokenStore.class, Cnd.where("supplierId", "=", supplier.getSupplierId()) .and("refreshToken", "=", dto.getRefreshToken()).and("isValid", "=", true)); if (store == null || store.getRefreshExpireTime() == null || new Date().after(store.getRefreshExpireTime())) { - throw new IllegalArgumentException("刷新令牌无效或已过期"); + throw new IllegalArgumentException("刷新令牌已失效,请重新获取授权"); } invalidateOldToken(supplier.getSupplierId(), supplier.getClientId()); return createToken(supplier); @@ -66,68 +107,73 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { @Override public MallInboundPointsResult queryPoints(MallPointQueryDTO dto) { - validateToken(dto.getSupplierId(), dto.getToken()); return MallInboundPointsResult.success(pointsMallUserPointsService.availablePoints(dto.getUserId())); } @Override public MallInboundResult receivePending(MallPendingOrderDTO dto) { - validateToken(dto.getSupplierId(), dto.getToken()); if (dto.getOrderInfo() == null || StrUtil.isBlank(dto.getOrderInfo().getOrderId())) { return MallInboundResult.fail(400, "订单信息不能为空"); } - if (dao.count(PointsMallOrderMain.class, Cnd.where("orderId", "=", dto.getOrderInfo().getOrderId()).and("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false)) > 0) { + if (dao.count(PointsMallOrderMain.class, Cnd.where("orderId", "=", dto.getOrderInfo().getOrderId()) + .and("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false)) > 0) { return MallInboundResult.fail(-1, "订单已存在"); } - Trans.exec((Atom) () -> dao.insert(toMain(dto.getSupplierId(), dto.getUserId(), dto.getOrderInfo(), 0))); + Trans.exec((Atom) () -> dao.insert(toMain(dto.getSupplierId(), dto.getUserId(), dto.getOrderInfo(), ORDER_PENDING_PAY))); return MallInboundResult.success(); } @Override public MallInboundResult confirmPurchase(MallPurchaseConfirmDTO dto) { - validateToken(dto.getSupplierId(), dto.getToken()); return updateMainOrderPay(dto.getSupplierId(), dto.getOrderId(), 1, dto.getTotalPrice(), dto.getWPayOrAPay(), dto.getPointsPrice()); } @Override public MallInboundResult purchaseResult(MallPurchaseResultDTO dto) { - validateToken(dto.getSupplierId(), dto.getToken()); - int state = Boolean.TRUE.equals(dto.getPurchaseResult()) ? 1 : 0; - return updateMainOrderPay(dto.getSupplierId(), dto.getOrderId(), state, dto.getTotalPrice(), dto.getWPayOrAPay(), dto.getPointsPrice()); + int cashPaid = Boolean.TRUE.equals(dto.getPurchaseResult()) ? 1 : 0; + return updateMainOrderPay(dto.getSupplierId(), dto.getOrderId(), cashPaid, dto.getTotalPrice(), dto.getWPayOrAPay(), dto.getPointsPrice()); } @Override public MallInboundResult receiveEvent(MallOrderEventDTO dto) { - validateToken(dto.getSupplierId(), dto.getToken()); Integer type = dto.getOrderType(); if (type == null) { return MallInboundResult.fail(400, "订单事件类型不能为空"); } + if (type == 1) { + return cancelMainOrder(dto, false); + } if (type == 2) { return splitSubOrder(dto); } if (type == 3) { - return updateSubState(dto, 3); + return updateSubState(dto, ORDER_CANCELLED); } if (type == 4) { - return updateSubState(dto, 4); + return updateSubState(dto, ORDER_REFUNDED); } if (type == 5) { - return updateSubState(dto, 5); + return updateSubState(dto, ORDER_EXCHANGE); } if (type == 6) { - return updateSubState(dto, 6); + return updateSubState(dto, ORDER_COMPLETED); } if (type == 7) { - return updateSubState(dto, 7); + return cancelMainOrder(dto, true); + } + if (type == 8) { + return updateSubState(dto, ORDER_ABOLISH); + } + if (type == 11) { + return markInvoiceNotice(dto); } return MallInboundResult.success(); } @Override public MallOutboundResult queryOrderInfo(MallOrderQueryDTO dto) { - validateToken(dto.getSupplierId(), dto.getToken()); - Sql sql = Sqls.create("select * from points_mall_order_main where supplierId=@supplierId and orderId=@orderId and delFlag=0"); + String table = Integer.valueOf(2).equals(dto.getOrderType()) ? "points_mall_order_sub" : "points_mall_order_main"; + Sql sql = Sqls.create("select * from " + table + " where supplierId=@supplierId and orderId=@orderId and delFlag=0"); sql.params().set("supplierId", dto.getSupplierId()); sql.params().set("orderId", dto.getOrderId()); sql.setCallback(Sqls.callback.records()); @@ -136,33 +182,126 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { return MallOutboundResult.success(list); } - private PointsMallSupplier checkedSupplier(String supplierId, String clientId, String clientSecret, String timestamp) { - if (StrUtil.hasBlank(supplierId, clientId, clientSecret, timestamp)) { - throw new IllegalArgumentException("供应商认证参数不能为空"); + @Override + public MallOutboundResult applyInvoice(MallInvoiceApplyDTO dto) { + if (dto == null || StrUtil.hasBlank(dto.getSupplierId(), dto.getSettlementId(), dto.getOrderIds())) { + return MallOutboundResult.fail(400, "开票申请参数不能为空"); + } + List orderIds = splitIds(dto.getOrderIds()); + List orders = dao.query(PointsMallOrderSub.class, Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "in", orderIds).and("delFlag", "=", false)); + if (orders.isEmpty()) { + return MallOutboundResult.fail(404, "未找到可开票订单"); + } + if (dto.getOrderNum() != null && dto.getOrderNum() != orders.size()) { + return MallOutboundResult.fail(400, "订单数量与开票申请不一致"); + } + BigDecimal total = orders.stream().map(PointsMallOrderSub::getTotalPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); + if (dto.getOrderTotalPrice() != null && total.compareTo(dto.getOrderTotalPrice()) != 0) { + return MallOutboundResult.fail(400, "订单金额与开票申请不一致"); + } + Trans.exec((Atom) () -> saveInvoiceApply(dto, orderIds, total)); + return MallOutboundResult.success(); + } + + @Override + public GetInvoiceInfoDTO queryInvoicesInfo(QueryInvoiceInfoDTO dto) { + if (dto == null || StrUtil.hasBlank(dto.getSupplierId(), dto.getSettlementId())) { + throw new IllegalArgumentException("发票查询参数不能为空"); + } + PointsMallInvoiceMain main = dao.fetch(PointsMallInvoiceMain.class, Cnd.where("settlementId", "=", dto.getSettlementId()) + .and("delFlag", "=", false)); + if (main == null) { + throw new IllegalArgumentException("发票信息不存在"); + } + List invoiceInfos = dao.query(PointsMallInvoiceInfo.class, Cnd.where("mainId", "=", main.getId()).and("delFlag", "=", false)) + .stream().map(this::toInvoiceInfoDTO).collect(Collectors.toList()); + GetInvoiceInfoDTO result = new GetInvoiceInfoDTO(); + result.setBSuccess(main.getBSuccess()); + result.setSettlementId(main.getSettlementId()); + result.setSucOrderIds(main.getSucOrderIds()); + result.setFailOrderIds(main.getFailOrderIds()); + result.setFailMsg(main.getFailMsg()); + result.setInvoiceInfos(invoiceInfos); + return result; + } + + @Override + public MallPictureOutboundResult queryFileBase64Info(PictureQueryDTO dto) { + if (dto == null || StrUtil.hasBlank(dto.getSupplierId(), dto.getQueryType(), dto.getIdNumber())) { + return MallPictureOutboundResult.fail(400, "图片查询参数不能为空"); + } + Map map = "2".equals(dto.getQueryType()) ? queryInvoiceFiles(dto) : queryProductPictures(dto); + MallPictureOutboundResult result = MallPictureOutboundResult.success(map); + if ("2".equals(dto.getQueryType())) { + result.setFileType(firstInvoiceFileType(dto)); + } + return result; + } + + @Override + public MallInboundResult unReconciledMsg(UnReconciledMsgNoticeDTO dto) { + if (dto == null || StrUtil.hasBlank(dto.getSupplierId(), dto.getOrderIds())) { + return MallInboundResult.fail(400, "对账异常通知参数不能为空"); + } + List orderIds = splitIds(dto.getOrderIds()); + Trans.exec((Atom) () -> { + for (String orderId : orderIds) { + PointsMallReconciliationRecord record = new PointsMallReconciliationRecord(); + record.setSupplierId(dto.getSupplierId()); + record.setOrderId(orderId); + record.setDiffReason(dto.getUnReconciledMsg()); + record.setDiffType(Convert.toInt(dto.getUnReconciledType(), null)); + record.setBatchNo(StrUtil.blankToDefault(dto.getUniqueSeqNo(), dto.getStartDate() + "_" + dto.getEndDate())); + record.setNoticeStatus(1); + record.setPushTime(1); + dao.insert(record); + } + }); + return MallInboundResult.success(); + } + + @Override + public MallInboundResult payCompletion(OrderPayFinishNoticeDTO dto) { + if (dto == null || StrUtil.isBlank(dto.getSupplierId()) || dto.getExpFinalInfos() == null) { + return MallInboundResult.fail(400, "支付完成通知参数不能为空"); + } + Trans.exec((Atom) () -> { + for (FinalStatementDTO item : dto.getExpFinalInfos()) { + if (item == null || StrUtil.isBlank(item.getSettlementId())) { + continue; + } + PointsMallInvoiceMain main = dao.fetch(PointsMallInvoiceMain.class, Cnd.where("settlementId", "=", item.getSettlementId()) + .and("delFlag", "=", false)); + if (main != null) { + main.setBSuccess(1); + dao.updateIgnoreNull(main); + } + List orderIds = splitIds(item.getOrderIds()); + if (!orderIds.isEmpty()) { + dao.update(PointsMallOrderSub.class, Chain.make("invoiceStatus", 1), Cnd.where("supplierId", "=", dto.getSupplierId()).and("orderId", "in", orderIds)); + } + } + }); + return MallInboundResult.success(); + } + + private PointsMallSupplier checkedSupplier(String supplierId, String clientId, String clientSecret, String sendSha256, String timestamp) { + if (StrUtil.hasBlank(supplierId, clientId, clientSecret, sendSha256, timestamp)) { + throw new IllegalArgumentException("供应商授权信息不能为空"); } PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class, Cnd.where("supplierId", "=", supplierId) .and("clientId", "=", clientId).and("delFlag", "=", false)); if (supplier == null) { - throw new IllegalArgumentException("供应商和客户端信息不匹配"); + throw new IllegalArgumentException("供应商不存在或已停用"); } - String serverSha256 = SecureUtil.sha256(supplier.getClientId() + supplier.getClientSecret() + timestamp + clientSecret); - if (!Objects.equals(clientSecret, serverSha256)) { + String serverSha256 = SecureUtil.sha256(supplier.getClientId() + supplier.getClientSecret() + timestamp); + if (!Objects.equals(sendSha256, serverSha256)) { throw new IllegalArgumentException("签名验证信息错误"); } return supplier; } - private void validateToken(String supplierId, String token) { - if (StrUtil.hasBlank(supplierId, token)) { - throw new IllegalArgumentException("供应商ID和token不能为空"); - } - PointsMallSupplierTokenStore store = dao.fetch(PointsMallSupplierTokenStore.class, Cnd.where("supplierId", "=", supplierId) - .and("accessToken", "=", token).and("isValid", "=", true)); - if (store == null || store.getAccessExpireTime() == null || new Date().after(store.getAccessExpireTime())) { - throw new IllegalArgumentException("token无效或已过期"); - } - } - private MallInboundTokenResult createToken(PointsMallSupplier supplier) { String accessToken = UUID.randomUUID().toString().replace("-", ""); String refreshToken = UUID.randomUUID().toString().replace("-", ""); @@ -184,7 +323,8 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { } private MallInboundResult updateMainOrderPay(String supplierId, String orderId, Integer cashPaid, BigDecimal totalPrice, BigDecimal cash, BigDecimal points) { - PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", supplierId).and("orderId", "=", orderId).and("delFlag", "=", false)); + PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", supplierId) + .and("orderId", "=", orderId).and("delFlag", "=", false)); if (main == null) { return MallInboundResult.fail(404, "订单不存在"); } @@ -192,26 +332,61 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { main.setTotalPrice(nvl(totalPrice, main.getTotalPrice())); main.setWPayOrAPay(nvl(cash, main.getWPayOrAPay())); main.setPointsPrice(nvl(points, main.getPointsPrice())); - main.setOrderState(cashPaid == 1 ? 1 : main.getOrderState()); + main.setOrderState(cashPaid == 1 ? ORDER_FINISH_PAY : main.getOrderState()); main.setOrderUpdateTime(new Date()); dao.updateIgnoreNull(main); return MallInboundResult.success(); } + private MallInboundResult cancelMainOrder(MallOrderEventDTO dto, boolean paidNotSplit) { + String mainOrderId = StrUtil.blankToDefault(dto.getMainOrderId(), dto.getOrderId()); + if (StrUtil.isBlank(mainOrderId)) { + return MallInboundResult.fail(400, "主订单信息不能为空"); + } + PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "=", mainOrderId).and("delFlag", "=", false)); + if (main == null) { + return MallInboundResult.fail(404, "主订单不存在"); + } + if (!paidNotSplit && !Integer.valueOf(ORDER_PENDING_PAY).equals(main.getOrderState())) { + return MallInboundResult.fail(400, "只能取消未支付主单"); + } + main.setOrderState(ORDER_CANCELLED); + main.setOrderUpdateTime(new Date()); + dao.updateIgnoreNull(main); + dao.update(PointsMallOrderSub.class, Chain.make("orderState", ORDER_CANCELLED).add("orderUpdateTime", new Date()), + Cnd.where("supplierId", "=", dto.getSupplierId()).and("mainOrderId", "=", mainOrderId).and("delFlag", "=", false)); + return MallInboundResult.success(); + } + private MallInboundResult splitSubOrder(MallOrderEventDTO dto) { PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", dto.getSupplierId()) .and("orderId", "=", dto.getMainOrderId()).and("delFlag", "=", false)); if (main == null) { return MallInboundResult.fail(404, "主订单不存在"); } - if (dao.count(PointsMallOrderSub.class, Cnd.where("orderId", "=", dto.getOrderId()).and("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false)) > 0) { - return MallInboundResult.fail(-1, "子订单已存在"); + List subOrderIds = splitIds(dto.getOrderId()); + if (subOrderIds.isEmpty()) { + return MallInboundResult.fail(400, "子订单信息不能为空"); } + List products = StrUtil.isBlank(main.getExtJson()) || "null".equalsIgnoreCase(main.getExtJson()) + ? Collections.emptyList() + : JSONUtil.toList(main.getExtJson(), OrderProInfoDTO.class); Trans.exec((Atom) () -> { - PointsMallOrderSub sub = toSub(main, dto.getOrderId()); - dao.insert(sub); - List products = StrUtil.isBlank(main.getExtJson()) || "null".equalsIgnoreCase(main.getExtJson()) ? Collections.emptyList() : JSONUtil.toList(main.getExtJson(), OrderProInfoDTO.class); - insertProducts(dto.getOrderId(), products); + for (String subOrderId : subOrderIds) { + PointsMallOrderSub sub = dao.fetch(PointsMallOrderSub.class, Cnd.where("orderId", "=", subOrderId) + .and("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false)); + if (sub == null) { + sub = toSub(main, subOrderId); + sub.setOrderState(ORDER_IN_PROGRESS); + dao.insert(sub); + insertProducts(subOrderId, products); + } else { + sub.setOrderState(ORDER_IN_PROGRESS); + sub.setOrderUpdateTime(new Date()); + dao.updateIgnoreNull(sub); + } + } }); return MallInboundResult.success(); } @@ -224,16 +399,105 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { } sub.setOrderState(state); sub.setOrderUpdateTime(new Date()); - if (state == 4) { + if (state == ORDER_RECEIVED) { sub.setOrderFinishTime(new Date()); } - if (state == 5) { + if (state == ORDER_COMPLETED) { sub.setOrderCompleteTime(new Date()); } dao.updateIgnoreNull(sub); return MallInboundResult.success(); } + private MallInboundResult markInvoiceNotice(MallOrderEventDTO dto) { + String mainOrderId = StrUtil.blankToDefault(dto.getMainOrderId(), dto.getOrderId()); + if (StrUtil.isBlank(mainOrderId)) { + return MallInboundResult.fail(400, "主订单信息不能为空"); + } + dao.update(PointsMallOrderSub.class, Chain.make("invoiceStatus", 1), Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("mainOrderId", "=", mainOrderId).and("delFlag", "=", false)); + return MallInboundResult.success(); + } + + private void saveInvoiceApply(MallInvoiceApplyDTO dto, List orderIds, BigDecimal total) { + PointsMallInvoiceMain main = dao.fetch(PointsMallInvoiceMain.class, Cnd.where("settlementId", "=", dto.getSettlementId()).and("delFlag", "=", false)); + if (main == null) { + main = new PointsMallInvoiceMain(); + main.setSettlementId(dto.getSettlementId()); + main.setBSuccess(0); + main.setSucOrderIds(String.join(",", orderIds)); + main.setFailOrderIds(""); + main.setFailMsg(""); + dao.insert(main); + } else { + main.setBSuccess(0); + main.setSucOrderIds(String.join(",", orderIds)); + main.setFailOrderIds(""); + main.setFailMsg(""); + dao.updateIgnoreNull(main); + } + + PointsMallInvoiceInfo info = new PointsMallInvoiceInfo(); + info.setMainId(main.getId()); + info.setInvoiceId(dto.getSettlementId()); + info.setInvoiceCode(dto.getInvoiceCode()); + info.setInvoiceDate(parseDate(dto.getInvoiceDate())); + info.setInvoiceNakeAmount(nvl(dto.getInvoiceNakedPrice(), total)); + info.setInvoiceTaxAmount(nvl(dto.getInvoiceTaxPrice(), BigDecimal.ZERO)); + info.setInvoiceAmount(total); + info.setInvoiceType(Convert.toInt(dto.getInvoiceType(), null)); + info.setInvoiceAddress(dto.getInvoiceAddress()); + info.setInvoiceContact(dto.getInvoiceContact()); + info.setInvoiceContent(dto.getInvoiceContent()); + info.setInvoiceBank(dto.getBankName()); + info.setInvoiceAccount(dto.getBankAccount()); + info.setTaxIdNumber(dto.getInvoiceCode()); + info.setRemark(dto.getRemark()); + dao.insert(info); + + dao.update(PointsMallOrderSub.class, Chain.make("invoiceStatus", 2).add("invoiceCode", dto.getSettlementId()), + Cnd.where("supplierId", "=", dto.getSupplierId()).and("orderId", "in", orderIds)); + } + + private Map queryProductPictures(PictureQueryDTO dto) { + Cnd cnd = Cnd.where("orderSubId", "=", dto.getIdNumber()).and("delFlag", "=", false); + if (dto.getFileIdList() != null && !dto.getFileIdList().isEmpty()) { + cnd.and("sku", "in", dto.getFileIdList()); + } + List products = dao.query(PointsMallOrderSubProduct.class, cnd); + Map map = new LinkedHashMap<>(); + for (PointsMallOrderSubProduct product : products) { + map.put(product.getSku(), product.getPicInfo()); + } + return map; + } + + private Map queryInvoiceFiles(PictureQueryDTO dto) { + PointsMallInvoiceMain main = dao.fetch(PointsMallInvoiceMain.class, Cnd.where("settlementId", "=", dto.getIdNumber()).and("delFlag", "=", false)); + if (main == null) { + return Collections.emptyMap(); + } + Cnd cnd = Cnd.where("mainId", "=", main.getId()).and("delFlag", "=", false); + if (dto.getFileIdList() != null && !dto.getFileIdList().isEmpty()) { + cnd.and("invoiceId", "in", dto.getFileIdList()); + } + List invoices = dao.query(PointsMallInvoiceInfo.class, cnd); + Map map = new LinkedHashMap<>(); + for (PointsMallInvoiceInfo invoice : invoices) { + map.put(invoice.getInvoiceId(), invoice.getImageEncode()); + } + return map; + } + + private String firstInvoiceFileType(PictureQueryDTO dto) { + PointsMallInvoiceMain main = dao.fetch(PointsMallInvoiceMain.class, Cnd.where("settlementId", "=", dto.getIdNumber()).and("delFlag", "=", false)); + if (main == null) { + return null; + } + PointsMallInvoiceInfo info = dao.fetch(PointsMallInvoiceInfo.class, Cnd.where("mainId", "=", main.getId()).and("delFlag", "=", false)); + return info == null ? null : info.getFileType(); + } + private PointsMallOrderMain toMain(String supplierId, String userId, OrderInfoDTO orderInfo, Integer state) { PointsMallOrderMain main = new PointsMallOrderMain(); main.setOrderId(orderInfo.getOrderId()); @@ -313,9 +577,16 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { dto.setOrderNumberId(record.getString("orderNumberId")); dto.setSupplierId(record.getString("supplierId")); dto.setAplName(record.getString("aplName")); + dto.setCreateTime(formatDate(record.get("orderCreateTime"))); + dto.setUpdateTime(formatDate(record.get("orderUpdateTime"))); + dto.setDeliveryTime(formatDate(record.get("deliveryTime"))); + dto.setOrderFinishTime(formatDate(record.get("orderFinishTime"))); + dto.setCompleteTime(formatDate(record.get("orderCompleteTime"))); dto.setDeliveryStatus(record.getString("deliveryStatus")); dto.setFreightCost(decimal(record.get("freightCost"))); + dto.setWPayOrAPayFreightCost(decimal(record.get("wPayOrAPayFreightCost"))); dto.setRefund(decimal(record.get("refund"))); + dto.setWPayOrAPayRefund(decimal(record.get("wPayOrAPayRefund"))); dto.setLogisticsOrderId(record.getString("logisticsOrderId")); dto.setCrrgBsnNm(record.getString("crrgBsnNm")); dto.setOrderState(record.getInt("orderState")); @@ -323,6 +594,49 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { dto.setWPayOrAPay(decimal(record.get("wPayOrAPay"))); dto.setPointsPrice(decimal(record.get("pointsPrice"))); dto.setInvoiceCode(record.getString("invoiceCode")); + dto.setOrderProInfos(readProducts(dto.getOrderId(), record.getString("extJson"))); + return dto; + } + + private List readProducts(String orderId, String extJson) { + List products = dao.query(PointsMallOrderSubProduct.class, Cnd.where("orderSubId", "=", orderId).and("delFlag", "=", false)); + if (!products.isEmpty()) { + return products.stream().map(this::toProductDTO).collect(Collectors.toList()); + } + if (StrUtil.isBlank(extJson) || "null".equalsIgnoreCase(extJson)) { + return Collections.emptyList(); + } + return JSONUtil.toList(extJson, OrderProInfoDTO.class); + } + + private OrderProInfoDTO toProductDTO(PointsMallOrderSubProduct product) { + OrderProInfoDTO dto = new OrderProInfoDTO(); + dto.setSku(product.getSku()); + dto.setNumber(product.getNumber()); + dto.setPrice(product.getPrice()); + dto.setName(product.getName()); + dto.setTaxRate(product.getTaxRate()); + dto.setPicInfo(StrUtil.isBlank(product.getPicInfo()) ? Collections.emptyList() : Collections.singletonList(product.getPicInfo())); + dto.setFileId(product.getSku()); + dto.setFilePath(product.getPicInfo()); + return dto; + } + + private InvoiceInfoDTO toInvoiceInfoDTO(PointsMallInvoiceInfo info) { + InvoiceInfoDTO dto = new InvoiceInfoDTO(); + dto.setInvoiceId(info.getInvoiceId()); + dto.setInvoiceCode(info.getInvoiceCode()); + dto.setInvoiceDate(toLocalDate(info.getInvoiceDate())); + dto.setInvoiceNakeAmount(info.getInvoiceNakeAmount()); + dto.setInvoiceTaxRate(info.getInvoiceTaxRate()); + dto.setInvoiceTaxAmount(info.getInvoiceTaxAmount()); + dto.setInvoiceAmount(info.getInvoiceAmount()); + dto.setInvoiceType(info.getInvoiceType()); + dto.setUrl(info.getUrl()); + dto.setImageEncode(info.getImageEncode()); + dto.setFileType(info.getFileType()); + dto.setCheckCode(info.getCheckCode()); + dto.setInvoiceAddress(info.getInvoiceAddress()); return dto; } @@ -333,6 +647,28 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { return DateUtil.parse(value.replace("T", " ")); } + private String formatDate(Object value) { + if (value == null) { + return null; + } + return DateUtil.format(Convert.toDate(value), "yyyy-MM-dd HH:mm:ss"); + } + + private LocalDate toLocalDate(Date date) { + return date == null ? null : date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + } + + private List splitIds(String value) { + if (StrUtil.isBlank(value)) { + return Collections.emptyList(); + } + return Arrays.stream(value.split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .distinct() + .collect(Collectors.toList()); + } + private BigDecimal nvl(BigDecimal value) { return value == null ? BigDecimal.ZERO : value; } @@ -349,10 +685,6 @@ public class PointsMallBridgeServiceImpl implements PointsMallBridgeService { if (StrUtil.isBlank(value)) { return null; } - try { - return Integer.valueOf(value); - } catch (NumberFormatException e) { - return null; - } + return Convert.toInt(value, null); } } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/order/controller/PointsMallOrderSubController.java b/src/main/java/com/budwk/app/zhgh/pointsmall/order/controller/PointsMallOrderSubController.java new file mode 100644 index 00000000..79e42bf8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/order/controller/PointsMallOrderSubController.java @@ -0,0 +1,86 @@ +package com.budwk.app.zhgh.pointsmall.order.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderExchange; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; +import com.budwk.app.zhgh.pointsmall.order.param.PointsMallOrderPageParam; +import com.budwk.app.zhgh.pointsmall.order.service.PointsMallOrderService; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.adaptor.JsonAdaptor; +import org.nutz.mvc.annotation.AdaptBy; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; +import org.nutz.mvc.annotation.POST; + +@IocBean +@Ok("json:full") +@At("/platform/zhgh/points-mall/order/sub") +@AdaptBy(type = JsonAdaptor.class) +public class PointsMallOrderSubController { + + @Inject + private PointsMallOrderService pointsMallOrderService; + + @POST + @At("/page") + @SaCheckPermission("points.mall.order") + public Result pageData(@Param("..") PointsMallOrderPageParam param) { + return Result.success(pointsMallOrderService.pageSub(param)); + } + + @POST + @At("/product") + @SaCheckPermission("points.mall.order") + public Result productList(@Param("orderId") String orderId) { + return Result.success(pointsMallOrderService.listSubProducts(orderId)); + } + + @POST + @At("/exchange/list") + @SaCheckPermission("points.mall.order") + public Result exchangeList(@Param("mainOrderId") String mainOrderId) { + return Result.success(pointsMallOrderService.listExchange(mainOrderId)); + } + + @POST + @At("/exchange/product") + @SaCheckPermission("points.mall.order") + public Result exchangeProductList(@Param("orderId") String orderId) { + return Result.success(pointsMallOrderService.listExchangeProducts(orderId)); + } + + @POST + @At("/update") + @SaCheckPermission("points.mall.order") + public Result update(@Param("..") PointsMallOrderSub orderSub) { + return result(pointsMallOrderService.updateSub(orderSub)); + } + + @POST + @At("/delete") + @SaCheckPermission("points.mall.order") + public Result delete(@Param("id") String id) { + return result(pointsMallOrderService.deleteSub(id)); + } + + @POST + @At("/exchange/update") + @SaCheckPermission("points.mall.order") + public Result updateExchange(@Param("..") PointsMallOrderExchange exchange) { + return result(pointsMallOrderService.updateExchange(exchange)); + } + + @POST + @At("/exchange/delete") + @SaCheckPermission("points.mall.order") + public Result deleteExchange(@Param("id") String id) { + return result(pointsMallOrderService.deleteExchange(id)); + } + + private Result result(boolean success) { + return success ? Result.success("操作成功") : Result.error("操作失败"); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/PointsMallOrderService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/PointsMallOrderService.java index 612165e0..9a02083f 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/PointsMallOrderService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/PointsMallOrderService.java @@ -3,6 +3,8 @@ package com.budwk.app.zhgh.pointsmall.order.service; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.BaseService; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderExchange; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; import com.budwk.app.zhgh.pointsmall.order.param.PointsMallMobileOrderPageParam; import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; import com.budwk.app.zhgh.pointsmall.order.param.PointsMallOrderPageParam; @@ -28,5 +30,13 @@ public interface PointsMallOrderService extends BaseService List listExchangeProducts(String orderId); + boolean updateSub(PointsMallOrderSub orderSub); + + boolean deleteSub(String id); + + boolean updateExchange(PointsMallOrderExchange exchange); + + boolean deleteExchange(String id); + List listSuppliers(); } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderServiceImpl.java b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderServiceImpl.java index 247ab0e9..9bafd7ac 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderServiceImpl.java @@ -3,19 +3,23 @@ package com.budwk.app.zhgh.pointsmall.order.service.impl; import cn.hutool.core.util.StrUtil; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderExchange; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; import com.budwk.app.zhgh.pointsmall.order.param.PointsMallMobileOrderPageParam; -import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; import com.budwk.app.zhgh.pointsmall.order.param.PointsMallOrderPageParam; import com.budwk.app.zhgh.pointsmall.order.service.PointsMallOrderService; +import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; +import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; import org.nutz.dao.entity.Record; import org.nutz.dao.sql.Sql; -import org.nutz.dao.Sqls; import org.nutz.ioc.loader.annotation.IocBean; import java.util.Arrays; +import java.util.Date; import java.util.List; @IocBean(args = {"refer:dao"}) @@ -97,10 +101,12 @@ public class PointsMallOrderServiceImpl extends BaseServiceImpl 0; + } + + @Override + public boolean deleteSub(String id) { + if (StrUtil.isBlank(id)) { + return false; + } + return dao().update(PointsMallOrderSub.class, Chain.make("delFlag", true), Cnd.where("id", "=", id)) > 0; + } + + @Override + public boolean updateExchange(PointsMallOrderExchange exchange) { + if (exchange == null || StrUtil.isBlank(exchange.getId())) { + return false; + } + exchange.setOrderUpdateTime(new Date()); + return dao().updateIgnoreNull(exchange) > 0; + } + + @Override + public boolean deleteExchange(String id) { + if (StrUtil.isBlank(id)) { + return false; + } + return dao().update(PointsMallOrderExchange.class, Chain.make("delFlag", true), Cnd.where("id", "=", id)) > 0; + } + @Override public List listSuppliers() { return dao().query(PointsMallSupplier.class, Cnd.where("delFlag", "=", false).asc("sortCode")); diff --git a/src/main/resources/views/platform/zhghh5/points-mall/index.html b/src/main/resources/views/platform/zhghh5/points-mall/index.html index 9a6f0e50..b58408fb 100644 --- a/src/main/resources/views/platform/zhghh5/points-mall/index.html +++ b/src/main/resources/views/platform/zhghh5/points-mall/index.html @@ -84,6 +84,7 @@ layout("/layouts/platform_h5.html"){