From d127e534f89ac11eaab4495795c32346ef1dbd01 Mon Sep 17 00:00:00 2001 From: liuy <37787198+LiuyCodes@users.noreply.github.com> Date: Wed, 3 Sep 2025 10:07:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(zanhuo):=20=E6=B7=BB=E5=8A=A0=E7=94=A8?= =?UTF-8?q?=E5=8F=8B=E4=BA=91=E5=A5=97=E4=BB=B6=E6=8E=A5=E5=8F=A3=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E5=8A=9F=E8=83=BD-=20=E6=96=B0=E5=A2=9E=20EventType?= =?UTF-8?q?=20=E6=9E=9A=E4=B8=BE=E7=B1=BB=EF=BC=8C=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E4=BA=86=E5=90=84=E7=A7=8D=E4=BA=8B=E4=BB=B6=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=20-=20=E6=B7=BB=E5=8A=A0=20YsConstant=20=E7=B1=BB=EF=BC=8C?= =?UTF-8?q?=E5=8C=85=E5=90=AB=E7=94=A8=E5=8F=8B=E4=BA=91=E5=A5=97=E4=BB=B6?= =?UTF-8?q?=E7=9A=84=E5=B8=B8=E9=87=8F=E9=85=8D=E7=BD=AE=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=A4=9A=E4=B8=AA=20Yonsuite=20=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=9A=84=20DTO=20=E7=B1=BB=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=94=80=E5=94=AE=E8=AE=A2=E5=8D=95=E3=80=81=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E8=AE=A1=E5=88=92=E7=AD=89=E6=95=B0=E6=8D=AE=20-=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E8=8E=B7=E5=8F=96=20Access=20Token?= =?UTF-8?q?=20=E5=92=8C=E8=B0=83=E7=94=A8=E4=B8=9A=E5=8A=A1=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E7=9A=84=E5=B7=A5=E5=85=B7=E7=B1=BB=20-=20=E5=9C=A8?= =?UTF-8?q?=20TocSalesSettlement=20=E7=B1=BB=E4=B8=AD=E9=9B=86=E6=88=90?= =?UTF-8?q?=E4=BA=86=20CallYsBusinessApi=20=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/zanhuo/constant/EventType.java | 245 ++++++++++++++++++ .../plugin/zanhuo/constant/YsConstant.java | 44 ++++ .../zanhuo/sale/TocSalesSettlement.java | 4 + .../salesorder/YsOrderDefineCharacter.java | 17 ++ .../dto/salesorder/YsOrderDetails.java | 127 +++++++++ .../dto/salesorder/YsPaymentSchedules.java | 30 +++ .../yonsuite/dto/salesorder/YsSaleOrder.java | 118 +++++++++ .../dto/salesorder/YsSignSubjects.java | 30 +++ .../dto/token/AccessTokenResponse.java | 40 +++ .../yonsuite/dto/token/DcUrlResult.java | 32 +++ .../yonsuite/dto/token/EventContent.java | 123 +++++++++ .../yonsuite/dto/token/GenericResponse.java | 51 ++++ .../dto/token/RefreshTokenResponse.java | 35 +++ .../zanhuo/yonsuite/dto/token/Suite.java | 47 ++++ .../zanhuo/yonsuite/dto/token/SuiteAuth.java | 74 ++++++ .../yonsuite/dto/token/TokenUrlDto.java | 27 ++ .../yonsuite/dto/token/UserTokenResponse.java | 74 ++++++ .../yonsuite/util/CallYsBusinessApi.java | 62 +++++ .../zanhuo/yonsuite/util/GetYsToken.java | 78 ++++++ .../zanhuo/yonsuite/util/RequestTool.java | 157 +++++++++++ .../zanhuo/yonsuite/util/SignHelper.java | 52 ++++ .../yonsuite/util/YonSuiteTokenManager.java | 92 +++++++ .../zanhuo/yonsuite/util/PullYsDataTest.java | 43 +++ 23 files changed, 1602 insertions(+) create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/constant/EventType.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/constant/YsConstant.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsOrderDefineCharacter.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsOrderDetails.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsPaymentSchedules.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsSaleOrder.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsSignSubjects.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/AccessTokenResponse.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/DcUrlResult.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/EventContent.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/GenericResponse.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/RefreshTokenResponse.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/Suite.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/SuiteAuth.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/TokenUrlDto.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/UserTokenResponse.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/CallYsBusinessApi.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/GetYsToken.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/RequestTool.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/SignHelper.java create mode 100644 base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/YonSuiteTokenManager.java create mode 100644 base-buildpackage/src/test/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/PullYsDataTest.java diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/constant/EventType.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/constant/EventType.java new file mode 100644 index 00000000..20a93543 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/constant/EventType.java @@ -0,0 +1,245 @@ +package com.hzya.frame.plugin.zanhuo.constant; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.constant + * @Project:kangarooDataCenterV3 + * @name:EventType + * @Date:2025/9/2 17:37 + * @Filename:EventType + */ +public enum EventType { + /** + * 检查回调地址有效性 + */ + CHECK_URL, + + /** + * 员工增加 + */ + STAFF_ADD, + + /** + * 员工更改 + */ + STAFF_UPDATE, + + /** + * 员工启用 + */ + STAFF_ENABLE, + + /** + * 员工停用 + */ + STAFF_DISABLE, + + /** + * 员工删除 + */ + STAFF_DELETE, + + + /** + * 部门创建 + */ + DEPT_ADD, + + /** + * 部门修改 + */ + DEPT_UPDATE, + + /** + * 部门启用 + */ + DEPT_ENABLE, + + /** + * 部门停用 + */ + DEPT_DISABLE, + + /** + * 部门删除 + */ + DEPT_DELETE, + + + /** + * 用户增加 + */ + USER_ADD, + + /** + * 用户删除 + */ + USER_DELETE, + /** + * 用户启用 + */ + USER_ENABLE, + /** + * 用户停用 + */ + USER_DISABLE, + /** + * 用户注销事件 + */ + DELETE_DIWORKSESSION, + + /** + * 元数据修改 + */ + META_ALTER, + + /** + * UNKNOWN + **/ + UNKNOWN, + + /** + * 任职增加 + */ + JOBINFO_ADD, + + /** + * 任职更新 + */ + JOBINFO_UPDATE, + + /** + * 物料档案新增 + */ + YXYBASEDOC_PC_PRODUCT_INSERT, + + /** + * 物料档案修改 + */ + YXYBASEDOC_PC_PRODUCT_UPDATE, + + /** + * 物料档案删除 + */ + YXYBASEDOC_PC_PRODUCT_DELETE, + + /** + * 物料分类新增 + */ + YXYBASEDOC_PC_MANAGEMENTCLASS_INSERT, + + /** + * 物料分类修改 + */ + YXYBASEDOC_PC_MANAGEMENTCLASS_UPDATE, + + /** + * 物料分类删除 + */ + YXYBASEDOC_PC_MANAGEMENTCLASS_DELETE, + + /** + * 计量单位新增 + */ + YXYBASEDOC_PC_UNIT_INSERT, + + /** + * 计量单位修改 + */ + YXYBASEDOC_PC_UNIT_UPDATE, + + /** + * 计量单位删除 + */ + YXYBASEDOC_PC_UNIT_DELETE, + + /** + * SKU属性新增 + */ + YXYBASEDOC_PC_PRODUCTSKUPRO_INSERT, + + /** + * SKU属性修改 + */ + YXYBASEDOC_PC_PRODUCTSKUPRO_UPDATE, + + /** + * SKU属性删除 + */ + YXYBASEDOC_PC_PRODUCTSKUPRO_DELETE, + + /** + * 物料属性新增 + */ + YXYBASEDOC_PC_PRODUCTPRO_INSERT, + + /** + * 物料属性修改 + */ + YXYBASEDOC_PC_PRODUCTPRO_UPDATE, + + /** + * 物料属性删除 + */ + YXYBASEDOC_PC_PRODUCTPRO_DELETE, + + /** + * 仓库新增 + */ + YXYBASEDOC_AA_WAREHOUSE_INSERT, + + /** + * 仓库修改 + */ + YXYBASEDOC_AA_WAREHOUSE_UPDATE, + + /** + * 仓库删除 + */ + YXYBASEDOC_AA_WAREHOUSE_DELETE, + + /** + * 客户档案新增 + */ + YXYBASEDOC_AA_MERCHANT_INSERT, + + /** + * 客户档案修改 + */ + YXYBASEDOC_AA_MERCHANT_UPDATE, + + /** + * 客户档案删除 + */ + YXYBASEDOC_AA_MERCHANT_DELETE, + + /** + * 物料规格新增 + */ + YXYBASEDOC_PC_SPEPRO_INSERT, + + /** + * 物料规格修改 + */ + YXYBASEDOC_PC_SPEPRO_UPDATE, + + /** + * 物料规格删除 + */ + YXYBASEDOC_PC_SPEPRO_DELETE, + + /** + * 物料新增-old + */ + YXYBASEDOC_ADD_NOTIFY, + + /** + * 物料修改-old + */ + YXYBASEDOC_UPDATE_NOTIFY, + + /** + * 物料删除-old + */ + YXYBASEDOC_DELETE_NOTIFY; +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/constant/YsConstant.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/constant/YsConstant.java new file mode 100644 index 00000000..470a1373 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/constant/YsConstant.java @@ -0,0 +1,44 @@ +package com.hzya.frame.plugin.zanhuo.constant; + +/** + * YS常量 + * + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.constant + * @Project:kangarooDataCenterV3 + * @name:YsConstant + * @Date:2025/9/2 17:15 + * @Filename:YsConstant + */ +public class YsConstant { + + /** + * 赞货租户id + */ + public static String tenantId = "ipi140f4"; + + /** + * 赞货中台appKey + */ + public static String appKey = "c9d8c213f65e488facb03170abb7f9be"; + + /** + * 赞货应用AppSecret + */ + public static String appSecret = "db86b3a6f4248ecde1f5b3e8ad521b0a4e3c075e"; + + /** + * 获取租户所在数据中心域名对应的地址 + */ + public static String openApiUrl = "https://apigateway.yonyoucloud.com"; + + /** + * 租户所在数据中心的核心网关域名,调用业务接口时需要拼接核心网关域名和接口相对路径 + */ + public static String gatewayUrl = "https://c4.yonyoucloud.com/iuap-api-gateway"; + + /** + * 租户所在数据中心的auth域名,调用获取token接口时,需要拼接auth域名和获取token接口相对路径 + */ + public static String tokenUrl = "https://c4.yonyoucloud.com/iuap-api-auth"; +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/sale/TocSalesSettlement.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/sale/TocSalesSettlement.java index e3a18b77..e485fed3 100644 --- a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/sale/TocSalesSettlement.java +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/sale/TocSalesSettlement.java @@ -11,6 +11,7 @@ import com.hzya.frame.plugin.zanhuo.dto.jackyun.datadto.salessettlement.TradeSet import com.hzya.frame.plugin.zanhuo.jackyun.JackyunApi; import com.hzya.frame.plugin.zanhuo.util.SplitListByCountUtil; import com.hzya.frame.plugin.zanhuo.util.jackyun.JackYunApiUtil; +import com.hzya.frame.plugin.zanhuo.yonsuite.util.CallYsBusinessApi; import com.hzya.frame.web.entity.JsonResultEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,6 +47,9 @@ public class TocSalesSettlement extends PluginBaseEntity { @Autowired private MongoTemplate mongoTemplate; + @Autowired + private CallYsBusinessApi callYsBusinessApi; + @Override public void initialize() { logger.info(getPluginLabel() + "执行初始化方法initialize()"); diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsOrderDefineCharacter.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsOrderDefineCharacter.java new file mode 100644 index 00000000..6207e10c --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsOrderDefineCharacter.java @@ -0,0 +1,17 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder + * @Project:kangarooDataCenterV3 + * @name:YsOrderDefineCharacter + * @Date:2025/9/2 15:54 + * @Filename:YsOrderDefineCharacter + */ +@Data +public class YsOrderDefineCharacter { + private String YWY; + private String id; +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsOrderDetails.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsOrderDetails.java new file mode 100644 index 00000000..d6a75f23 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsOrderDetails.java @@ -0,0 +1,127 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder + * @Project:kangarooDataCenterV3 + * @name:YsOrderDetails + * @Date:2025/9/2 15:55 + * @Filename:YsOrderDetails + */ +@Data +public class YsOrderDetails { + private String id; + private String stockId; + @JsonProperty("orderDetailPrices!discountRate") + private String orderDetailPrices_discountRate; + private String costCenter_code; + private String providerProfitCenter_code; + private String consumerProfitCenter_code; + private String taxIssuedDiscountline; + private String isExpiryDateManage; + private String bizId; + @JsonProperty("orderDetailPrices!particularlyMoneyDomesticTaxfree") + private String orderDetailPrices_particularlyMoneyDomesticTaxfree; + private String isSkuReserve; + @JsonProperty("orderDetailPrices!natSum") + private String orderDetailPrices_natSum; + @JsonProperty("orderDetailPrices!natMoney") + private String orderDetailPrices_natMoney; + private String productId; + @JsonProperty("orderDetailPrices!orderDetailId") + private String orderDetailPrices_orderDetailId; + private String pointsMoney; + private String promotionMoney; + @JsonProperty("orderDetailPrices!saleCost_domestic_taxfree") + private String orderDetailPrices_saleCost_domestic_taxfree; + private String productId_priceListFlag; + private String masterUnitId; + private String cusDiscountMoney; + private String invExchRate; + private String cusDiscountRate; + private String unitExchangeTypePrice; + @JsonProperty("orderDetailPrices!saleCost_orig_taxfree") + private String orderDetailPrices_saleCost_orig_taxfree; + @JsonProperty("orderDetailPrices!oriTax") + private String orderDetailPrices_oriTax; + private String particularlyMoney; + private String iProductAuxUnitId; + @JsonProperty("orderDetailPrices!particularlyMoneyOrigTaxfree") + private String orderDetailPrices_particularlyMoneyOrigTaxfree; + @JsonProperty("orderDetailPrices!natUnitPrice") + private String orderDetailPrices_natUnitPrice; + @JsonProperty("orderDetailPrices!saleCost_domestic") + private String orderDetailPrices_saleCost_domestic; + private String invPriceExchRate; + private String isBatchManage; + @JsonProperty("orderDetailPrices!isDeleted") + private String orderDetailPrices_isDeleted; + private String oriSum; + private String noTaxSalePrice; + private String salePrice; + @JsonProperty("orderDetailPrices!oriMoney") + private String orderDetailPrices_oriMoney; + private String lowestPrice; + private String priceQty; + private String stockOrgId; + private String prodPrice; + private String iProductUnitId; + @JsonProperty("orderDetailPrices!natTaxUnitPrice") + private String orderDetailPrices_natTaxUnitPrice; + private String priceMark; + private String orderProductType; + private String subQty; + private String consignTime; + private String skuId; + private String ordRealMoney; + @JsonProperty("orderDetailPrices!salePrice_domestic") + private String orderDetailPrices_salePrice_domestic; + private String marketPricie; + private String taxId; + private String qty; + private String realProductCode; + private String settlementOrgId; + private String oriTaxUnitPrice; + @JsonProperty("orderDetailPrices!lineDiscountMoney") + private String orderDetailPrices_lineDiscountMoney; + @JsonProperty("orderDetailPrices!natTax") + private String orderDetailPrices_natTax; + private String isreserve; + private String prodCost; + private String productId_pbatchName; + private String specDescription; + @JsonProperty("orderDetailPrices!salePrice_domestic_taxfree") + private String orderDetailPrices_salePrice_domestic_taxfree; + private String unitExchangeType; + private String noTaxSaleCost; + private String saleCost; + @JsonProperty("orderDetailPrices!oriUnitPrice") + private String orderDetailPrices_oriUnitPrice; + private String salesOrgId; + private String orderRebateMoney; + private String cashRebateMoney; + private String _status; + private String orderProductApportionName; + private String memo; + private String projectId_code; + private String isAdvRecInv; + @JsonProperty("orderDetailPrices!prepayInvRvnRecogBkgMeth") + private String orderDetailPrices_prepayInvRvnRecogBkgMeth; + // private String orderDetailDefineCharacter; +// private String voucher.order.OrderDetail; + // private String orderDetailCharacteristics; +// private String voucher.order.OrderDetail; + @JsonProperty("orderDetailPrices!checkByRevenueManagement") + private String orderDetailPrices_checkByRevenueManagement; + @JsonProperty("orderDetailPrices!serviceStartDate") + private String orderDetailPrices_serviceStartDate; + @JsonProperty("orderDetailPrices!serviceEndDate") + private String orderDetailPrices_serviceEndDate; + @JsonProperty(" orderDetailPrices!calBase") + private String orderDetailPrices_calBase; + private String batchId; + private String batchNo; +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsPaymentSchedules.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsPaymentSchedules.java new file mode 100644 index 00000000..c19aa05d --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsPaymentSchedules.java @@ -0,0 +1,30 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder + * @Project:kangarooDataCenterV3 + * @name:YsPaymentSchedules + * @Date:2025/9/2 16:37 + * @Filename:YsPaymentSchedules + */ +@Data +public class YsPaymentSchedules { + private String startDateTime; + private String fixAccoutDateTime; + private String expiringDateTime; + private String number; + private String name; + private String payRatio; + private String startDate; + private String startName; + private String accountType; + private String accountUnit; + private String accountDay; + private String currencyPk; + private String rate; + private String natCurrencyPk; + private String amount; +} \ No newline at end of file diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsSaleOrder.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsSaleOrder.java new file mode 100644 index 00000000..480409b1 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsSaleOrder.java @@ -0,0 +1,118 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder + * @Project:kangarooDataCenterV3 + * @name:YsSaleOrder + * @Date:2025/9/2 15:27 + * @Filename:YsSaleOrder + */ +@Data +public class YsSaleOrder { + private String resubmitCheckKey; + private String salesOrgId; + private String transactionTypeId; + private String vouchdate; + private String code; + private String agentId; + private String corpContact; + private String saleDepartmentId; + private String retailInvestors; + private String retailAgentName; + private String receiveContacter; + private String receiveContacterPhone; + private String settlementOrgId; + private String hopeReceiveDate; + private String sendDate; + private String source; + private String orderDate; + private String bizId; + private String agentRelationId; + private String invoiceMoney; + private String version; + private String isWfControlled; + @JsonProperty("orderPrices!currency") + private String orderPrices_currency; + @JsonProperty("orderPrices!signFileId") + private String orderPrices_signFileId; + @JsonProperty("orderPrices!exchRate") + private String orderPrices_exchRate; + @JsonProperty("orderPrices!exchangeRateType") + private String orderPrices_exchangeRateType; + @JsonProperty("orderPrices!natCurrency") + private String orderPrices_natCurrency; + @JsonProperty("orderPrices!taxInclusive;") + private String orderPrices_taxInclusive; + private String creditBalance; + private String agentTaxItem; + private String lockIn; + private String bmake_voucher_delivery; + private String bizFlow; + private String bizFlow_version; + private String isFlowCoreBill; + private String rebateValidFlag; + private String id; + private String receiveId; + private String receiveZipCode; + private String receiveTelePhone; + private String receiver; + private String receiveMobile; + private String receivecode; + private String receiveAddress; + private String orderPayType; + private String settlement; + private String shippingChoiceId; + private String invoiceAgentId; + private String tradeRouteID; + private String modifyInvoiceType; + private String bdInvoiceTypeId; + private String invoiceUpcType; + private String invoiceTitle; + private String invoiceTitleType; + private String bankName; + private String receievInvoiceMobile; + private String receievInvoiceEmail; + private String taxNum; + private String subBankName; + private String bankAccount; + private String invoiceTelephone; + private String invoiceAddress; + private String promotionMoney; + private String rebateMoney; + private String rebateCashMoney; + private String pointsMoney; + private String reight; + private String payMoney; + private String orderPayMoney; + private String realMoney; + private String orderRealMoney; + @JsonProperty("orderPrices!totalMoneyOrigTaxfree") + private String orderPrices_totalMoneyOrigTaxfree; + @JsonProperty("orderPrices!orderPayMoneyOrigTaxfree") + private String orderPrices_orderPayMoneyOrigTaxfree; + @JsonProperty("orderPrices!orderPayMoneyDomestic") + private String orderPrices_orderPayMoneyDomestic; + @JsonProperty("orderPrices!orderPayMoneyDomesticTaxfree") + private String orderPrices_orderPayMoneyDomesticTaxfree; + @JsonProperty("orderPrices!orderId") + private String orderPrices_orderId; + @JsonProperty("orderPrices!wholeDiscountRate") + private String orderPrices_wholeDiscountRate; + @JsonProperty("orderPrices!discountAfterMoney") + private String orderPrices_discountAfterMoney; + @JsonProperty("orderPrices!discountMoney") + private String orderPrices_discountMoney; + + private YsOrderDefineCharacter orderDefineCharacter; + // private String voucher.order.Order; + private YsOrderDetails orderDetails; + private YsPaymentSchedules paymentSchedules; + private String _status; + private String memo; + private String opposeMemo; + private YsSignSubjects signSubjects; +} \ No newline at end of file diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsSignSubjects.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsSignSubjects.java new file mode 100644 index 00000000..8460e154 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/salesorder/YsSignSubjects.java @@ -0,0 +1,30 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.salesorder + * @Project:kangarooDataCenterV3 + * @name:YsSignSubjects + * @Date:2025/9/2 16:43 + * @Filename:YsSignSubjects + */ +@Data +public class YsSignSubjects { + private String id; + private String mainid; + private String signOrder; + private String signSubjectType; + private String signOrgId; + private String signAgentId; + private String address; + private String postalCode; + private String telephone; + private String facsimile; + private String bankOfDeposit; + private String bankAccount; + private String memo; + private String isOriginator; + private String isDefault; +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/AccessTokenResponse.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/AccessTokenResponse.java new file mode 100644 index 00000000..95f8b5b2 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/AccessTokenResponse.java @@ -0,0 +1,40 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:AccessTokenResponse + * @Date:2025/9/2 17:26 + * @Filename:AccessTokenResponse + */ +public class AccessTokenResponse { + /** + * 获取的访问令牌 access_token + */ + @JsonProperty(value = "access_token") + private String accessToken; + + /** + * 访问令牌的过期时间,单位秒 + */ + private long expire; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public long getExpire() { + return expire; + } + + public void setExpire(long expire) { + this.expire = expire; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/DcUrlResult.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/DcUrlResult.java new file mode 100644 index 00000000..60b7178c --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/DcUrlResult.java @@ -0,0 +1,32 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:DcUrlResult + * @Date:2025/9/2 17:27 + * @Filename:DcUrlResult + */ +public class DcUrlResult { + + private String gatewayUrl; + + private String tokenUrl; + + public String getGatewayUrl() { + return gatewayUrl; + } + + public void setGatewayUrl(String gatewayUrl) { + this.gatewayUrl = gatewayUrl; + } + + public String getTokenUrl() { + return tokenUrl; + } + + public void setTokenUrl(String tokenUrl) { + this.tokenUrl = tokenUrl; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/EventContent.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/EventContent.java new file mode 100644 index 00000000..f044370c --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/EventContent.java @@ -0,0 +1,123 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.hzya.frame.plugin.zanhuo.constant.EventType; + +import java.io.Serializable; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:EventContent + * @Date:2025/9/2 17:27 + * @Filename:EventContent + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class EventContent implements Serializable { + /** + * 事件类型 + **/ + private EventType type; + + /** + * 事件唯一的业务 uuid + **/ + private String eventId; + + /** + * 事件创建的 unix 时间戳 + **/ + private long timestamp; + + /** + * 事件涉及的租户 id + **/ + private String tenantId; + + /** + * 变动的 staff id + **/ + private String[] staffId; + + /** + * 变动的 dept id + **/ + private String[] deptId; + + /** + * 变动的 user id + */ + private String[] userId; + + /** + * 附加消息内容,一般是json字符串,下发相关额外事件参数 + */ + private String content; + + public EventType getType() { + return type; + } + + public void setType(EventType type) { + this.type = type; + } + + public String getEventId() { + return eventId; + } + + public void setEventId(String eventId) { + this.eventId = eventId; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String[] getStaffId() { + return staffId; + } + + public void setStaffId(String[] staffId) { + this.staffId = staffId; + } + + public String[] getDeptId() { + return deptId; + } + + public void setDeptId(String[] deptId) { + this.deptId = deptId; + } + + public String[] getUserId() { + return userId; + } + + public void setUserId(String[] userId) { + this.userId = userId; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/GenericResponse.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/GenericResponse.java new file mode 100644 index 00000000..98dfd63b --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/GenericResponse.java @@ -0,0 +1,51 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:GenericResponse + * @Date:2025/9/2 17:28 + * @Filename:GenericResponse + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GenericResponse { + + public static final String SUCCESS_CODE = "00000"; + + private String code; + + private String message; + + private T data; + + public boolean isSuccess() { + return SUCCESS_CODE.equals(code); + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/RefreshTokenResponse.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/RefreshTokenResponse.java new file mode 100644 index 00000000..bffb46f7 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/RefreshTokenResponse.java @@ -0,0 +1,35 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:RefreshTokenResponse + * @Date:2025/9/2 17:36 + * @Filename:RefreshTokenResponse + */ +public class RefreshTokenResponse { + + @JsonProperty("user_access_token") + private String userAccessToken; + + private long expired; + + public String getUserAccessToken() { + return userAccessToken; + } + + public void setUserAccessToken(String userAccessToken) { + this.userAccessToken = userAccessToken; + } + + public long getExpired() { + return expired; + } + + public void setExpired(long expired) { + this.expired = expired; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/Suite.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/Suite.java new file mode 100644 index 00000000..28d4a6c8 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/Suite.java @@ -0,0 +1,47 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:Suite + * @Date:2025/9/2 17:30 + * @Filename:Suite + */ +public class Suite { + /** + * 套件 key + */ + private String suiteKey; + + private String suiteSecret; + + /** + * 推送的套件票据 + */ + private String suiteTicket; + + public String getSuiteKey() { + return suiteKey; + } + + public void setSuiteKey(String suiteKey) { + this.suiteKey = suiteKey; + } + + public String getSuiteTicket() { + return suiteTicket; + } + + public void setSuiteTicket(String suiteTicket) { + this.suiteTicket = suiteTicket; + } + + public String getSuiteSecret() { + return suiteSecret; + } + + public void setSuiteSecret(String suiteSecret) { + this.suiteSecret = suiteSecret; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/SuiteAuth.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/SuiteAuth.java new file mode 100644 index 00000000..1f3ab5d4 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/SuiteAuth.java @@ -0,0 +1,74 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +import java.time.Instant; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:SuiteAuth + * @Date:2025/9/2 17:32 + * @Filename:SuiteAuth + */ + +/** + * 记录套件租户的授权信息 + */ +public class SuiteAuth { + /** + * 授权的套件 + */ + private String suiteKey; + + /** + * 授权的租户 id + */ + private String tenantId; + + /** + * 该租户对应的访问令牌 + */ + private String accessToken; + + /** + * 访问令牌过期时间点 + */ + private Instant expireAt; + + public void updateAccessToken(AccessTokenResponse response) { + this.accessToken = response.getAccessToken(); + this.expireAt = Instant.now().plusSeconds(response.getExpire()); + } + + public String getSuiteKey() { + return suiteKey; + } + + public void setSuiteKey(String suiteKey) { + this.suiteKey = suiteKey; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public Instant getExpireAt() { + return expireAt; + } + + public void setExpireAt(Instant expireAt) { + this.expireAt = expireAt; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/TokenUrlDto.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/TokenUrlDto.java new file mode 100644 index 00000000..77a9234a --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/TokenUrlDto.java @@ -0,0 +1,27 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:TokenUrlDto + * @Date:2025/9/3 10:00 + * @Filename:TokenUrlDto + */ +@Data +public class TokenUrlDto { + private String accessToken; + private String gatewayUrl; + private String tokenUrl; + + public TokenUrlDto() { + } + + public TokenUrlDto(String accessToken, String gatewayUrl, String tokenUrl) { + this.accessToken = accessToken; + this.gatewayUrl = gatewayUrl; + this.tokenUrl = tokenUrl; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/UserTokenResponse.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/UserTokenResponse.java new file mode 100644 index 00000000..0eb234a3 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/dto/token/UserTokenResponse.java @@ -0,0 +1,74 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.dto.token; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.dto.token + * @Project:kangarooDataCenterV3 + * @name:UserTokenResponse + * @Date:2025/9/2 17:32 + * @Filename:UserTokenResponse + */ +public class UserTokenResponse { + + @JsonProperty("user_access_token") + private String userAccessToken; + + @JsonProperty("token_type") + private String tokenType; + + @JsonProperty("refresh_token") + private String refreshToken; + + @JsonProperty("expires_in") + private long expiresIn; + + @JsonProperty("id_token") + private String idToken; + + public String getUserAccessToken() { + return userAccessToken; + } + + public UserTokenResponse setUserAccessToken(String userAccessToken) { + this.userAccessToken = userAccessToken; + return this; + } + + public String getTokenType() { + return tokenType; + } + + public UserTokenResponse setTokenType(String tokenType) { + this.tokenType = tokenType; + return this; + } + + public String getRefreshToken() { + return refreshToken; + } + + public UserTokenResponse setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + return this; + } + + public long getExpiresIn() { + return expiresIn; + } + + public UserTokenResponse setExpiresIn(long expiresIn) { + this.expiresIn = expiresIn; + return this; + } + + public String getIdToken() { + return idToken; + } + + public UserTokenResponse setIdToken(String idToken) { + this.idToken = idToken; + return this; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/CallYsBusinessApi.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/CallYsBusinessApi.java new file mode 100644 index 00000000..14cf1046 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/CallYsBusinessApi.java @@ -0,0 +1,62 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.util; + +import cn.hutool.core.lang.Assert; +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.TokenUrlDto; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * 调用YS业务接口 + * + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.util + * @Project:kangarooDataCenterV3 + * @name:CallYsBusinessApi + * @Date:2025/9/3 09:25 + * @Filename:CallYsBusinessApi + */ +@Component +public class CallYsBusinessApi { + Logger logger = LoggerFactory.getLogger(CallYsBusinessApi.class); + + @Autowired + private YonSuiteTokenManager tokenManager; + + /** + * 调用YS业务接口 (POST JSON) + * + * @param requestUrl 接口的URL (不包含查询参数) + * @param businessJsonData 业务数据的JSON字符串 + * @return 接口返回的原始字符串 + */ + public String callYsBusinessApi(String requestUrl, String businessJsonData) { + String result = null; + try { + Assert.notNull(requestUrl, "requestUrl不能为空"); + Assert.notNull(businessJsonData, "businessJsonData不能为空"); + + TokenUrlDto validAccessToken = tokenManager.getValidAccessToken(); + String accessToken = validAccessToken.getAccessToken(); + String gatewayUrl = validAccessToken.getGatewayUrl(); + + Map queryParams = new HashMap<>(); + queryParams.put("access_token", accessToken); + +// String requestBody = String.format("{\"data\": %s}", businessJsonData); + + // 4. 使用RequestTool发起POST请求 + logger.info("向YS业务接口发起请求, URL: {}, Body: {}", gatewayUrl + requestUrl, businessJsonData); + result = RequestTool.doPost(gatewayUrl + requestUrl, queryParams, businessJsonData); + logger.info("YS业务接口响应: {}", result); + } catch (Exception e) { + logger.error("调用YS业务接口异常, URL: " + requestUrl, e); + throw new RuntimeException("调用YS业务接口异常", e); + } + return result; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/GetYsToken.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/GetYsToken.java new file mode 100644 index 00000000..44de3b09 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/GetYsToken.java @@ -0,0 +1,78 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.util; + +import com.hzya.frame.plugin.zanhuo.constant.YsConstant; +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.AccessTokenResponse; +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.DcUrlResult; +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.GenericResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import com.fasterxml.jackson.core.type.TypeReference; + +import java.util.HashMap; +import java.util.Map; + +/** + * YS接口获取类 + * + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.util + * @Project:kangarooDataCenterV3 + * @name:PullYsData + * @Date:2025/9/2 16:47 + * @Filename:PullYsData + */ +@Component +public class GetYsToken { + + Logger logger = LoggerFactory.getLogger(GetYsToken.class); + + /** + * 获取aaccess_token + * + * @author liuyang + */ + public AccessTokenResponse getAccessTokenV2(DcUrlResult dcUrl) throws Exception { +// DcUrlResult dcUrl = getGateway(); + String tokenUrl = dcUrl.getTokenUrl(); + + Map params = new HashMap<>(); + // 除签名外的其他参数 + params.put("appKey", YsConstant.appKey); + params.put("timestamp", String.valueOf(System.currentTimeMillis())); + // 计算签名 + String signature = SignHelper.sign(params, YsConstant.appSecret); + params.put("signature", signature); + + // 请求 + String requestUrl = tokenUrl + "/open-auth/selfAppAuth/getAccessToken"; + GenericResponse response = RequestTool.doGet(requestUrl, params, new TypeReference>() { + }); + + if (response.isSuccess()) { + return response.getData(); + } + + logger.error("请求开放平台接口失败,code: {}, message: {}", response.getCode(), response.getMessage()); + throw new RuntimeException("请求开放平台接口失败, code: " + response.getCode() + ", message: " + response.getMessage()); + } + + /** + * 获取租户所在数据中心域名 + * + * @author liuyang + */ + public DcUrlResult getGateway() throws Exception { + try { + Map params = new HashMap<>(); + params.put("tenantId", YsConstant.tenantId); + String requestUrl = YsConstant.openApiUrl + "/open-auth/dataCenter/getGatewayAddress"; + GenericResponse response = RequestTool.doGet(requestUrl, params, new TypeReference>() { + }); + return response.getData(); + } catch (Exception e) { + logger.error("getGateway方法抛出异常", e); + throw new RuntimeException("getGateway方法抛出异常", e); + } + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/RequestTool.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/RequestTool.java new file mode 100644 index 00000000..cc8eaf70 --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/RequestTool.java @@ -0,0 +1,157 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.util; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.util + * @Project:kangarooDataCenterV3 + * @name:RequestTool + * @Date:2025/9/2 17:54 + * @Filename:RequestTool + */ +public class RequestTool { + private static final String HEADER_CONTENT_JSON = "application/json"; + + private static final String DEFAULT_CHARSET = "UTF-8"; + + private static PoolingHttpClientConnectionManager cm = null; + + private static ObjectMapper mapper = new ObjectMapper(); + + private static CloseableHttpClient httpClient; + + /** + * 记录开放平台请求结果 + */ + public static class Response { + /** + * 该请求的 http 状态码 + * 200 为正常的返回结果 + */ + private int status; + + /** + * 请求返回消息 + * 当 status == 200 时会返回 response body 中的字符串 + * 当 status !== 200 时会返回具体的错误信息 + */ + private String result; + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + } + + static { + cm = new PoolingHttpClientConnectionManager(); + cm.setMaxTotal(500); + cm.setDefaultMaxPerRoute(50); + + RequestConfig globalConfig = RequestConfig.custom().setConnectionRequestTimeout(1000) // 连接池获取连接超时 + .setConnectTimeout(1000) // 连接建立超时 + .setSocketTimeout(5000) // 等待响应超时 + .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build(); + + httpClient = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(globalConfig).build(); + } + + private static CloseableHttpClient getHttpClient() { + return httpClient; + } + + public static T doGet(String requestUrl, Map paramMap, Class type) throws IOException { + return mapper.readValue(doGet(requestUrl, paramMap), type); + } + + public static T doGet(String requestUrl, Map paramMap, TypeReference typeReference) throws IOException { + return mapper.readValue(doGet(requestUrl, paramMap), typeReference); + } + + public static String doGet(String requestUrl, Map paramMap) throws IOException { + CloseableHttpClient httpClient = getHttpClient(); + StringBuilder param = new StringBuilder("?"); + if (paramMap != null) { + for (Map.Entry entry : paramMap.entrySet()) { + param.append(entry.getKey()); + param.append("="); + param.append(entry.getValue()); + param.append("&"); + } + param.deleteCharAt(param.length() - 1); + } + + HttpGet get = new HttpGet(requestUrl + param); + String responseString = httpClient.execute(get, response -> EntityUtils.toString(response.getEntity())); + get.releaseConnection(); + return responseString; + } + + /** + * 执行一个HTTP POST请求,将JSON字符串数据发布到指定的URL + * + * @param requestUrl 请求的URL + * @param queryParams URL的查询参数 (例如 access_token) + * @param jsonBody 要发送的JSON格式的请求体 + * @return 响应的字符串 + * @throws IOException + */ + public static String doPost(String requestUrl, Map queryParams, String jsonBody) throws IOException { + CloseableHttpClient httpClient = getHttpClient(); + + // 构造带查询参数的URL + StringBuilder urlWithParams = new StringBuilder(requestUrl); + if (queryParams != null && !queryParams.isEmpty()) { + urlWithParams.append("?"); + for (Map.Entry entry : queryParams.entrySet()) { + urlWithParams.append(entry.getKey()); + urlWithParams.append("="); + urlWithParams.append(entry.getValue()); + urlWithParams.append("&"); + } + urlWithParams.deleteCharAt(urlWithParams.length() - 1); + } + + // 创建HttpPost对象 + HttpPost post = new HttpPost(urlWithParams.toString()); + + // 设置请求体 + if (jsonBody != null) { + StringEntity entity = new StringEntity(jsonBody, StandardCharsets.UTF_8); + entity.setContentEncoding(StandardCharsets.UTF_8.name()); + entity.setContentType(HEADER_CONTENT_JSON); + post.setEntity(entity); + } + + // 执行请求并获取响应 + String responseString = httpClient.execute(post, response -> EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8)); + post.releaseConnection(); + return responseString; + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/SignHelper.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/SignHelper.java new file mode 100644 index 00000000..a2a2151d --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/SignHelper.java @@ -0,0 +1,52 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.util; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Map; +import java.util.TreeMap; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.util + * @Project:kangarooDataCenterV3 + * @name:SignHelper + * @Date:2025/9/2 18:07 + * @Filename:SignHelper + */ +public class SignHelper { + /** + * 按参数名排序后依次拼接参数名称与数值,之后对该字符串使用 HmacSHA256 加签,加签结果进行 base 64 返回 + * @param params 请求参数 map + * @param suiteSecret 套件密钥,用作 mac key + * @return 签名 + * @throws NoSuchAlgorithmException + * @throws UnsupportedEncodingException + * @throws InvalidKeyException + */ + public static String sign(Map params, String suiteSecret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException { + // use tree map to sort params by name + Map treeMap; + if (params instanceof TreeMap) { + treeMap = params; + } else { + treeMap = new TreeMap<>(params); + } + + StringBuilder stringBuilder = new StringBuilder(); + for (Map.Entry entry : treeMap.entrySet()) { + stringBuilder.append(entry.getKey()).append(entry.getValue()); + } + + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(suiteSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); + byte[] signData = mac.doFinal(stringBuilder.toString().getBytes(StandardCharsets.UTF_8)); + String base64String = Base64.getEncoder().encodeToString(signData); + return URLEncoder.encode(base64String, "UTF-8"); + } +} diff --git a/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/YonSuiteTokenManager.java b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/YonSuiteTokenManager.java new file mode 100644 index 00000000..99a2517f --- /dev/null +++ b/base-buildpackage/src/main/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/YonSuiteTokenManager.java @@ -0,0 +1,92 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.util; + +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.AccessTokenResponse; +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.DcUrlResult; +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.TokenUrlDto; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * YS Token管理器 + * + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.util + * @Project:kangarooDataCenterV3 + * @name:YonSuiteTokenManager + * @Date:2025/9/3 09:19 + * @Filename:YonSuiteTokenManager + */ +@Component +public class YonSuiteTokenManager { + + Logger logger = LoggerFactory.getLogger(GetYsToken.class); + + @Autowired + private GetYsToken pullYsData; + + //缓存获取到的AccessToken + private String accessToken; + + //Token的过期时间戳(单位:毫秒) + private long expiryTimestamp; + + //业务接口 + private String gatewayUrl; + + //认证接口 + private String tokenUrl; + + //容错时间,提前200秒刷新Token + private static final long FAULT_TOLERANCE_SECONDS = 200L; + + /** + * 对外提供获取有效AccessToken的唯一入口 + * 此方法是线程安全的,防止多个线程同时刷新Token + * + * @return 有效的AccessToken字符串 + */ + public synchronized TokenUrlDto getValidAccessToken() { + // 检查Token是否为null或者是否已过期 + if (accessToken == null || System.currentTimeMillis() >= expiryTimestamp) { + logger.info("AccessToken为空或已过期,准备刷新..."); + refreshToken(); + } + return new TokenUrlDto(accessToken, gatewayUrl, tokenUrl); + } + + /** + * 内部方法,负责调用API刷新Token并更新缓存和过期时间 + */ + private void refreshToken() { + try { + logger.info("开始调用getAccessTokenV2接口获取新Token..."); + DcUrlResult gateway = pullYsData.getGateway(); + AccessTokenResponse response = pullYsData.getAccessTokenV2(gateway); + + if (response != null && response.getAccessToken() != null) { + // 更新本地状态值 + this.accessToken = response.getAccessToken(); + this.gatewayUrl = gateway.getGatewayUrl(); + this.tokenUrl = gateway.getTokenUrl(); + + // 计算新的过期时间戳 + long expiresInSeconds = response.getExpire(); + long expiresInMillis = expiresInSeconds * 1000L; + long bufferMillis = FAULT_TOLERANCE_SECONDS * 1000L; + + // 新的过期时间 = 当前时间 + 接口返回的有效时长 - 容错时间 + this.expiryTimestamp = System.currentTimeMillis() + expiresInMillis - bufferMillis; + + logger.info("成功刷新AccessToken,新的Token将在 {} 秒后过期(已包含{}秒容错时间)。", (this.expiryTimestamp - System.currentTimeMillis()) / 1000, FAULT_TOLERANCE_SECONDS); + } else { + logger.error("获取AccessToken失败,API返回为空或Token为空。"); + throw new RuntimeException("无法获取有效的AccessToken"); + } + } catch (Exception e) { + logger.error("刷新AccessToken时发生异常", e); + throw new RuntimeException("刷新AccessToken时发生异常", e); + } + } +} diff --git a/base-buildpackage/src/test/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/PullYsDataTest.java b/base-buildpackage/src/test/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/PullYsDataTest.java new file mode 100644 index 00000000..08739d26 --- /dev/null +++ b/base-buildpackage/src/test/java/com/hzya/frame/plugin/zanhuo/yonsuite/util/PullYsDataTest.java @@ -0,0 +1,43 @@ +package com.hzya.frame.plugin.zanhuo.yonsuite.util; + +import com.hzya.frame.WebappApplication; +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.AccessTokenResponse; +import com.hzya.frame.plugin.zanhuo.yonsuite.dto.token.DcUrlResult; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.plugin.zanhuo.yonsuite.util + * @Project:kangarooDataCenterV3 + * @name:PullYsDataTest + * @Date:2025/9/2 18:29 + * @Filename:PullYsDataTest + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = WebappApplication.class) +public class PullYsDataTest { + + @Autowired + private GetYsToken pullYsData; + + @Test + public void getAccessTokenV2() { + try { + DcUrlResult gateway = pullYsData.getGateway(); + AccessTokenResponse accessTokenV2 = pullYsData.getAccessTokenV2(gateway); + System.out.println(accessTokenV2.getAccessToken()); +// System.out.println(accessTokenV2.getExpire()); + //当前时间+7200秒=过期时间 + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void getGateway() { + } +} \ No newline at end of file