diff --git a/README.md b/README.md index c8c82f56..932e39d2 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,53 @@ -# 启航电商ERP系统-微服务版 +# 启航电商ERP系统 + +> **欢迎来到我们的开源项目!创新、协作、高质量的代码。您的Star🌟,是我们前进的动力! 💪✨🏆** + +> **项目持续更新中,还有很多不足,请多包含!如有任何疑问请提交issuse!谢谢! 💪✨🏆** ## 一、系统介绍 +启航电商ERP系统2.0版本是一个完整开箱即用的开源电商ERP系统,经历1.0版本的迭代优化和客户使用验证。开发者可以直接部署即可使用。 + +启航电商ERP系统是一个专注核心订单处理业务,主体功能包括:商品库管理(商品、SKU、分类、属性、供应商等)、订单库管理、店铺订单管理、发货管理(支持多供应商发货)、电子面单打印、售后管理、库存管理、店铺管理(店铺管理、店铺商品管理、店铺电子面单账号管理、平台参数设置)等。 + +与此同时该系统会陆续增加供外部调用的API,以便开发者满足自己的个性化业务需求。 + +启航电商ERP系统支持:淘宝天猫、京东、拼多多、抖店、微信小店等平台,后续将继续对接其他电商平台。 + +![](docs/preview.png) + +#### 系统特点 ++ 1、启航电商ERP系统是一个专注核心订单业务处理并且又能快速方便扩展个性化需求的一个底座。 + ++ 2、该系统适合想自研电商系统的企业快速构建业务。**系统并不适合小卖家,小卖家还是老老实实使用市面上流行的SAAS吧。** + ++ 3、使用启航电商ERP系统的前置条件是:**自行申请各电商开放平台的AppKey** [开放平台申请说明](https://mp.weixin.qq.com/s/KqyNlIVl43dTWicaAeLR1g) + + +#### 主体功能 启航电商ERP系统支持多平台多店铺订单、售后、商品等管理,目前已接入:淘宝、京东、拼多多、抖店、微信小店,后续会继续接入快手小店、小红书等。 主体功能包括: -+ 商品管理:商品库管理、店铺商品管理(拉取店铺商品、ERP关联)。 ++ 商品库管理:商品库管理、分类&分类属性管理、供应商管理等。 + 订单管理:店铺订单同步、管理。 + 发货管理:电子面单打印、发货记录、物流跟踪等。 + 售后管理:店铺售后同步、售后处理(补发、换货、退货处理)等。 -+ 店铺&平台参数设置:店铺管理、平台参数设置。 ++ 店铺&平台参数设置:店铺管理、店铺商品管理(拉取店铺商品、ERP关联)、店铺电子面单账户管理、平台参数设置。 -**基本上覆盖了电商网店管理日常业务,可使用接口对接内部ERP系统。** +**基本上覆盖了电商订单业务处理全流程,可使用接口对接内部ERP系统。** -**订单打单(电子面单打印)已支持:淘宝、京东、拼多多、抖店、微信小店** +**订单打单(电子面单打印)已支持:抖店、微信小店** -本项目采用SpringCloudAlibaba微服务架构+Vue2+Element开发。 +#### 系统架构 +本项目后端采用`SpringCloudAlibaba`微服务架构开发。 - +前端采用`Vue2`+`ElementUI`开发 ++ 后端技术及组件 + + Nacos 注册中心 + + Redis + + Kafka 消息队列 ## 二、关键流程 @@ -57,32 +85,52 @@ graph TD ## 三、功能模块 +#### 1、商品管理 ++ 商品库管理:管理商品库商品,提供手动录入、API接收功能,可以设置自己发货还是供应商发货(影响到后台分单逻辑,即时生效)。 ++ 商品库SKU明细:查看所有商品库SKU ++ 商品分类管理 ++ 商品品牌管理 ++ 供应商管理 -### 1、订单管理 -+ 从平台同步订单 -+ 订单发货 - + 获取订单收货地址信息 - + 推送物流信息到平台 -+ 订单备注修改 - -### 2、发货管理 -+ 电子面单打印 -+ 订单发货 - -### 3、售后管理 -+ 从平台同步售后列表 -+ 售后处理(同意、备注) +#### 2、订单管理 ++ 订单库:聚合订单查询、详情、管理。 ++ 订单明细:聚合订单明细查询。 ++ 店铺订单管理:订单API拉取、订单API更新、订单手动推送等,支持淘宝天猫、京东、拼多多、抖店、微信视频号。 -### 4、店铺管理 -+ 从平台同步商品信息 -+ 关联ERP sku +#### 3、发货管理 ++ 待发货清单:(商品维度、订单维度),展示待分配发货的清单(系统会根据商品设置的自己发货还是供应商发货自动分配到发货订单库) ++ 取号发货:电子面单取号发货 ++ 订单打印:电子面单打印,支持淘宝天猫、京东、拼多多、抖店、微信视频号。 ++ 备货出库:电子面单取号之后会加入备货清单,提供给仓库备货查询。发货之后会从备货清单中移除。 ++ 发货记录:发货记录,提供手动发货功能。 ++ 物流跟踪:提供发货物流查询。 ++ 快递快递管理:管理发货的快递公司(支持从平台拉取、支持线下渠道手动添加发货快递)。 ++ 面单账户管理:管理店铺开通的电子面单账户 -**支持多店铺管理** +#### 4、售后管理 ++ 售后中新:聚合售后查询、详情、管理。 ++ 店铺售后管理:售后API拉取、售后API更新、手动推送、售后操作(同意、备注)。 ++ 售后处理记录:售后处理的记录查询,提供手动售后处理功能。 + + +#### 5、库存管理 ++ 商品库存管理:查询库存 ++ 商品入库管理:支持手动入库 ++ 商品出库管理:支持手动出库 ++ 仓库仓位设置 + +#### 6、店铺&平台设置 ++ 店铺管理 ++ 店铺商品管理:店铺商品管理,店铺商品API拉取、店铺商品API更新(进行店铺商品与商品库商品关联,根据SKU编码关联)。 ++ 平台设置 ++ 订单更新日志:查询更新日志,主动排错。 ++ 售后更新日志:查询更新日志,主动排错。 ++ 定时任务配置 -## 四、软件架构 +## 四、项目架构 ### 1、开发环境级组件 #### 1.1 开发环境 + Jdk:17 @@ -93,23 +141,27 @@ graph TD + MySQL8 + Redis:7.x + Kafka(消息队列) -+ Nacos:2.2.0(配置中心、注册中心) ++ Nacos:2.3.1(注册中心) + Sentinel(分布式流量治理组件) - ### 2、项目结构 -#### 2.1 公共版本 +#### 2.1 `core`公共类库 +`common` 项目公共模块 + `security` 公共权限验证模块 +#### 2.2 `module` ++ `goods`:商品模块 ++ `open`:开放平台模块 ++ `order`:订单模块 ++ `shop`:店铺模块 ++ `stock`:库存模块 ++ `sys`:系统模块 -+ `goods` -商品模块 -#### 2.2 微服务 +#### 2.3 `api`微服务 + `gateway` 网关项目,负责微服务接口转发,前端统一通过网关调用其他微服务接口; @@ -166,7 +218,7 @@ oms主功能微服务,主要功能包括: `启动KRaft模式kafka` + 0 进入kafka解压目录 + 1 生成UUID`bin\windows\kafka-storage.bat random-uuid` - + 2 格式化`bin\windows\kafka-storage.bat format -t ujpyXZx-S9-jGlwxgORmow -c config\kraft\server.properties` + + 2 格式化`bin\windows\kafka-storage.bat format -t 7HZlayMPQdmMVcXnsFk8dg -c config\kraft\server.properties` + 3 启动`bin\windows\kafka-server-start.bat config\kraft\server.properties` #### 3.2、导入数据库 @@ -217,28 +269,36 @@ server { } ``` -## 四、一起交流 + +## 五、支持一下 **感谢大家的关注与支持!希望利用本人从事电商10余年的经验帮助到大家提升工作效率!** -### 4.1 赠人玫瑰手留余香 -💖 如果觉得有用记得点 Star⭐ - +### 5.1 赠人玫瑰手留余香 +💖 如果觉得有用记得点个 Star⭐ -### 4.2 加入知识星球一起交流 + + +### 5.2 一起交流 💖 欢迎加入知识星期获得作者帮助和朋友们一起交流! - ++ 微信公众号 + + + ++ 知识星球 + + -### 4.3 捐助作者 +### 5.3 捐助作者 作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭 -### 4.4 获取授权与服务 +### 5.4 获取授权与服务 [如何获取授权与服务](https://mp.weixin.qq.com/s/mATn2nfc5bUePohS_s2WGw) diff --git a/api/gateway/src/main/java/cn/qihangerp/gateway/Gateway.java b/api/gateway/src/main/java/cn/qihangerp/gateway/Gateway.java index bbe6f119..20400e38 100644 --- a/api/gateway/src/main/java/cn/qihangerp/gateway/Gateway.java +++ b/api/gateway/src/main/java/cn/qihangerp/gateway/Gateway.java @@ -14,7 +14,7 @@ public class Gateway { public static void main( String[] args ) { - System.out.println( "Hello api! " ); + System.out.println( "Hello gateway! " ); SpringApplication.run(Gateway.class, args); } diff --git a/api/gateway/src/main/resources/application.yaml b/api/gateway/src/main/resources/application.yaml index 489f7494..2122a0ec 100644 --- a/api/gateway/src/main/resources/application.yaml +++ b/api/gateway/src/main/resources/application.yaml @@ -13,8 +13,8 @@ spring: nacos: discovery: server-addr: 127.0.0.1:8848 - username: nacos - password: nacos +# username: nacos +# password: nacos sentinel: transport: dashboard: 127.0.0.1:8888 # sentinel控制台地址 diff --git a/api/oms-api/src/main/resources/application.yml b/api/oms-api/src/main/resources/application.yml index a83c2275..08531bbf 100644 --- a/api/oms-api/src/main/resources/application.yml +++ b/api/oms-api/src/main/resources/application.yml @@ -11,8 +11,8 @@ spring: # serverAddr: 127.0.0.1:8848 discovery: server-addr: 127.0.0.1:8848 - username: nacos - password: nacos +# username: nacos +# password: nacos data: # redis 配置 diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/JdApiCommon.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/JdApiCommon.java new file mode 100644 index 00000000..c6c813a9 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/JdApiCommon.java @@ -0,0 +1,72 @@ +package cn.qihangerp.open.jd; + +import cn.qihangerp.common.ResultVo; +import cn.qihangerp.common.ResultVoEnum; +import cn.qihangerp.common.api.ShopApiParams; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.enums.HttpStatus; +import cn.qihangerp.domain.OShopPlatform; +import cn.qihangerp.module.service.OShopPlatformService; +import cn.qihangerp.module.service.OShopService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +@AllArgsConstructor +@Component +public class JdApiCommon { + private final OShopService shopService; + private final OShopPlatformService platformService; +// private final ServerConfig serverConfig; + /** + * 更新前的检查 + * + * @param shopId + * @return + * @throws + */ + public ResultVo checkBefore(Long shopId) { + var shop = shopService.selectShopById(shopId); + if (shop == null) { +// return new ApiResult<>(EnumResultVo.ParamsError.getIndex(), "参数错误,没有找到店铺"); + return ResultVo.error(HttpStatus.PARAMS_ERROR, "参数错误,没有找到店铺"); + } + + if (shop.getType() != EnumShopType.JD.getIndex() && shop.getType() != EnumShopType.JDVC.getIndex()) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "参数错误,店铺不是JD店铺"); + } + OShopPlatform platform = platformService.selectById(EnumShopType.JD.getIndex()); + + if (!StringUtils.hasText(platform.getAppKey())) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "平台配置错误,没有找到AppKey"); + } + if (!StringUtils.hasText(platform.getAppSecret())) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "第三方平台配置错误,没有找到AppSercet"); + } + if (!StringUtils.hasText(platform.getRedirectUri())) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "第三方平台配置错误,没有找到RedirectUri"); + } + if (!StringUtils.hasText(platform.getServerUrl())) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "第三方平台配置错误,没有找到ServerUrl"); + } + + if(shop.getSellerId() == null || shop.getSellerId() <= 0) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "第三方平台配置错误,没有找到SellerUserId"); + } + + ShopApiParams params = new ShopApiParams(); + params.setAppKey(platform.getAppKey()); + params.setAppSecret(platform.getAppSecret()); + params.setAccessToken(shop.getAccessToken()); + params.setRedirectUri(platform.getRedirectUri()); + params.setServerUrl(platform.getServerUrl()); + params.setSellerId(shop.getSellerId()); + if (!StringUtils.hasText(shop.getAccessToken())) { + + return ResultVo.error(ResultVoEnum.UNAUTHORIZED.getIndex(), "Token已过期,请重新授权", params); + } + + return ResultVo.success(HttpStatus.SUCCESS, params); + } + +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdGoodsApiController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdGoodsApiController.java new file mode 100644 index 00000000..f3cea573 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdGoodsApiController.java @@ -0,0 +1,129 @@ +package cn.qihangerp.open.jd.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.enums.HttpStatus; +import cn.qihangerp.domain.OShopPullLasttime; +import cn.qihangerp.domain.OShopPullLogs; +import cn.qihangerp.module.open.jd.domain.JdGoodsSku; +import cn.qihangerp.module.open.jd.service.JdGoodsService; +import cn.qihangerp.module.service.OShopPullLasttimeService; +import cn.qihangerp.module.service.OShopPullLogsService; +import cn.qihangerp.open.PullRequest; +import cn.qihangerp.open.common.ApiResultVo; +import cn.qihangerp.open.jd.JdApiCommon; +import cn.qihangerp.open.jd.JdGoodsApiHelper; +import cn.qihangerp.open.jd.response.JdGoodsSkuListResponse; +import lombok.AllArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.Date; + +@RequestMapping("/jd/goods") +@RestController +@AllArgsConstructor +public class JdGoodsApiController { + private final JdApiCommon jdApiCommon; + private final JdGoodsService goodsService; + private final OShopPullLogsService pullLogsService; + private final OShopPullLasttimeService pullLasttimeService; + + + + /** + * 拉取商品列表(包含sku) + * @param params + * @return + * @throws Exception + */ + @RequestMapping(value = "/pull_goods", method = RequestMethod.POST) + public AjaxResult pullSkuList(@RequestBody PullRequest params) throws Exception { + if (params.getShopId() == null || params.getShopId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + Long currTimeMillis = System.currentTimeMillis(); + Date currDateTime = new Date(); + var checkResult = jdApiCommon.checkBefore(params.getShopId()); + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg(), checkResult.getData()); + } + String accessToken = checkResult.getData().getAccessToken(); + String serverUrl = checkResult.getData().getServerUrl(); + String appKey = checkResult.getData().getAppKey(); + String appSecret = checkResult.getData().getAppSecret(); + // 获取最后更新时间 + LocalDateTime startTime = null; + LocalDateTime endTime = null; + OShopPullLasttime lasttime = pullLasttimeService.getLasttimeByShop(params.getShopId(), "GOODS"); + if(params.getPullType()!=null && params.getPullType()==1) { + if (lasttime != null) { + // 按更新时间来 + startTime = lasttime.getLasttime().minusHours(7*24);//取上次结束一个小时前 + endTime = LocalDateTime.now(); + } + } +// String pullParams = "{PageNo:1,PageSize:50,startTime:"+startTime+",endTime:"+endTime+"}"; + String pullParams = "{startTime:"+startTime+",endTime:"+endTime+"}"; + + + ApiResultVo resultVo = JdGoodsApiHelper.pullGoodsSkuList(appKey, appSecret, accessToken); + if(resultVo.getCode() !=0 ){ + OShopPullLogs logs = new OShopPullLogs(); + logs.setShopId(params.getShopId()); + logs.setShopType(EnumShopType.JD.getIndex()); + logs.setPullType("GOODS"); + logs.setPullWay("主动拉取商品sku"); + logs.setPullParams(pullParams); + logs.setPullResult(resultVo.getMsg()); + logs.setPullTime(currDateTime); + logs.setDuration(System.currentTimeMillis() - currTimeMillis); + pullLogsService.save(logs); + return AjaxResult.error("接口拉取错误:"+resultVo.getMsg()); + } + + int successTotal = 0; + for (var sku: resultVo.getList()){ + JdGoodsSku jdGoodsSku = new JdGoodsSku(); + BeanUtils.copyProperties(sku,jdGoodsSku); + goodsService.saveGoodsSku(params.getShopId(),jdGoodsSku); + successTotal++; + } + // 添加拉取日志 + OShopPullLogs logs = new OShopPullLogs(); + logs.setShopId(params.getShopId()); + logs.setShopType(EnumShopType.JD.getIndex()); + logs.setPullType("GOODS"); + logs.setPullWay("主动拉取商品sku"); + logs.setPullParams(pullParams); + logs.setPullResult("{successTotal:"+successTotal+"}"); + logs.setPullTime(currDateTime); + logs.setDuration(System.currentTimeMillis() - currTimeMillis); + pullLogsService.save(logs); + + + if(lasttime == null){ + // 新增 + OShopPullLasttime insertLasttime = new OShopPullLasttime(); + insertLasttime.setShopId(params.getShopId()); + insertLasttime.setCreateTime(new Date()); + insertLasttime.setLasttime(endTime==null?LocalDateTime.now():endTime); + insertLasttime.setPullType("GOODS"); + pullLasttimeService.save(insertLasttime); + + }else { + // 修改 + OShopPullLasttime updateLasttime = new OShopPullLasttime(); + updateLasttime.setId(lasttime.getId()); + updateLasttime.setUpdateTime(new Date()); + updateLasttime.setLasttime(endTime==null?LocalDateTime.now():endTime); + pullLasttimeService.updateById(updateLasttime); + } + return AjaxResult.success("接口拉取成功,总数据:"+successTotal); + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdGoodsController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdGoodsController.java new file mode 100644 index 00000000..d2241ecc --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdGoodsController.java @@ -0,0 +1,73 @@ +package cn.qihangerp.open.jd.controller; + + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.PageQuery; +import cn.qihangerp.common.PageResult; +import cn.qihangerp.common.TableDataInfo; + +import cn.qihangerp.domain.bo.LinkErpGoodsSkuBo; +import cn.qihangerp.module.goods.domain.OGoodsSku; +import cn.qihangerp.module.goods.service.OGoodsSkuService; +import cn.qihangerp.module.open.jd.domain.JdGoods; +import cn.qihangerp.module.open.jd.domain.JdGoodsSku; +import cn.qihangerp.module.open.jd.domain.bo.JdGoodsBo; +import cn.qihangerp.module.open.jd.domain.vo.JdGoodsSkuListVo; +import cn.qihangerp.module.open.jd.service.JdGoodsService; +import cn.qihangerp.module.open.jd.service.JdGoodsSkuService; + +import cn.qihangerp.security.common.BaseController; +import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.*; + +@RequestMapping("/jd/goods") +@RestController +@AllArgsConstructor +public class JdGoodsController extends BaseController { + private final JdGoodsService goodsService; + private final JdGoodsSkuService skuService; + private final OGoodsSkuService oGoodsSkuService; + @RequestMapping(value = "/list", method = RequestMethod.GET) + public TableDataInfo goodsList(JdGoodsBo bo, PageQuery pageQuery) { + PageResult result = goodsService.queryPageList(bo, pageQuery); + + return getDataTable(result); + } + + @RequestMapping(value = "/skuList", method = RequestMethod.GET) + public TableDataInfo skuList(JdGoodsBo bo, PageQuery pageQuery) { + PageResult result = skuService.queryPageList(bo, pageQuery); + + return getDataTable(result); + } + + /** + * 获取店铺订单详细信息 + */ + @GetMapping(value = "/sku/{id}") + public AjaxResult getSkuInfo(@PathVariable("id") Long id) + { + return AjaxResult.success(skuService.getById(id)); + } + @PostMapping(value = "/sku/linkErp") + public AjaxResult linkErp(@RequestBody LinkErpGoodsSkuBo bo) + { + if(StringUtils.isBlank(bo.getId())){ + return AjaxResult.error(500,"缺少参数Id"); + } + if(StringUtils.isBlank(bo.getErpGoodsSkuId())){ + return AjaxResult.error(500,"缺少参数oGoodsSkuId"); + } + OGoodsSku oGoodsSku = oGoodsSkuService.getById(bo.getErpGoodsSkuId()); + + if(oGoodsSku == null) return AjaxResult.error(1500,"未找到系统商品sku"); + JdGoodsSku sku = new JdGoodsSku(); + sku.setId(bo.getId()); + sku.setOGoodsSkuId(Long.parseLong(bo.getErpGoodsSkuId())); + skuService.updateById(sku); + return success(); + } + +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOAuthController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOAuthController.java new file mode 100644 index 00000000..7e75fe51 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOAuthController.java @@ -0,0 +1,70 @@ +package cn.qihangerp.open.jd.controller; + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.domain.OShopPlatform; +import cn.qihangerp.module.open.jd.domain.bo.JdTokenCreateBo; +import cn.qihangerp.module.service.OShopPlatformService; +import cn.qihangerp.module.service.OShopService; +import com.alibaba.fastjson2.JSONObject; +import lombok.AllArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +@RequestMapping("/jd") +@AllArgsConstructor +@RestController +public class JdOAuthController { + private final OShopPlatformService platformService; + private final OShopService shopService; + private static Logger log = LoggerFactory.getLogger(JdOAuthController.class); + + @GetMapping("/oauth") + public AjaxResult OAuth(@RequestParam Long shopId) throws IOException, InterruptedException { + //查询店铺信息 + var shop = shopService.selectShopById(shopId); + OShopPlatform platform = platformService.selectById(shop.getType()); + + String url = "https://open-oauth.jd.com/oauth2/to_login?app_key=" + platform.getAppKey()+ + "&response_type=code&redirect_uri=" + URLEncoder.encode(platform.getRedirectUri(), "UTF-8")+ + "&state="+shopId+"&scope=snsapi_base"; + return AjaxResult.success("SUCCESS",url); + } + + @PostMapping("/tokenCreate") + public AjaxResult callback(@RequestBody JdTokenCreateBo bo) throws IOException, InterruptedException { + log.info("京东授权返回code"); + if (!StringUtils.hasText(bo.getCode())) return AjaxResult.error("code不能为空"); + OShopPlatform platform = platformService.getById(bo.getShopType()); +// String code = request.getParameter("code");//gwide6 +// JdClient client=new DefaultJdClient(serverUrl,accessToken,appKey,appSecret); + + String url = "https://open-oauth.jd.com/oauth2/access_token?app_key=" + platform.getAppKey() + "&app_secret=" + platform.getAppSecret() + + "&grant_type=authorization_code&code=" + bo.getCode(); + + HttpClient client = HttpClient.newBuilder().build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(url)).header("Content-Type", "application/json").GET() + .build(); + HttpResponse result = client.send(request, HttpResponse.BodyHandlers.ofString()); + String s = result.body(); + JSONObject resultJson = JSONObject.parse(result.body()); + if(resultJson.getInteger("code")==0){ + //保存accessToken + String token = resultJson.getString("access_token"); + shopService.updateSessionKey(bo.getShopId(),token); + return AjaxResult.success("SUCCESS"); + }else { + return AjaxResult.error(resultJson.getString("msg")); + } + + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderAfterSaleApiController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderAfterSaleApiController.java new file mode 100644 index 00000000..1006eca0 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderAfterSaleApiController.java @@ -0,0 +1,188 @@ +package cn.qihangerp.open.jd.controller; + + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.ResultVoEnum; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.enums.HttpStatus; +import cn.qihangerp.common.mq.MqMessage; +import cn.qihangerp.common.mq.MqType; +import cn.qihangerp.common.mq.MqUtils; +import cn.qihangerp.common.utils.DateUtils; +import cn.qihangerp.domain.OShopPullLasttime; +import cn.qihangerp.domain.OShopPullLogs; +import cn.qihangerp.module.open.jd.domain.JdRefund; +import cn.qihangerp.module.open.jd.service.JdRefundService; +import cn.qihangerp.module.service.OShopPullLasttimeService; +import cn.qihangerp.module.service.OShopPullLogsService; +import cn.qihangerp.open.PullRequest; +import cn.qihangerp.open.common.ApiResultVo; +import cn.qihangerp.open.jd.JdAfterSaleApiHelper; +import cn.qihangerp.open.jd.JdApiCommon; +import cn.qihangerp.open.jd.model.AfterSale; +import cn.qihangerp.open.jd.model.Refund; +import lombok.AllArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; + +@RequestMapping("/jd/refund") +@RestController +@AllArgsConstructor +public class JdOrderAfterSaleApiController { + private final JdApiCommon jdApiCommon; + private final OShopPullLogsService pullLogsService; + private final MqUtils mqUtils; + private final OShopPullLasttimeService pullLasttimeService; + private final JdRefundService afterSaleService; + + /** + * 拉取售后数据 + * + * @param params + * @return + * @throws Exception + */ + @RequestMapping(value = "/pull_after_list", method = RequestMethod.POST) + public AjaxResult pullList(@RequestBody PullRequest params) throws Exception { + if (params.getShopId() == null || params.getShopId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + Date currDateTime = new Date(); + long beginTime = System.currentTimeMillis(); + var checkResult = jdApiCommon.checkBefore(params.getShopId()); + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg(), checkResult.getData()); + } + String accessToken = checkResult.getData().getAccessToken(); + String serverUrl = checkResult.getData().getServerUrl(); + String appKey = checkResult.getData().getAppKey(); + String appSecret = checkResult.getData().getAppSecret(); + Long sellerId = checkResult.getData().getSellerId(); + + // 获取最后更新时间 + LocalDateTime startTime = null; + LocalDateTime endTime = null; + OShopPullLasttime lasttime = pullLasttimeService.getLasttimeByShop(params.getShopId(), "REFUND"); + if (lasttime == null) { + endTime = LocalDateTime.now(); + startTime = endTime.minusDays(1); + } else { + startTime = lasttime.getLasttime().minusHours(1);//取上次结束一个小时前 + endTime = startTime.plusDays(1);//取24小时 + if (endTime.isAfter(LocalDateTime.now())) { + endTime = LocalDateTime.now(); + } + } + + String startTimeStr = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + String endTimeStr = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + //获取退款 + ApiResultVo refundVo = JdAfterSaleApiHelper.pullRefundList(startTime, endTime, appKey, appSecret, accessToken); + + int insertSuccess = 0; + int totalError = 0; + int hasExist = 0; + + //循环插入订单数据到数据库 + /*******处理取消订单*****/ + for (var item : refundVo.getList()) { + JdRefund afterSale = new JdRefund(); + afterSale.setApplyId(item.getId()); + afterSale.setServiceId(item.getId()); + afterSale.setRefundId(item.getId()); + afterSale.setOrderId(item.getOrderId()); + afterSale.setApplyTime(item.getApplyTime()); + afterSale.setCustomerExpect(1);//售前退款 + afterSale.setCustomerName("售前退款"); + afterSale.setApplyRefundSum(item.getApplyRefundSum()); + afterSale.setBuyerId(item.getBuyerId()); + afterSale.setBuyerName(item.getBuyerName()); + afterSale.setRefundCheckTime(item.getCheckTime()); + afterSale.setRefundStatus(item.getStatus()); + afterSale.setRefundCheckUsername(item.getCheckUserName()); + afterSale.setRefundCheckRemark(item.getCheckRemark()); + afterSale.setRefundReason(item.getReason()); + afterSale.setRefundSystemId(item.getSystemId()); +// jdAfterSaleList.add(afterSale); + var result = afterSaleService.saveRefund(params.getShopId(), afterSale); + if (result.getCode() == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + hasExist++; + +// mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE, after.getServiceId().toString())); + } else if (result.getCode() == ResultVoEnum.SUCCESS.getIndex()) { + insertSuccess++; + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE, afterSale.getServiceId().toString())); +// kafkaTemplate.send(MqType.REFUND_MQ, JSONObject.toJSONString(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE,afterSale.getServiceId().toString()))); + } else { + totalError++; + } + } + + //获取售后 + ApiResultVo afterSaleVo = JdAfterSaleApiHelper.pullAfterSaleList(sellerId, startTime, endTime, appKey, appSecret, accessToken); + /*******处理售后list*****/ + for (var after : afterSaleVo.getList()) { + JdRefund afterSale = new JdRefund(); + BeanUtils.copyProperties(after, afterSale); +// afterSale.setOrderId(after.getOrderId() + ""); + afterSale.setApplyTime(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(after.getApplyTime()))); + afterSale.setRefundId(0L); + afterSale.setShopId(params.getShopId()); + var result = afterSaleService.saveRefund(params.getShopId(), afterSale); + if (result.getCode() == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + hasExist++; + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE, after.getServiceId().toString())); +// kafkaTemplate.send(MqType.REFUND_MQ, JSONObject.toJSONString(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE,afterSale.getServiceId().toString()))); + } else if (result.getCode() == ResultVoEnum.SUCCESS.getIndex()) { + insertSuccess++; + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE, after.getServiceId().toString())); +// kafkaTemplate.send(MqType.REFUND_MQ, JSONObject.toJSONString(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE,afterSale.getServiceId().toString()))); + } else { + totalError++; + } + } + + if (lasttime == null) { + // 新增 + OShopPullLasttime insertLasttime = new OShopPullLasttime(); + insertLasttime.setShopId(params.getShopId()); + insertLasttime.setCreateTime(new Date()); + insertLasttime.setLasttime(endTime); + insertLasttime.setPullType("REFUND"); + pullLasttimeService.save(insertLasttime); + + } else { + // 修改 + OShopPullLasttime updateLasttime = new OShopPullLasttime(); + updateLasttime.setId(lasttime.getId()); + updateLasttime.setUpdateTime(new Date()); + updateLasttime.setLasttime(endTime); + pullLasttimeService.updateById(updateLasttime); + } + OShopPullLogs logs = new OShopPullLogs(); + logs.setShopId(params.getShopId()); + logs.setShopType(EnumShopType.JD.getIndex()); + logs.setPullType("REFUND"); + logs.setPullWay("主动拉取"); + logs.setPullParams("{ApplyTimeBegin:" + startTimeStr + ",ApplyTimeEnd:" + endTimeStr + ",PageIndex:1,PageSize:100}"); + logs.setPullResult("{total:" + insertSuccess + ",hasExist:" + hasExist + ",totalError:" + totalError + "}"); + logs.setPullTime(currDateTime); + logs.setDuration(System.currentTimeMillis() - beginTime); + pullLogsService.save(logs); +// mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE,item.getId())); + return AjaxResult.success(); + } + + +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderAfterSaleController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderAfterSaleController.java new file mode 100644 index 00000000..15159ef9 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderAfterSaleController.java @@ -0,0 +1,48 @@ +package cn.qihangerp.open.jd.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.PageQuery; +import cn.qihangerp.common.PageResult; +import cn.qihangerp.common.TableDataInfo; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.mq.MqMessage; +import cn.qihangerp.common.mq.MqType; +import cn.qihangerp.common.mq.MqUtils; +import cn.qihangerp.module.open.jd.domain.JdRefund; +import cn.qihangerp.module.open.jd.domain.bo.JdAfterBo; +import cn.qihangerp.module.open.jd.domain.bo.JdOrderPushBo; +import cn.qihangerp.module.open.jd.service.JdOrderService; +import cn.qihangerp.module.open.jd.service.JdRefundService; +import cn.qihangerp.security.common.BaseController; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@AllArgsConstructor +@RestController +@RequestMapping("/jd/after") +public class JdOrderAfterSaleController extends BaseController { + private final JdOrderService orderService; +// private final JdRefundService refundService; +// private final JdOrderAfterService afterService; + private final JdRefundService afterSaleService; + private final MqUtils mqUtils; + @RequestMapping(value = "/list", method = RequestMethod.GET) + public TableDataInfo goodsList(JdAfterBo bo, PageQuery pageQuery) { + PageResult result = afterSaleService.queryPageList(bo, pageQuery); + + return getDataTable(result); + } + + @PostMapping("/push_oms") + @ResponseBody + public AjaxResult pushOms(@RequestBody JdOrderPushBo bo) { + // TODO:需要优化消息格式 + if(bo!=null && bo.getIds()!=null) { + for(String id: bo.getIds()) { + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD, MqType.REFUND_MESSAGE, id)); + } + } + return success(); + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderApiController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderApiController.java new file mode 100644 index 00000000..4e6e7987 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderApiController.java @@ -0,0 +1,223 @@ +package cn.qihangerp.open.jd.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.ResultVoEnum; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.enums.HttpStatus; +import cn.qihangerp.common.mq.MqMessage; +import cn.qihangerp.common.mq.MqType; +import cn.qihangerp.common.mq.MqUtils; +import cn.qihangerp.domain.OShopPullLasttime; +import cn.qihangerp.domain.OShopPullLogs; +import cn.qihangerp.module.open.jd.domain.JdOrder; +import cn.qihangerp.module.open.jd.domain.JdOrderItem; +import cn.qihangerp.module.open.jd.service.JdOrderService; +import cn.qihangerp.module.service.OShopPullLasttimeService; +import cn.qihangerp.module.service.OShopPullLogsService; +import cn.qihangerp.open.PullRequest; +import cn.qihangerp.open.common.ApiResultVo; +import cn.qihangerp.open.jd.JdApiCommon; +import cn.qihangerp.open.jd.JdOrderApiHelper; +import cn.qihangerp.open.jd.response.JdOrderDetailResponse; +import cn.qihangerp.open.jd.response.JdOrderListResponse; +import lombok.AllArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@RequestMapping("/jd/order") +@RestController +@AllArgsConstructor +public class JdOrderApiController { + private final JdApiCommon jdApiCommon; +// private final RedisCache redisCache; + private final MqUtils mqUtils; + private final JdOrderService orderService; + private final OShopPullLasttimeService pullLasttimeService; + private final OShopPullLogsService pullLogsService; + + @RequestMapping(value = "/pull_order_jd", method = RequestMethod.POST) + public AjaxResult pullList(@RequestBody PullRequest params) throws Exception { + if (params.getShopId() == null || params.getShopId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + + Date currDateTime = new Date(); + long beginTime = System.currentTimeMillis(); + + var checkResult = jdApiCommon.checkBefore(params.getShopId()); + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg(),checkResult.getData()); + } + String accessToken = checkResult.getData().getAccessToken(); + String serverUrl = checkResult.getData().getServerUrl(); + String appKey = checkResult.getData().getAppKey(); + String appSecret = checkResult.getData().getAppSecret(); + + // 获取最后更新时间 + LocalDateTime startTime = null; + LocalDateTime endTime = null; + OShopPullLasttime lasttime = pullLasttimeService.getLasttimeByShop(params.getShopId(), "ORDER"); + if(lasttime == null){ + endTime = LocalDateTime.now(); + startTime = endTime.minusDays(1); + }else{ + startTime = lasttime.getLasttime().minusHours(1);//取上次结束一个小时前 + Duration duration = Duration.between(startTime, LocalDateTime.now()); + long hours = duration.toHours(); + if (hours > 24) { + // 大于24小时,只取24小时 + endTime = startTime.plusHours(24); + } else { + endTime = LocalDateTime.now(); + } +// endTime = startTime.plusDays(1);//取24小时 +// if(endTime.isAfter(LocalDateTime.now())){ +// endTime = LocalDateTime.now(); +// } + } + + //第一次获取 + ApiResultVo upResult = JdOrderApiHelper.pullOrder(startTime,endTime,appKey,appSecret,accessToken); + if(upResult.getCode() !=0) return AjaxResult.error(1500,upResult.getMsg()); + int insertSuccess = 0;//新增成功的订单 + int totalError = 0; + int hasExistOrder = 0;//已存在的订单数 + //循环插入订单数据到数据库 + for (var orderInfo : upResult.getList()) { + JdOrder jdOrder = new JdOrder(); + BeanUtils.copyProperties(orderInfo,jdOrder); + jdOrder.setFullname(orderInfo.getConsigneeInfo().getFullname()); + jdOrder.setFullAddress(orderInfo.getConsigneeInfo().getFullAddress()); + jdOrder.setTelephone(orderInfo.getConsigneeInfo().getTelephone()); + jdOrder.setMobile(orderInfo.getConsigneeInfo().getMobile()); + jdOrder.setProvince(orderInfo.getConsigneeInfo().getProvince()); + jdOrder.setProvinceId(orderInfo.getConsigneeInfo().getProvinceId()); + jdOrder.setCity(orderInfo.getConsigneeInfo().getCity()); + jdOrder.setCityId(orderInfo.getConsigneeInfo().getCityId()); + jdOrder.setTown(orderInfo.getConsigneeInfo().getTown()); + jdOrder.setTownId(orderInfo.getConsigneeInfo().getTownId()); + List jdOrderItemList = new ArrayList<>(); + if(orderInfo.getItemInfoList()!=null && orderInfo.getItemInfoList().size()>0){ + for (var item:orderInfo.getItemInfoList()){ + JdOrderItem jdOrderItem = new JdOrderItem(); + BeanUtils.copyProperties(item,jdOrderItem); + jdOrderItem.setOrderId(orderInfo.getOrderId()); + jdOrderItemList.add(jdOrderItem); + } + } + jdOrder.setItems(jdOrderItemList); + //插入订单数据 + var result = orderService.saveOrder(params.getShopId(), jdOrder); + if (result.getCode() == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + hasExistOrder++; + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD,MqType.ORDER_MESSAGE,orderInfo.getOrderId())); + } else if (result.getCode() == ResultVoEnum.SUCCESS.getIndex()) { + insertSuccess++; + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD,MqType.ORDER_MESSAGE,orderInfo.getOrderId())); + } else { + totalError++; + } + } + if(totalError==0) { + if (lasttime == null) { + // 新增 + OShopPullLasttime insertLasttime = new OShopPullLasttime(); + insertLasttime.setShopId(params.getShopId()); + insertLasttime.setCreateTime(new Date()); + insertLasttime.setLasttime(endTime); + insertLasttime.setPullType("ORDER"); + pullLasttimeService.save(insertLasttime); + + } else { + // 修改 + OShopPullLasttime updateLasttime = new OShopPullLasttime(); + updateLasttime.setId(lasttime.getId()); + updateLasttime.setUpdateTime(new Date()); + updateLasttime.setLasttime(endTime); + pullLasttimeService.updateById(updateLasttime); + } + } + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + String paramsStr = "{startTime:"+startTime.format(df)+",endTime:"+endTime.format(df)+"}"; + String resultStr ="{insertSuccess:"+insertSuccess+",hasExistOrder:"+hasExistOrder+",totalError:"+totalError+"}"; + + OShopPullLogs logs = new OShopPullLogs(); + logs.setShopType(EnumShopType.JD.getIndex()); + logs.setShopId(params.getShopId()); + logs.setPullType("ORDER"); + logs.setPullWay("主动拉取"); + logs.setPullParams(paramsStr); + logs.setPullResult(resultStr); + logs.setPullTime(currDateTime); + logs.setDuration(System.currentTimeMillis() - beginTime); + pullLogsService.save(logs); + String msg = "成功{startTime:"+startTime.format(df)+",endTime:"+endTime.format(df)+"}总共找到:" + upResult.getTotalRecords() + "条订单,新增:" + insertSuccess + "条,添加错误:" + totalError + "条,更新:" + hasExistOrder + "条"; + return AjaxResult.success(msg); + } + + /** + * 拉取详情 + * @param params + * @return + * @throws Exception + */ + @RequestMapping(value = "/pull_order_detail", method = RequestMethod.POST) + public AjaxResult pullDetail(@RequestBody PullRequest params) throws Exception { + if (params.getShopId() == null || params.getShopId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + if (params.getOrderId() == null) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,缺少orderId"); + } + Date currDateTime = new Date(); + long beginTime = System.currentTimeMillis(); + + var checkResult = jdApiCommon.checkBefore(params.getShopId()); + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg(),checkResult.getData()); + } + String accessToken = checkResult.getData().getAccessToken(); + String serverUrl = checkResult.getData().getServerUrl(); + String appKey = checkResult.getData().getAppKey(); + String appSecret = checkResult.getData().getAppSecret(); + ApiResultVo upResult = JdOrderApiHelper.pullOrderDetail(params.getOrderId(),appKey,appSecret,accessToken); + if(upResult.getCode() == ResultVoEnum.SUCCESS.getIndex()){ + JdOrder jdOrder = new JdOrder(); + BeanUtils.copyProperties(jdOrder,upResult.getData()); + List jdOrderItemList = new ArrayList<>(); + if(upResult.getData().getItemInfoList()!=null && upResult.getData().getItemInfoList().size()>0){ + for (var item:upResult.getData().getItemInfoList()){ + JdOrderItem jdOrderItem = new JdOrderItem(); + BeanUtils.copyProperties(item,jdOrderItem); + jdOrderItemList.add(jdOrderItem); + } + } + jdOrder.setItems(jdOrderItemList); + // 更新Order + var result = orderService.saveOrder(params.getShopId(), jdOrder); + if (result.getCode() == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD,MqType.ORDER_MESSAGE,upResult.getData().getOrderId())); + } else if (result.getCode() == ResultVoEnum.SUCCESS.getIndex()) { + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD,MqType.ORDER_MESSAGE,upResult.getData().getOrderId())); + } + return AjaxResult.success(); + }else{ + return AjaxResult.error(); + } + } +} + + diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderController.java new file mode 100644 index 00000000..529b95ab --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/JdOrderController.java @@ -0,0 +1,43 @@ +package cn.qihangerp.open.jd.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.PageQuery; +import cn.qihangerp.common.PageResult; +import cn.qihangerp.common.TableDataInfo; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.mq.MqMessage; +import cn.qihangerp.common.mq.MqType; +import cn.qihangerp.common.mq.MqUtils; +import cn.qihangerp.module.open.jd.domain.JdOrder; +import cn.qihangerp.module.open.jd.domain.bo.JdOrderBo; +import cn.qihangerp.module.open.jd.domain.bo.JdOrderPushBo; +import cn.qihangerp.module.open.jd.service.JdOrderService; +import cn.qihangerp.security.common.BaseController; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@AllArgsConstructor +@RestController +@RequestMapping("/jd/order") +public class JdOrderController extends BaseController { + private final JdOrderService orderService; + private final MqUtils mqUtils; + @RequestMapping(value = "/list", method = RequestMethod.GET) + public TableDataInfo orderList(JdOrderBo bo, PageQuery pageQuery) { + PageResult result = orderService.queryPageList(bo, pageQuery); + + return getDataTable(result); + } + @PostMapping("/push_oms") + @ResponseBody + public AjaxResult pushOms(@RequestBody JdOrderPushBo bo) { + // TODO:需要优化消息格式 + if(bo!=null && bo.getIds()!=null) { + for(String id: bo.getIds()) { + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.JD, MqType.ORDER_MESSAGE, id)); + } + } + return success(); + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/feign/JdOrderFeignController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/feign/JdOrderFeignController.java new file mode 100644 index 00000000..b83d3d36 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/feign/JdOrderFeignController.java @@ -0,0 +1,33 @@ +package cn.qihangerp.open.jd.controller.feign; + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.module.open.jd.domain.JdOrder; +import cn.qihangerp.module.open.jd.domain.JdVcOrder; +import cn.qihangerp.module.open.jd.service.JdOrderService; +import cn.qihangerp.module.open.jd.service.JdVcOrderService; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@AllArgsConstructor +@RestController +@RequestMapping("/jd/order") +public class JdOrderFeignController { + private final JdOrderService jdOrderService; + private final JdVcOrderService jdVcOrderService; + @GetMapping(value = "/get_detail") + public AjaxResult getInfo(Long orderId,Integer vc) + { + if(vc!=null && vc==1){ + // jdvc + JdVcOrder jdVcOrder = jdVcOrderService.queryDetailByOrderId(orderId); + if(jdVcOrder!=null) return AjaxResult.success(jdVcOrder); + else return AjaxResult.error(500,"没有找到订单信息"); + }else { + JdOrder order = jdOrderService.queryDetailByOrderId(orderId); + if (order == null) return AjaxResult.error(404, "没有找到订单"); + else return AjaxResult.success(order); + } + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/feign/JdRefundFeignController.java b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/feign/JdRefundFeignController.java new file mode 100644 index 00000000..ece83b96 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/jd/controller/feign/JdRefundFeignController.java @@ -0,0 +1,38 @@ +package cn.qihangerp.open.jd.controller.feign; + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.module.open.jd.domain.JdRefund; +import cn.qihangerp.module.open.jd.domain.JdVcRefund; +import cn.qihangerp.module.open.jd.service.JdRefundService; +import cn.qihangerp.module.open.jd.service.JdVcRefundService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@AllArgsConstructor +@RestController +@RequestMapping("/jd/refund") +public class JdRefundFeignController { + private final JdVcRefundService jdVcRefundService; + private final JdRefundService jdRefundService; + + @GetMapping(value = "/get_detail") + public AjaxResult getInfo(Long refundId,Integer vc) + { + if(vc!=null && vc==1) { + // jdvc + JdVcRefund refund = jdVcRefundService.getById(refundId); + if (refund == null) return AjaxResult.error(404, "没有找到退款单"); + else return AjaxResult.success(refund); + }else { + //jd pop + List list = jdRefundService.list(new LambdaQueryWrapper().eq(JdRefund::getServiceId, refundId)); + if(list.isEmpty()) return AjaxResult.error(404,"没有找到售后单"); + else return AjaxResult.success(list.get(0)); + } + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/pdd/controller/feign/OrderFeignController.java b/api/open-api/src/main/java/cn/qihangerp/open/pdd/controller/feign/OrderFeignController.java index 35211868..4e5c95c8 100644 --- a/api/open-api/src/main/java/cn/qihangerp/open/pdd/controller/feign/OrderFeignController.java +++ b/api/open-api/src/main/java/cn/qihangerp/open/pdd/controller/feign/OrderFeignController.java @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RestController; @AllArgsConstructor @RestController -@RequestMapping("/api/open-api/pdd/order") +@RequestMapping("/pdd/order") public class OrderFeignController { private final PddOrderService orderService; @GetMapping(value = "/get_detail") diff --git a/api/open-api/src/main/java/cn/qihangerp/open/pdd/controller/feign/RefundFeignController.java b/api/open-api/src/main/java/cn/qihangerp/open/pdd/controller/feign/RefundFeignController.java index a0548d8a..7159d0e6 100644 --- a/api/open-api/src/main/java/cn/qihangerp/open/pdd/controller/feign/RefundFeignController.java +++ b/api/open-api/src/main/java/cn/qihangerp/open/pdd/controller/feign/RefundFeignController.java @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RestController; @AllArgsConstructor @RestController -@RequestMapping("/api/open-api/pdd/refund") +@RequestMapping("/pdd/refund") public class RefundFeignController { private final PddRefundService refundService; @GetMapping(value = "/get_detail") diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/OrderAssembleHelper.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/OrderAssembleHelper.java new file mode 100644 index 00000000..7d1f7b86 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/OrderAssembleHelper.java @@ -0,0 +1,112 @@ +package cn.qihangerp.open.tao; + + +import cn.qihangerp.module.open.tao.domain.TaoOrder; +import cn.qihangerp.module.open.tao.domain.TaoOrderItem; +import cn.qihangerp.open.tao.response.TaoOrderListResponse; +import org.springframework.util.StringUtils; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +public class OrderAssembleHelper { + /** + * 组织订单 + * @param trade + * @return + */ + public static TaoOrder assembleOrder(TaoOrderListResponse trade) { + + TaoOrder order = new TaoOrder(); + order.setTid(trade.getTid()); + order.setTitle(trade.getTitle()); + order.setType(trade.getType()); + order.setSellerFlag(trade.getSeller_flag() + ""); + order.setHasBuyerMessage(trade.isHas_buyer_message() + ""); + order.setCreditCardFee(trade.getCredit_card_fee()); + order.setCreated(trade.getCreated()); + order.setModified(trade.getModified()); + order.setPayTime(trade.getPay_time()); +// order.setPrice(Double.parseDouble(trade.getPrice())); + try { + order.setTotalFee(StringUtils.hasText(trade.getTotal_fee()) ? Double.parseDouble(trade.getTotal_fee()) : null); + order.setAdjustFee(StringUtils.hasText(trade.getAdjust_fee()) ? Double.parseDouble(trade.getAdjust_fee()) : null); + order.setPostFee(StringUtils.hasText(trade.getPost_fee()) ? BigDecimal.valueOf(Double.parseDouble(trade.getPost_fee())) : null); + order.setDiscountFee(StringUtils.hasText(trade.getDiscount_fee()) ? BigDecimal.valueOf(Double.parseDouble(trade.getDiscount_fee())) : null); + order.setPayment(BigDecimal.valueOf(Double.parseDouble(trade.getPayment()))); + order.setReceivedPayment(StringUtils.hasText(trade.getDiscount_fee()) ? BigDecimal.valueOf(Double.parseDouble(trade.getReceived_payment())) : null); + } catch (Exception ee) { + ee.printStackTrace(); + } + order.setBuyerNick(trade.getBuyer_nick()); + order.setBuyerOpenUid(trade.getBuyer_open_uid()); + order.setAlipayNo(trade.getAlipay_no()); +// order.setBuyerAlipayNo(trade.getBuyerAlipayNo()); +// order.setBuyerEmail(trade.getBuyerEmail()); +// order.setBuyerMemo(trade.getBuyerMemo()); +// order.setBuyerMessage(trade.getBuyerMessage()); +// order.setMarkDesc(trade.getMarkDesc()); +// order.setSellerMemo(trade.getSellerMemo()); + +// order.setReceiverCountry(trade.getReceiverCountry()); + order.setReceiverState(trade.getReceiver_state()); + order.setReceiverCity(trade.getReceiver_city()); + order.setReceiverDistrict(trade.getReceiver_district()); + order.setReceiverTown(trade.getReceiver_town()); + order.setReceiverAddress(trade.getReceiver_address()); + order.setReceiverName(trade.getReceiver_name()); + order.setReceiverMobile(trade.getReceiver_mobile()); +// order.setReceiverPhone(trade.getReceiverPhone()); + order.setSid(trade.getSid()); +// order.setYfxFee(trade.getYfxFee()); + order.setHasYfx(trade.isHas_yfx() + ""); +// order.setLogisticsInvoiceNo(trade.getinvoice); +// order.setNumIid(trade.getNumIid() + ""); +// order.setNum(trade.getNum().intValue()); + order.setStatus(trade.getStatus()); +// order.setConsignTime(trade.getConsignTime()); +// order.setEndTime(trade.getEndTime()); + order.setOaid(trade.getOaid()); + List items = new ArrayList<>(); + for (var item : trade.getOrders()) { + TaoOrderItem orderItem = new TaoOrderItem(); + orderItem.setTitle(item.getTitle()); + orderItem.setTid(Long.parseLong(trade.getTid())); + orderItem.setOid(Long.parseLong(item.getOid())); + orderItem.setTotalFee(StringUtils.hasText(item.getTotal_fee()) ? BigDecimal.valueOf(Double.parseDouble(item.getTotal_fee())): BigDecimal.valueOf(0)); + orderItem.setDiscountFee(StringUtils.hasText(item.getDiscount_fee()) ? BigDecimal.valueOf(Double.parseDouble(item.getDiscount_fee())): BigDecimal.valueOf(0)); + orderItem.setAdjustFee(StringUtils.hasText(item.getAdjust_fee()) ?BigDecimal.valueOf(Double.parseDouble(item.getAdjust_fee())): BigDecimal.valueOf(0)); + orderItem.setDivideOrderFee( StringUtils.hasText(item.getDivide_order_fee()) ? Double.parseDouble(item.getDivide_order_fee()):null); + orderItem.setPartMjzDiscount(StringUtils.hasText(item.getPart_mjz_discount()) ? Double.parseDouble(item.getPart_mjz_discount()):0.0); + orderItem.setPayment(StringUtils.hasText(item.getPayment()) ? Double.parseDouble(item.getPayment()):0.0); + orderItem.setPrice(StringUtils.hasText(item.getPrice()) ? BigDecimal.valueOf(Double.parseDouble(item.getPrice())): BigDecimal.valueOf(0)); + orderItem.setPicPath(item.getPic_path()); + orderItem.setNumIid(item.getNum_iid()); + orderItem.setSkuId(item.getSku_id()); +// orderItem.setOuterIid(item.getOuterIid()); + orderItem.setOuterSkuId(item.getOuter_sku_id()); + orderItem.setSkuPropertiesName(item.getSku_properties_name()); +// orderItem.setItemMealId(item.getItemMealId() == null ? "" : item.getItemMealId() + ""); +// orderItem.setItemMealName(item.getItemMealName()); + orderItem.setNum(item.getNum()); + orderItem.setRefundStatus(item.getRefund_status()); + orderItem.setStatus(item.getStatus()); +// orderItem.setBuyerRate(item.getBuyerRate() + ""); +// orderItem.setSellerRate(item.getSellerRate() + ""); +// orderItem.setRefundId(item.getRefundId()); + orderItem.setSellerType(item.getSeller_type()); + orderItem.setCid(item.getCid()); + orderItem.setEndTime(item.getEnd_time()); + orderItem.setConsignTime(item.getConsign_time()); + orderItem.setShippingType(item.getShipping_type()); + orderItem.setLogisticsCompany(item.getLogistics_company()); + orderItem.setInvoiceNo(item.getInvoice_no()); + + items.add(orderItem); + } + order.setItems(items); + return order; + + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/TaoApiCommon.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/TaoApiCommon.java new file mode 100644 index 00000000..6f7779ff --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/TaoApiCommon.java @@ -0,0 +1,96 @@ +package cn.qihangerp.open.tao; + +import cn.qihangerp.common.ResultVo; +import cn.qihangerp.common.ResultVoEnum; +import cn.qihangerp.common.api.ShopApiParams; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.enums.HttpStatus; +import cn.qihangerp.domain.OShopPlatform; +import cn.qihangerp.module.service.OShopPlatformService; +import cn.qihangerp.module.service.OShopService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +@AllArgsConstructor +@Component +public class TaoApiCommon { + private final OShopService shopService; + private final OShopPlatformService platformService; + + /** + * 更新前的检查 + * + * @param shopId + * @return + * @throws + */ + public ResultVo checkBefore(Long shopId) { + var shop = shopService.selectShopById(shopId); + if (shop == null) { +// return new ApiResult<>(EnumResultVo.ParamsError.getIndex(), "参数错误,没有找到店铺"); +// return ApiResult.build(HttpStatus.PARAMS_ERROR,"参数错误,没有找到店铺"); + return ResultVo.error(HttpStatus.PARAMS_ERROR, "参数错误,没有找到店铺"); + } + + if (shop.getType() != EnumShopType.TAO.getIndex()) { +// return ApiResult.build(HttpStatus.PARAMS_ERROR, "参数错误,店铺不是淘系店铺"); + return ResultVo.error(HttpStatus.PARAMS_ERROR, "参数错误,店铺不是淘系店铺"); + } + + OShopPlatform platform = platformService.selectById(EnumShopType.TAO.getIndex()); + + if(!StringUtils.hasText(platform.getAppKey())) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "平台配置错误,没有找到AppKey"); + } + if(!StringUtils.hasText(platform.getAppSecret())) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "第三方平台配置错误,没有找到AppSercet"); + } + if(!StringUtils.hasText(platform.getServerUrl())) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "第三方平台配置错误,没有找到ServerUrl"); + } + if(shop.getSellerId() == null || shop.getSellerId() <= 0) { + return ResultVo.error(HttpStatus.PARAMS_ERROR, "第三方平台配置错误,没有找到SellerUserId"); + } + + ShopApiParams params = new ShopApiParams(); + params.setAppKey(platform.getAppKey()); + params.setAppSecret(platform.getAppSecret()); + params.setAccessToken(shop.getAccessToken()); +// params.setRedirectUri(serverConfig.getUrl()+"/taoapi2/tao_oauth"); + params.setRedirectUri(platform.getRedirectUri()); + params.setServerUrl(platform.getServerUrl()); + + if (!StringUtils.hasText(shop.getAccessToken())) { + + return ResultVo.error(ResultVoEnum.UNAUTHORIZED.getIndex(), "Token已过期,请重新授权", params); + } + + /****************先查询卖家对不对***************/ +// TaobaoClient client = new DefaultTaobaoClient(url, appkey, secret); +// UserSellerGetRequest reqSeller = new UserSellerGetRequest(); +// reqSeller.setFields("nick,user_id"); +// UserSellerGetResponse rsp = client.execute(reqSeller, sessionKey); +// if(StringUtils.hasText(rsp.getErrorCode())){ +// if(rsp.getErrorCode().equals("27")){ +// return new ApiResult<>(EnumResultVo.TokenFail.getIndex(), "Token已过期,请重新授权",params); +// } +// else if(rsp.getErrorCode().equals("11")){ +// if(rsp.getSubCode().equals("isv.permission-api-package-limit")) +// return new ApiResult<>(EnumResultVo.ParamsError.getIndex(), "请检查淘宝用户API:taobao.user.seller.get是否具有访问权限",params); +// return new ApiResult<>(EnumResultVo.ParamsError.getIndex(), rsp.getSubCode(),params); +// } +// else if(rsp.getErrorCode().equals("25")){ +// return new ApiResult<>(EnumResultVo.ParamsError.getIndex(), "无效签名!请检查SessionKey、appKey、appSecret是否匹配",params); +// } else +// return new ApiResult<>(EnumResultVo.ParamsError.getIndex(), "参数错误!"+(StringUtils.hasText(rsp.getSubMsg()) ? rsp.getSubMsg(): rsp.getMsg())); +// } +// if(rsp.getUser() == null || rsp.getUser().getUserId() == null){ +// return new ApiResult<>(EnumResultVo.ParamsError.getIndex(), "参数错误!请设置店铺SellerUserId值!",params); +// } +// else if (shop.getSellerUserId().longValue() != rsp.getUser().getUserId().longValue()) { +// return new ApiResult<>(EnumResultVo.TokenFail.getIndex(), "当前用户是:" + rsp.getUser().getNick() + ",请重新授权",params); +// } + return ResultVo.success(HttpStatus.SUCCESS,params); + } + +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/TaoRequest.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/TaoRequest.java new file mode 100644 index 00000000..b3015753 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/TaoRequest.java @@ -0,0 +1,50 @@ +package cn.qihangerp.open.tao; + +public class TaoRequest { + private Long shopId;//店铺Id + private Long orderId;//订单id + private Long refundId; + private Integer updType;//更新类型0拉取新订单1更新订单 + + private Integer pullType;//拉取类型:0或不传全量;1更新(用于拉取商品的条件) + + public Integer getPullType() { + return pullType; + } + + public void setPullType(Integer pullType) { + this.pullType = pullType; + } + + public Integer getUpdType() { + return updType; + } + + public void setUpdType(Integer updType) { + this.updType = updType; + } + + public Long getOrderId() { + return orderId; + } + + public void setOrderId(Long orderId) { + this.orderId = orderId; + } + + public Long getShopId() { + return shopId; + } + + public void setShopId(Long shopId) { + this.shopId = shopId; + } + + public Long getRefundId() { + return refundId; + } + + public void setRefundId(Long refundId) { + this.refundId = refundId; + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoGoodsApiController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoGoodsApiController.java new file mode 100644 index 00000000..de8a4853 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoGoodsApiController.java @@ -0,0 +1,198 @@ +package cn.qihangerp.open.tao.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.ResultVoEnum; +import cn.qihangerp.common.api.ShopApiParams; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.enums.HttpStatus; +import cn.qihangerp.common.utils.StringUtils; +import cn.qihangerp.domain.OShopPullLasttime; +import cn.qihangerp.domain.OShopPullLogs; +import cn.qihangerp.module.open.tao.domain.TaoGoods; +import cn.qihangerp.module.open.tao.domain.TaoGoodsSku; +import cn.qihangerp.module.open.tao.service.TaoGoodsService; +import cn.qihangerp.module.service.OShopPullLasttimeService; +import cn.qihangerp.module.service.OShopPullLogsService; +import cn.qihangerp.open.common.ApiResultVo; +import cn.qihangerp.open.common.DateUtil; +import cn.qihangerp.open.tao.TaoApiCommon; +import cn.qihangerp.open.tao.TaoGoodsApiHelper; +import cn.qihangerp.open.tao.TaoRequest; +import cn.qihangerp.open.tao.response.TaoGoodsResponse; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@Slf4j +@RequestMapping("/tao/goods") +@RestController +@AllArgsConstructor +public class TaoGoodsApiController { + private final TaoApiCommon taoApiCommon; + private final TaoGoodsService goodsService; + private final OShopPullLogsService pullLogsService; + private final OShopPullLasttimeService pullLasttimeService; +/** + * @api {post} /api/v1/pull_goods 更新店铺商品列表 + * @apiVersion 1.0.0 + * @apiName pullGoods + * @apiGroup taoGood + * @apiParam {String} startTime 开始时间 + * @apiParam {String} endTime 结束时间 + * @apiParam {Number} shopId 店铺id(东方符号:7) + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK{ + "code": "0成功其他失败", + "msg": "成功或失败信息" + } + */ + @RequestMapping(value = "/pull_goods", method = RequestMethod.POST) + public AjaxResult pullGoodsList(@RequestBody TaoRequest req) throws Exception { + if (req.getShopId() == null || req.getShopId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); +// return ApiResult.build(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + Date currDateTime = new Date(); + long startTimeMillis = System.currentTimeMillis(); + var checkResult = taoApiCommon.checkBefore(req.getShopId()); + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg()); + } + ShopApiParams shopApiParams = checkResult.getData(); + String sessionKey = shopApiParams.getAccessToken(); + String url = shopApiParams.getServerUrl(); + String appKey = shopApiParams.getAppKey(); + String appSecret = shopApiParams.getAppSecret(); + + // 获取最后更新时间 + LocalDateTime startTime = null; + LocalDateTime endTime = null; + OShopPullLasttime lasttime = pullLasttimeService.getLasttimeByShop(req.getShopId(), "GOODS"); + if(req.getPullType()!=null && req.getPullType()==1) { + if (lasttime != null) { + // 按更新时间来 + startTime = lasttime.getLasttime().minusHours(7*24);//取上次结束一个小时前 + endTime = LocalDateTime.now(); + } + } + + Long pageIndex = 1L; + Long pageSize = 100L; + +// ApiResult listApiResult = GoodsApiHelper.pullGoods(pageIndex, pageSize, url, appKey, appSecret, sessionKey); + try { + ApiResultVo listApiResult = TaoGoodsApiHelper.pullGoodsList(appKey, appSecret, sessionKey); +// ApiResultVo listApiResult = GoodsApiHelper.pullGoods(pageIndex, pageSize, url, appKey, appSecret, sessionKey, startTime, endTime); + + int insertSuccess = 0;//新增成功的订单 + int totalError = 0; + int hasExistOrder = 0;//已存在的订单数 + + for (var g : listApiResult.getList()) { + TaoGoods taoGoods = new TaoGoods(); + BeanUtils.copyProperties(g, taoGoods); + // TODO:转换goods + taoGoods.setNumIid(g.getNum_iid()); + taoGoods.setTitle(g.getTitle()); + taoGoods.setType(g.getType()); + taoGoods.setCid(g.getCid()); + taoGoods.setPicUrl(g.getPic_url()); + taoGoods.setNum(g.getNum()); + taoGoods.setValidThru(g.getValid_thru()); + taoGoods.setHasDiscount(g.isHas_discount() + ""); + taoGoods.setHasInvoice(g.isHas_invoice() + ""); + taoGoods.setHasWarranty(g.isHas_warranty() + ""); + taoGoods.setHasShowcase(g.isHas_showcase() + ""); + taoGoods.setModified(DateUtil.stringtoDate(g.getModified())); + taoGoods.setDelistTime(StringUtils.isEmpty(g.getDelist_time()) ? null : DateUtil.stringtoDate(g.getDelist_time())); + taoGoods.setPostageId(g.getPostage_id()); + taoGoods.setOuterId(g.getOuter_id()); + taoGoods.setListTime(StringUtils.isEmpty(g.getList_time()) ? null : DateUtil.stringtoDate(g.getList_time())); + taoGoods.setPrice(g.getPrice()); + taoGoods.setSoldQuantity(g.getSold_quantity()); + taoGoods.setShopId(req.getShopId()); + List skuList = new ArrayList<>(); + if (g.getSkuList() != null && g.getSkuList().size() > 0) { + for (var s : g.getSkuList()) { + TaoGoodsSku taoGoodsSku = new TaoGoodsSku(); + BeanUtils.copyProperties(s, taoGoodsSku); +// taoGoodsSku.setShopId(req.getShopId()); + taoGoodsSku.setNumIid(s.getNum_iid()); + taoGoodsSku.setIid(s.getIid()); + taoGoodsSku.setSkuId(s.getSku_id()); + taoGoodsSku.setProperties(s.getProperties()); + taoGoodsSku.setPropertiesName(s.getProperties_name()); + taoGoodsSku.setQuantity(s.getQuantity()); + taoGoodsSku.setSkuSpecId(s.getSku_spec_id() + ""); + taoGoodsSku.setPrice(StringUtils.isEmpty(s.getPrice()) ? null : Double.parseDouble(s.getPrice())); + taoGoodsSku.setOuterId(s.getOuter_id()); + taoGoodsSku.setCreated(StringUtils.isEmpty(s.getCreated()) ? null : s.getCreated()); + taoGoodsSku.setModified(StringUtils.isEmpty(s.getModified()) ? null : s.getModified()); + taoGoodsSku.setStatus(s.getStatus()); + taoGoodsSku.setCreateTime(new Date()); + skuList.add(taoGoodsSku); + } + } + taoGoods.setSkus(skuList); + int result = goodsService.saveAndUpdateGoods(req.getShopId(), taoGoods); + if (result == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + hasExistOrder++; + } else if (result == ResultVoEnum.SUCCESS.getIndex()) { + insertSuccess++; + } else { + totalError++; + } + } + + OShopPullLogs logs = new OShopPullLogs(); + logs.setShopId(req.getShopId()); + logs.setShopType(EnumShopType.TAO.getIndex()); + logs.setPullType("GOODS"); + logs.setPullWay("主动拉取"); + logs.setPullParams("{PageNo:1,PageSize:100}"); + logs.setPullResult("{successTotal:" + listApiResult.getTotalRecords() + "}"); + logs.setPullTime(currDateTime); + logs.setDuration(System.currentTimeMillis() - startTimeMillis); + pullLogsService.save(logs); + if (totalError == 0) { + if (lasttime == null) { + // 新增 + OShopPullLasttime insertLasttime = new OShopPullLasttime(); + insertLasttime.setShopId(req.getShopId()); + insertLasttime.setCreateTime(new Date()); + insertLasttime.setLasttime(endTime == null ? LocalDateTime.now() : endTime); + insertLasttime.setPullType("GOODS"); + pullLasttimeService.save(insertLasttime); + + } else { + // 修改 + OShopPullLasttime updateLasttime = new OShopPullLasttime(); + updateLasttime.setId(lasttime.getId()); + updateLasttime.setUpdateTime(new Date()); + updateLasttime.setLasttime(endTime == null ? LocalDateTime.now() : endTime); + pullLasttimeService.updateById(updateLasttime); + } + } + + String msg = "成功,总共找到:" + listApiResult.getTotalRecords() + "条商品数据,新增:" + insertSuccess + "条,添加错误:" + totalError + "条,更新:" + hasExistOrder + "条"; + log.info(msg); +// return new ApiResult<>(EnumResultVo.SUCCESS.getIndex(), msg); + return AjaxResult.success(msg); + }catch (Exception e){ + e.printStackTrace(); + return AjaxResult.error("调用接口异常"); + } + } + +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoGoodsController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoGoodsController.java new file mode 100644 index 00000000..3194f8a6 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoGoodsController.java @@ -0,0 +1,72 @@ +package cn.qihangerp.open.tao.controller; + + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.PageQuery; +import cn.qihangerp.common.PageResult; +import cn.qihangerp.common.TableDataInfo; + +import cn.qihangerp.domain.bo.LinkErpGoodsSkuBo; +import cn.qihangerp.module.goods.domain.OGoodsSku; +import cn.qihangerp.module.goods.service.OGoodsSkuService; +import cn.qihangerp.module.open.tao.domain.TaoGoods; +import cn.qihangerp.module.open.tao.domain.TaoGoodsSku; +import cn.qihangerp.module.open.tao.domain.bo.TaoGoodsBo; +import cn.qihangerp.module.open.tao.domain.vo.TaoGoodsSkuListVo; +import cn.qihangerp.module.open.tao.service.TaoGoodsService; +import cn.qihangerp.module.open.tao.service.TaoGoodsSkuService; + +import cn.qihangerp.security.common.BaseController; +import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.*; + +@RequestMapping("/tao/goods") +@RestController +@AllArgsConstructor +public class TaoGoodsController extends BaseController { + private final TaoGoodsService goodsService; + private final TaoGoodsSkuService skuService; + private final OGoodsSkuService oGoodsSkuService; + @RequestMapping(value = "/list", method = RequestMethod.GET) + public TableDataInfo goodsList(TaoGoodsBo bo, PageQuery pageQuery) { + PageResult result = goodsService.queryPageList(bo, pageQuery); + + return getDataTable(result); + } + + @RequestMapping(value = "/skuList", method = RequestMethod.GET) + public TableDataInfo skuList(TaoGoodsBo bo, PageQuery pageQuery) { + PageResult result = skuService.queryPageList(bo, pageQuery); + + return getDataTable(result); + } + + /** + * 获取店铺订单详细信息 + */ + @GetMapping(value = "/sku/{id}") + public AjaxResult getSkuInfo(@PathVariable("id") Long id) + { + return AjaxResult.success(skuService.getById(id)); + } + @PostMapping(value = "/sku/linkErp") + public AjaxResult linkErp(@RequestBody LinkErpGoodsSkuBo bo) + { + if(StringUtils.isBlank(bo.getId())){ + return AjaxResult.error(500,"缺少参数Id"); + } + if(StringUtils.isBlank(bo.getErpGoodsSkuId())){ + return AjaxResult.error(500,"缺少参数oGoodsSkuId"); + } + OGoodsSku oGoodsSku = oGoodsSkuService.getById(bo.getErpGoodsSkuId()); + if(oGoodsSku == null) return AjaxResult.error(1500,"未找到系统商品sku"); + TaoGoodsSku sku = new TaoGoodsSku(); + sku.setId(bo.getId()); + sku.setOGoodsSkuId(bo.getErpGoodsSkuId()); + skuService.updateById(sku); + return success(); + } + +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOAuthController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOAuthController.java new file mode 100644 index 00000000..39cd0f56 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOAuthController.java @@ -0,0 +1,93 @@ +package cn.qihangerp.open.tao.controller; + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.utils.StringUtils; +import cn.qihangerp.domain.OShopPlatform; +import cn.qihangerp.module.open.tao.domain.bo.TaoTokenSaveBo; +import cn.qihangerp.module.service.OShopPlatformService; +import cn.qihangerp.module.service.OShopService; +import jakarta.servlet.http.HttpServletRequest; +import lombok.AllArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; + +/** + * 淘宝回调地址 + */ +@RequestMapping("/tao") +@AllArgsConstructor +@RestController +public class TaoOAuthController { + + private final OShopPlatformService platformService; + private final OShopService shopService; + private static Logger log = LoggerFactory.getLogger(TaoOAuthController.class); + /** + * 淘宝授权url + * + * @param shopId + * @return + * @throws IOException + * @throws InterruptedException + */ + @GetMapping("/oauth") + public AjaxResult OAuth(@RequestParam Long shopId) throws IOException, InterruptedException { + //查询店铺信息 + var shop = shopService.selectShopById(shopId); + OShopPlatform platform = platformService.selectById(shop.getType()); + + +// var entity = thirdSettingService.getEntity(shop.getType()); + String url = "http://container.open.taobao.com/container?appkey=" + platform.getAppKey() + "&state=" + shopId; + //https://oauth.taobao.com/authorize?response_type=token&force_auth=true&from_site=fuwu&client_id=28181872 + return AjaxResult.success("SUCCESS",url); + } + + /** + * 淘宝授权回调 + * @param model + * @param request + * @return + */ + @RequestMapping("/code_callback") + public String callback(Model model, HttpServletRequest request) { + log.info("淘系店铺授权回调开始"); + + String sessionKey = request.getParameter("top_session"); + String state = request.getParameter("state"); + if(StringUtils.isEmpty(state) ){ + return "错误:没有state参数,state参数就是店铺ID"; + } + if(StringUtils.isEmpty(sessionKey) ){ + return "错误:没有top_session参数,top_session参数就是access_token"; + } + try { + Long shopId = Long.parseLong(state); + var shop = shopService.selectShopById(shopId); + if(shop == null) { + return "错误:没有找到店铺"+shopId; + } + shopService.updateSessionKey(shopId, sessionKey); + return "成功:请关闭此页面"; + } catch (Exception e) { + return "异常:"+e.getMessage(); + } + } + @PostMapping("/saveSessionKey") + public AjaxResult saveSessionKey(@RequestBody TaoTokenSaveBo bo){ + log.info("保存淘宝开放平台SessionKey"); + if (!org.springframework.util.StringUtils.hasText(bo.getCode())) return AjaxResult.error("code不能为空"); + if (bo.getShopId()==null) return AjaxResult.error("shopId不能为空"); + var shop = shopService.selectShopById(bo.getShopId()); + if(shop == null) { + return AjaxResult.error("没有找到店铺"); + } + shopService.updateSessionKey(bo.getShopId(), bo.getCode()); + return AjaxResult.success(); + } + +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOrderApiController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOrderApiController.java new file mode 100644 index 00000000..6f775d40 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOrderApiController.java @@ -0,0 +1,243 @@ +package cn.qihangerp.open.tao.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.ResultVoEnum; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.enums.HttpStatus; +import cn.qihangerp.common.mq.MqMessage; +import cn.qihangerp.common.mq.MqType; +import cn.qihangerp.common.mq.MqUtils; +import cn.qihangerp.domain.OShopPullLasttime; +import cn.qihangerp.domain.OShopPullLogs; +import cn.qihangerp.module.open.tao.domain.TaoOrder; +import cn.qihangerp.module.open.tao.service.TaoOrderService; +import cn.qihangerp.module.service.OShopPullLasttimeService; +import cn.qihangerp.module.service.OShopPullLogsService; +import cn.qihangerp.open.common.ApiResultVo; +import cn.qihangerp.open.tao.OrderAssembleHelper; +import cn.qihangerp.open.tao.TaoApiCommon; +import cn.qihangerp.open.tao.TaoOrderApiHelper; +import cn.qihangerp.open.tao.TaoRequest; +import cn.qihangerp.open.tao.response.TaoOrderDetailResponse; +import cn.qihangerp.open.tao.response.TaoOrderListResponse; +import lombok.AllArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.*; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; + +/** + * 淘系订单更新 + */ +@AllArgsConstructor +@RestController +@RequestMapping("/api/open-api/tao/order") +public class TaoOrderApiController { + private static Logger log = LoggerFactory.getLogger(TaoOrderApiController.class); + + private final TaoOrderService orderService; + private final TaoApiCommon taoApiCommon; + private final MqUtils mqUtils; + private final OShopPullLogsService pullLogsService; + private final OShopPullLasttimeService pullLasttimeService; + /** + * 增量更新订单 + * @param req + * @return + * @throws + */ + @PostMapping("/pull_order_tao") + @ResponseBody + public AjaxResult pullIncrementOrder(@RequestBody TaoRequest req) { + log.info("/**************增量拉取tao订单****************/"); + if (req.getShopId() == null || req.getShopId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + Date currDateTime = new Date(); + long beginTime = System.currentTimeMillis(); + + var checkResult = taoApiCommon.checkBefore(req.getShopId()); + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg(),checkResult.getData()); + } + String sessionKey = checkResult.getData().getAccessToken(); + String url = checkResult.getData().getServerUrl(); + String appKey = checkResult.getData().getAppKey(); + String appSecret = checkResult.getData().getAppSecret(); + + log.info("/**************增量更新tao订单,条件判断完成,开始更新。。。。。。****************/"); + Long pageSize = 100l; + Long pageIndex = 1l; + // 取当前时间30分钟前 +// LocalDateTime endTime = LocalDateTime.now(); +// LocalDateTime startTime = endTime.minus(60*24, ChronoUnit.MINUTES); + // 获取最后更新时间 + LocalDateTime startTime = null; + LocalDateTime endTime = null; + OShopPullLasttime lasttime = pullLasttimeService.getLasttimeByShop(req.getShopId(), "ORDER"); + if(lasttime == null){ + endTime = LocalDateTime.now(); + startTime = endTime.minusDays(1); + }else { + startTime = lasttime.getLasttime().minusHours(1);//取上次结束一个小时前 + Duration duration = Duration.between(startTime, LocalDateTime.now()); + long hours = duration.toHours(); + if (hours > 24) { + // 大于24小时,只取24小时 + endTime = startTime.plusHours(24); + } else { + endTime = LocalDateTime.now(); + } +// endTime = startTime.plusDays(1);//取24小时 +// if(endTime.isAfter(LocalDateTime.now())){ +// endTime = LocalDateTime.now(); +// } + } + + //第一次获取 +// ApiResultVo upResult = OrderApiHelper.pullIncrementOrder(startTime,endTime,pageIndex, pageSize, url, appKey, appSecret, sessionKey); + + ApiResultVo upResult = TaoOrderApiHelper.pullTradeList(startTime,endTime,appKey, appSecret, sessionKey); + if (upResult.getCode() != ResultVoEnum.SUCCESS.getIndex()) { + log.info("/**************主动更新tao订单:第一次获取结果失败:" + upResult.getMsg() + "****************/"); + if(upResult.getCode() == HttpStatus.UNAUTHORIZED){ + return AjaxResult.error(HttpStatus.UNAUTHORIZED, "Token已过期,请重新授权",checkResult.getData()); + } + return AjaxResult.error(HttpStatus.SYSTEM_EXCEPTION, upResult.getMsg()); + } + + log.info("/**************主动更新tao订单:第一次获取结果:总记录数" + upResult.getTotalRecords() + "****************/"); + int insertSuccess = 0;//新增成功的订单 + int totalError = 0; + int hasExistOrder = 0;//已存在的订单数 + + //循环插入订单数据到数据库 + for (var order : upResult.getList()) { + TaoOrder taoOrder = OrderAssembleHelper.assembleOrder(order); + //插入订单数据 + var result = orderService.saveOrder(req.getShopId(), taoOrder); + if (result.getCode() == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + log.info("/**************主动更新tao订单:开始更新数据库:" + order.getTid() + "存在、更新************开始通知****/"); + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.ORDER_MESSAGE,order.getTid())); + hasExistOrder++; + } else if (result.getCode() == ResultVoEnum.SUCCESS.getIndex()) { + log.info("/**************主动更新tao订单:开始更新数据库:" + order.getTid() + "不存在、新增************开始通知****/"); + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO,MqType.ORDER_MESSAGE,order.getTid())); + insertSuccess++; + } else { + log.info("/**************主动更新tao订单:开始更新数据库:" + order.getTid() + "报错****************/"); + totalError++; + } + } + if(totalError == 0) { + if (lasttime == null) { + // 新增 + OShopPullLasttime insertLasttime = new OShopPullLasttime(); + insertLasttime.setShopId(req.getShopId()); + insertLasttime.setCreateTime(new Date()); + insertLasttime.setLasttime(endTime); + insertLasttime.setPullType("ORDER"); + pullLasttimeService.save(insertLasttime); + + } else { + // 修改 + OShopPullLasttime updateLasttime = new OShopPullLasttime(); + updateLasttime.setId(lasttime.getId()); + updateLasttime.setUpdateTime(new Date()); + updateLasttime.setLasttime(endTime); + pullLasttimeService.updateById(updateLasttime); + } + } + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + OShopPullLogs logs = new OShopPullLogs(); + logs.setShopType(EnumShopType.TAO.getIndex()); + logs.setShopId(req.getShopId()); + logs.setPullType("ORDER"); + logs.setPullWay("主动拉取"); + logs.setPullParams("{startTime:"+startTime.format(df)+",endTime:"+endTime.format(df)+"}"); + logs.setPullResult("{insert:"+insertSuccess+",update:"+hasExistOrder+",fail:"+totalError+"}"); + logs.setPullTime(currDateTime); + logs.setDuration(System.currentTimeMillis() - beginTime); + pullLogsService.save(logs); + + String msg = "成功{startTime:"+startTime.format(df)+",endTime:"+endTime.format(df)+"}总共找到:" + upResult.getTotalRecords() + "条订单,新增:" + insertSuccess + "条,添加错误:" + totalError + "条,更新:" + hasExistOrder + "条"; + log.info("/**************主动更新tao订单:END:" + msg + "****************/"); + return AjaxResult.success(msg); + } + + + /** + * 更新单个订单 + * + * @param taoRequest + * @return + * @throws + */ + @RequestMapping("/pull_order_detail") + @ResponseBody + public AjaxResult getOrderPullDetail(@RequestBody TaoRequest taoRequest) { + log.info("/**************主动更新tao订单by number****************/"); + if (taoRequest.getShopId() == null || taoRequest.getShopId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + if (taoRequest.getOrderId() == null || taoRequest.getOrderId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,缺少orderId"); + } + + var checkResult = taoApiCommon.checkBefore(taoRequest.getShopId()); + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg(), checkResult.getData()); + } + String sessionKey = checkResult.getData().getAccessToken(); + String url = checkResult.getData().getServerUrl(); + String appKey = checkResult.getData().getAppKey(); + String appSecret = checkResult.getData().getAppSecret(); + + +// ApiResultVo resultVo = OrderApiHelper.pullOrderDetail(taoRequest.getOrderId(), url, appKey, appSecret, sessionKey); + ApiResultVo resultVo = TaoOrderApiHelper.pullOrderDetail(taoRequest.getOrderId(), appKey, appSecret, sessionKey); + + if (resultVo.getCode() == ResultVoEnum.SUCCESS.getIndex()) { + TaoOrder taoOrder = new TaoOrder(); + BeanUtils.copyProperties(resultVo.getData(),taoOrder); +// List orderItems = new ArrayList<>(); +// if(resultVo.getData().getItems()!=null && resultVo.getData().getItems().size()>0){ +// for (var item : resultVo.getData().getItems()) { +// TaoOrderItem orderItem = new TaoOrderItem(); +// BeanUtils.copyProperties(item,orderItem); +// orderItems.add(orderItem); +// } +// } +// taoOrder.setItems(orderItems); + var result = orderService.saveOrder(taoRequest.getShopId(), taoOrder); + if (result.getCode() == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + log.info("/**************主动更新tao订单:开始更新数据库:" + result.getData() + "存在、更新****************/"); + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.ORDER_MESSAGE,resultVo.getData().getTid())); + } else if (result.getCode() == ResultVoEnum.SUCCESS.getIndex()) { + log.info("/**************主动更新tao订单:开始更新数据库:" + resultVo.getData() + "不存在、新增****************/"); + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO,MqType.ORDER_MESSAGE,resultVo.getData().getTid())); + } +// var result = orderService.updateOrder(resultVo.getData()); +// if (result.getCode() == ResultVoEnum.NotFound.getIndex()) { +// //已经存在 +// log.info("/**************主动更新tao订单:开始更新数据库:" + resultVo.getData().getId() + "存在、更新****************/"); +// } else if (result.getCode() == ResultVoEnum.SUCCESS.getIndex()) { +// mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.ORDER_MESSAGE,resultVo.getData().getTid())); +// log.info("/**************主动更新tao订单:开始更新数据库:" + resultVo.getData().getId() + "不存在、新增****************/"); +// } else { +// log.info("/**************主动更新tao订单:开始更新数据库:" + resultVo.getData().getId() + "报错****************/"); +// } + return AjaxResult.success(); + } else { + return AjaxResult.error(resultVo.getCode(), resultVo.getMsg()); + } + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOrderController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOrderController.java new file mode 100644 index 00000000..ba06771f --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoOrderController.java @@ -0,0 +1,55 @@ +package cn.qihangerp.open.tao.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.PageQuery; +import cn.qihangerp.common.PageResult; +import cn.qihangerp.common.TableDataInfo; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.mq.MqMessage; +import cn.qihangerp.common.mq.MqType; +import cn.qihangerp.common.mq.MqUtils; +import cn.qihangerp.module.open.tao.domain.TaoOrder; +import cn.qihangerp.module.open.tao.domain.bo.TaoOrderBo; +import cn.qihangerp.module.open.tao.domain.bo.TaoOrderPushBo; +import cn.qihangerp.module.open.tao.service.TaoOrderService; +import cn.qihangerp.security.common.BaseController; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@AllArgsConstructor +@RestController +@RequestMapping("/tao/order") +public class TaoOrderController extends BaseController { + private final TaoOrderService orderService; + private final MqUtils mqUtils; + @RequestMapping(value = "/list", method = RequestMethod.GET) + public TableDataInfo goodsList(TaoOrderBo bo, PageQuery pageQuery) { + PageResult result = orderService.queryPageList(bo, pageQuery); + + return getDataTable(result); + } + + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return success(orderService.queryDetailById(id)); + } + + /** + * 手动推送到系统 + * @param bo + * @return + */ + @PostMapping("/push_oms") + @ResponseBody + public AjaxResult pushOms(@RequestBody TaoOrderPushBo bo) { + // TODO:需要优化消息格式 + if(bo!=null && bo.getIds()!=null) { + for(String id: bo.getIds()) { + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.ORDER_MESSAGE, id)); + } + } + return success(); + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoRefundApiController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoRefundApiController.java new file mode 100644 index 00000000..3feef50e --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoRefundApiController.java @@ -0,0 +1,218 @@ +package cn.qihangerp.open.tao.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.ResultVoEnum; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.enums.HttpStatus; +import cn.qihangerp.common.mq.MqMessage; +import cn.qihangerp.common.mq.MqType; +import cn.qihangerp.common.mq.MqUtils; +import cn.qihangerp.domain.OShopPullLasttime; +import cn.qihangerp.domain.OShopPullLogs; +import cn.qihangerp.module.open.tao.domain.TaoRefund; +import cn.qihangerp.module.open.tao.service.TaoRefundService; +import cn.qihangerp.module.service.OShopPullLasttimeService; +import cn.qihangerp.module.service.OShopPullLogsService; +import cn.qihangerp.open.common.ApiResultVo; +import cn.qihangerp.open.tao.TaoApiCommon; +import cn.qihangerp.open.tao.TaoRefundApiHelper; +import cn.qihangerp.open.tao.TaoRequest; +import cn.qihangerp.open.tao.response.TaoRefundResponse; +import lombok.AllArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.Date; + +@AllArgsConstructor +@RestController +@RequestMapping("/tao/refund") +public class TaoRefundApiController { + private static Logger log = LoggerFactory.getLogger(TaoRefundApiController.class); + private final TaoApiCommon taoApiCommon; + private final TaoRefundService refundService; + private final MqUtils mqUtils; + private final OShopPullLogsService pullLogsService; + private final OShopPullLasttimeService pullLasttimeService; + /** + * 更新退货订单 + * + * @return + * @throws + */ + @RequestMapping("/pull_refund") + @ResponseBody + public AjaxResult refundOrderPull(@RequestBody TaoRequest taoRequest) { + log.info("/**************主动更新tao退货订单****************/"); + if (taoRequest.getShopId() == null || taoRequest.getShopId() <= 0) { +// return new ApiResult<>(EnumResultVo.ParamsError.getIndex(), "参数错误,没有店铺Id"); + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + Date currDateTime = new Date(); + long beginTime = System.currentTimeMillis(); + + Long shopId = taoRequest.getShopId(); + var checkResult = taoApiCommon.checkBefore(shopId); + + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg()); + } + + String sessionKey = checkResult.getData().getAccessToken(); + String url = checkResult.getData().getServerUrl(); + String appKey = checkResult.getData().getAppKey(); + String appSecret = checkResult.getData().getAppSecret(); + + + // 获取最后更新时间 + LocalDateTime startTime = null; + LocalDateTime endTime = null; + OShopPullLasttime lasttime = pullLasttimeService.getLasttimeByShop(taoRequest.getShopId(), "REFUND"); + if(lasttime == null){ + endTime = LocalDateTime.now(); + startTime = endTime.minusDays(1); + }else{ + startTime = lasttime.getLasttime().minusHours(1);//取上次结束一个小时前 + Duration duration = Duration.between(startTime, LocalDateTime.now()); + long hours = duration.toHours(); + if (hours > 24) { + // 大于24小时,只取24小时 + endTime = startTime.plusHours(24); + } else { + endTime = LocalDateTime.now(); + } +// endTime = startTime.plusDays(1);//取24小时 +// if(endTime.isAfter(LocalDateTime.now())){ +// endTime = LocalDateTime.now(); +// } + } +// Long pageSize = 100l; +// Long pageIndex = 1l; + + //第一次获取 +// ApiResultVo upResult = RefundApiHelper.pullRefund(startTime,endTime, url, appKey, appSecret, sessionKey); + ApiResultVo upResult = TaoRefundApiHelper.pullRefund(startTime, endTime, appKey, appSecret, sessionKey); + if (upResult.getCode() != 0) { + log.info("/**************主动更新tao退货订单:第一次获取结果失败:" + upResult.getMsg() + "****************/"); +// return new ApiResult<>(EnumResultVo.SystemException.getIndex(), upResult.getMsg()); + return AjaxResult.error(HttpStatus.ERROR ,upResult.getMsg()); + } + + log.info("/**************主动更新tao退货订单:第一次获取结果:总记录数" + upResult.getTotalRecords() + "****************/"); + int insertSuccess = 0;//新增成功的订单 + int totalError = 0; + int hasExistOrder = 0;//已存在的订单数 + + //循环插入订单数据到数据库 + for (var refund : upResult.getList()) { + TaoRefund taoRefund = new TaoRefund(); + BeanUtils.copyProperties(refund,taoRefund); + taoRefund.setShopId(taoRequest.getShopId()); + taoRefund.setDesc1(refund.getDesc()); + //插入订单数据 + var result = refundService.saveAndUpdateRefund(shopId, taoRefund); + if (result == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.REFUND_MESSAGE,refund.getRefundId())); + log.info("/**************主动更新tao退货订单:开始更新数据库:" + refund.getRefundId() + "存在、更新****************/"); + hasExistOrder++; + } else if (result == ResultVoEnum.SUCCESS.getIndex()) { + log.info("/**************主动更新tao退货订单:开始插入数据库:" + refund.getRefundId() + "不存在、新增****************/"); + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.REFUND_MESSAGE,refund.getRefundId())); + insertSuccess++; + } else { + log.info("/**************主动更新tao退货订单:开始更新数据库:" + refund.getRefundId() + "报错****************/"); + totalError++; + } + } + if(totalError ==0) { + if (lasttime == null) { + // 新增 + OShopPullLasttime insertLasttime = new OShopPullLasttime(); + insertLasttime.setShopId(taoRequest.getShopId()); + insertLasttime.setCreateTime(new Date()); + insertLasttime.setLasttime(endTime); + insertLasttime.setPullType("REFUND"); + pullLasttimeService.save(insertLasttime); + + } else { + // 修改 + OShopPullLasttime updateLasttime = new OShopPullLasttime(); + updateLasttime.setId(lasttime.getId()); + updateLasttime.setUpdateTime(new Date()); + updateLasttime.setLasttime(endTime); + pullLasttimeService.updateById(updateLasttime); + } + } + String msg = "成功,总共找到:" + upResult.getTotalRecords() + "条订单,新增:" + insertSuccess + "条,添加错误:" + totalError + "条,更新:" + hasExistOrder + "条"; + OShopPullLogs logs = new OShopPullLogs(); + logs.setShopType(EnumShopType.TAO.getIndex()); + logs.setShopId(taoRequest.getShopId()); + logs.setPullType("REFUND"); + logs.setPullWay("主动拉取"); + logs.setPullParams("{startTime:"+startTime+",endTime:"+endTime+"}"); + logs.setPullResult("{insert:"+insertSuccess+",update:"+hasExistOrder+",fail:"+totalError+"}"); + logs.setPullTime(currDateTime); + logs.setDuration(System.currentTimeMillis() - beginTime); + pullLogsService.save(logs); + log.info("/**************主动更新tao订单:END:" + msg + "****************/"); +// return new ApiResult<>(EnumResultVo.SUCCESS.getIndex(), msg); + return AjaxResult.success(msg); + } + + @RequestMapping("/pull_refund_detail") + @ResponseBody + public AjaxResult refundDetailPull(@RequestBody TaoRequest taoRequest) { + log.info("/**************主动更新tao退货订单****************/"); + if (taoRequest.getShopId() == null || taoRequest.getShopId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有店铺Id"); + } + if (taoRequest.getRefundId() == null || taoRequest.getRefundId() <= 0) { + return AjaxResult.error(HttpStatus.PARAMS_ERROR, "参数错误,没有refundId"); + } + Date currDateTime = new Date(); + long beginTime = System.currentTimeMillis(); + + Long shopId = taoRequest.getShopId(); + var checkResult = taoApiCommon.checkBefore(shopId); + + if (checkResult.getCode() != HttpStatus.SUCCESS) { + return AjaxResult.error(checkResult.getCode(), checkResult.getMsg()); + } + + String sessionKey = checkResult.getData().getAccessToken(); + String url = checkResult.getData().getServerUrl(); + String appKey = checkResult.getData().getAppKey(); + String appSecret = checkResult.getData().getAppSecret(); + + //获取 + ApiResultVo upResult = TaoRefundApiHelper.pullRefundDetail(taoRequest.getRefundId(), appKey, appSecret, sessionKey); + + if (upResult.getCode() != 0) { + log.info("/**************主动更新tao退货订单:第一次获取结果失败:" + upResult.getMsg() + "****************/"); + return AjaxResult.error(HttpStatus.ERROR, upResult.getMsg()); + } + TaoRefund taoRefund = new TaoRefund(); + BeanUtils.copyProperties(upResult.getData(),taoRefund); + //插入订单数据 + var result = refundService.saveAndUpdateRefund(shopId, taoRefund); + if (result == ResultVoEnum.DataExist.getIndex()) { + //已经存在 + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.REFUND_MESSAGE, upResult.getData().getRefundId())); + } else if (result == ResultVoEnum.SUCCESS.getIndex()) { + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.REFUND_MESSAGE, upResult.getData().getRefundId())); + } + + + return AjaxResult.success(); + } + +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoRefundController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoRefundController.java new file mode 100644 index 00000000..84ece2f1 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoRefundController.java @@ -0,0 +1,44 @@ +package cn.qihangerp.open.tao.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.common.PageQuery; +import cn.qihangerp.common.PageResult; +import cn.qihangerp.common.TableDataInfo; +import cn.qihangerp.common.enums.EnumShopType; +import cn.qihangerp.common.mq.MqMessage; +import cn.qihangerp.common.mq.MqType; +import cn.qihangerp.common.mq.MqUtils; +import cn.qihangerp.module.open.tao.domain.TaoRefund; +import cn.qihangerp.module.open.tao.domain.bo.TaoOrderPushBo; +import cn.qihangerp.module.open.tao.domain.bo.TaoRefundBo; +import cn.qihangerp.module.open.tao.service.TaoRefundService; +import cn.qihangerp.security.common.BaseController; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@AllArgsConstructor +@RestController +@RequestMapping("/tao/refund") +public class TaoRefundController extends BaseController { + private final TaoRefundService refundService; + private final MqUtils mqUtils; + @RequestMapping(value = "/list", method = RequestMethod.GET) + public TableDataInfo goodsList(TaoRefundBo bo, PageQuery pageQuery) { + PageResult result = refundService.queryPageList(bo, pageQuery); + + return getDataTable(result); + } + + @PostMapping("/push_oms") + @ResponseBody + public AjaxResult pushOms(@RequestBody TaoOrderPushBo bo) { + // TODO:需要优化消息格式 + if(bo!=null && bo.getIds()!=null) { + for(String id: bo.getIds()) { + mqUtils.sendApiMessage(MqMessage.build(EnumShopType.TAO, MqType.REFUND_MESSAGE, id)); + } + } + return success(); + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoShipController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoShipController.java new file mode 100644 index 00000000..ec1b465e --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/TaoShipController.java @@ -0,0 +1,24 @@ +package cn.qihangerp.open.tao.controller; + + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.module.open.tao.domain.bo.TaoOrderShipBo; +import cn.qihangerp.security.common.BaseController; +import lombok.AllArgsConstructor; +import lombok.extern.java.Log; +import org.springframework.web.bind.annotation.*; + +@Log +@AllArgsConstructor +@RestController +@RequestMapping("/tao/ship") +public class TaoShipController extends BaseController { + + @PostMapping("/order_ship") + @ResponseBody + public AjaxResult orderShip(@RequestBody TaoOrderShipBo bo) { + log.info("接收到oms发货通知:开始推送到tao平台"); + String tid= bo.getTid(); + return success(); + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/feign/TaoOrderFeignController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/feign/TaoOrderFeignController.java new file mode 100644 index 00000000..5a2c030d --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/feign/TaoOrderFeignController.java @@ -0,0 +1,23 @@ +package cn.qihangerp.open.tao.controller.feign; + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.module.open.tao.domain.TaoOrder; +import cn.qihangerp.module.open.tao.service.TaoOrderService; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@AllArgsConstructor +@RestController +@RequestMapping("/tao/order") +public class TaoOrderFeignController { + private final TaoOrderService orderService; + @GetMapping(value = "/get_detail") + public AjaxResult getInfo(String tid) + { + TaoOrder order = orderService.queryDetailByTid(tid); + if(order==null) return AjaxResult.error(404,"没有找到订单"); + else return AjaxResult.success(order); + } +} diff --git a/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/feign/TaoRefundFeignController.java b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/feign/TaoRefundFeignController.java new file mode 100644 index 00000000..f799b0a0 --- /dev/null +++ b/api/open-api/src/main/java/cn/qihangerp/open/tao/controller/feign/TaoRefundFeignController.java @@ -0,0 +1,26 @@ +package cn.qihangerp.open.tao.controller.feign; + +import cn.qihangerp.common.AjaxResult; +import cn.qihangerp.module.open.tao.domain.TaoRefund; +import cn.qihangerp.module.open.tao.service.TaoRefundService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@AllArgsConstructor +@RestController +@RequestMapping("/tao/refund") +public class TaoRefundFeignController { + private final TaoRefundService refundService; + @GetMapping(value = "/get_detail") + public AjaxResult getInfo(Long refundId) + { + List refundList = refundService.list(new LambdaQueryWrapper().eq(TaoRefund::getRefundId,refundId)); + if(refundList==null) return AjaxResult.error(404,"没有找到退款单"); + else return AjaxResult.success(refundList.get(0)); + } +} diff --git a/api/open-api/src/main/resources/application.yml b/api/open-api/src/main/resources/application.yml index d3286182..7e290236 100644 --- a/api/open-api/src/main/resources/application.yml +++ b/api/open-api/src/main/resources/application.yml @@ -9,8 +9,8 @@ spring: # serverAddr: 127.0.0.1:8848 discovery: server-addr: 127.0.0.1:8848 - username: nacos - password: nacos +# username: nacos +# password: nacos data: # redis 配置 redis: diff --git a/api/pom.xml b/api/pom.xml index 169880d5..8f388f21 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -19,7 +19,7 @@ oms-api sys-api open-api - + eureka-server UTF-8 diff --git a/api/sys-api/src/main/resources/application.yaml b/api/sys-api/src/main/resources/application.yaml index 8a91a9f3..3ed48aef 100644 --- a/api/sys-api/src/main/resources/application.yaml +++ b/api/sys-api/src/main/resources/application.yaml @@ -15,8 +15,8 @@ spring: # serverAddr: 127.0.0.1:8848 discovery: server-addr: 127.0.0.1:8848 - username: nacos - passowrd: nacos +# username: nacos +# passowrd: nacos data: # redis 配置 redis: diff --git a/docs/bak/dou-api-0.6.18.jar b/docs/bak/dou-api-0.6.18.jar deleted file mode 100644 index 388636e7..00000000 Binary files a/docs/bak/dou-api-0.6.18.jar and /dev/null differ diff --git a/docs/bak/jd-api-1.6.17.jar b/docs/bak/jd-api-1.6.17.jar deleted file mode 100644 index 91f59656..00000000 Binary files a/docs/bak/jd-api-1.6.17.jar and /dev/null differ diff --git a/docs/bak/kuaishou-merchant-open-sdk-1.0.10.jar b/docs/bak/kuaishou-merchant-open-sdk-1.0.10.jar deleted file mode 100644 index b654954a..00000000 Binary files a/docs/bak/kuaishou-merchant-open-sdk-1.0.10.jar and /dev/null differ diff --git a/docs/bak/open-sdk-1.0.jar b/docs/bak/open-sdk-1.0.jar deleted file mode 100644 index 085a5894..00000000 Binary files a/docs/bak/open-sdk-1.0.jar and /dev/null differ diff --git a/docs/bak/pdd-api-0.6.17.jar b/docs/bak/pdd-api-0.6.17.jar deleted file mode 100644 index 176bbb6c..00000000 Binary files a/docs/bak/pdd-api-0.6.17.jar and /dev/null differ diff --git a/docs/bak/tao-api2-1.6.16.jar b/docs/bak/tao-api2-1.6.16.jar deleted file mode 100644 index 666b7cb9..00000000 Binary files a/docs/bak/tao-api2-1.6.16.jar and /dev/null differ diff --git a/docs/bak/wei-api-1.6.20.jar b/docs/bak/wei-api-1.6.20.jar deleted file mode 100644 index 6d35f85e..00000000 Binary files a/docs/bak/wei-api-1.6.20.jar and /dev/null differ diff --git a/docs/preview.png b/docs/preview.png new file mode 100644 index 00000000..b06d397e Binary files /dev/null and b/docs/preview.png differ diff --git a/docs/微信公众号.jpg b/docs/微信公众号.jpg new file mode 100644 index 00000000..29b16257 Binary files /dev/null and b/docs/微信公众号.jpg differ diff --git a/preview.png b/preview.png deleted file mode 100644 index 0984195e..00000000 Binary files a/preview.png and /dev/null differ diff --git a/vue/src/views/goods/shopGoods/index.vue b/vue/src/views/goods/shopGoods/index.vue deleted file mode 100644 index b3a5eb9e..00000000 --- a/vue/src/views/goods/shopGoods/index.vue +++ /dev/null @@ -1,70 +0,0 @@ - - - diff --git a/vue/src/views/refund/pull/index.vue b/vue/src/views/refund/pull/index.vue index bd64aa95..12e19402 100644 --- a/vue/src/views/refund/pull/index.vue +++ b/vue/src/views/refund/pull/index.vue @@ -22,7 +22,7 @@