| @@ -148,6 +148,10 @@ public class ShiroConfig { | |||||
| // filterChainDefinitionMap.put("/role/**", "corsFilter,token"); | // filterChainDefinitionMap.put("/role/**", "corsFilter,token"); | ||||
| //商场初始化init | //商场初始化init | ||||
| // filterChainDefinitionMap.put("/wxProjectConfig/**", "anon"); | // filterChainDefinitionMap.put("/wxProjectConfig/**", "anon"); | ||||
| // filterChainDefinitionMap.put("/goodsCategory/**", "anon"); | |||||
| // filterChainDefinitionMap.put("/wxCoupon/goods/**", "anon"); | |||||
| // //test | // //test | ||||
| // filterChainDefinitionMap.put("/merchantPoi/spuSync", "anon"); | // filterChainDefinitionMap.put("/merchantPoi/spuSync", "anon"); | ||||
| @@ -0,0 +1,38 @@ | |||||
| package com.iformall.controller.basic; | |||||
| import com.iformall.annotation.SystemControllerLog; | |||||
| import com.iformall.annotation.TenantIgnore; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.controller.base.BaseController; | |||||
| import com.iformall.service.TtGoodsCategoryService; | |||||
| import io.swagger.annotations.ApiImplicitParams; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| /** | |||||
| * @author gongbiao | |||||
| */ | |||||
| @RestController | |||||
| @RequestMapping("goodsCategory") | |||||
| public class TtGoodsCategoryController extends BaseController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private TtGoodsCategoryService ttGoodsCategoryService; | |||||
| @TenantIgnore | |||||
| @ApiOperation("分页列表接口") | |||||
| @GetMapping("treeList") | |||||
| @ApiImplicitParams({}) | |||||
| @SystemControllerLog(description = "列表") | |||||
| public ResultData treeList() { | |||||
| logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::treeList"); | |||||
| return new ResultData(ttGoodsCategoryService.findTreeList()); | |||||
| } | |||||
| } | |||||
| @@ -137,80 +137,80 @@ public class TtMerchantPoiController extends BaseController { | |||||
| return ttMerchantPoiService.supplierQuery(getTenantInfo(),id); | return ttMerchantPoiService.supplierQuery(getTenantInfo(),id); | ||||
| } | } | ||||
| @ApiOperation("获取商品可用的POI") | |||||
| @GetMapping("/findPoi") | |||||
| @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||||
| @SystemControllerLog(description = "查询") | |||||
| public ResultData findPoi(Long couponChannelId) { | |||||
| logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::findPoi"); | |||||
| if(couponChannelId == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| return ttMerchantPoiService.findPoi(getTenantInfo(),couponChannelId); | |||||
| } | |||||
| @ApiOperation("商品同步") | |||||
| @PostMapping("spuSync") | |||||
| @SystemControllerLog(description = "商品同步") | |||||
| public ResultData spuSync(@RequestBody Map<String, String> param) { | |||||
| logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::spuSync"); | |||||
| String couponChannelIdStr = param.get("couponChannelId"); | |||||
| Long couponChannelId = null; | |||||
| try{ | |||||
| couponChannelId = Long.parseLong(couponChannelIdStr); | |||||
| }catch(Exception e){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_CAST_ERROR); | |||||
| } | |||||
| if(couponChannelId == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| // String merchantIdStr = param.get("merchantIds"); | |||||
| // List<Long> merchantIds = new ArrayList<>(); | |||||
| // @ApiOperation("获取商品可用的POI") | |||||
| // @GetMapping("/findPoi") | |||||
| // @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||||
| // @SystemControllerLog(description = "查询") | |||||
| // public ResultData findPoi(Long couponChannelId) { | |||||
| // logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::findPoi"); | |||||
| // if(couponChannelId == null){ | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| // } | |||||
| // return ttMerchantPoiService.findPoi(getTenantInfo(),couponChannelId); | |||||
| // } | |||||
| // @ApiOperation("商品同步") | |||||
| // @PostMapping("spuSync") | |||||
| // @SystemControllerLog(description = "商品同步") | |||||
| // public ResultData spuSync(@RequestBody Map<String, String> param) { | |||||
| // logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::spuSync"); | |||||
| // String couponChannelIdStr = param.get("couponChannelId"); | |||||
| // Long couponChannelId = null; | |||||
| // try{ | // try{ | ||||
| // List<String> strings = Arrays.asList(merchantIdStr.split(",")); | |||||
| // merchantIds = strings.stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); | |||||
| // couponChannelId = Long.parseLong(couponChannelIdStr); | |||||
| // }catch(Exception e){ | // }catch(Exception e){ | ||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_CAST_ERROR); | // return new ResultData(ErrorCode.SYS_PARAMETER_CAST_ERROR); | ||||
| // } | // } | ||||
| // if(merchantIds == null || merchantIds.size() == 0){ | |||||
| // if(couponChannelId == null){ | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | // return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | ||||
| // } | // } | ||||
| return ttMerchantPoiService.spuSync(getTenantInfo(),couponChannelId,null); | |||||
| } | |||||
| @ApiOperation("商品同步查询") | |||||
| @GetMapping("spuGet") | |||||
| @SystemControllerLog(description = "商品同步查询") | |||||
| public ResultData spuGet(Long couponChannelId) { | |||||
| logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::spuGet"); | |||||
| if(couponChannelId == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| return ttMerchantPoiService.spuGet(getTenantInfo(),couponChannelId); | |||||
| } | |||||
| @ApiOperation("商品状态同步") | |||||
| @PostMapping("spuStatusSync") | |||||
| @SystemControllerLog(description = "商品状态同步") | |||||
| public ResultData spuStatusSync(@RequestBody Map<String, Long> param) { | |||||
| logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::spuStatusSync"); | |||||
| Long couponChannelId = param.get("couponChannelId"); | |||||
| if(couponChannelId == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| return ttMerchantPoiService.spuStatusSync(getTenantInfo(),couponChannelId); | |||||
| } | |||||
| @ApiOperation("商品库存同步") | |||||
| @PostMapping("spuStockSync") | |||||
| @SystemControllerLog(description = "商品库存同步") | |||||
| public ResultData spuStockSync(@RequestBody Map<String, Long> param) { | |||||
| logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::spuStockSync"); | |||||
| Long couponChannelId = param.get("couponChannelId"); | |||||
| if(couponChannelId == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| return ttMerchantPoiService.spuStockSync(getTenantInfo(),couponChannelId); | |||||
| } | |||||
| //// String merchantIdStr = param.get("merchantIds"); | |||||
| //// List<Long> merchantIds = new ArrayList<>(); | |||||
| //// try{ | |||||
| //// List<String> strings = Arrays.asList(merchantIdStr.split(",")); | |||||
| //// merchantIds = strings.stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); | |||||
| //// }catch(Exception e){ | |||||
| //// return new ResultData(ErrorCode.SYS_PARAMETER_CAST_ERROR); | |||||
| //// } | |||||
| //// if(merchantIds == null || merchantIds.size() == 0){ | |||||
| //// return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| //// } | |||||
| // return ttMerchantPoiService.spuSync(getTenantInfo(),couponChannelId,null); | |||||
| // } | |||||
| // @ApiOperation("商品同步查询") | |||||
| // @GetMapping("spuGet") | |||||
| // @SystemControllerLog(description = "商品同步查询") | |||||
| // public ResultData spuGet(Long couponChannelId) { | |||||
| // logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::spuGet"); | |||||
| // if(couponChannelId == null){ | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| // } | |||||
| // return ttMerchantPoiService.spuGet(getTenantInfo(),couponChannelId); | |||||
| // } | |||||
| // | |||||
| // @ApiOperation("商品状态同步") | |||||
| // @PostMapping("spuStatusSync") | |||||
| // @SystemControllerLog(description = "商品状态同步") | |||||
| // public ResultData spuStatusSync(@RequestBody Map<String, Long> param) { | |||||
| // logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::spuStatusSync"); | |||||
| // Long couponChannelId = param.get("couponChannelId"); | |||||
| // if(couponChannelId == null){ | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| // } | |||||
| // return ttMerchantPoiService.spuStatusSync(getTenantInfo(),couponChannelId); | |||||
| // } | |||||
| // | |||||
| // @ApiOperation("商品库存同步") | |||||
| // @PostMapping("spuStockSync") | |||||
| // @SystemControllerLog(description = "商品库存同步") | |||||
| // public ResultData spuStockSync(@RequestBody Map<String, Long> param) { | |||||
| // logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::spuStockSync"); | |||||
| // Long couponChannelId = param.get("couponChannelId"); | |||||
| // if(couponChannelId == null){ | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| // } | |||||
| // return ttMerchantPoiService.spuStockSync(getTenantInfo(),couponChannelId); | |||||
| // } | |||||
| } | } | ||||
| @@ -10,10 +10,13 @@ import com.iformall.controller.base.BaseController; | |||||
| import com.iformall.domain.po.*; | import com.iformall.domain.po.*; | ||||
| import com.iformall.domain.po.base.TenantEntity; | import com.iformall.domain.po.base.TenantEntity; | ||||
| import com.iformall.domain.vo.WxWeappInfo; | import com.iformall.domain.vo.WxWeappInfo; | ||||
| import com.iformall.douyin.pay.TtPayService; | |||||
| import com.iformall.douyin.payv2.request.CallBackSettingsRequest; | |||||
| import com.iformall.enums.*; | import com.iformall.enums.*; | ||||
| import com.iformall.service.*; | import com.iformall.service.*; | ||||
| import com.iformall.shiro.PasswordHelper; | import com.iformall.shiro.PasswordHelper; | ||||
| import com.iformall.utils.Constant; | import com.iformall.utils.Constant; | ||||
| import com.iformall.utils.MaUtil; | |||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| @@ -94,6 +97,9 @@ public class WxProjectConfigController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private WechatWebProperties wechatWebProperties; | private WechatWebProperties wechatWebProperties; | ||||
| @Autowired | |||||
| private MaUtil maUtil; | |||||
| @Autowired | @Autowired | ||||
| @Qualifier("openRedisTemplate") | @Qualifier("openRedisTemplate") | ||||
| RedisTemplate<String, String> openRedisTemplate; | RedisTemplate<String, String> openRedisTemplate; | ||||
| @@ -774,4 +780,74 @@ public class WxProjectConfigController extends BaseController { | |||||
| } | } | ||||
| } | } | ||||
| @ApiOperation("获取抖音支付2.0 回调接口配置") | |||||
| @GetMapping("/ttcallback/query/settings") | |||||
| @SystemControllerLog(description = "") | |||||
| @TenantIgnore | |||||
| public ResultData ttcallbackQuerySettings(String appid) { | |||||
| logger.debug("[" + getIpAddr() + "] WxProjectConfigController::ttcallbackQuerySettings"); | |||||
| try { | |||||
| WxAppinfo appinfo = wxAppinfoService.getByAppId(appid); | |||||
| if(appinfo == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"未找到对应的小程序"); | |||||
| } | |||||
| if(!EnumAppPlat.TOUTIAO.getCode().equals(appinfo.getPlat()) || !EnumAppType.C.getCode().equals(appinfo.getType())){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"该小程序不支持"); | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountService.getById(appinfo.getPayId()); | |||||
| if(payAccount == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"未找到对应的支付数据"); | |||||
| } | |||||
| TtPayService ttPayService = maUtil.getTtPayService(appinfo, payAccount); | |||||
| CallBackSettingsRequest callBackSettingsRequest = ttPayService.querySettings(); | |||||
| return new ResultData(callBackSettingsRequest); | |||||
| }catch (Exception e){ | |||||
| logger.error(e.getMessage(),e); | |||||
| return new ResultData(ErrorCode.SYS_SERVER_ERROR); | |||||
| } | |||||
| } | |||||
| @ApiOperation("配置抖音支付2.0 回调接口") | |||||
| @PostMapping("/ttcallback/settings") | |||||
| @SystemControllerLog(description = "商场集团-更新") | |||||
| @TenantIgnore | |||||
| public ResultData ttcallbackSettings(@RequestBody Map<String, String> map) { | |||||
| logger.debug("[" + getIpAddr() + "] WxProjectConfigController::ttcallbackSettings"); | |||||
| String appid = map.get("appid"); | |||||
| String create_order_callback = map.get("create_order_callback"); | |||||
| String refund_callback = map.get("refund_callback"); | |||||
| String delivery_qrcode_redirect = map.get("delivery_qrcode_redirect"); | |||||
| if(StringUtils.isBlank(appid) || StringUtils.isBlank(create_order_callback) | |||||
| || StringUtils.isBlank(refund_callback)){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| try { | |||||
| WxAppinfo appinfo = wxAppinfoService.getByAppId(appid); | |||||
| if(appinfo == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"未找到对应的小程序"); | |||||
| } | |||||
| if(!EnumAppPlat.TOUTIAO.getCode().equals(appinfo.getPlat()) || !EnumAppType.C.getCode().equals(appinfo.getType())){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"该小程序不支持"); | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountService.getById(appinfo.getPayId()); | |||||
| if(payAccount == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"未找到对应的支付数据"); | |||||
| } | |||||
| TtPayService ttPayService = maUtil.getTtPayService(appinfo, payAccount); | |||||
| CallBackSettingsRequest request = new CallBackSettingsRequest(); | |||||
| request.setCreateOrderCallback(create_order_callback); | |||||
| request.setRefundCallback(refund_callback); | |||||
| request.setDeliveryQrcodeRedirect(delivery_qrcode_redirect); | |||||
| boolean b = ttPayService.callbackSettings(request); | |||||
| if(b){ | |||||
| return new ResultData(); | |||||
| }else{ | |||||
| return new ResultData(ErrorCode.SYS_SERVER_ERROR); | |||||
| } | |||||
| }catch (Exception e){ | |||||
| logger.error(e.getMessage(),e); | |||||
| return new ResultData(ErrorCode.SYS_SERVER_ERROR); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,184 @@ | |||||
| package com.iformall.controller.market; | |||||
| import com.iformall.annotation.SystemControllerLog; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.controller.base.BaseController; | |||||
| import com.iformall.domain.po.WxCoupon; | |||||
| import com.iformall.domain.po.base.BaseEntity; | |||||
| import com.iformall.domain.vo.TtCouponChannelVo; | |||||
| import com.iformall.domain.vo.TtCouponVo; | |||||
| import com.iformall.douyin.web.bean.GoodsTemplateGet; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.service.*; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiImplicitParam; | |||||
| import io.swagger.annotations.ApiImplicitParams; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| @RestController | |||||
| @RequestMapping("ttgoods") | |||||
| @Api(description = "抖音商品库") | |||||
| public class TtCouponGoodsController extends BaseController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxCouponService wxCouponService; | |||||
| @Autowired | |||||
| private TtCouponGoodsService ttCouponGoodsService; | |||||
| @Autowired | |||||
| private TtMerchantPoiService ttMerchantPoiService; | |||||
| @Autowired | |||||
| private TtGoodsCategoryService ttGoodsCategoryService; | |||||
| @ApiOperation("分页列表接口") | |||||
| @GetMapping("couponList") | |||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), | |||||
| @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) | |||||
| @SystemControllerLog(description = "-列表") | |||||
| public ResultData couponList(@ModelAttribute TtCouponVo ttCouponVo, Integer pageNum, Integer pageSize) { | |||||
| logger.debug("[" + getIpAddr() + "] WxCouponController::couponList"); | |||||
| if (ttCouponVo == null) ttCouponVo = new TtCouponVo(); | |||||
| ttCouponVo.updateTenantInfo(getTenantInfo()); | |||||
| ttCouponVo.setType(EnumCouponType.COUPON_DOUYIN.getCode()); | |||||
| if(StringUtils.isNotBlank(ttCouponVo.getSortColumn())){ | |||||
| String coryColumn = "c."+ttCouponVo.getSortColumns(); | |||||
| ttCouponVo.setSortColumns(coryColumn); | |||||
| ttCouponVo.setSortColumn(null); | |||||
| }else{ | |||||
| ttCouponVo.setSortColumns(BaseEntity.SortField.CCreateDate_DESC, BaseEntity.SortField.CId_DESC); | |||||
| } | |||||
| if (ttCouponVo.getStatus() != null && ttCouponVo.getStatus() == -1) | |||||
| ttCouponVo.setStatus(null); | |||||
| return ttCouponGoodsService.couponList(ttCouponVo, pageNum, pageSize); | |||||
| } | |||||
| @ApiOperation("分页列表接口") | |||||
| @GetMapping("channelList") | |||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), | |||||
| @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) | |||||
| @SystemControllerLog(description = "-列表") | |||||
| public ResultData channelList(@ModelAttribute TtCouponChannelVo ttChannelVo, Integer pageNum, Integer pageSize) { | |||||
| logger.debug("[" + getIpAddr() + "] WxCouponController::channelList"); | |||||
| if (ttChannelVo == null) ttChannelVo = new TtCouponChannelVo(); | |||||
| ttChannelVo.updateTenantInfo(getTenantInfo()); | |||||
| ttChannelVo.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_DOUYIN_LIST.getCode()); | |||||
| if(null == ttChannelVo.getSourceType()){ | |||||
| ttChannelVo.setSourceType(EnumCouponSourceType.COUPONSource_Admin.getCode()); | |||||
| } | |||||
| if(StringUtils.isNotBlank(ttChannelVo.getSortColumn())){ | |||||
| String coryColumn = "cc."+ttChannelVo.getSortColumns(); | |||||
| ttChannelVo.setSortColumns(coryColumn); | |||||
| ttChannelVo.setSortColumn(null); | |||||
| }else{ | |||||
| ttChannelVo.setSortColumns(BaseEntity.SortField.CCUpdateDate_DESC); | |||||
| } | |||||
| return ttCouponGoodsService.channelList(ttChannelVo, pageNum, pageSize); | |||||
| } | |||||
| @ApiOperation("根据类目获取商品模板") | |||||
| @GetMapping("getTemplate") | |||||
| @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||||
| @SystemControllerLog(description = "根据类目获取商品模板") | |||||
| public ResultData getGoodsTemplate(Long couponId,Integer categoryId,Integer productType) { | |||||
| logger.debug("[" + getIpAddr() + "] WxCouponController::getGoodsTemplate"); | |||||
| if(productType == null){ | |||||
| productType = 1; | |||||
| } | |||||
| if(couponId == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| WxCoupon coupon = wxCouponService.getAttrsById(couponId, getTenantInfo().getTenantId()); | |||||
| if(coupon == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| try { | |||||
| GoodsTemplateGet goodsTemplateGet = ttMerchantPoiService.getTtWebService(getTenantInfo()).getGoodsService().templateGet(categoryId, productType); | |||||
| ttGoodsCategoryService.adminIsShow(goodsTemplateGet); | |||||
| ttGoodsCategoryService.handTemplate(goodsTemplateGet,coupon); | |||||
| return new ResultData(goodsTemplateGet); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| return new ResultData(ErrorCode.SYS_SERVER_ERROR.getCode(),e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation("提交审核") | |||||
| @PostMapping("product/save") | |||||
| @SystemControllerLog(description = "提交审核") | |||||
| public ResultData productSave(@RequestBody WxCoupon wxCoupon) { | |||||
| if (wxCoupon.getId() == null) { | |||||
| return new ResultData(ResultData.ERROR, "缺少id"); | |||||
| } | |||||
| WxCoupon coupon = wxCouponService.getById(wxCoupon.getId(), getTenantInfo().getTenantId()); | |||||
| if(coupon == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); | |||||
| } | |||||
| try { | |||||
| return ttCouponGoodsService.productSave(coupon); | |||||
| } catch (Exception e) { | |||||
| return new ResultData(ErrorCode.SYS_SERVER_ERROR.getCode(),e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation("实时查询审核状态") | |||||
| @GetMapping("product/draft") | |||||
| @SystemControllerLog(description = "实时查询审核状态") | |||||
| public ResultData productDraft(Long id) { | |||||
| if (id == null) { | |||||
| return new ResultData(ResultData.ERROR, "缺少id"); | |||||
| } | |||||
| return ttCouponGoodsService.productDraftGet(getTenantInfo(),id); | |||||
| } | |||||
| @ApiOperation("实时查询线上商品状态") | |||||
| @GetMapping("product/online") | |||||
| @SystemControllerLog(description = "实时查询审核状态") | |||||
| public ResultData productOnline(Long id) { | |||||
| if (id == null) { | |||||
| return new ResultData(ResultData.ERROR, "缺少id"); | |||||
| } | |||||
| return ttCouponGoodsService.productOnlineGet(getTenantInfo(),id); | |||||
| } | |||||
| @ApiOperation("实时同步上下架状态") | |||||
| @GetMapping("product/operate") | |||||
| @SystemControllerLog(description = "实时同步上下架状态") | |||||
| public ResultData productOperate(Long id) { | |||||
| if (id == null) { | |||||
| return new ResultData(ResultData.ERROR, "缺少id"); | |||||
| } | |||||
| return ttCouponGoodsService.productOperate(getTenantInfo(),id); | |||||
| } | |||||
| @ApiOperation("实时同步库存") | |||||
| @GetMapping("product/stock/sync") | |||||
| @SystemControllerLog(description = "实时同步库存") | |||||
| public ResultData productStockSync(Long id) { | |||||
| if (id == null) { | |||||
| return new ResultData(ResultData.ERROR, "缺少id"); | |||||
| } | |||||
| return ttCouponGoodsService.productStockSync(getTenantInfo(),id); | |||||
| } | |||||
| } | |||||
| @@ -52,6 +52,7 @@ public class WxCouponChannelController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| @Qualifier("objectCommonRedisTemplate") | @Qualifier("objectCommonRedisTemplate") | ||||
| RedisTemplate<String, Object> redisTemplate; | RedisTemplate<String, Object> redisTemplate; | ||||
| @ApiOperation("分页列表接口") | @ApiOperation("分页列表接口") | ||||
| @GetMapping("list") | @GetMapping("list") | ||||
| @@ -98,6 +99,23 @@ public class WxCouponChannelController extends BaseController { | |||||
| return resultData; | return resultData; | ||||
| } | } | ||||
| @ApiOperation("预审核上架") | |||||
| @PostMapping("updateOnline") | |||||
| @SystemControllerLog(description = "预审核上架") | |||||
| public ResultData updateOnline(@RequestBody WxCouponChannel wxCouponChannel) { | |||||
| wxCouponChannel.updateTenantInfo(getTenantInfo()); | |||||
| if (wxCouponChannel.getId() == null) { | |||||
| return new ResultData(ResultData.ERROR, "缺少id"); | |||||
| } | |||||
| ResultData resultData = wxCouponChannelService.updateOnline(wxCouponChannel); | |||||
| if(resultData.code == 200){ | |||||
| CouponCacheUtils.removeCouponChannelCache(redisTemplate, wxCouponChannel.getId()); | |||||
| CouponCacheUtils.removeDouyinLivePageCache(redisTemplate, wxCouponChannel.getTenantId(), null, null); | |||||
| } | |||||
| return resultData; | |||||
| } | |||||
| @ApiOperation("根据id查询接口") | @ApiOperation("根据id查询接口") | ||||
| @@ -13,14 +13,12 @@ import com.iformall.domain.po.WxCouponChannel; | |||||
| import com.iformall.domain.po.WxCouponPassword; | import com.iformall.domain.po.WxCouponPassword; | ||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.base.TenantEntity; | import com.iformall.domain.po.base.TenantEntity; | ||||
| import com.iformall.domain.vo.TtCouponVo; | |||||
| import com.iformall.domain.vo.WxCouponStatisVo; | import com.iformall.domain.vo.WxCouponStatisVo; | ||||
| import com.iformall.douyin.web.bean.GoodsTemplateGet; | |||||
| import com.iformall.enums.*; | import com.iformall.enums.*; | ||||
| import com.iformall.mapper.WxCouponChannelMapper; | import com.iformall.mapper.WxCouponChannelMapper; | ||||
| import com.iformall.service.WxCouponPasswordService; | |||||
| import com.iformall.service.WxCouponService; | |||||
| import com.iformall.service.WxFlowService; | |||||
| import com.iformall.service.WxMallService; | |||||
| import com.iformall.service.WxPayAccountService; | |||||
| import com.iformall.service.*; | |||||
| import com.iformall.service.util.CouponCacheUtils; | import com.iformall.service.util.CouponCacheUtils; | ||||
| import com.iformall.utils.DateUtils; | import com.iformall.utils.DateUtils; | ||||
| import com.iformall.utils.RedisLock; | import com.iformall.utils.RedisLock; | ||||
| @@ -29,6 +27,7 @@ import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiImplicitParam; | import io.swagger.annotations.ApiImplicitParam; | ||||
| import io.swagger.annotations.ApiImplicitParams; | import io.swagger.annotations.ApiImplicitParams; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import org.apache.commons.collections.CollectionUtils; | import org.apache.commons.collections.CollectionUtils; | ||||
| import org.apache.commons.collections.map.HashedMap; | import org.apache.commons.collections.map.HashedMap; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| @@ -227,6 +226,45 @@ public class WxCouponController extends BaseController { | |||||
| return result; | return result; | ||||
| } | } | ||||
| @ApiOperation("根据id更新接口") | |||||
| @PostMapping("continueAdd") | |||||
| @SystemControllerLog(description = "继续添加") | |||||
| public ResultData continueAdd(@RequestBody WxCoupon wxCoupon) { | |||||
| logger.debug("[" + getIpAddr() + "] WxCouponController::update"); | |||||
| if (wxCoupon.getId() == null) { | |||||
| return new ResultData(ResultData.ERROR, "缺少id"); | |||||
| } | |||||
| if(wxCoupon.getProductType() == null || wxCoupon.getCategoryId() == null){ | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "缺少必要参数"); | |||||
| } | |||||
| wxCoupon.updateTenantInfo(getTenantInfo()); | |||||
| if(EnumDelFlag.YES.getCode().equals(wxCoupon.getIsDel())){ | |||||
| WxCouponChannel query = new WxCouponChannel(); | |||||
| query.updateTenantInfo(wxCoupon); | |||||
| query.setCouponId(wxCoupon.getId()); | |||||
| query.setStatus(EnumCouponChannelStatus.STATUS_THROW_IN.getCode()); | |||||
| if (CollectionUtils.isNotEmpty(wxCouponChannelMapper.findList(query))) { | |||||
| return new ResultData(ResultData.ERROR, "有活动正在上架,请先下架。"); | |||||
| } | |||||
| } | |||||
| WxCoupon coupon = wxCouponService.getById(wxCoupon.getId(),wxCoupon.getTenantId()); | |||||
| if (null == coupon) { | |||||
| return new ResultData(ResultData.ERROR, "券未查询到。"+wxCoupon.getId()); | |||||
| } | |||||
| coupon.setProductType(wxCoupon.getProductType()); | |||||
| coupon.setCategoryId(wxCoupon.getCategoryId()); | |||||
| coupon.setProductAttrs(wxCoupon.getProductAttrs()); | |||||
| coupon.setSkuAttrs(wxCoupon.getSkuAttrs()); | |||||
| ResultData result = wxCouponService.updateTtProduct(coupon); | |||||
| CouponCacheUtils.removeCouponCache(redisTemplate, wxCoupon.getId()); | |||||
| CouponCacheUtils.removeCouponMerchantCache(redisTemplate, wxCoupon.getId()); | |||||
| return result; | |||||
| } | |||||
| @ApiOperation("根据id更新库存及有效期接口") | @ApiOperation("根据id更新库存及有效期接口") | ||||
| @PostMapping("updateStokeAndValidDate") | @PostMapping("updateStokeAndValidDate") | ||||
| @SystemControllerLog(description = "券投放-库存/有效期更新") | @SystemControllerLog(description = "券投放-库存/有效期更新") | ||||
| @@ -123,7 +123,7 @@ public class WxCouponOrderController extends BaseController { | |||||
| wxCouponOrder.getMerchantName().isEmpty()) { | wxCouponOrder.getMerchantName().isEmpty()) { | ||||
| wxCouponOrder.setMerchantName(null); | wxCouponOrder.setMerchantName(null); | ||||
| } | } | ||||
| wxCouponOrderService.exportData(wxCouponOrder, request, response); | |||||
| wxCouponOrderService.exportData(false,wxCouponOrder, request, response); | |||||
| } | } | ||||
| } | } | ||||
| @@ -7,24 +7,17 @@ import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | import com.iformall.common.ResultData; | ||||
| import com.iformall.controller.base.BaseController; | import com.iformall.controller.base.BaseController; | ||||
| import com.iformall.domain.dto.OrderSaveDto; | import com.iformall.domain.dto.OrderSaveDto; | ||||
| import com.iformall.domain.po.WxCUser; | |||||
| import com.iformall.domain.po.WxCUserBasicInfo; | |||||
| import com.iformall.domain.po.WxCoupon; | |||||
| import com.iformall.domain.po.WxCouponChannel; | |||||
| import com.iformall.domain.po.WxOrder; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.domain.po.base.BaseEntity; | import com.iformall.domain.po.base.BaseEntity; | ||||
| import com.iformall.domain.vo.WxMerchantSubsidyVo; | import com.iformall.domain.vo.WxMerchantSubsidyVo; | ||||
| import com.iformall.domain.vo.WxOrderQueryVo; | import com.iformall.domain.vo.WxOrderQueryVo; | ||||
| import com.iformall.enums.*; | import com.iformall.enums.*; | ||||
| import com.iformall.exception.MallinkException; | import com.iformall.exception.MallinkException; | ||||
| import com.iformall.service.WxCUserBasicInfoService; | |||||
| import com.iformall.service.WxCUserService; | |||||
| import com.iformall.service.WxCouponChannelService; | |||||
| import com.iformall.service.WxCouponService; | |||||
| import com.iformall.service.WxOrderService; | |||||
| import com.iformall.service.*; | |||||
| import com.iformall.service.order.OrderFactory; | import com.iformall.service.order.OrderFactory; | ||||
| import com.iformall.service.order.entity.WxComposeOrder; | import com.iformall.service.order.entity.WxComposeOrder; | ||||
| import com.iformall.utils.MaUtil; | |||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiImplicitParam; | import io.swagger.annotations.ApiImplicitParam; | ||||
| import io.swagger.annotations.ApiImplicitParams; | import io.swagger.annotations.ApiImplicitParams; | ||||
| @@ -54,6 +47,9 @@ public class WxOrderController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private WxOrderService wxOrderService; | private WxOrderService wxOrderService; | ||||
| @Autowired | |||||
| private WxPayOrderService wxPayOrderService; | |||||
| @Autowired | @Autowired | ||||
| private WxCUserService wxCUserService; | private WxCUserService wxCUserService; | ||||
| @@ -62,7 +58,7 @@ public class WxOrderController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private WxCUserBasicInfoService wxCUserBasicInfoService; | private WxCUserBasicInfoService wxCUserBasicInfoService; | ||||
| @Autowired | @Autowired | ||||
| OrderFactory orderFactory; | OrderFactory orderFactory; | ||||
| @@ -193,7 +189,7 @@ public class WxOrderController extends BaseController { | |||||
| // 免费券 | // 免费券 | ||||
| WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(EnumComposeOrder.SINGLE.getCode()).createDBMainOrder(coupon, user, 0, EnumPayWay.PAY_WAY_NOT_UNPAY_CREDIT); | WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(EnumComposeOrder.SINGLE.getCode()).createDBMainOrder(coupon, user, 0, EnumPayWay.PAY_WAY_NOT_UNPAY_CREDIT); | ||||
| order = wxOrderService.saveFreeOrderForCoupon(new Date(),false,composeOrder,user, coupon, 1, | order = wxOrderService.saveFreeOrderForCoupon(new Date(),false,composeOrder,user, coupon, 1, | ||||
| wxCouponChannel, orderSaveDto.getFormId(), null,EnumPayWay.PAY_WAY_NOT_UNPAY_CREDIT, | |||||
| wxCouponChannel, orderSaveDto.getFormId(), null,null,EnumPayWay.PAY_WAY_NOT_UNPAY_CREDIT, | |||||
| EnumOrderShopingType.ONLINE_PURCHASE.getCode(),null); | EnumOrderShopingType.ONLINE_PURCHASE.getCode(),null); | ||||
| return new ResultData(order); | return new ResultData(order); | ||||
| } catch (MallinkException e) { | } catch (MallinkException e) { | ||||
| @@ -268,4 +264,19 @@ public class WxOrderController extends BaseController { | |||||
| } | } | ||||
| @ApiOperation("查看抖音订单状态") | |||||
| @GetMapping("/ttorderQuery") | |||||
| @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||||
| @SystemControllerLog(description = "订单管理-id查询") | |||||
| public ResultData ttorderQuery(Long id) { | |||||
| logger.debug("[" + getIpAddr() + "] WxOrderController::ttorderQuery"); | |||||
| // WxBatchOrder wxBatchOrder = wxOrderService.getWxBatchOrder(getTenantInfo(), id); | |||||
| // if(wxBatchOrder == null || !EnumPayWay.PAY_WAY_TT.getCode().equals(wxBatchOrder.getPayVendor())){ | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "订单未找到或不支持"); | |||||
| // } | |||||
| return new ResultData(wxPayOrderService.ttorderQuery(getTenantInfo(),id)); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,303 @@ | |||||
| ALTER TABLE wx_order_0 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_1 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_2 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_3 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_4 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_5 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_6 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_7 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_8 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_9 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_10 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_11 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_12 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_13 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_14 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_15 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_16 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_17 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_18 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_19 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_20 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_21 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_22 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_23 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_24 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_25 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_26 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_27 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_28 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_29 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_30 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_31 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_32 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_33 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_34 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_35 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_36 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_37 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_38 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_39 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_40 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_41 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_42 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_43 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_44 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_45 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_46 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_47 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_48 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_49 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_50 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_51 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_52 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_53 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_54 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_55 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_56 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_57 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_58 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_59 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_60 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_61 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_62 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_63 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_64 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_65 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_66 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_67 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_68 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_69 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_70 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_71 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_72 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_73 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_74 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_75 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_76 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_77 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_78 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_79 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_80 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_81 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_82 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_83 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_84 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_85 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_86 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_87 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_88 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_89 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_90 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_91 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_92 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_93 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_94 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_95 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_96 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_97 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_98 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_order_99 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_0 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_1 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_2 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_3 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_4 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_5 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_6 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_7 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_8 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_9 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_10 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_11 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_12 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_13 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_14 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_15 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_16 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_17 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_18 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_19 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_20 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_21 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_22 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_23 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_24 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_25 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_26 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_27 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_28 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_29 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_30 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_31 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_32 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_33 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_34 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_35 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_36 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_37 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_38 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_39 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_40 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_41 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_42 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_43 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_44 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_45 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_46 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_47 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_48 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_49 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_50 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_51 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_52 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_53 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_54 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_55 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_56 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_57 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_58 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_59 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_60 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_61 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_62 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_63 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_64 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_65 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_66 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_67 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_68 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_69 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_70 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_71 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_72 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_73 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_74 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_75 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_76 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_77 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_78 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_79 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_80 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_81 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_82 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_83 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_84 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_85 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_86 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_87 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_88 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_89 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_90 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_91 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_92 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_93 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_94 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_95 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_96 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_97 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_98 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_coupon_order_99 ADD COLUMN `ext_param` VARCHAR(1000) COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_0 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_1 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_2 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_3 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_4 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_5 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_6 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_7 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_8 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_9 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_10 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_11 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_12 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_13 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_14 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_15 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_16 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_17 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_18 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_19 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_20 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_21 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_22 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_23 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_24 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_25 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_26 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_27 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_28 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_29 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_30 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_31 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_32 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_33 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_34 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_35 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_36 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_37 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_38 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_39 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_40 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_41 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_42 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_43 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_44 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_45 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_46 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_47 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_48 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_49 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_50 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_51 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_52 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_53 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_54 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_55 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_56 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_57 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_58 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_59 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_60 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_61 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_62 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_63 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_64 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_65 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_66 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_67 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_68 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_69 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_70 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_71 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_72 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_73 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_74 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_75 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_76 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_77 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_78 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_79 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_80 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_81 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_82 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_83 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_84 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_85 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_86 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_87 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_88 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_89 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_90 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_91 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_92 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_93 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_94 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_95 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_96 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_97 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_98 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| ALTER TABLE wx_batch_order_99 ADD COLUMN `ext_param` text COMMENT '额外参数,用于第三方平台'; | |||||
| @@ -0,0 +1,505 @@ | |||||
| ALTER TABLE `mallink`.`tt_coupon_channel_poi` | |||||
| ADD COLUMN `coupon_channel_id` bigint(20) NOT NULL AFTER `parent_tenant_id`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_0` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_1` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_2` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_3` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_4` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_5` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_6` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_7` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_8` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_9` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_10` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_11` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_12` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_13` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_14` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_15` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_16` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_17` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_18` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_19` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_20` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_21` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_22` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_23` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_24` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_25` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_26` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_27` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_28` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_29` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_30` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_31` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_32` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_33` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_34` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_35` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_36` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_37` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_38` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_39` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_40` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_41` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_42` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_43` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_44` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_45` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_46` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_47` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_48` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_49` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_50` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_51` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_52` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_53` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_54` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_55` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_56` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_57` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_58` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_59` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_60` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_61` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_62` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_63` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_64` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_65` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_66` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_67` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_68` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_69` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_70` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_71` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_72` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_73` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_74` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_75` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_76` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_77` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_78` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_79` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_80` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_81` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_82` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_83` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_84` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_85` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_86` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_87` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_88` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_89` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_90` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_91` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_92` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_93` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_94` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_95` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_96` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_97` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_98` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| ALTER TABLE `mallink`.`wx_coupon_99` | |||||
| ADD COLUMN `product_type` tinyint(1) DEFAULT 1 COMMENT 'EnumTtProductType' AFTER `gift_list`, | |||||
| ADD COLUMN `category_id` int(11) DEFAULT NULL COMMENT '商品类目' AFTER `product_type`, | |||||
| ADD COLUMN `product_attrs` json COMMENT '商品动态属性' AFTER `category_id`, | |||||
| ADD COLUMN `sku_attrs` json COMMENT 'sku动态属性' AFTER `product_attrs`; | |||||
| @@ -0,0 +1,4 @@ | |||||
| INSERT INTO `mallink`.`mall_permission`(`id`, `name`, `parent_id`, `available`, `permission`, `resource_type`, `module_color`, `module_color_num`, `url`, `icon`, `version_type`, `sort`) VALUES (676, '抖音宣传页', 605, 'Y', NULL, 1, NULL, NULL, 'ttxcList', NULL, 0, 671); | |||||
| UPDATE `mallink`.`mall_sale_type` SET `menus` = '[1, 2, 4, 5, 6, 50, 105, 110, 201, 205, 202, 211, 212, 221, 222, 223, 251, 409, 410, 411, 416, 500, 502, 504, 505, 506, 507, 508, 511, 512, 521, 522, 523, 531, 532, 591, 592, 595, 602, 605, 606, 607, 610, 647, 671, 675, 676, 680, 711, 901, 902, 904, 907, 60702]' WHERE `id` = 11; | |||||
| @@ -2,6 +2,7 @@ package com.iformall.controller; | |||||
| import com.alibaba.fastjson.JSONObject; | import com.alibaba.fastjson.JSONObject; | ||||
| import com.github.pagehelper.PageInfo; | import com.github.pagehelper.PageInfo; | ||||
| import com.iformall.annotation.AuthIgnore; | |||||
| import com.iformall.annotation.RedisCache; | import com.iformall.annotation.RedisCache; | ||||
| import com.iformall.common.ErrorCode; | import com.iformall.common.ErrorCode; | ||||
| import com.iformall.common.Result; | import com.iformall.common.Result; | ||||
| @@ -35,6 +36,9 @@ import java.util.List; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| @RestController | @RestController | ||||
| @RequestMapping("/api/couponOrder") | @RequestMapping("/api/couponOrder") | ||||
| @Api(description = "卡券相关接口") | @Api(description = "卡券相关接口") | ||||
| @@ -463,4 +467,43 @@ public class WxCouponOrderController extends BaseController { | |||||
| } | } | ||||
| return new ResultData(); | return new ResultData(); | ||||
| } | } | ||||
| @ApiOperation(value = "B端核销列表链接") | |||||
| @GetMapping("/getVerifiedExportUrl") | |||||
| public ResultData getVerifiedExportUrl(@ModelAttribute WxCouponOrderBVo wxCouponOrder) { | |||||
| //只有B端管理员才能操作这个 | |||||
| WxMerchantBUser buser = this.getLoginBUser(); | |||||
| WxMerchant merchantQ= new WxMerchant(); | |||||
| merchantQ.updateTenantInfo(buser); | |||||
| merchantQ.setId(buser.getMerchantId()); | |||||
| WxMerchant merchant = wxMerchantService.findOne(merchantQ); | |||||
| if (!(buser.getPhone().equals(merchant.getLinkPhone()))) { | |||||
| return new ResultData(ErrorCode.SYS_SERVER_ERROR.getCode(),"只有商户管理员才能进行此操作"); | |||||
| } | |||||
| if (wxCouponOrder == null) wxCouponOrder = new WxCouponOrderBVo(); | |||||
| wxCouponOrder.updateTenantInfo(getTenantInfo()); | |||||
| StringBuffer sb = new StringBuffer("/api/couponOrder/unLogin/verifiedExport?verifyMerchantId=").append(buser.getMerchantId()) | |||||
| .append("&tenantId="+wxCouponOrder.getTenantId()); | |||||
| if (null != wxCouponOrder.getVerifyStartDate()) { | |||||
| sb.append("&verifyStartDate=").append(wxCouponOrder.getVerifyStartDate()); | |||||
| } | |||||
| if (null != wxCouponOrder.getVerifyEndDate()) { | |||||
| sb.append("&verifyEndDate=").append(wxCouponOrder.getVerifyEndDate()); | |||||
| } | |||||
| return new ResultData(sb.toString()); | |||||
| } | |||||
| @GetMapping("/unLogin/verifiedExport") | |||||
| @AuthIgnore | |||||
| public void verifiedExport(@ModelAttribute WxCouponOrderBVo wxCouponOrder, HttpServletRequest request, HttpServletResponse response) { | |||||
| logger.debug("[" + getIpAddr() + "] WxCouponOrderController::exportData"); | |||||
| if (wxCouponOrder == null) { | |||||
| return; | |||||
| } | |||||
| wxCouponOrder.setStartDate(DateUtils.stringToDate("2022-01-01 00:00:00",DateUtils.DATE_TIME_PATTERN)); | |||||
| wxCouponOrder.setEndDate(DateUtils.stringToDate("2122-01-01 00:00:00",DateUtils.DATE_TIME_PATTERN)); | |||||
| wxCouponOrderService.exportData(true,wxCouponOrder, request, response); | |||||
| } | |||||
| } | } | ||||
| @@ -110,7 +110,11 @@ public class WxCouponController extends BaseController { | |||||
| if (null == coupon) { | if (null == coupon) { | ||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "couponChannel找不到coupon" + couponChannelId); | return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "couponChannel找不到coupon" + couponChannelId); | ||||
| } | } | ||||
| if(EnumCouponType.COUPON_GIFT.getCode().equals(coupon.getType())){ | |||||
| WxCoupon attrsById = couponService.getAttrsById(couponChannel.getCouponId(), couponChannel.getTenantId()); | |||||
| coupon.setProductAttrs(attrsById.getProductAttrs()); | |||||
| coupon.setSkuAttrs(attrsById.getSkuAttrs()); | |||||
| if(EnumCouponType.COUPON_GIFT.getCode().equals(coupon.getType())){ | |||||
| WxCoupon couponQ = new WxCoupon(); | WxCoupon couponQ = new WxCoupon(); | ||||
| couponQ.updateTenantInfo(coupon); | couponQ.updateTenantInfo(coupon); | ||||
| List<Long> longs = JSON.parseArray(coupon.getGiftList(), Long.class); | List<Long> longs = JSON.parseArray(coupon.getGiftList(), Long.class); | ||||
| @@ -103,7 +103,7 @@ public class WxCouponPasswordController extends BaseController { | |||||
| try { | try { | ||||
| WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(EnumComposeOrder.SINGLE.getCode()).createDBMainOrder(coupon, member, 0, payWay); | WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(EnumComposeOrder.SINGLE.getCode()).createDBMainOrder(coupon, member, 0, payWay); | ||||
| WxOrder order = orderService.saveFreeOrderForCoupon(new Date(),false,composeOrder,member, coupon, 1, | WxOrder order = orderService.saveFreeOrderForCoupon(new Date(),false,composeOrder,member, coupon, 1, | ||||
| null, formId, couponPassword.getId(),payWay, | |||||
| null, formId, couponPassword.getId(),null,payWay, | |||||
| EnumOrderShopingType.ONLINE_PURCHASE.getCode(),null); | EnumOrderShopingType.ONLINE_PURCHASE.getCode(),null); | ||||
| } catch (MallinkException e) { | } catch (MallinkException e) { | ||||
| setCouponPasswordStatus(couponPassword, EnumCouponPasswordStatus.getEnum(pwdStatus)); | setCouponPasswordStatus(couponPassword, EnumCouponPasswordStatus.getEnum(pwdStatus)); | ||||
| @@ -1,6 +1,10 @@ | |||||
| package com.iformall.controller; | package com.iformall.controller; | ||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONArray; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||
| import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||||
| import com.github.pagehelper.PageInfo; | import com.github.pagehelper.PageInfo; | ||||
| import com.iformall.annotation.AuthIgnore; | import com.iformall.annotation.AuthIgnore; | ||||
| import com.iformall.annotation.TenantIgnore; | import com.iformall.annotation.TenantIgnore; | ||||
| @@ -10,20 +14,28 @@ import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | import com.iformall.common.ResultData; | ||||
| import com.iformall.domain.dto.OrderComposeSaveDto; | import com.iformall.domain.dto.OrderComposeSaveDto; | ||||
| import com.iformall.domain.dto.OrderSaveDto; | import com.iformall.domain.dto.OrderSaveDto; | ||||
| import com.iformall.domain.dto.PlatPushOrderSaveDto; | |||||
| import com.iformall.domain.po.*; | import com.iformall.domain.po.*; | ||||
| import com.iformall.domain.po.base.BaseEntity; | import com.iformall.domain.po.base.BaseEntity; | ||||
| import com.iformall.domain.po.base.TenantEntity; | import com.iformall.domain.po.base.TenantEntity; | ||||
| import com.iformall.domain.po.tt.TtCUser; | |||||
| import com.iformall.domain.vo.WxCouponCVo; | import com.iformall.domain.vo.WxCouponCVo; | ||||
| import com.iformall.domain.vo.WxOrderCouponPressVo; | import com.iformall.domain.vo.WxOrderCouponPressVo; | ||||
| import com.iformall.domain.vo.WxOrderCouponVo; | import com.iformall.domain.vo.WxOrderCouponVo; | ||||
| import com.iformall.douyin.pay.TtPayService; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import com.iformall.douyin.payv2.result.CreateOrderCallback; | |||||
| import com.iformall.enums.*; | import com.iformall.enums.*; | ||||
| import com.iformall.exception.MallinkException; | import com.iformall.exception.MallinkException; | ||||
| import com.iformall.interceptor.BodyReaderHttpServletRequestWrapper; | |||||
| import com.iformall.service.*; | import com.iformall.service.*; | ||||
| import com.iformall.service.cuser.CUserServiceFactory; | |||||
| import com.iformall.service.order.OrderFactory; | import com.iformall.service.order.OrderFactory; | ||||
| import com.iformall.service.order.entity.WxComposeOrder; | import com.iformall.service.order.entity.WxComposeOrder; | ||||
| import com.iformall.service.pay.entity.PayExtraParam; | import com.iformall.service.pay.entity.PayExtraParam; | ||||
| import com.iformall.utils.Constant; | import com.iformall.utils.Constant; | ||||
| import com.iformall.utils.IPUtil; | import com.iformall.utils.IPUtil; | ||||
| import com.iformall.utils.MaUtil; | |||||
| import com.iformall.utils.RedisLock; | import com.iformall.utils.RedisLock; | ||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| @@ -38,10 +50,8 @@ import org.springframework.beans.factory.annotation.Qualifier; | |||||
| import org.springframework.data.redis.core.RedisTemplate; | import org.springframework.data.redis.core.RedisTemplate; | ||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
| import java.util.ArrayList; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.util.*; | |||||
| @RestController | @RestController | ||||
| @RequestMapping("/api/order/") | @RequestMapping("/api/order/") | ||||
| @@ -58,6 +68,9 @@ public class WxOrderController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private WxCouponService wxCouponService; | private WxCouponService wxCouponService; | ||||
| @Autowired | |||||
| private CUserServiceFactory cuserFactory; | |||||
| @Autowired | @Autowired | ||||
| private WxCUserBasicInfoService wxCUserBasicInfoService; | private WxCUserBasicInfoService wxCUserBasicInfoService; | ||||
| @@ -79,6 +92,9 @@ public class WxOrderController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private OrderFactory orderFactory; | private OrderFactory orderFactory; | ||||
| @Autowired | |||||
| private MaUtil maUtil; | |||||
| @Autowired | @Autowired | ||||
| @Qualifier("couponDetailRedisTemplate") | @Qualifier("couponDetailRedisTemplate") | ||||
| RedisTemplate<String, WxCouponCVo> cdRedisTemplate; | RedisTemplate<String, WxCouponCVo> cdRedisTemplate; | ||||
| @@ -122,7 +138,7 @@ public class WxOrderController extends BaseController { | |||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| return new ResultData(Result.ERROR,e.getMessage()); | return new ResultData(Result.ERROR,e.getMessage()); | ||||
| } | } | ||||
| return wxOrderService.composeSaveOrder(false,EnumComposeOrder.ONE_NUMBER_ORDER_BATCH,orderSaveDto,memberId,EnumPayWay.PAY_WAY_WECHAT,getTenantInfo()); | |||||
| return wxOrderService.composeSaveOrder(false,EnumComposeOrder.ONE_NUMBER_ORDER_BATCH,orderSaveDto,memberId,getPayWay(),getTenantInfo()); | |||||
| } | } | ||||
| @ApiOperation(value = "单个券单个订单,卡(分账导致无法批量下单)、拼团,砍价用", notes = "{\"couponChannelId\":\"String\",\"couponId\":\"String\",\"press\":\"String\",\"orderGroupId\":\"String\",\"formId\":\"String\"}") | @ApiOperation(value = "单个券单个订单,卡(分账导致无法批量下单)、拼团,砍价用", notes = "{\"couponChannelId\":\"String\",\"couponId\":\"String\",\"press\":\"String\",\"orderGroupId\":\"String\",\"formId\":\"String\"}") | ||||
| @@ -142,6 +158,208 @@ public class WxOrderController extends BaseController { | |||||
| list.add(dto); | list.add(dto); | ||||
| return wxOrderService.composeSaveOrder(false,EnumComposeOrder.SINGLE,list,memberId,getPayWay(),getTenantInfo()); | return wxOrderService.composeSaveOrder(false,EnumComposeOrder.SINGLE,list,memberId,getPayWay(),getTenantInfo()); | ||||
| } | } | ||||
| @AuthIgnore | |||||
| @ApiOperation(value = "抖音支付2.0与下单回调推送订单", notes = "{\"couponChannelId\":\"String\",\"couponId\":\"String\",\"press\":\"String\",\"orderGroupId\":\"String\",\"formId\":\"String\"}") | |||||
| @PostMapping("douyinPushOrder") | |||||
| public Map<String,Object> douyinPushOrder(HttpServletRequest request) { | |||||
| Map<String, Object> map = new HashMap(); | |||||
| SignatureHeader header = new SignatureHeader(); | |||||
| header.setTimeStamp(request.getHeader("Byte-Timestamp")); | |||||
| header.setNonce(request.getHeader("Byte-Nonce-Str")); | |||||
| header.setSigned(request.getHeader("Byte-Signature")); | |||||
| logger.info("支付2.0预下单回调---header{}"+header.toString()); | |||||
| String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); | |||||
| logger.info("支付2.0预下单回调---body{}"+body); | |||||
| try { | |||||
| JSONObject jsonObject = JSONObject.parseObject(body); | |||||
| String msg = jsonObject.getString("msg"); | |||||
| JSONObject msgObject = JSONObject.parseObject(msg); | |||||
| String app_id = msgObject.getString("app_id"); | |||||
| String open_id = msgObject.getString("open_id"); | |||||
| //透传字段 | |||||
| Map<String,String> couponMap = new HashMap<>(); | |||||
| try{ | |||||
| String cp_extra = msgObject.getString("cp_extra"); | |||||
| if(StringUtils.isBlank(cp_extra)){ | |||||
| map.put("err_no",ErrorCode.SYS_PARAMETER_NOT_NULL.getCode()); | |||||
| map.put("err_tips","缺少透传字段"); | |||||
| return map; | |||||
| } | |||||
| couponMap = JSONObject.parseObject(cp_extra, Map.class); | |||||
| }catch(Exception e){ | |||||
| } | |||||
| if(couponMap.isEmpty()){ | |||||
| map.put("err_no",ErrorCode.SYS_PARAMETER_NOT_NULL.getCode()); | |||||
| map.put("err_tips","透传字段格式不正确"); | |||||
| return map; | |||||
| } | |||||
| //验证app | |||||
| WxAppinfo appinfo = wxAppinfoService.getByAppId(app_id); | |||||
| if(appinfo == null || !EnumAppPlat.TOUTIAO.getCode().equals(appinfo.getPlat()) | |||||
| || !EnumAppType.C.getCode().equals(appinfo.getType())){ | |||||
| map.put("err_no",ErrorCode.APP_ID_NOT_FOUND.getCode()); | |||||
| map.put("err_tips",ErrorCode.APP_ID_NOT_FOUND.getMessage()); | |||||
| return map; | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountService.getById(appinfo.getPayId()); | |||||
| if(payAccount == null){ | |||||
| map.put("err_no",ErrorCode.API_KEY_NOT_FOUND.getCode()); | |||||
| map.put("err_tips","未找到支付配置"); | |||||
| return map; | |||||
| } | |||||
| TenantEntity tenantEntity = new TenantEntity(); | |||||
| tenantEntity.updateTenantInfo(appinfo); | |||||
| //验证用户 | |||||
| Long memberId = null; | |||||
| TtCUser cuser = (TtCUser) cuserFactory.getCUserService(EnumAppPlat.TOUTIAO).getByOpenId(open_id, tenantEntity.getTenantId()); | |||||
| if(cuser != null && cuser.getUserId() != null){ | |||||
| memberId = cuser.getUserId(); | |||||
| } | |||||
| if(memberId == null){ | |||||
| map.put("err_no",ErrorCode.USER_NOT_MEMBER.getCode()); | |||||
| map.put("err_tips",ErrorCode.USER_NOT_MEMBER.getMessage()); | |||||
| return map; | |||||
| } | |||||
| TtPayService ttPayService = maUtil.getTtPayService(appinfo, payAccount); | |||||
| CreateOrderCallback createOrderCallback = ttPayService.parseOrderNotifyV2Result(body, header); | |||||
| JSONObject allExtParam = new JSONObject(); | |||||
| allExtParam.put("order_id",createOrderCallback.getOrderId()); | |||||
| allExtParam.put("total_amount",createOrderCallback.getTotalAmount()); | |||||
| allExtParam.put("discount",createOrderCallback.getDiscount()); | |||||
| allExtParam.put("open_id",createOrderCallback.getOpenId()); | |||||
| List<PlatPushOrderSaveDto> list = new ArrayList<>(); | |||||
| for (CreateOrderCallback.Good good:createOrderCallback.getGoods()) { | |||||
| PlatPushOrderSaveDto dto = new PlatPushOrderSaveDto(); | |||||
| dto.setCouponChannelId(Long.parseLong(couponMap.get(good.getGoodsId()))); | |||||
| dto.setCount(good.getQuantity()); | |||||
| dto.setExtParam(JSON.toJSONString(good.getItemOrderInfoList())); | |||||
| list.add(dto); | |||||
| } | |||||
| ResultData resultData = wxOrderService.platPushSaveOrder(true, EnumComposeOrder.ONE_NUMBER_ORDER_BATCH, allExtParam.toJSONString(), list, memberId, EnumPayWay.PAY_WAY_TT, tenantEntity); | |||||
| logger.info("resultData{}"+JSON.toJSONString(resultData)); | |||||
| if(resultData.code == 200){ | |||||
| WxComposeOrder order = (WxComposeOrder) resultData.data; | |||||
| Map<String, Object> data = new HashMap<>(); | |||||
| data.put("out_order_no",order.getMainOrderId().toString()); | |||||
| // data.put("pay_expire_seconds",300); | |||||
| data.put("order_entry_schema",wxOrderService.getOrderEntrySchema(order.getMainOrderId())); | |||||
| // List<Map<String,Object>> goodsValid = new ArrayList<>(); | |||||
| // for (Long couponChannelId:order.getCouponChannelMap().keySet()) { | |||||
| // Map<String,Object> goodsValidMap = new HashMap<>(); | |||||
| // WxCouponChannel couponChannel = order.getCouponChannelMap().get(couponChannelId); | |||||
| // goodsValidMap.put("goods_id",couponChannel.getTtSpuId()); | |||||
| // WxCoupon wxCoupon = order.getCouponMap().get(couponChannel.getCouponId()); | |||||
| // if(EnumCouponValidType.BETWEEN_TWO_TIME.getCode().equals(wxCoupon.getValidType())){ | |||||
| // goodsValidMap.put("valid_start_time",wxCoupon.getValidStartDate().getTime()); | |||||
| // goodsValidMap.put("valid_end_time",wxCoupon.getValidEndDate().getTime()); | |||||
| // }else{ | |||||
| // goodsValidMap.put("valid_duration",(long)wxCoupon.getValidDays()*24*3600*1000); | |||||
| // } | |||||
| // goodsValid.add(goodsValidMap); | |||||
| // } | |||||
| // data.put("order_valid_time",goodsValid); | |||||
| map.put("data",data); | |||||
| map.put("err_no",0); | |||||
| map.put("err_tips",resultData.message); | |||||
| logger.info("resultData{}"+JSON.toJSONString(map)); | |||||
| return map; | |||||
| }else{ | |||||
| map.put("err_no",resultData.code); | |||||
| map.put("err_tips",resultData.message); | |||||
| return map; | |||||
| } | |||||
| } catch (TtPayException e) { | |||||
| logger.error(e.getMessage()); | |||||
| map.put("err_no",ErrorCode.SYS_BEAN_EMPTY_PROPERTY_ERROR.getCode()); | |||||
| map.put("err_tips",e.getMessage()); | |||||
| return map; | |||||
| } catch (Exception e){ | |||||
| logger.error(e.getMessage()); | |||||
| map.put("err_no",ErrorCode.SYS_SERVER_ERROR.getCode()); | |||||
| map.put("err_tips",e.getMessage()); | |||||
| return map; | |||||
| } | |||||
| } | |||||
| // @ApiOperation(value = "更新订单状态", notes = "{\"payOrderId\":\"string\",\"composeOrderId\":\"string\",\"status\":integer,\"reason\":\"string\"}") | |||||
| // @PostMapping("/updatePayOrder") | |||||
| // public ResultData updatePayOrder(@RequestBody Map<String, Object> paramMap) { | |||||
| // logger.info("/api/pay/updatePayOrder" + paramMap.toString()); | |||||
| // String orderIdStr = (String) paramMap.get("composeOrderId"); | |||||
| // if (StringUtils.isBlank(orderIdStr)) { | |||||
| // logger.info("orderId不能为空: " + paramMap.toString()); | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "orderId不能为空"); | |||||
| // } | |||||
| // Long orderId = 0L; | |||||
| // try { | |||||
| // orderId = Long.valueOf(orderIdStr); | |||||
| // } catch (NumberFormatException e) { | |||||
| // logger.error("orderId参数不正确: " + paramMap.toString() + ", e:" + e.getMessage()); | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "orderId参数不正确"); | |||||
| // } | |||||
| // | |||||
| // WxBatchOrder batchOrder = wxOrderService.getWxBatchOrder(getTenantInfo(),orderId); | |||||
| // if(batchOrder == null){ | |||||
| // return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "未找到订单"); | |||||
| // } | |||||
| // | |||||
| // WxPayOrder payOrder = new WxPayOrder(); | |||||
| // payOrder.setOrderId(orderId); | |||||
| // payOrder.updateTenantInfo(getTenantInfo()); | |||||
| // payOrder.setPayVendor(getPayWay().getCode()); | |||||
| // payOrder.setComposeOrder(batchOrder.getOrderType()); | |||||
| // | |||||
| // try { | |||||
| // WxPayOrder byObj = wxPayOrderService.getByObj(payOrder); | |||||
| // if(byObj != null){ | |||||
| // return new ResultData(Result.SUCCESS, "支付状态更新成功"); | |||||
| // }else{ | |||||
| // | |||||
| // | |||||
| // WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(payOrder.getComposeOrder()).getComposeOrder(payOrder.getOrderId(), payOrder.getTenantId()); | |||||
| // | |||||
| // WxAppinfo appInfo = wxAppinfoService.getCAppInfo(payOrder, EnumPayWay.getEnum(payOrder.getPayVendor()).getPlat()); | |||||
| // //WxCUser user = getUser(); | |||||
| // //WxAppinfo appInfo = getAppInfo(user.getAppId()); | |||||
| // if (null == appInfo) { | |||||
| // return new ResultData(ErrorCode.PAY_ORDER_ERROR, "当前支付类型["+payOrder.getPayVendor()+"]找不到C端appInfo"); | |||||
| // } | |||||
| // WxPayAccount payAccount = wxPayAccountService.getById(appInfo.getPayId()); | |||||
| // try { | |||||
| // WxPayOrder wo = wxPayOrderService.handleWxOrderQuery(payOrder, composeOrder,appInfo, payAccount, IdWorker.get(),false); | |||||
| // if (null != wo) { | |||||
| // return new ResultData(Result.SUCCESS, "支付状态更新成功", composeOrder); | |||||
| // } | |||||
| // }catch(MallinkException e) { | |||||
| // //已经同步了微信的支付状态,表示已经更新 | |||||
| // return new ResultData(Result.SUCCESS, "支付状态更新成功", composeOrder); | |||||
| // } | |||||
| // | |||||
| // return new ResultData(ErrorCode.PAY_ORDER_ERROR, "查询微信订单支付状态失败,请稍后!"); | |||||
| // } | |||||
| // } catch (MallinkException e) { | |||||
| // logger.error("支付状态更新失败2: " + payOrder.toString() + ", e:" + e.getMessage(),e); | |||||
| // return new ResultData(e.getErrorCode(), e.getMessage()); | |||||
| // } catch (Exception e) { | |||||
| // logger.error("支付状态更新失败3: " + payOrder.toString() + ", e:" + e.getMessage(),e); | |||||
| // return new ResultData(ErrorCode.PAY_ORDER_ERROR, "支付状态更新失败3: " + payOrder.toString() + ", e:" + e.getMessage()); | |||||
| // } | |||||
| // } | |||||
| @ApiOperation(value = "取消订单", notes = "{\"orderId\":\"string\"}") | @ApiOperation(value = "取消订单", notes = "{\"orderId\":\"string\"}") | ||||
| @PostMapping("cancel") | @PostMapping("cancel") | ||||
| @@ -169,7 +387,6 @@ public class WxOrderController extends BaseController { | |||||
| if (null != payOrder) { | if (null != payOrder) { | ||||
| WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(payOrder.getComposeOrder()).getComposeOrder(payOrder.getOrderId(), payOrder.getTenantId()); | WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(payOrder.getComposeOrder()).getComposeOrder(payOrder.getOrderId(), payOrder.getTenantId()); | ||||
| //查询微信订单状态并更新 | //查询微信订单状态并更新 | ||||
| boolean hasCompleted = wxPayOrderService.hasCompleted(composeOrder,payOrder); | boolean hasCompleted = wxPayOrderService.hasCompleted(composeOrder,payOrder); | ||||
| if (!hasCompleted) { | if (!hasCompleted) { | ||||
| WxAppinfo appInfo = wxAppinfoService.getCAppInfo(payOrder, EnumPayWay.getEnum(payOrder.getPayVendor()).getPlat()); | WxAppinfo appInfo = wxAppinfoService.getCAppInfo(payOrder, EnumPayWay.getEnum(payOrder.getPayVendor()).getPlat()); | ||||
| @@ -714,5 +931,25 @@ public class WxOrderController extends BaseController { | |||||
| // | // | ||||
| // return openId; | // return openId; | ||||
| // } | // } | ||||
| @AuthIgnore | |||||
| @ApiOperation(value = "抖音支付2.0与退款回调推送订单", notes = "{\"couponChannelId\":\"String\",\"couponId\":\"String\",\"press\":\"String\",\"orderGroupId\":\"String\",\"formId\":\"String\"}") | |||||
| @PostMapping("douyinRefundOrder") | |||||
| public Map<String,Object> douyinRefundOrder(HttpServletRequest request) { | |||||
| SignatureHeader header = new SignatureHeader(); | |||||
| header.setTimeStamp(request.getHeader("Byte-Timestamp")); | |||||
| header.setNonce(request.getHeader("Byte-Nonce-Str")); | |||||
| header.setSigned(request.getHeader("Byte-Signature")); | |||||
| logger.info("支付2.0预下单回调---header{}"+header.toString()); | |||||
| String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); | |||||
| logger.info("支付2.0预下单回调---body{}"+body); | |||||
| Map<String, Object> map = new HashMap(); | |||||
| map.put("err_no",1001); | |||||
| map.put("err_tips","未找到支付信息"); | |||||
| return map; | |||||
| } | |||||
| } | } | ||||
| @@ -100,10 +100,11 @@ public class WxPayOrderController extends BaseController { | |||||
| return new ResultData(ErrorCode.USER_IS_NOT_MEMBER.getCode(), "暂未成为会员,请授权手机号"); | return new ResultData(ErrorCode.USER_IS_NOT_MEMBER.getCode(), "暂未成为会员,请授权手机号"); | ||||
| } | } | ||||
| return _create(orderIdStr,composeOrderType,user.getUserId(),getPayWay(),user.getAppId(),new PayExtraParam("openId",user.getOpenId()),request); | |||||
| return _create(orderIdStr,composeOrderType,user.getUserId(),getPayWay(),user.getAppId(),new PayExtraParam("openId",user.getOpenId()),true,request); | |||||
| } | } | ||||
| private ResultData _create(String orderIdStr,String composeOrderType,Long userId, EnumPayWay payWay,String appId,PayExtraParam parm,HttpServletRequest request) { | |||||
| private ResultData _create(String orderIdStr,String composeOrderType,Long userId, EnumPayWay payWay, | |||||
| String appId,PayExtraParam parm,boolean isCreatePay,HttpServletRequest request) { | |||||
| WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoService.getById(userId,getFinalTenantId()); | WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoService.getById(userId,getFinalTenantId()); | ||||
| if ( null == wxCUserBasicInfo) { | if ( null == wxCUserBasicInfo) { | ||||
| logger.error("会员用户不存在."+userId); | logger.error("会员用户不存在."+userId); | ||||
| @@ -128,7 +129,7 @@ public class WxPayOrderController extends BaseController { | |||||
| try { | try { | ||||
| record.setIp(IPUtil.getIpAddr(request)); | record.setIp(IPUtil.getIpAddr(request)); | ||||
| record.setComposeOrder(Integer.parseInt(composeOrderType)); | record.setComposeOrder(Integer.parseInt(composeOrderType)); | ||||
| return wxPayOrderService.createPayOrder(appInfo, wxCUserBasicInfo, record, payWay,parm); | |||||
| return wxPayOrderService.createPayOrder(appInfo, wxCUserBasicInfo, record, payWay,parm,isCreatePay); | |||||
| } catch (MallinkException e) { | } catch (MallinkException e) { | ||||
| logger.error("payment wechat, order create error, req 2: " + record.toString() + ", e:" + e.getMessage(),e); | logger.error("payment wechat, order create error, req 2: " + record.toString() + ", e:" + e.getMessage(),e); | ||||
| return new ResultData(e.getErrorCode(), e.getMessage()); | return new ResultData(e.getErrorCode(), e.getMessage()); | ||||
| @@ -138,6 +139,30 @@ public class WxPayOrderController extends BaseController { | |||||
| } | } | ||||
| } | } | ||||
| @RequestMapping(value = "/ttcreatev2", method = RequestMethod.POST) | |||||
| public ResultData _ttcreatev2(@RequestBody Map<String, String> paramMap, HttpServletRequest request) throws Exception { | |||||
| logger.info("/api/pay/create" + paramMap.toString()); | |||||
| String orderIdStr = paramMap.get("orderId"); | |||||
| if (StringUtils.isBlank(orderIdStr)) { | |||||
| logger.info("orderId不能为空: " + paramMap.toString()); | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "orderId不能为空"); | |||||
| } | |||||
| String composeOrderType = paramMap.get("composeOrderType"); | |||||
| if (StringUtils.isBlank(composeOrderType)) { | |||||
| logger.info("composeOrderType不能为空: " + paramMap.toString()); | |||||
| return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "composeOrderType不能为空"); | |||||
| } | |||||
| CUser user = getCUser(); | |||||
| if (!user.basicInfoIs()) { | |||||
| logger.error("暂未成为会员,请授权手机号"); | |||||
| return new ResultData(ErrorCode.USER_IS_NOT_MEMBER.getCode(), "暂未成为会员,请授权手机号"); | |||||
| } | |||||
| return _create(orderIdStr,composeOrderType,user.getUserId(),getPayWay(),user.getAppId(),new PayExtraParam("openId",user.getOpenId()),false,request); | |||||
| } | |||||
| @ApiOperation(value = "更新支付订单状态", notes = "{\"payOrderId\":\"string\",\"composeOrderId\":\"string\",\"status\":integer,\"reason\":\"string\"}") | @ApiOperation(value = "更新支付订单状态", notes = "{\"payOrderId\":\"string\",\"composeOrderId\":\"string\",\"status\":integer,\"reason\":\"string\"}") | ||||
| @PostMapping("/updatePayOrder") | @PostMapping("/updatePayOrder") | ||||
| public ResultData updatePayOrder(@RequestBody Map<String, Object> paramMap) { | public ResultData updatePayOrder(@RequestBody Map<String, Object> paramMap) { | ||||
| @@ -112,6 +112,7 @@ public class ShiroConfig { | |||||
| filterChainDefinitionMap.put("/alipay/notify/**", "anon"); | filterChainDefinitionMap.put("/alipay/notify/**", "anon"); | ||||
| filterChainDefinitionMap.put("/ttPay/notify/**", "anon"); | filterChainDefinitionMap.put("/ttPay/notify/**", "anon"); | ||||
| filterChainDefinitionMap.put("/ttweb/notify/**", "anon"); | |||||
| filterChainDefinitionMap.put("/jinmao/notify/**", "anon"); | filterChainDefinitionMap.put("/jinmao/notify/**", "anon"); | ||||
| @@ -219,7 +219,7 @@ public class JinMaoController extends BaseController { | |||||
| try { | try { | ||||
| inputStream = request.getInputStream(); | inputStream = request.getInputStream(); | ||||
| String paramStr = IOUtils.toString(inputStream, "utf-8"); | String paramStr = IOUtils.toString(inputStream, "utf-8"); | ||||
| logger.info("dfh heartBeat: {}",paramStr); | |||||
| // logger.info("dfh heartBeat: {}",paramStr); | |||||
| if (StringUtils.isBlank(paramStr)) { | if (StringUtils.isBlank(paramStr)) { | ||||
| generateHeartBeatResult(response,"unvalid param", "参数不能为空paramStr",currentTime); | generateHeartBeatResult(response,"unvalid param", "参数不能为空paramStr",currentTime); | ||||
| return ; | return ; | ||||
| @@ -2,25 +2,28 @@ package com.iformall.controller.callback; | |||||
| import com.alibaba.fastjson.JSON; | import com.alibaba.fastjson.JSON; | ||||
| import com.alibaba.fastjson.JSONObject; | import com.alibaba.fastjson.JSONObject; | ||||
| import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||||
| import com.iformall.common.ErrorCode; | import com.iformall.common.ErrorCode; | ||||
| import com.iformall.common.ResultData; | import com.iformall.common.ResultData; | ||||
| import com.iformall.controller.base.BaseController; | import com.iformall.controller.base.BaseController; | ||||
| import com.iformall.domain.po.WxAppinfo; | import com.iformall.domain.po.WxAppinfo; | ||||
| import com.iformall.domain.po.WxBatchOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.WxPayOrder; | import com.iformall.domain.po.WxPayOrder; | ||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.domain.po.msg.FmInsideNotifyRefundSuccessMsg; | import com.iformall.domain.po.msg.FmInsideNotifyRefundSuccessMsg; | ||||
| import com.iformall.douyin.pay.DouYinPayHelper; | import com.iformall.douyin.pay.DouYinPayHelper; | ||||
| import com.iformall.douyin.pay.TtPayService; | |||||
| import com.iformall.douyin.payv2.result.CreateOrderCallback; | |||||
| import com.iformall.enums.*; | import com.iformall.enums.*; | ||||
| import com.iformall.interceptor.BodyReaderHttpServletRequestWrapper; | import com.iformall.interceptor.BodyReaderHttpServletRequestWrapper; | ||||
| import com.iformall.mq.MqBaseProducer; | import com.iformall.mq.MqBaseProducer; | ||||
| import com.iformall.service.WxAppinfoService; | |||||
| import com.iformall.service.WxPayAccountService; | |||||
| import com.iformall.service.WxPayOrderService; | |||||
| import com.iformall.service.WxRefundOrderService; | |||||
| import com.iformall.service.*; | |||||
| import com.iformall.service.order.OrderFactory; | import com.iformall.service.order.OrderFactory; | ||||
| import com.iformall.service.order.entity.WxComposeOrder; | import com.iformall.service.order.entity.WxComposeOrder; | ||||
| import com.iformall.service.pay.PayServiceFactory; | import com.iformall.service.pay.PayServiceFactory; | ||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | ||||
| import com.iformall.utils.MaUtil; | |||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| @@ -28,6 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||
| import java.nio.charset.StandardCharsets; | |||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| @@ -50,6 +54,9 @@ public class TtPayController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private WxPayOrderService wxPayOrderService; | private WxPayOrderService wxPayOrderService; | ||||
| @Autowired | |||||
| private WxOrderService wxOrderService; | |||||
| @Autowired | @Autowired | ||||
| private OrderFactory orderFactory; | private OrderFactory orderFactory; | ||||
| @@ -59,6 +66,9 @@ public class TtPayController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private MqBaseProducer mqBaseProducer; | private MqBaseProducer mqBaseProducer; | ||||
| @Autowired | |||||
| private MaUtil maUtil; | |||||
| /** | /** | ||||
| * timestamp number Unix 时间戳,10 位,整型数 | * timestamp number Unix 时间戳,10 位,整型数 | ||||
| * nonce string 随机数 | * nonce string 随机数 | ||||
| @@ -75,60 +85,119 @@ public class TtPayController extends BaseController { | |||||
| */ | */ | ||||
| @PostMapping(value = "/orderPay") | @PostMapping(value = "/orderPay") | ||||
| @ResponseBody | @ResponseBody | ||||
| public Map<String,Object> createOrder( @RequestBody Map<String, Object> parameterMap){ | |||||
| public Map<String,Object> createOrder( @RequestBody Map<String, Object> parameterMap,HttpServletRequest request){ | |||||
| logger.debug("[" + getIpAddr() + "] TtOrderCallbackController::orderPay"); | logger.debug("[" + getIpAddr() + "] TtOrderCallbackController::orderPay"); | ||||
| Map<String,Object> resultMap = new HashMap<>(); | Map<String,Object> resultMap = new HashMap<>(); | ||||
| // String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); | // String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); | ||||
| logger.info("抖音支付通知-----body{}"+parameterMap); | |||||
| // Map<String, Object> parameterMap = JSONObject.parseObject(body, Map.class); | |||||
| logger.info("抖音通知-----body{}"+parameterMap); | |||||
| try { | try { | ||||
| // Map<String, Object> parameterMap = JSONObject.parseObject(body, Map.class); | |||||
| String timestamp = (String) parameterMap.get("timestamp"); | |||||
| String nonce = (String) parameterMap.get("nonce"); | |||||
| // {"appid":"tt9da4eb19029c2bb301","cp_orderno":"557490321114062848","cp_extra":"","way":"2","channel_no":"2021052622001418391405536769","channel_gateway_no":"12105260162116189897","payment_order_no":"2021052622001418391405536769","out_channel_order_no":"","total_amount":100} | |||||
| String msg = (String) parameterMap.get("msg"); | String msg = (String) parameterMap.get("msg"); | ||||
| String type = (String) parameterMap.get("type"); | String type = (String) parameterMap.get("type"); | ||||
| String msgSignature = (String) parameterMap.get("msg_signature"); | |||||
| String version = (String) parameterMap.get("version"); | |||||
| Map<String, Object> pMap = JSONObject.parseObject(msg, Map.class); | Map<String, Object> pMap = JSONObject.parseObject(msg, Map.class); | ||||
| String appid = (String) pMap.get("appid"); | |||||
| WxAppinfo appinfo = appinfoService.getByAppId(appid); | |||||
| WxPayAccount payAccount = payAccountService.getById(appinfo.getPayId()); | |||||
| Map<String,Object> paramMap = new HashMap<>(); | |||||
| paramMap.put("token",payAccount.getNotifyToken()); | |||||
| paramMap.put("timestamp",timestamp); | |||||
| paramMap.put("nonce",nonce); | |||||
| paramMap.put("msg",msg); | |||||
| String sign = DouYinPayHelper.getTTBackSign(paramMap, "SHA1"); | |||||
| if(!msgSignature.equalsIgnoreCase(sign)){ | |||||
| resultMap.put("err_tips","error"); | |||||
| return resultMap; | |||||
| String appid; | |||||
| WxAppinfo appinfo; | |||||
| WxPayAccount payAccount; | |||||
| Boolean is2_0 = false; | |||||
| if(StringUtils.isNotBlank(version) && "2.0".equals(version)){//支付2.0 回调 | |||||
| is2_0 = true; | |||||
| String msgSignature = request.getHeader("Byte-Signature"); | |||||
| String timestamp = request.getHeader("Byte-Timestamp"); | |||||
| String nonce = request.getHeader("Byte-Nonce-Str"); | |||||
| appid = (String) pMap.get("app_id"); | |||||
| appinfo = appinfoService.getByAppId(appid); | |||||
| payAccount = payAccountService.getById(appinfo.getPayId()); | |||||
| TtPayService ttPayService = maUtil.getTtPayService(appinfo, payAccount); | |||||
| String beforeSign = String.format("%s\n%s\n%s\n", | |||||
| timestamp, | |||||
| nonce, | |||||
| JSON.toJSONString(parameterMap)); | |||||
| boolean verify = ttPayService.getConfig().getVerifier().verify(beforeSign.getBytes(StandardCharsets.UTF_8), msgSignature); | |||||
| if(!verify){ | |||||
| logger.info("抖音通知(2.0)-----{}签名效验失败"); | |||||
| resultMap.put("err_tips","error"); | |||||
| return resultMap; | |||||
| } | |||||
| logger.info("抖音通知(2.0)-----{}签名效验成功"); | |||||
| }else{ | |||||
| String msgSignature = (String) parameterMap.get("msg_signature"); | |||||
| String timestamp = (String) parameterMap.get("timestamp"); | |||||
| String nonce = (String) parameterMap.get("nonce"); | |||||
| appid = (String) pMap.get("appid"); | |||||
| appinfo = appinfoService.getByAppId(appid); | |||||
| payAccount = payAccountService.getById(appinfo.getPayId()); | |||||
| Map<String,Object> paramMap = new HashMap<>(); | |||||
| paramMap.put("token",payAccount.getNotifyToken()); | |||||
| paramMap.put("timestamp",timestamp); | |||||
| paramMap.put("nonce",nonce); | |||||
| paramMap.put("msg",msg); | |||||
| String sign = DouYinPayHelper.getTTBackSign(paramMap, "SHA1"); | |||||
| if(!msgSignature.equalsIgnoreCase(sign)){ | |||||
| logger.info("抖音通知-----{}签名效验失败"); | |||||
| resultMap.put("err_tips","error"); | |||||
| return resultMap; | |||||
| } | |||||
| logger.info("抖音通知-----{}签名效验成功"); | |||||
| } | } | ||||
| if("payment".equals(type)){//支付回调 | if("payment".equals(type)){//支付回调 | ||||
| String cp_orderno = (String) pMap.get("cp_orderno");//开发者传入订单号 | |||||
| String out_order_no; | |||||
| if(is2_0){ | |||||
| out_order_no = (String)pMap.get("out_order_no"); | |||||
| }else{ | |||||
| out_order_no = (String) pMap.get("cp_orderno"); | |||||
| } | |||||
| String way = (String) pMap.get("way");//2-支付宝,1-微信 | String way = (String) pMap.get("way");//2-支付宝,1-微信 | ||||
| if (!StringUtils.isNotBlank(cp_orderno)) { | |||||
| if (!StringUtils.isNotBlank(out_order_no)) { | |||||
| try { | try { | ||||
| Long payOrderId = Long.valueOf(cp_orderno); | |||||
| WxPayOrder wxpayOrder = wxPayOrderService.getById(payOrderId, appinfo.getTenantId()); | |||||
| Long orderId = Long.valueOf(out_order_no); | |||||
| WxPayOrder wxpayOrder = wxPayOrderService.getById(orderId, appinfo.getTenantId()); | |||||
| if(wxpayOrder == null){ | |||||
| TenantEntity tenantEntity = new TenantEntity(); | |||||
| tenantEntity.setTenantId(appinfo.getTenantId()); | |||||
| tenantEntity.setParentTenantId(appinfo.getParentTenantId()); | |||||
| WxBatchOrder batchOrder = wxOrderService.getWxBatchOrder(tenantEntity,orderId); | |||||
| if(batchOrder == null){ | |||||
| logger.error("未找到订单"+orderId); | |||||
| } | |||||
| } | |||||
| PayQueryAdapterResult queryResult = payServiceFactory.getPayAdapterService(wxpayOrder.getPayVendor()).queryPayStatus(wxpayOrder, appinfo, payAccount); | PayQueryAdapterResult queryResult = payServiceFactory.getPayAdapterService(wxpayOrder.getPayVendor()).queryPayStatus(wxpayOrder, appinfo, payAccount); | ||||
| if (EnumPayStatus.PAY_STATUS_SUCCESS.getCode() == queryResult.getCode()) { | if (EnumPayStatus.PAY_STATUS_SUCCESS.getCode() == queryResult.getCode()) { | ||||
| WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(wxpayOrder.getComposeOrder()).getComposeOrder(wxpayOrder.getOrderId(), wxpayOrder.getTenantId()); | WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(wxpayOrder.getComposeOrder()).getComposeOrder(wxpayOrder.getOrderId(), wxpayOrder.getTenantId()); | ||||
| wxPayOrderService.handleSuccessOrder(wxpayOrder, composeOrder, queryResult, true,false); | wxPayOrderService.handleSuccessOrder(wxpayOrder, composeOrder, queryResult, true,false); | ||||
| } | } | ||||
| } catch (NumberFormatException e) { | } catch (NumberFormatException e) { | ||||
| logger.error("payOrderId参数不正确: " + paramMap.toString() + ", e:" + e.getMessage()); | |||||
| logger.error("payOrderId参数不正确: " + toString() + ", e:" + e.getMessage()); | |||||
| } | } | ||||
| } | } | ||||
| resultMap.put("err_no",0); | resultMap.put("err_no",0); | ||||
| resultMap.put("err_tips","success"); | resultMap.put("err_tips","success"); | ||||
| }else if("refund".equals(type)){//退款回调 | }else if("refund".equals(type)){//退款回调 | ||||
| String cp_refundno = (String) pMap.get("cp_refundno"); | |||||
| String status = (String) pMap.get("status"); | |||||
| Integer refund_amount = (Integer) pMap.get("refund_amount"); | |||||
| String cp_refundno,status; | |||||
| Integer refund_amount; | |||||
| if(is2_0){ | |||||
| cp_refundno = (String) pMap.get("out_refund_no"); | |||||
| status = (String) pMap.get("status"); | |||||
| refund_amount = (Integer) pMap.get("refund_total_amount"); | |||||
| }else{ | |||||
| cp_refundno = (String) pMap.get("cp_refundno"); | |||||
| status = (String) pMap.get("status"); | |||||
| refund_amount = (Integer) pMap.get("refund_amount"); | |||||
| } | |||||
| Map<String,String> map = new HashMap<>(); | Map<String,String> map = new HashMap<>(); | ||||
| map.put("appid",appid); | map.put("appid",appid); | ||||
| @@ -150,6 +219,8 @@ public class TtPayController extends BaseController { | |||||
| resultMap.put("err_no",0); | resultMap.put("err_no",0); | ||||
| resultMap.put("err_tips","success"); | resultMap.put("err_tips","success"); | ||||
| }else if("settle".equals(type)){ | |||||
| } | } | ||||
| return resultMap; | return resultMap; | ||||
| @@ -0,0 +1,123 @@ | |||||
| package com.iformall.controller.callback; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.controller.base.BaseController; | |||||
| import com.iformall.domain.po.TtCouponChannelPoi; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.enums.EnumSpuSyncStatus; | |||||
| import com.iformall.service.*; | |||||
| import com.iformall.utils.DateUtils; | |||||
| import me.chanjar.weixin.common.util.crypto.SHA1; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.util.Date; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| @RestController | |||||
| @RequestMapping("/ttweb/notify") | |||||
| public class TtWebController extends BaseController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private String fmExceptionEmails; | |||||
| @Autowired | |||||
| private MailService mailService; | |||||
| @Autowired | |||||
| private WxAppinfoService wxAppinfoService; | |||||
| @Autowired | |||||
| private TtCouponGoodsService ttCouponGoodsService; | |||||
| /** | |||||
| * { | |||||
| * "event": "verify_webhook", | |||||
| * "client_key": "", | |||||
| * "content": { | |||||
| * "challenge": 12345 | |||||
| * } | |||||
| * } | |||||
| */ | |||||
| @PostMapping(value = "/notice") | |||||
| @ResponseBody | |||||
| public Map<String,Object> notice( @RequestBody Map<String, Object> parameterMap,HttpServletRequest request){ | |||||
| logger.debug("[" + getIpAddr() + "] TtOrderCallbackController::notice"); | |||||
| logger.info("抖音开放平台通知-----{}"+JSON.toJSONString(parameterMap)); | |||||
| Map<String,Object> resultMap = new HashMap<>(); | |||||
| String event = (String) parameterMap.get("event"); | |||||
| String client_key = (String) parameterMap.get("client_key"); | |||||
| WxAppinfo appInfo = wxAppinfoService.getByAppId(client_key); | |||||
| if(appInfo == null){ | |||||
| resultMap.put("err_code",1000); | |||||
| resultMap.put("err_tips","error"); | |||||
| return resultMap; | |||||
| } | |||||
| String header = request.getHeader("X-Douyin-Signature"); | |||||
| String sha1gen = SHA1.gen(appInfo.getSecret(), JSON.toJSONString(parameterMap)); | |||||
| //发邮件 | |||||
| String[] receivers = fmExceptionEmails.split(","); | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| sb.append(DateUtils.date2String(new Date())); | |||||
| sb.append("\n"); | |||||
| sb.append("抖音开放平台通知{}"+JSON.toJSONString(parameterMap)); | |||||
| sb.append("\n"); | |||||
| sb.append("sha1gen{}"+sha1gen); | |||||
| sb.append("\n"); | |||||
| sb.append("header{}"+header); | |||||
| //发送邮件 | |||||
| mailService.sendSimpleMail(receivers, "抖音开放平台通知", sb.toString()); | |||||
| String content = (String) parameterMap.get("content"); | |||||
| JSONObject jsonObject = JSON.parseObject(content); | |||||
| if("verify_webhook".equals(event)){ | |||||
| String challenge = jsonObject.getString("challenge"); | |||||
| // String challenge = (String) content.get("challenge"); | |||||
| resultMap.put("challenge",challenge); | |||||
| return resultMap; | |||||
| }else if("life_goods_audit".equals(event)){ | |||||
| String product_id = jsonObject.getString("product_id"); | |||||
| String reason = jsonObject.getString("reason"); | |||||
| String status = jsonObject.getString("status"); | |||||
| // String product_id = content.get("product_id").toString(); | |||||
| // String reason = (String) content.get("reason"); | |||||
| // String status = (String) content.get("status"); | |||||
| TtCouponChannelPoi couponChannelPoi = new TtCouponChannelPoi(); | |||||
| couponChannelPoi.updateTenantInfo(appInfo); | |||||
| couponChannelPoi.setSpuId(product_id); | |||||
| if("FAIL".equals(status)){ | |||||
| couponChannelPoi.setLastStatus(EnumSpuSyncStatus.sync_audit_rejection.getCode()); | |||||
| couponChannelPoi.setLastStatusDesc(reason); | |||||
| }else if("PASS".equals(status)){ | |||||
| couponChannelPoi.setLastStatus(EnumSpuSyncStatus.sync_audit_pass.getCode()); | |||||
| couponChannelPoi.setLastStatusDesc(reason); | |||||
| }else{ | |||||
| resultMap.put("err_code",1000); | |||||
| resultMap.put("err_tips","error"); | |||||
| return resultMap; | |||||
| } | |||||
| ttCouponGoodsService.handlerTtGoodsAudit(couponChannelPoi); | |||||
| resultMap.put("err_code",0); | |||||
| resultMap.put("err_tips","success"); | |||||
| return resultMap; | |||||
| } | |||||
| resultMap.put("err_code",1000); | |||||
| resultMap.put("err_tips","error"); | |||||
| return resultMap; | |||||
| } | |||||
| } | |||||
| @@ -39,6 +39,8 @@ public class MqBaseConsumer { | |||||
| @Autowired | @Autowired | ||||
| private FmInsideOrderPushMsgServiceImpl fmInsideOrderPushMsgService; | private FmInsideOrderPushMsgServiceImpl fmInsideOrderPushMsgService; | ||||
| @Autowired | @Autowired | ||||
| private FmInsideOrderPushDeliveryMsgServiceImpl fmInsideOrderPushDeliveryMsgServiceImpl; | |||||
| @Autowired | |||||
| private FmInsideCLoginMsgServiceImpl fmInsideCLoginMsgService; | private FmInsideCLoginMsgServiceImpl fmInsideCLoginMsgService; | ||||
| @Autowired | @Autowired | ||||
| private MqBaseProducer mqBaseProducer; | private MqBaseProducer mqBaseProducer; | ||||
| @@ -115,6 +117,11 @@ public class MqBaseConsumer { | |||||
| FmInsideOrderPushMsg msg = (FmInsideOrderPushMsg)JsonUtil.readValue(message,FmInsideOrderPushMsg.class); | FmInsideOrderPushMsg msg = (FmInsideOrderPushMsg)JsonUtil.readValue(message,FmInsideOrderPushMsg.class); | ||||
| fmInsideOrderPushMsgService.send(msg); | fmInsideOrderPushMsgService.send(msg); | ||||
| } | } | ||||
| else if(EnumMsgRecordType.INSIDE_ORDER_PUSH_DELIVERY.getCode().equals(baseMsg.getMsgType())) { | |||||
| // 内部消息 - 2.0核销同步 | |||||
| FmInsideOrderPushMsg msg = (FmInsideOrderPushMsg)JsonUtil.readValue(message,FmInsideOrderPushMsg.class); | |||||
| fmInsideOrderPushDeliveryMsgServiceImpl.send(msg); | |||||
| } | |||||
| //else if(EnumMsgRecordType.INSIDE_NOTIFY_PAY_SUCCESS.getCode().equals(baseMsg.getMsgType())) { | //else if(EnumMsgRecordType.INSIDE_NOTIFY_PAY_SUCCESS.getCode().equals(baseMsg.getMsgType())) { | ||||
| // 内部消息 - 微信支付通知 | // 内部消息 - 微信支付通知 | ||||
| //FmInsideNotifyPaySuccessMsg msg = (FmInsideNotifyPaySuccessMsg)JsonUtil.readValue(message,FmInsideNotifyPaySuccessMsg.class); | //FmInsideNotifyPaySuccessMsg msg = (FmInsideNotifyPaySuccessMsg)JsonUtil.readValue(message,FmInsideNotifyPaySuccessMsg.class); | ||||
| @@ -68,13 +68,13 @@ public class CouponExpiringSchedule { | |||||
| wxCouponSendMapper.offExpiriedCouponSendByCouponStatus(mall.getTenantId()); | wxCouponSendMapper.offExpiriedCouponSendByCouponStatus(mall.getTenantId()); | ||||
| List<Long> ids = wxCouponChannelMapper.getExpiriedCouponChannelIdsByCouponStatus(mall.getTenantId()); | |||||
| List<Long> couponIds = wxCouponChannelMapper.getExpiriedCouponIdsByCouponStatus(mall.getTenantId()); | |||||
| wxCouponChannelMapper.offExpiriedCouponChannelByCouponStatus(mall.getTenantId()); | wxCouponChannelMapper.offExpiriedCouponChannelByCouponStatus(mall.getTenantId()); | ||||
| //同步poi | //同步poi | ||||
| if(ids != null && ids.size() > 0){ | |||||
| for (Long id: ids) { | |||||
| if(couponIds != null && couponIds.size() > 0){ | |||||
| for (Long couponId: couponIds) { | |||||
| try{ | try{ | ||||
| wxCouponChannelService.spuStatusSync(mall,id); | |||||
| wxCouponChannelService.spuStatusSyncByCoupon(mall,couponId); | |||||
| }catch(Exception e){ | }catch(Exception e){ | ||||
| logger.error("send spuStatusSync error: " + e.getMessage()); | logger.error("send spuStatusSync error: " + e.getMessage()); | ||||
| } | } | ||||
| @@ -107,34 +107,34 @@ public class CouponExpiringSchedule { | |||||
| List<WxMall> malls = getMalls(); | List<WxMall> malls = getMalls(); | ||||
| for (WxMall mall : malls) { | for (WxMall mall : malls) { | ||||
| try { | try { | ||||
| List<Long> ids = new ArrayList<>(); | |||||
| List<Long> couponIds = new ArrayList<>(); | |||||
| List<Long> id1s = wxCouponChannelMapper.getExpiriedCouponChannelIdsByEndTime(mall.getTenantId()); | |||||
| if(id1s != null && id1s.size() > 0){ | |||||
| ids.removeAll(id1s); | |||||
| ids.addAll(id1s); | |||||
| List<Long> couponId1s = wxCouponChannelMapper.getExpiriedCouponIdsByEndTime(mall.getTenantId()); | |||||
| if(couponId1s != null && couponId1s.size() > 0){ | |||||
| couponIds.removeAll(couponId1s); | |||||
| couponIds.addAll(couponId1s); | |||||
| } | } | ||||
| wxCouponChannelMapper.offExpiriedCouponChannelByEndTime(mall.getTenantId()); | wxCouponChannelMapper.offExpiriedCouponChannelByEndTime(mall.getTenantId()); | ||||
| List<Long> id2s = wxCouponChannelMapper.getExpiriedCouponChannelIdsByValidDate(mall.getTenantId()); | |||||
| if(id2s != null && id2s.size() > 0){ | |||||
| ids.removeAll(id2s); | |||||
| ids.addAll(id2s); | |||||
| List<Long> couponId2s = wxCouponChannelMapper.getExpiriedCouponIdsByValidDate(mall.getTenantId()); | |||||
| if(couponId2s != null && couponId2s.size() > 0){ | |||||
| couponIds.removeAll(couponId2s); | |||||
| couponIds.addAll(couponId2s); | |||||
| } | } | ||||
| wxCouponChannelMapper.offExpiriedCouponChannelByValidDate(mall.getTenantId()); | wxCouponChannelMapper.offExpiriedCouponChannelByValidDate(mall.getTenantId()); | ||||
| List<Long> id3s = wxCouponChannelMapper.getExpiriedCouponChannelIdsByCouponStatus(mall.getTenantId()); | |||||
| List<Long> id3s = wxCouponChannelMapper.getExpiriedCouponIdsByCouponStatus(mall.getTenantId()); | |||||
| if(id3s != null && id3s.size() > 0){ | if(id3s != null && id3s.size() > 0){ | ||||
| ids.removeAll(id3s); | |||||
| ids.addAll(id3s); | |||||
| couponIds.removeAll(id3s); | |||||
| couponIds.addAll(id3s); | |||||
| } | } | ||||
| wxCouponChannelMapper.offExpiriedCouponChannelByCouponStatus(mall.getTenantId()); | wxCouponChannelMapper.offExpiriedCouponChannelByCouponStatus(mall.getTenantId()); | ||||
| //同步poi | //同步poi | ||||
| if(ids != null && ids.size() > 0){ | |||||
| for (Long id: ids) { | |||||
| if(couponIds != null && couponIds.size() > 0){ | |||||
| for (Long couponId: couponIds) { | |||||
| try{ | try{ | ||||
| wxCouponChannelService.spuStatusSync(mall,id); | |||||
| wxCouponChannelService.spuStatusSyncByCoupon(mall,couponId); | |||||
| }catch(Exception e){ | }catch(Exception e){ | ||||
| logger.error("send spuStatusSync error: " + e.getMessage()); | logger.error("send spuStatusSync error: " + e.getMessage()); | ||||
| } | } | ||||
| @@ -353,7 +353,7 @@ public class OrderExpiringSchedule { | |||||
| wxOrderMapper.updateById(updateOrder); | wxOrderMapper.updateById(updateOrder); | ||||
| logger.info("券订单: " + order.getId() + " create at " + order.getCreateDate() + " expired at " + new Date()); | logger.info("券订单: " + order.getId() + " create at " + order.getCreateDate() + " expired at " + new Date()); | ||||
| wxOrderService.sendInsideOrderPushMsg(order,order.getComposeOrderId()); | |||||
| // wxOrderService.sendInsideOrderPushMsg(order,order.getComposeOrderId()); | |||||
| } | } | ||||
| @@ -0,0 +1,76 @@ | |||||
| package com.iformall.schedule; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.douyin.pay.TtPayService; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import com.iformall.douyin.payv2.request.TtRefundAuditMsgRequest; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.mapper.*; | |||||
| import com.iformall.utils.MaUtil; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.scheduling.annotation.Scheduled; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.List; | |||||
| @Component | |||||
| public class OrderRefundAuditSchedule { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| WxOrderMapper wxOrderMapper; | |||||
| @Autowired | |||||
| WxAppinfoMapper wxAppinfoMapper; | |||||
| @Autowired | |||||
| WxRefundOrderMapper wxRefundOrderMapper; | |||||
| @Autowired | |||||
| WxPayAccountMapper wxPayAccountMapper; | |||||
| @Autowired | |||||
| MaUtil maUtil; | |||||
| private List<WxAppinfo> getAppInfos() { | |||||
| WxAppinfo appinfo =new WxAppinfo(); | |||||
| appinfo.setPlat(EnumAppPlat.TOUTIAO.getCode()); | |||||
| appinfo.setType(EnumAppType.C.getCode()); | |||||
| return wxAppinfoMapper.findList(appinfo); | |||||
| } | |||||
| @Scheduled(cron = "0 */10 * * * *?") // 每10分钟检查一次 | |||||
| //@Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次 | |||||
| public void merchantAuditCallback() { | |||||
| logger.info("退款自动审核start"); | |||||
| List<WxAppinfo> appInfos = getAppInfos(); | |||||
| for (WxAppinfo appinfo : appInfos) { | |||||
| WxRefundOrder refundOrder = new WxRefundOrder(); | |||||
| refundOrder.updateTenantInfo(appinfo); | |||||
| refundOrder.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode()); | |||||
| List<WxRefundOrder> list = wxRefundOrderMapper.findList(refundOrder); | |||||
| if(list != null && list.size() > 0){ | |||||
| WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId()); | |||||
| TtPayService ttPayService = maUtil.getTtPayService(appinfo, payAccount); | |||||
| for (WxRefundOrder order:list) { | |||||
| try { | |||||
| TtRefundAuditMsgRequest request = new TtRefundAuditMsgRequest(); | |||||
| request.setOutRefundNo(order.getId().toString()); | |||||
| request.setRefundAuditStatus(1); | |||||
| ttPayService.merchantAuditCallback(request); | |||||
| } catch (TtPayException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -42,8 +42,8 @@ public class SharingOrderRedoSchedule { | |||||
| } | } | ||||
| @Async | @Async | ||||
| @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨02:00分账重试 | |||||
| // @Scheduled(cron = "0 0 0/1 * * ?") // 测试 | |||||
| // @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨02:00分账重试 | |||||
| @Scheduled(cron = "0 0/10 * * * ?") // 测试 | |||||
| public void sharingOrderResultSchedule() { | public void sharingOrderResultSchedule() { | ||||
| List<WxMall> malls = getMalls(); | List<WxMall> malls = getMalls(); | ||||
| for (WxMall mall: malls) { | for (WxMall mall: malls) { | ||||
| @@ -35,8 +35,8 @@ public class SharingOrderResultSchedule { | |||||
| } | } | ||||
| @Async | @Async | ||||
| @Scheduled(cron = "0 15 0 * * ?") // 每天凌晨3:00更新分账结果 | |||||
| //@Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次 | |||||
| // @Scheduled(cron = "0 15 0 * * ?") // 每天凌晨3:00更新分账结果 | |||||
| @Scheduled(cron = "* */15 * * * ?") // 测试10秒中一次 | |||||
| public void sharingOrderResultSchedule() { | public void sharingOrderResultSchedule() { | ||||
| List<WxMall> malls = getMalls(); | List<WxMall> malls = getMalls(); | ||||
| for (WxMall mall: malls) { | for (WxMall mall: malls) { | ||||
| @@ -59,21 +59,21 @@ public class TtMerchantPoiSchedule { | |||||
| // } | // } | ||||
| // } | // } | ||||
| @Async | |||||
| @Scheduled(cron = "0 0 */1 * * *?") // 每小时检查一次 | |||||
| public void supplierQueryTaskSchedule() { | |||||
| TtCouponChannelPoi ttCouponChannelPoi = new TtCouponChannelPoi(); | |||||
| ttCouponChannelPoi.setLastStatus(EnumSpuSyncStatus.sync_auditing.getCode()); | |||||
| List<TtCouponChannelPoi> list = ttCouponChannelPoiMapper.findList(ttCouponChannelPoi); | |||||
| if(list != null && list.size() > 0){ | |||||
| for (TtCouponChannelPoi poi:list) { | |||||
| try{ | |||||
| ttMerchantPoiService.spuGet(poi,poi.getId()); | |||||
| }catch(Exception e){ | |||||
| logger.error("查询商品同步任务失败"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // @Async | |||||
| // @Scheduled(cron = "0 0 */1 * * *?") // 每小时检查一次 | |||||
| // public void supplierQueryTaskSchedule() { | |||||
| // TtCouponChannelPoi ttCouponChannelPoi = new TtCouponChannelPoi(); | |||||
| // ttCouponChannelPoi.setLastStatus(EnumSpuSyncStatus.sync_auditing.getCode()); | |||||
| // List<TtCouponChannelPoi> list = ttCouponChannelPoiMapper.findList(ttCouponChannelPoi); | |||||
| // if(list != null && list.size() > 0){ | |||||
| // for (TtCouponChannelPoi poi:list) { | |||||
| // try{ | |||||
| // ttMerchantPoiService.spuGet(poi,poi.getId()); | |||||
| // }catch(Exception e){ | |||||
| // logger.error("查询商品同步任务失败"); | |||||
| // } | |||||
| // } | |||||
| // } | |||||
| // } | |||||
| } | } | ||||
| @@ -24,13 +24,13 @@ public class TtOrderPushErrorSchedule { | |||||
| private WxOrderService wxOrderService; | private WxOrderService wxOrderService; | ||||
| @Async | @Async | ||||
| @Scheduled(cron = "0 0 1 * * ?") | |||||
| @Scheduled(cron = "0 0 */2 * * ?") | |||||
| public void OrderPushErrorTaskSchedule() { | public void OrderPushErrorTaskSchedule() { | ||||
| List<TtOrderPushError> orderPushErrors = ttOrderPushErrorMapper.findList(new TtOrderPushError()); | List<TtOrderPushError> orderPushErrors = ttOrderPushErrorMapper.findList(new TtOrderPushError()); | ||||
| if(orderPushErrors != null && orderPushErrors.size() > 0){ | if(orderPushErrors != null && orderPushErrors.size() > 0){ | ||||
| for (TtOrderPushError error:orderPushErrors) { | for (TtOrderPushError error:orderPushErrors) { | ||||
| try{ | try{ | ||||
| wxOrderService.sendInsideOrderPushMsg(error,error.getId()); | |||||
| wxOrderService.sendInsideOrderPushDeliveryMsg(error,null,error.getId()); | |||||
| }catch(Exception e){ | }catch(Exception e){ | ||||
| logger.error("订单同步重试error"); | logger.error("订单同步重试error"); | ||||
| } | } | ||||
| @@ -0,0 +1,32 @@ | |||||
| package com.iformall.domain.dto; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import com.iformall.domain.po.UserBasicInfoAddress; | |||||
| import com.iformall.domain.po.WxCoupon; | |||||
| import com.iformall.domain.po.WxCouponChannel; | |||||
| @Data | |||||
| public class PlatPushOrderSaveDto implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| Long couponChannelId;//【传入参数】渠道商品编号,对饮我们系统的编号 | |||||
| int count;//【传入参数】购买数量 | |||||
| Long orderGroupId;//【传入参数】拼团主订单号 | |||||
| boolean isPress = false;//【传入参数】,是否砍价 | |||||
| String formId ; //【传入参数】,非必传 | |||||
| Integer shippingType = 0;//EnumOrderShopingType【传入参数】配送类型 | |||||
| UserBasicInfoAddress address;//【传入参数】配送地址 | |||||
| String extParam;//数组格式长度与数量一致(一个券一个订单时)【传入参数】json,额外的信息,可能每个平台不一样 | |||||
| WxCoupon wxCoupon;//【非传入参数】。 | |||||
| WxCouponChannel wxCouponChannel;//【非传入参数】。 | |||||
| } | |||||
| @@ -17,11 +17,15 @@ import java.util.Date; | |||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||
| public class TtCouponChannelPoi extends TenantEntity { | public class TtCouponChannelPoi extends TenantEntity { | ||||
| protected Long id;//coupon_channel_id | |||||
| protected Long id;//coupon_id | |||||
| @io.swagger.annotations.ApiModelProperty(value="couponChannelId",name="couponChannelId") | |||||
| private Long couponChannelId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="spuId",name="spuId") | @io.swagger.annotations.ApiModelProperty(value="spuId",name="spuId") | ||||
| private String spuId; | private String spuId; | ||||
| //该字段状态更新不及时,不作为业务使用 | |||||
| @io.swagger.annotations.ApiModelProperty(value="状态:0-审核中,1-上架,2-下架,3-审核拒绝 4-审核通过",name="status") | @io.swagger.annotations.ApiModelProperty(value="状态:0-审核中,1-上架,2-下架,3-审核拒绝 4-审核通过",name="status") | ||||
| private Integer status; | private Integer status; | ||||
| @@ -0,0 +1,29 @@ | |||||
| package com.iformall.domain.po; | |||||
| import com.baomidou.mybatisplus.annotation.TableField; | |||||
| import com.baomidou.mybatisplus.annotation.TableName; | |||||
| import com.iformall.domain.po.base.BaseEntity; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| @TableName(value = "tt_goods_category") | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class TtGoodsCategory extends BaseEntity { | |||||
| protected Integer id; | |||||
| @io.swagger.annotations.ApiModelProperty(value="",name="name") | |||||
| private String name; | |||||
| @io.swagger.annotations.ApiModelProperty(value="",name="parentId") | |||||
| private Integer parentId; | |||||
| @TableField(exist = false) | |||||
| protected List<TtGoodsCategory> child; | |||||
| } | |||||
| @@ -1,5 +1,8 @@ | |||||
| package com.iformall.domain.po; | package com.iformall.domain.po; | ||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils; | |||||
| import com.baomidou.mybatisplus.annotation.TableField; | import com.baomidou.mybatisplus.annotation.TableField; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import com.iformall.domain.po.base.TenantEntity; | import com.iformall.domain.po.base.TenantEntity; | ||||
| @@ -42,6 +45,9 @@ public class WxBatchOrder extends TenantEntity { | |||||
| @io.swagger.annotations.ApiModelProperty(value = "EnumYesOrNo是否抖音poi订单", name = "isTtPoiOrder") | @io.swagger.annotations.ApiModelProperty(value = "EnumYesOrNo是否抖音poi订单", name = "isTtPoiOrder") | ||||
| private Integer isTtPoiOrder; | private Integer isTtPoiOrder; | ||||
| @io.swagger.annotations.ApiModelProperty(value = "额外参数,总参数", name = "extParam") | |||||
| private String extParam; | |||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| @io.swagger.annotations.ApiModelProperty(value = "订单集合", name = "orders") | @io.swagger.annotations.ApiModelProperty(value = "订单集合", name = "orders") | ||||
| @@ -56,4 +62,15 @@ public class WxBatchOrder extends TenantEntity { | |||||
| return null; | return null; | ||||
| } | } | ||||
| public Object getExpParamValue(String key) { | |||||
| if (StringUtils.isBlank(extParam)) { | |||||
| return null; | |||||
| } | |||||
| JSONObject o = JSON.parseObject(extParam); | |||||
| if (null == o ) { | |||||
| return null; | |||||
| } | |||||
| return o.get(key); | |||||
| } | |||||
| } | } | ||||
| @@ -1,10 +1,12 @@ | |||||
| package com.iformall.domain.po; | package com.iformall.domain.po; | ||||
| import com.aliyun.openservices.shade.com.alibaba.fastjson.JSONObject; | |||||
| import com.baomidou.mybatisplus.annotation.TableField; | import com.baomidou.mybatisplus.annotation.TableField; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import com.iformall.common.SortColumn; | import com.iformall.common.SortColumn; | ||||
| import com.iformall.domain.po.base.TenantEntity; | import com.iformall.domain.po.base.TenantEntity; | ||||
| import com.iformall.domain.vo.WxCouponStatisVo; | import com.iformall.domain.vo.WxCouponStatisVo; | ||||
| import com.iformall.douyin.web.bean.GoodsTemplateGet; | |||||
| import com.iformall.enums.EnumCouponType; | import com.iformall.enums.EnumCouponType; | ||||
| import com.iformall.enums.EnumValidStatus; | import com.iformall.enums.EnumValidStatus; | ||||
| import com.iformall.utils.Constant; | import com.iformall.utils.Constant; | ||||
| @@ -14,6 +16,7 @@ import cn.afterturn.easypoi.excel.annotation.Excel; | |||||
| import lombok.Data; | import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | import lombok.ToString; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.math.BigDecimal; | import java.math.BigDecimal; | ||||
| @@ -237,9 +240,60 @@ public class WxCoupon extends TenantEntity { | |||||
| @io.swagger.annotations.ApiModelProperty(value="富文本内容",name="html") | @io.swagger.annotations.ApiModelProperty(value="富文本内容",name="html") | ||||
| private String html; | private String html; | ||||
| //List<Long> String | |||||
| @io.swagger.annotations.ApiModelProperty(value="卷包内容",name="giftList") | @io.swagger.annotations.ApiModelProperty(value="卷包内容",name="giftList") | ||||
| private String giftList; | private String giftList; | ||||
| @io.swagger.annotations.ApiModelProperty(value="EnumTtProductType",name="productType") | |||||
| private Integer productType; | |||||
| @io.swagger.annotations.ApiModelProperty(value="tt_goods_category",name="categoryId") | |||||
| private Integer categoryId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="JSON",name="productAttrs") | |||||
| private String productAttrs; | |||||
| @TableField(exist = false) | |||||
| private Map<String,String> productAttrKeyValueMap; | |||||
| public Map<String,String> getProductAttrKeyValueMap(){ | |||||
| Map<String,String> productAttrKeyValueMap = new HashMap<>(); | |||||
| if(StringUtils.isNotBlank(productAttrs)){ | |||||
| try{ | |||||
| List<GoodsTemplateGet.ProductAttrs> productAttrs = JSONObject.parseArray(this.productAttrs, GoodsTemplateGet.ProductAttrs.class); | |||||
| for (GoodsTemplateGet.ProductAttrs attr:productAttrs) { | |||||
| if(StringUtils.isNotBlank(attr.getData())){ | |||||
| productAttrKeyValueMap.put(attr.getKey(),attr.getData()); | |||||
| } | |||||
| } | |||||
| }catch(Exception e){ | |||||
| } | |||||
| } | |||||
| return productAttrKeyValueMap; | |||||
| } | |||||
| @io.swagger.annotations.ApiModelProperty(value="JSON",name="skuAttrs") | |||||
| private String skuAttrs; | |||||
| @TableField(exist = false) | |||||
| private Map<String,String> skuAttrKeyValueMap; | |||||
| public Map<String,String> getSkuAttrKeyValueMap(){ | |||||
| Map<String,String> skuAttrKeyValueMap = new HashMap<>(); | |||||
| if(StringUtils.isNotBlank(skuAttrs)){ | |||||
| try{ | |||||
| List<GoodsTemplateGet.ProductAttrs> skuAttrs = JSONObject.parseArray(this.skuAttrs, GoodsTemplateGet.ProductAttrs.class); | |||||
| for (GoodsTemplateGet.ProductAttrs attr:skuAttrs) { | |||||
| if(StringUtils.isNotBlank(attr.getData())){ | |||||
| skuAttrKeyValueMap.put(attr.getKey(),attr.getData()); | |||||
| } | |||||
| } | |||||
| }catch(Exception e){ | |||||
| } | |||||
| } | |||||
| return skuAttrKeyValueMap; | |||||
| } | |||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| private List<WxCoupon> giftCouponList; | private List<WxCoupon> giftCouponList; | ||||
| @@ -1,5 +1,8 @@ | |||||
| package com.iformall.domain.po; | package com.iformall.domain.po; | ||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils; | |||||
| import com.baomidou.mybatisplus.annotation.TableField; | import com.baomidou.mybatisplus.annotation.TableField; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import com.fasterxml.jackson.annotation.JsonFormat; | import com.fasterxml.jackson.annotation.JsonFormat; | ||||
| @@ -83,6 +86,21 @@ public class WxCouponOrder extends TenantEntity { | |||||
| @io.swagger.annotations.ApiModelProperty(value="补贴",name="subsidy") | @io.swagger.annotations.ApiModelProperty(value="补贴",name="subsidy") | ||||
| private Integer subsidy; | private Integer subsidy; | ||||
| @io.swagger.annotations.ApiModelProperty(value="额外参数,用于第三方平台",name="extParam") | |||||
| private String extParam; | |||||
| public Object getExpParamValue(String key) { | |||||
| if (StringUtils.isBlank(extParam)) { | |||||
| return null; | |||||
| } | |||||
| JSONObject o = JSON.parseObject(extParam); | |||||
| if (null == o ) { | |||||
| return null; | |||||
| } | |||||
| return o.get(key); | |||||
| } | |||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| private String couponName; | private String couponName; | ||||
| @@ -346,6 +346,10 @@ public class WxMerchant extends TenantEntity { | |||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| private String addr; | private String addr; | ||||
| @io.swagger.annotations.ApiModelProperty(value=" supplierExtId",name="supplierExtId") | |||||
| @TableField(exist = false) | |||||
| private String supplierExtId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="ttPoi",name="ttPoi") | @io.swagger.annotations.ApiModelProperty(value="ttPoi",name="ttPoi") | ||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| private String ttPoi; | private String ttPoi; | ||||
| @@ -1,6 +1,10 @@ | |||||
| package com.iformall.domain.po; | package com.iformall.domain.po; | ||||
| import cn.afterturn.easypoi.excel.annotation.Excel; | import cn.afterturn.easypoi.excel.annotation.Excel; | ||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils; | |||||
| import com.baomidou.mybatisplus.annotation.TableField; | import com.baomidou.mybatisplus.annotation.TableField; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import com.iformall.common.SortColumn; | import com.iformall.common.SortColumn; | ||||
| @@ -119,6 +123,19 @@ public class WxOrder extends TenantEntity { | |||||
| @io.swagger.annotations.ApiModelProperty(value="父订单编号",name="parentOrderId") | @io.swagger.annotations.ApiModelProperty(value="父订单编号",name="parentOrderId") | ||||
| private Long parentOrderId; | private Long parentOrderId; | ||||
| @io.swagger.annotations.ApiModelProperty(value="额外参数,用于第三方平台",name="extParam") | |||||
| private String extParam; | |||||
| public Object getExpParamValue(String key) { | |||||
| if (StringUtils.isBlank(extParam)) { | |||||
| return null; | |||||
| } | |||||
| JSONObject o = JSON.parseObject(extParam); | |||||
| if (null == o ) { | |||||
| return null; | |||||
| } | |||||
| return o.get(key); | |||||
| } | |||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| protected List<Long> couponIds; | protected List<Long> couponIds; | ||||
| @@ -12,4 +12,7 @@ public class FmInsideOrderPushMsg extends BaseMsg{ | |||||
| @io.swagger.annotations.ApiModelProperty(value = "", name = "composeOrderId") | @io.swagger.annotations.ApiModelProperty(value = "", name = "composeOrderId") | ||||
| private Long batchOrderId; | private Long batchOrderId; | ||||
| @io.swagger.annotations.ApiModelProperty(value = "", name = "couponOrderId") | |||||
| private Long couponOrderId; | |||||
| } | } | ||||
| @@ -10,8 +10,8 @@ import lombok.ToString; | |||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||
| public class FmInsideProductPushMsg extends BaseMsg{ | public class FmInsideProductPushMsg extends BaseMsg{ | ||||
| @io.swagger.annotations.ApiModelProperty(value = "卷Id", name = "couponChannelId") | |||||
| private Long couponChannelId; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "卷Id", name = "couponId") | |||||
| private Long couponId; | |||||
| @io.swagger.annotations.ApiModelProperty(value = "同步类型", name = "syncType") | @io.swagger.annotations.ApiModelProperty(value = "同步类型", name = "syncType") | ||||
| private EnumPushType syncType; | private EnumPushType syncType; | ||||
| @@ -0,0 +1,41 @@ | |||||
| package com.iformall.domain.vo; | |||||
| import com.baomidou.mybatisplus.annotation.TableField; | |||||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||||
| import com.iformall.domain.po.WxCoupon; | |||||
| import com.iformall.domain.po.WxCouponChannel; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.ToString; | |||||
| import java.io.Serializable; | |||||
| import java.math.BigDecimal; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by syf on 2018/8/22. | |||||
| */ | |||||
| @JsonIgnoreProperties(value = {"handler"}) | |||||
| @Data | |||||
| @ToString(callSuper = true) | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class TtCouponChannelVo extends WxCouponChannelVo implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| @io.swagger.annotations.ApiModelProperty(value="spuId",name="spuId") | |||||
| private String spuId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="状态:0-审核中,1-上架,2-下架,3-审核拒绝 4-审核通过",name="poiStatus") | |||||
| private Integer poiStatus; | |||||
| @io.swagger.annotations.ApiModelProperty(value="描述",name="statusDesc") | |||||
| private String statusDesc; | |||||
| @io.swagger.annotations.ApiModelProperty(value="状态:0-审核中,1-上架,2-下架,3-审核拒绝 4-审核通过",name="lastStatus") | |||||
| private Integer lastStatus; | |||||
| @io.swagger.annotations.ApiModelProperty(value="描述",name="lastStatusDesc") | |||||
| private String lastStatusDesc; | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| package com.iformall.domain.vo; | |||||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||||
| import com.iformall.domain.po.WxCoupon; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.ToString; | |||||
| import java.io.Serializable; | |||||
| @Data | |||||
| @ToString(callSuper = true) | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class TtCouponVo extends WxCoupon implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| @io.swagger.annotations.ApiModelProperty(value="couponChannelId",name="couponChannelId") | |||||
| private Long couponChannelId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="spuId",name="spuId") | |||||
| private String spuId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="状态:0-审核中,1-上架,2-下架,3-审核拒绝 4-审核通过",name="poiStatus") | |||||
| private Integer poiStatus; | |||||
| @io.swagger.annotations.ApiModelProperty(value="描述",name="statusDesc") | |||||
| private String statusDesc; | |||||
| @io.swagger.annotations.ApiModelProperty(value="状态:0-审核中,1-上架,2-下架,3-审核拒绝 4-审核通过",name="lastStatus") | |||||
| private Integer lastStatus; | |||||
| @io.swagger.annotations.ApiModelProperty(value="描述",name="lastStatusDesc") | |||||
| private String lastStatusDesc; | |||||
| } | |||||
| @@ -220,6 +220,8 @@ public class WxCouponOrderBVo extends WxCouponOrder { | |||||
| @Excel(name = "核销商户", width = 50, orderNum = "4") | @Excel(name = "核销商户", width = 50, orderNum = "4") | ||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| private String verifyMerchantName; | private String verifyMerchantName; | ||||
| @TableField(exist = false) | |||||
| private Long verifyMerchantId; | |||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| private Long floor; | private Long floor; | ||||
| @@ -101,6 +101,10 @@ public class WxMerchantVo extends TenantEntity { | |||||
| @io.swagger.annotations.ApiModelProperty(value = "置顶时间", name = "topTime") | @io.swagger.annotations.ApiModelProperty(value = "置顶时间", name = "topTime") | ||||
| private Date topTime; | private Date topTime; | ||||
| @io.swagger.annotations.ApiModelProperty(value=" supplierExtId",name="supplierExtId") | |||||
| @TableField(exist = false) | |||||
| private String supplierExtId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="ttPoi",name="ttPoi") | @io.swagger.annotations.ApiModelProperty(value="ttPoi",name="ttPoi") | ||||
| @TableField(exist = false) | @TableField(exist = false) | ||||
| private String ttPoi; | private String ttPoi; | ||||
| @@ -132,6 +136,7 @@ public class WxMerchantVo extends TenantEntity { | |||||
| this.linkLinePhone = m.getLinkLinePhone(); | this.linkLinePhone = m.getLinkLinePhone(); | ||||
| this.topTime = m.getTopTime(); | this.topTime = m.getTopTime(); | ||||
| this.addr = m.getAddr(); | this.addr = m.getAddr(); | ||||
| this.supplierExtId = m.getSupplierExtId(); | |||||
| this.ttPoi = m.getTtPoi(); | this.ttPoi = m.getTtPoi(); | ||||
| this.longitude = m.getLongitude(); | this.longitude = m.getLongitude(); | ||||
| this.latitude = m.getLatitude(); | this.latitude = m.getLatitude(); | ||||
| @@ -6,7 +6,6 @@ import java.security.NoSuchAlgorithmException; | |||||
| import java.util.*; | import java.util.*; | ||||
| import com.iformall.common.ErrorCode; | import com.iformall.common.ErrorCode; | ||||
| import com.iformall.douyin.pay.enums.AppAddSubMerchantUrlType; | |||||
| import com.iformall.douyin.pay.orderQuery.QueryMerchantResult; | import com.iformall.douyin.pay.orderQuery.QueryMerchantResult; | ||||
| import com.iformall.douyin.pay.orderQuery.QueryRefundResult; | import com.iformall.douyin.pay.orderQuery.QueryRefundResult; | ||||
| import com.iformall.douyin.pay.orderQuery.QuerySettleResult; | import com.iformall.douyin.pay.orderQuery.QuerySettleResult; | ||||
| @@ -22,7 +21,6 @@ import com.iformall.utils.HttpUtil; | |||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import springfox.documentation.spring.web.json.Json; | |||||
| /** | /** | ||||
| * 抖音小程序支付 | * 抖音小程序支付 | ||||
| @@ -356,48 +354,52 @@ public class DouYinPayHelper { | |||||
| public static void main(String[] args) { | public static void main(String[] args) { | ||||
| //测试 | //测试 | ||||
| // String mcuid = "70777649963225930610";//商户号 | // String mcuid = "70777649963225930610";//商户号 | ||||
| String appid = "ttef6599d8705b49b101"; | |||||
| String salt = "G8DdHfRcEPXB8kHQsnpVWvhLfMC7MZQ72aweTei8";//支付密钥 | |||||
| // String appid = "ttef6599d8705b49b101"; | |||||
| // String salt = "G8DdHfRcEPXB8kHQsnpVWvhLfMC7MZQ72aweTei8";//支付密钥 | |||||
| //生产 | //生产 | ||||
| // String mcuid = "69739487619282066230"; | // String mcuid = "69739487619282066230"; | ||||
| // String appid = "tt8183f73e1ebb053701"; | |||||
| // String salt = "rtQwyvhZHMuMYrY6GBm8DnhvEu0fuJUVHYS2KP6P"; | |||||
| String appid = "ttc0cdb6705ff345f301"; | |||||
| String salt = "FhGHClzfdDEPW6Cq4hw2GyoynJbpeq6wLQyM5iub"; | |||||
| AppAddSubMerchant appAddSubMerchant = new AppAddSubMerchant(); | |||||
| appAddSubMerchant.setAppId("ttef6599d8705b49b101"); | |||||
| appAddSubMerchant.setSalt("G8DdHfRcEPXB8kHQsnpVWvhLfMC7MZQ72aweTei8"); | |||||
| appAddSubMerchant.setSubMerchantId("666438479039619072"); | |||||
| appAddSubMerchant.setUrlType(2); | |||||
| AppAddSubMerchantResult appAddSubMerchantResult = appAddSubMerchant(appAddSubMerchant); | |||||
| System.out.println(appAddSubMerchantResult.toString()); | |||||
| // AppAddSubMerchant appAddSubMerchant = new AppAddSubMerchant(); | |||||
| // appAddSubMerchant.setAppId("ttef6599d8705b49b101"); | |||||
| // appAddSubMerchant.setSalt("G8DdHfRcEPXB8kHQsnpVWvhLfMC7MZQ72aweTei8"); | |||||
| // appAddSubMerchant.setSubMerchantId("666438479039619072"); | |||||
| // appAddSubMerchant.setUrlType(2); | |||||
| // AppAddSubMerchantResult appAddSubMerchantResult = appAddSubMerchant(appAddSubMerchant); | |||||
| // System.out.println(appAddSubMerchantResult.toString()); | |||||
| // Settle settle = new Settle(); | // Settle settle = new Settle(); | ||||
| // settle.setAppId(appid); | // settle.setAppId(appid); | ||||
| // settle.setSalt(salt); | // settle.setSalt(salt); | ||||
| ///** | ///** | ||||
| // * {"settle_params":"[{\"amount\":19,\"merchant_uid\":\"69798058370993871733\"}]", | |||||
| // * "settle_desc":"客户提现。", | |||||
| // * "sign":"94fa5f559880870f2fda53c67b236a3f", | |||||
| // * "out_settle_no":"572578660822212608", | |||||
| // * "out_order_no":"572308600038809600", | |||||
| // * "app_id":"tt9da4eb19029c2bb301"} | |||||
| // * {settle_params=[{"amount":6859,"merchant_uid":"70878359464980830803"}], | |||||
| // * settle_desc=自主完结分账, sign=9acc782f9196bb45823fdbe7e14b24df, | |||||
| // * out_settle_no=687210710707761152, | |||||
| // * out_order_no=687209074036342784, app_id=ttc0cdb6705ff345f301} | |||||
| // * response:{"err_no":6006,"err_tips":"其他分账方分账比例超限","settle_no":""} | |||||
| // * | |||||
| // * request:{settle_params=[{"amount":6900,"merchant_uid":"70878359464980830803"}], | |||||
| // * settle_desc=自主完结分账, sign=d3541104ea0a6234f96ea753aa514f7c, | |||||
| // * out_settle_no=687210746524631040, out_order_no=687208992638238720, app_id=ttc0cdb6705ff345f301} | |||||
| // * response:{"err_no":6006,"err_tips":"其他分账方分账比例超限","settle_no":""} | |||||
| // */ | // */ | ||||
| // settle.setOutSettleNo("57257866081118888"); | |||||
| // settle.setOutOrderNo("613967802405908480"); | |||||
| // settle.setOutSettleNo("687210746524631040"); | |||||
| // settle.setOutOrderNo("687208992638238720"); | |||||
| // settle.setSettleDesc("手动处理。"); | // settle.setSettleDesc("手动处理。"); | ||||
| // List list = new ArrayList<>(); | // List list = new ArrayList<>(); | ||||
| // Map<String,Object> settleParams = new HashMap<>(); | // Map<String,Object> settleParams = new HashMap<>(); | ||||
| // settleParams.put("merchant_uid",mcuid); | |||||
| // settleParams.put("amount",5); | |||||
| // settleParams.put("merchant_uid","70878359464980830803"); | |||||
| // settleParams.put("amount",6859); | |||||
| // list.add(settleParams); | // list.add(settleParams); | ||||
| // settle.setSettleParams(JSON.toJSONString(list)); | // settle.setSettleParams(JSON.toJSONString(list)); | ||||
| // SettleResult settle1 = settle(settle); | // SettleResult settle1 = settle(settle); | ||||
| // System.out.println(settle1.toString()); | // System.out.println(settle1.toString()); | ||||
| // QuerySettleResult querySettleResult = settleQuery(appid, salt, "57257866081118888", null); | |||||
| // System.out.println(querySettleResult.toString()); | |||||
| QuerySettleResult querySettleResult = settleQuery(appid, salt, "687210746524631040", null); | |||||
| System.out.println(querySettleResult.toString()); | |||||
| // OrderQueryResult orderQueryResult = orderQuery(appid, salt, "613879951804915712", null); | // OrderQueryResult orderQueryResult = orderQuery(appid, salt, "613879951804915712", null); | ||||
| // System.out.println(orderQueryResult.toString()); | // System.out.println(orderQueryResult.toString()); | ||||
| @@ -0,0 +1,48 @@ | |||||
| package com.iformall.douyin.pay; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import com.iformall.douyin.payv2.request.ProfitSharingRequest; | |||||
| import com.iformall.douyin.payv2.result.ProfitSharingResult; | |||||
| /** | |||||
| * 支付V2-资金应用-分账 | |||||
| * https://bytedance.feishu.cn/docx/doxcnj21j74jHyXEq6Ybg3AzOxh | |||||
| * @author pg 2021-6-23 | |||||
| * @date 2021-6-23 | |||||
| */ | |||||
| public interface ProfitSharingV2Service { | |||||
| /** | |||||
| * <pre> | |||||
| * 请求分账API | |||||
| * 接口简介 | |||||
| * 一笔订单完成后,开发者可以通过分账接口将这笔订单产生的资金结算给各个分账方。 | |||||
| * - 结算规则统一为核销D+3; | |||||
| * - CPS订单比较特殊,统一结算规则是核销D+3 | |||||
| * - 结算规则为核销D+3,表示订单到达“终态”3天后可以分账,“终态”表示所有的券/商品已核销或已退款 | |||||
| * - 如对上述结算规则有特殊需求,请联系对应行业经理(餐饮@Xinru Chen 酒旅@Jie Zhou @Yuekai Zhao 到综@Yankai Ouyang ) | |||||
| * - 若分账失败,请参考文档进行自查分账失败如何自查 | |||||
| * 核销D+3 | |||||
| * - 例如用户的一笔订单买了5张团购券,其中3张先核销,剩余2张再退款,最终退款完成的时间就是订单到达终态的时间。订单到达终态3天后,则可以发起分账 | |||||
| * | |||||
| * 返回 小程序分账id,系统会确保不超过64个字节(数字+ASCII) | |||||
| * | |||||
| */ | |||||
| String profitSharing(ProfitSharingRequest request) throws TtPayException; | |||||
| /** | |||||
| * <pre> | |||||
| * 查询分账接口 | |||||
| * out_order_no string 否 开发者交易订单id,长度<64byte,数字ASCII字符 | |||||
| * out_settle_no string 否 开发者分账单id,长度<64byte,数字、ASCII字符 | |||||
| * order_id string 否 抖音开平侧订单id,长度<64byte,数字、ASCII | |||||
| * settle_id string 否 抖音开平侧分账单id,长度<64byte,数字、ASCII | |||||
| * - 查询优先级: settle_id > order_id > out_settle_no > out_order_no,4个参数选填一个 | |||||
| * - 例如:请求填写了settle_id和order_id,服务只会按settle_id来查询,忽略order_id | |||||
| * - 如果未查询到结果,会返回空数组 | |||||
| * - 注意:对于担保交易和交易1.0的订单,如果需要根据order_id/out_order_no查询订单的分账记录,建议使用order_id(抖音开平侧支付单id查询),若使用out_order_no可能存在查询不到的情况 | |||||
| * | |||||
| */ | |||||
| ProfitSharingResult getProfitSharingResult(String out_settle_no) throws TtPayException; | |||||
| } | |||||
| @@ -0,0 +1,201 @@ | |||||
| package com.iformall.douyin.pay; | |||||
| import com.github.binarywang.wxpay.bean.WxPayApiData; | |||||
| import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import com.iformall.douyin.payv2.config.TtPayConfig; | |||||
| import com.iformall.douyin.payv2.request.*; | |||||
| import com.iformall.douyin.payv2.result.*; | |||||
| import org.apache.http.client.methods.HttpPost; | |||||
| import org.apache.http.client.methods.HttpRequestBase; | |||||
| /** | |||||
| * <pre> | |||||
| * 支付相关接口. | |||||
| * Created by Binary Wang on 2016/7/28. | |||||
| * </pre> | |||||
| * | |||||
| */ | |||||
| public interface TtPayService { | |||||
| /** | |||||
| * 获取微信支付请求url前缀,沙箱环境可能不一样. | |||||
| * | |||||
| * @return the pay base url | |||||
| */ | |||||
| String getPayBaseUrl(); | |||||
| /** | |||||
| * 发送post请求,得到响应字符串. | |||||
| * | |||||
| * @param url 请求地址 | |||||
| * @param requestStr 请求信息 | |||||
| * @return 返回请求结果字符串 string | |||||
| * @throws TtPayException the tt pay exception | |||||
| */ | |||||
| String postV2(String url, String requestStr) throws TtPayException; | |||||
| /** | |||||
| * 发送post请求,得到响应字符串. | |||||
| * | |||||
| * @param url 请求地址 | |||||
| * @param httpPost 请求信息 | |||||
| * @return 返回请求结果字符串 string | |||||
| * @throws TtPayException the tt pay exception | |||||
| */ | |||||
| String postV2(String url, HttpPost httpPost) throws TtPayException; | |||||
| /** | |||||
| * 发送http请求,得到响应字符串. | |||||
| * | |||||
| * @param url 请求地址 | |||||
| * @param httpRequest 请求信息,可以是put,post,get,delete等请求 | |||||
| * @return 返回请求结果字符串 string | |||||
| * @throws TtPayException the tt pay exception | |||||
| */ | |||||
| String requestV2(String url, HttpRequestBase httpRequest) throws TtPayException; | |||||
| /** | |||||
| * 发送get V2请求,得到响应字符串. | |||||
| * | |||||
| * @param url 请求地址 | |||||
| * @return 返回请求结果字符串 string | |||||
| * @throws TtPayException the tt pay exception | |||||
| */ | |||||
| String getV2(String url) throws TtPayException; | |||||
| /** | |||||
| * 获取分账服务类. | |||||
| * | |||||
| * @return the ent pay service | |||||
| */ | |||||
| ProfitSharingV2Service getProfitSharingV2Service(); | |||||
| /** | |||||
| * 2.1 交易回调设置接口 | |||||
| */ | |||||
| boolean callbackSettings(CallBackSettingsRequest settings) throws TtPayException; | |||||
| /** | |||||
| * 2.2 查询交易回调设置接口 | |||||
| */ | |||||
| CallBackSettingsRequest querySettings() throws TtPayException; | |||||
| /** | |||||
| * 解析预下单回调 | |||||
| * | |||||
| */ | |||||
| CreateOrderCallback parseOrderNotifyV2Result(String notifyData, SignatureHeader header) throws TtPayException; | |||||
| /** | |||||
| * 交易系统2.0模版下单依赖入口前端js-api,如果用户没有更新抖音,就没法使用模版下单,开发者可用该接口替用户发起下单,开发者发起的下单流程则不会有预下单回调,当低版本减少后,会下掉该接口,请不要应用于其它场景,否则会影响业务(对于poi商品,目前只支持团购券) | |||||
| * @param request | |||||
| * @return | |||||
| * @throws TtPayException | |||||
| */ | |||||
| TtPayUnifiedOrderV2Result createOrderV2(TtPayUnifiedOrderV2Request request) throws TtPayException; | |||||
| /** | |||||
| * <pre> | |||||
| * 5. 订单信息接口 | |||||
| */ | |||||
| TtPayOrderQueryV2Result queryOrderV2(String orderId, String outOrderNo) throws TtPayException; | |||||
| /** | |||||
| * <pre> | |||||
| * 5. 订单信息接口 | |||||
| */ | |||||
| TtPayOrderQueryV2Result queryOrderV2(TtPayOrderQueryV2Request request) throws TtPayException; | |||||
| /** | |||||
| * <pre> | |||||
| * 5. cps订单信息接口 | |||||
| */ | |||||
| TtPayCpsOrderQueryV2Result queryCpsOrderV2(String orderId, String outOrderNo) throws TtPayException; | |||||
| /** | |||||
| * 推送核销状态(非闭环核销) | |||||
| */ | |||||
| boolean pushDelivery(TtOrderPushDeliveryRequest request) throws TtPayException; | |||||
| /** | |||||
| * 获取配置. | |||||
| * | |||||
| * @return the config | |||||
| */ | |||||
| TtPayConfig getConfig(); | |||||
| /** | |||||
| * 设置配置对象. | |||||
| * | |||||
| * @param config the config | |||||
| */ | |||||
| void setConfig(TtPayConfig config); | |||||
| /** | |||||
| * <pre> | |||||
| * 开发者可用该接口替用户发起退款,开发者发起的退款流程则不会有退款申请回调。 | |||||
| * - 过期自动退说明 | |||||
| * - 过期自动退的退款被拒绝退款后,不会再次发起。 | |||||
| * - 在交易系统2.0产生的订单,如果用户购买的商品是过期退商品,交易系统2.0会自动发起退款,创建退款单,退款流程和用户发起退款流程相同。 | |||||
| * - 发起过期自动退条件 | |||||
| * - 非POI 商品 | |||||
| * - 前端传入合法的商品过期时间 | |||||
| * - 前端传入的goodsLabels中包含过期退标签 | |||||
| * - POI 商品 | |||||
| * - POI 商品设置了过期时间 | |||||
| * - POI 商品的 sub_title包含过期退标签 | |||||
| * - 旧订单系统不会自动发起过期自动退,仍需开发者处理。 | |||||
| * - 过期自动退的退款单由系统创建,因此 退款申请回调和状态通知回调 cp_extra 会是空值。 | |||||
| * - 外部退款单号说明 | |||||
| * - 已经在担保支付或者交易1.0使用过的外部退款单号,请不要在交易2.0使用,当交易2.0系统发现该外部退款单号已经在担保支付或者交易1.0创建过退款单号时,会拒绝创建退款单。 | |||||
| * - 已经升级到交易2.0的接口之后,不支持再降级使用交易1.0,否则产生的后果由开发者承担。 | |||||
| */ | |||||
| TtPayRefundV2Result refundV2(TtPayRefundV2Request request) throws TtPayException; | |||||
| /** | |||||
| * 5. 退款申请回调 | |||||
| * 当用户从交易的模板组件发起退款后,抖音开平交易系统会给向开发者的服务发起请求,用于通知开发者用户发起退款,开发者响应时需要返回必填的信息。 | |||||
| * 注意 | |||||
| * - 退款单的创建是在退款申请回调之前,退款申请回调请求开发者服务失败,也不会在C端展示错误,退款申请回调请求失败后会进行重试。 | |||||
| * - 请务必确保退款申请回调请求能按照正确的格式和参数要求返回。 | |||||
| * - 请求返回的外部退款单号也务必确保在同一小程序内不会重复,否则也会被认为请求失败。 | |||||
| * - 开发者返回的err_no 不为 0 也会认为请求失败,会进行重试,请确保请求成功,有拒绝退款的场景请在退款审核阶段拒绝退款。 | |||||
| * - 如果一直请求开发者服务失败,退款单将无法被推进到退款审核阶段,请务必确保响应无问题。 | |||||
| * - 退款申请回调务必做好幂等处理,相同的系统退款单号重复请求应当被视为相同的一次退款。 | |||||
| * | |||||
| */ | |||||
| RefundOrderCallback refundOrderNotifyV2Result(String notifyData, SignatureHeader header) throws TtPayException; | |||||
| /** | |||||
| * 退款审核结果同步 | |||||
| * @param request | |||||
| * @return | |||||
| * @throws TtPayException | |||||
| */ | |||||
| boolean merchantAuditCallback(TtRefundAuditMsgRequest request) throws TtPayException; | |||||
| /** | |||||
| * <pre> | |||||
| * 查询退款 | |||||
| * | |||||
| */ | |||||
| TtPayRefundQueryV2Result refundQueryV2(TtPayRefundQueryV2Request request) throws TtPayException; | |||||
| /** | |||||
| * 获取微信请求数据,方便接口调用方获取处理. | |||||
| * | |||||
| * @return the wx api data | |||||
| */ | |||||
| WxPayApiData getWxApiData(); | |||||
| } | |||||
| @@ -0,0 +1,216 @@ | |||||
| package com.iformall.douyin.pay.exception; | |||||
| import com.github.binarywang.wxpay.bean.result.BaseWxPayResult; | |||||
| import com.google.common.base.Joiner; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| /** | |||||
| * <pre> | |||||
| * 支付异常结果类 | |||||
| * Created by Binary Wang on 2017-6-6. | |||||
| * </pre> | |||||
| * | |||||
| * @author BinaryWang | |||||
| */ | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = false) | |||||
| public class TtPayException extends Exception { | |||||
| private static final long serialVersionUID = -1246675502834889819L; | |||||
| /** | |||||
| * 自定义错误讯息. | |||||
| */ | |||||
| private String customErrorMsg; | |||||
| /** | |||||
| * 返回状态码. | |||||
| */ | |||||
| private String returnCode; | |||||
| /** | |||||
| * 返回信息. | |||||
| */ | |||||
| private String returnMsg; | |||||
| /** | |||||
| * 业务结果. | |||||
| */ | |||||
| private String resultCode; | |||||
| /** | |||||
| * 错误代码. | |||||
| */ | |||||
| private String errCode; | |||||
| /** | |||||
| * 错误代码描述. | |||||
| */ | |||||
| private String errCodeDes; | |||||
| /** | |||||
| * 微信支付返回的结果xml字符串. | |||||
| */ | |||||
| private String xmlString; | |||||
| /** | |||||
| * Instantiates a new Wx pay exception. | |||||
| * | |||||
| * @param customErrorMsg the custom error msg | |||||
| */ | |||||
| public TtPayException(String customErrorMsg) { | |||||
| super(customErrorMsg); | |||||
| this.customErrorMsg = customErrorMsg; | |||||
| } | |||||
| /** | |||||
| * Instantiates a new Wx pay exception. | |||||
| * | |||||
| * @param customErrorMsg the custom error msg | |||||
| * @param tr the tr | |||||
| */ | |||||
| public TtPayException(String customErrorMsg, Throwable tr) { | |||||
| super(customErrorMsg, tr); | |||||
| this.customErrorMsg = customErrorMsg; | |||||
| } | |||||
| private TtPayException(Builder builder) { | |||||
| super(builder.buildErrorMsg()); | |||||
| returnCode = builder.returnCode; | |||||
| returnMsg = builder.returnMsg; | |||||
| resultCode = builder.resultCode; | |||||
| errCode = builder.errCode; | |||||
| errCodeDes = builder.errCodeDes; | |||||
| xmlString = builder.xmlString; | |||||
| } | |||||
| /** | |||||
| * 通过BaseWxPayResult生成异常对象. | |||||
| * | |||||
| * @param payBaseResult the pay base result | |||||
| * @return the wx pay exception | |||||
| */ | |||||
| public static TtPayException from(BaseWxPayResult payBaseResult) { | |||||
| return TtPayException.newBuilder() | |||||
| .xmlString(payBaseResult.getXmlString()) | |||||
| .returnMsg(payBaseResult.getReturnMsg()) | |||||
| .returnCode(payBaseResult.getReturnCode()) | |||||
| .resultCode(payBaseResult.getResultCode()) | |||||
| .errCode(payBaseResult.getErrCode()) | |||||
| .errCodeDes(payBaseResult.getErrCodeDes()) | |||||
| .build(); | |||||
| } | |||||
| /** | |||||
| * New builder builder. | |||||
| * | |||||
| * @return the builder | |||||
| */ | |||||
| public static Builder newBuilder() { | |||||
| return new Builder(); | |||||
| } | |||||
| /** | |||||
| * The type Builder. | |||||
| */ | |||||
| public static final class Builder { | |||||
| private String returnCode; | |||||
| private String returnMsg; | |||||
| private String resultCode; | |||||
| private String errCode; | |||||
| private String errCodeDes; | |||||
| private String xmlString; | |||||
| private Builder() { | |||||
| } | |||||
| /** | |||||
| * Return code builder. | |||||
| * | |||||
| * @param returnCode the return code | |||||
| * @return the builder | |||||
| */ | |||||
| public Builder returnCode(String returnCode) { | |||||
| this.returnCode = returnCode; | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * Return msg builder. | |||||
| * | |||||
| * @param returnMsg the return msg | |||||
| * @return the builder | |||||
| */ | |||||
| public Builder returnMsg(String returnMsg) { | |||||
| this.returnMsg = returnMsg; | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * Result code builder. | |||||
| * | |||||
| * @param resultCode the result code | |||||
| * @return the builder | |||||
| */ | |||||
| public Builder resultCode(String resultCode) { | |||||
| this.resultCode = resultCode; | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * Err code builder. | |||||
| * | |||||
| * @param errCode the err code | |||||
| * @return the builder | |||||
| */ | |||||
| public Builder errCode(String errCode) { | |||||
| this.errCode = errCode; | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * Err code des builder. | |||||
| * | |||||
| * @param errCodeDes the err code des | |||||
| * @return the builder | |||||
| */ | |||||
| public Builder errCodeDes(String errCodeDes) { | |||||
| this.errCodeDes = errCodeDes; | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * Xml string builder. | |||||
| * | |||||
| * @param xmlString the xml string | |||||
| * @return the builder | |||||
| */ | |||||
| public Builder xmlString(String xmlString) { | |||||
| this.xmlString = xmlString; | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * Build wx pay exception. | |||||
| * | |||||
| * @return the wx pay exception | |||||
| */ | |||||
| public TtPayException build() { | |||||
| return new TtPayException(this); | |||||
| } | |||||
| /** | |||||
| * Build error msg string. | |||||
| * | |||||
| * @return the string | |||||
| */ | |||||
| public String buildErrorMsg() { | |||||
| return Joiner.on(",").skipNulls().join( | |||||
| returnCode == null ? null : String.format("返回代码:[%s]", returnCode), | |||||
| returnMsg == null ? null : String.format("返回信息:[%s]", returnMsg), | |||||
| resultCode == null ? null : String.format("结果代码:[%s]", resultCode), | |||||
| errCode == null ? null : String.format("错误代码:[%s]", errCode), | |||||
| errCodeDes == null ? null : String.format("错误详情:[%s]", errCodeDes), | |||||
| xmlString == null ? null : "返回的原始报文:\n" + xmlString | |||||
| ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,255 @@ | |||||
| package com.iformall.douyin.pay.impl; | |||||
| import com.alibaba.fastjson.TypeReference; | |||||
| import com.github.binarywang.wxpay.bean.WxPayApiData; | |||||
| import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||||
| import com.github.binarywang.wxpay.exception.WxPayException; | |||||
| import com.github.binarywang.wxpay.v3.util.AesUtils; | |||||
| import com.google.gson.Gson; | |||||
| import com.google.gson.GsonBuilder; | |||||
| import com.iformall.douyin.pay.ProfitSharingV2Service; | |||||
| import com.iformall.douyin.pay.TtPayService; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import com.iformall.douyin.payv2.config.TtPayConfig; | |||||
| import com.iformall.douyin.payv2.request.*; | |||||
| import com.iformall.douyin.payv2.result.*; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import java.io.IOException; | |||||
| import java.nio.charset.StandardCharsets; | |||||
| import java.security.GeneralSecurityException; | |||||
| import java.util.*; | |||||
| /** | |||||
| * <pre> | |||||
| * 支付接口请求抽象实现类 | |||||
| * Created by Binary Wang on 2017-7-8. | |||||
| * </pre> | |||||
| * | |||||
| * @author <a href="https://github.com/binarywang">Binary Wang</a> | |||||
| */ | |||||
| public abstract class BaseTtPayServiceImpl implements TtPayService { | |||||
| private static final String TOTAL_FUND_COUNT = "资金流水总笔数"; | |||||
| /** | |||||
| * The Log. | |||||
| */ | |||||
| final Logger log = LoggerFactory.getLogger(this.getClass()); | |||||
| private static final Gson GSON = new GsonBuilder().create(); | |||||
| /** | |||||
| * The constant wxApiData. | |||||
| */ | |||||
| static ThreadLocal<WxPayApiData> wxApiData = new ThreadLocal<>(); | |||||
| private ProfitSharingV2Service profitSharingV2Service = new ProfitSharingV2ServiceImpl(this); | |||||
| /** | |||||
| * The Config. | |||||
| */ | |||||
| protected TtPayConfig config; | |||||
| @Override | |||||
| public ProfitSharingV2Service getProfitSharingV2Service() { | |||||
| return profitSharingV2Service; | |||||
| } | |||||
| @Override | |||||
| public TtPayConfig getConfig() { | |||||
| return this.config; | |||||
| } | |||||
| @Override | |||||
| public void setConfig(TtPayConfig config) { | |||||
| this.config = config; | |||||
| } | |||||
| @Override | |||||
| public String getPayBaseUrl() { | |||||
| return this.getConfig().getPayBaseUrl(); | |||||
| } | |||||
| @Override | |||||
| public boolean callbackSettings(CallBackSettingsRequest request) throws TtPayException { | |||||
| String url = String.format("%s/api/apps/trade/v2/settings", this.getPayBaseUrl()); | |||||
| String response = this.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult baseTtPayResult = GSON.fromJson(response, BaseTtPayResult.class); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return true; | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public CallBackSettingsRequest querySettings() throws TtPayException { | |||||
| String url = String.format("%s/api/apps/trade/v2/query_settings", this.getPayBaseUrl()); | |||||
| String response = this.postV2(url,""); | |||||
| BaseTtPayResult<CallBackSettingsRequest> baseTtPayResult = GSON.fromJson(response, | |||||
| new TypeReference<BaseTtPayResult<CallBackSettingsRequest>>(){}.getType()); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return baseTtPayResult.getData(); | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public CreateOrderCallback parseOrderNotifyV2Result(String notifyData, SignatureHeader header) throws TtPayException { | |||||
| if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) { | |||||
| throw new TtPayException("非法请求,头部信息验证失败"); | |||||
| } | |||||
| OriginNotifyResponse response = GSON.fromJson(notifyData, OriginNotifyResponse.class); | |||||
| try { | |||||
| CreateOrderCallback createOrderCallback = GSON.fromJson(response.getMsg(), CreateOrderCallback.class); | |||||
| return createOrderCallback; | |||||
| } catch (Exception e) { | |||||
| throw new TtPayException("解析报文异常!", e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 校验通知签名 | |||||
| * | |||||
| * @param header 通知头信息 | |||||
| * @param data 通知数据 | |||||
| * @return true:校验通过 false:校验不通过 | |||||
| */ | |||||
| private boolean verifyNotifySign(SignatureHeader header, String data) { | |||||
| String beforeSign = String.format("%s\n%s\n%s\n", | |||||
| header.getTimeStamp(), | |||||
| header.getNonce(), | |||||
| data); | |||||
| return this.getConfig().getVerifier().verify( | |||||
| beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned()); | |||||
| } | |||||
| @Override | |||||
| public TtPayUnifiedOrderV2Result createOrderV2(TtPayUnifiedOrderV2Request request) throws TtPayException{ | |||||
| String url = String.format("%s/api/apps/trade/v2/create_order", this.getPayBaseUrl()); | |||||
| String response = this.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult<TtPayUnifiedOrderV2Result> baseTtPayResult = GSON.fromJson(response, | |||||
| new TypeReference<BaseTtPayResult<TtPayUnifiedOrderV2Result>>(){}.getType()); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return baseTtPayResult.getData(); | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public TtPayOrderQueryV2Result queryOrderV2(String orderId, String outOrderNo) throws TtPayException { | |||||
| TtPayOrderQueryV2Request request = new TtPayOrderQueryV2Request(); | |||||
| request.setOutOrderNo(StringUtils.trimToNull(outOrderNo)); | |||||
| request.setOrderId(StringUtils.trimToNull(orderId)); | |||||
| return this.queryOrderV2(request); | |||||
| } | |||||
| @Override | |||||
| public TtPayOrderQueryV2Result queryOrderV2(TtPayOrderQueryV2Request request) throws TtPayException { | |||||
| String url = String.format("%s/api/apps/trade/v2/query_order", this.getPayBaseUrl()); | |||||
| String response = this.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult<TtPayOrderQueryV2Result> baseTtPayResult = GSON.fromJson(response, | |||||
| new TypeReference<BaseTtPayResult<TtPayOrderQueryV2Result>>(){}.getType()); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return baseTtPayResult.getData(); | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| public TtPayCpsOrderQueryV2Result queryCpsOrderV2(String orderId, String outOrderNo) throws TtPayException{ | |||||
| String url = String.format("%s/api/apps/trade/v2/query_cps", this.getPayBaseUrl()); | |||||
| TtPayOrderQueryV2Request request = new TtPayOrderQueryV2Request(); | |||||
| request.setOutOrderNo(StringUtils.trimToNull(outOrderNo)); | |||||
| request.setOrderId(StringUtils.trimToNull(orderId)); | |||||
| String response = this.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult<TtPayCpsOrderQueryV2Result> baseTtPayResult = GSON.fromJson(response, | |||||
| new TypeReference<BaseTtPayResult<TtPayCpsOrderQueryV2Result>>(){}.getType()); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return baseTtPayResult.getData(); | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public boolean pushDelivery(TtOrderPushDeliveryRequest request) throws TtPayException{ | |||||
| String url = String.format("%s/api/apps/trade/v2/push_delivery", this.getPayBaseUrl()); | |||||
| String response = this.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult baseTtPayResult = GSON.fromJson(response, BaseTtPayResult.class); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return true; | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public TtPayRefundV2Result refundV2(TtPayRefundV2Request request) throws TtPayException { | |||||
| String url = String.format("%s/api/apps/trade/v2/create_refund", this.getPayBaseUrl()); | |||||
| String response = this.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult<TtPayRefundV2Result> baseTtPayResult = GSON.fromJson(response, | |||||
| new TypeReference<BaseTtPayResult<TtPayRefundV2Result>>(){}.getType()); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return baseTtPayResult.getData(); | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public RefundOrderCallback refundOrderNotifyV2Result(String notifyData, SignatureHeader header) throws TtPayException { | |||||
| if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) { | |||||
| throw new TtPayException("非法请求,头部信息验证失败"); | |||||
| } | |||||
| OriginNotifyResponse response = GSON.fromJson(notifyData, OriginNotifyResponse.class); | |||||
| try { | |||||
| RefundOrderCallback refundOrderCallback = GSON.fromJson(response.getMsg(), RefundOrderCallback.class); | |||||
| return refundOrderCallback; | |||||
| } catch (Exception e) { | |||||
| throw new TtPayException("解析报文异常!", e); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public boolean merchantAuditCallback(TtRefundAuditMsgRequest request) throws TtPayException{ | |||||
| String url = String.format("%s/api/apps/trade/v2/merchant_audit_callback", this.getPayBaseUrl()); | |||||
| String response = this.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult baseTtPayResult = GSON.fromJson(response, BaseTtPayResult.class); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return true; | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public TtPayRefundQueryV2Result refundQueryV2(TtPayRefundQueryV2Request request) throws TtPayException{ | |||||
| String url = String.format("%s/api/apps/trade/v2/query_refund", this.getPayBaseUrl()); | |||||
| String response = this.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult<TtPayRefundQueryV2Result> baseTtPayResult = GSON.fromJson(response, | |||||
| new TypeReference<BaseTtPayResult<TtPayRefundQueryV2Result>>(){}.getType()); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| return baseTtPayResult.getData(); | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public WxPayApiData getWxApiData() { | |||||
| try { | |||||
| return wxApiData.get(); | |||||
| } finally { | |||||
| //一般来说,接口请求会在一个线程内进行,这种情况下,每个线程get的会是之前所存入的数据, | |||||
| // 但以防万一有同一线程多次请求的问题,所以每次获取完数据后移除对应数据 | |||||
| wxApiData.remove(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,76 @@ | |||||
| package com.iformall.douyin.pay.impl; | |||||
| import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||||
| import com.google.gson.Gson; | |||||
| import com.google.gson.GsonBuilder; | |||||
| import com.google.gson.JsonObject; | |||||
| import com.iformall.douyin.pay.ProfitSharingV2Service; | |||||
| import com.iformall.douyin.pay.TtPayService; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import com.iformall.douyin.payv2.auth.Verifier; | |||||
| import com.iformall.douyin.payv2.request.ProfitSharingRequest; | |||||
| import com.iformall.douyin.payv2.result.BaseTtPayResult; | |||||
| import com.iformall.douyin.payv2.result.ProfitSharingResult; | |||||
| import lombok.RequiredArgsConstructor; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||||
| import java.nio.charset.StandardCharsets; | |||||
| /** | |||||
| * 支付V2-资金应用-分账Service | |||||
| * | |||||
| * @author pg 2021-6-23 | |||||
| * @version 1.0 | |||||
| */ | |||||
| @Slf4j | |||||
| @RequiredArgsConstructor | |||||
| public class ProfitSharingV2ServiceImpl implements ProfitSharingV2Service { | |||||
| private static final Gson GSON = new GsonBuilder().create(); | |||||
| private final TtPayService payService; | |||||
| @Override | |||||
| public String profitSharing(ProfitSharingRequest request) throws TtPayException { | |||||
| String url = String.format("%s/api/apps/trade/v2/create_settle", this.payService.getPayBaseUrl()); | |||||
| String result = this.payService.postV2(url, GSON.toJson(request)); | |||||
| BaseTtPayResult baseTtPayResult = GSON.fromJson(result, BaseTtPayResult.class); | |||||
| if(baseTtPayResult.isSuccess()){ | |||||
| Object data = baseTtPayResult.getData(); | |||||
| JsonObject asJsonObject = GSON.toJsonTree(data).getAsJsonObject(); | |||||
| return GsonHelper.getString(asJsonObject,"settle_id"); | |||||
| }else{ | |||||
| throw new TtPayException(baseTtPayResult.getErrTips()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public ProfitSharingResult getProfitSharingResult(String out_settle_no) throws TtPayException { | |||||
| String url = String.format("%s/api/apps/trade/v2/query_settle", this.payService.getPayBaseUrl()); | |||||
| JsonObject jsonObject = new JsonObject(); | |||||
| jsonObject.addProperty("out_settle_no",out_settle_no); | |||||
| String result = this.payService.postV2(url,jsonObject.toString()); | |||||
| return GSON.fromJson(result, ProfitSharingResult.class); | |||||
| } | |||||
| /** | |||||
| * 校验通知签名 | |||||
| * | |||||
| * @param header 通知头信息 | |||||
| * @param data 通知数据 | |||||
| * @return true:校验通过 false:校验不通过 | |||||
| */ | |||||
| private boolean verifyNotifySign(SignatureHeader header, String data) throws TtPayException { | |||||
| String beforeSign = String.format("%s\n%s\n%s\n", | |||||
| header.getTimeStamp(), | |||||
| header.getNonce(), | |||||
| data); | |||||
| Verifier verifier = this.payService.getConfig().getVerifier(); | |||||
| if (verifier == null) { | |||||
| throw new TtPayException("检验对象为空"); | |||||
| } | |||||
| return verifier.verify( | |||||
| beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,155 @@ | |||||
| package com.iformall.douyin.pay.impl; | |||||
| import com.google.gson.JsonElement; | |||||
| import com.google.gson.JsonObject; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import me.chanjar.weixin.common.util.json.GsonParser; | |||||
| import org.apache.http.HttpStatus; | |||||
| import org.apache.http.client.config.RequestConfig; | |||||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||||
| import org.apache.http.client.methods.HttpGet; | |||||
| import org.apache.http.client.methods.HttpPost; | |||||
| import org.apache.http.client.methods.HttpRequestBase; | |||||
| import org.apache.http.entity.StringEntity; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | |||||
| import org.apache.http.util.EntityUtils; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.nio.charset.StandardCharsets; | |||||
| /** | |||||
| * <pre> | |||||
| * 支付请求实现类,apache httpclient实现. | |||||
| * Created by Binary Wang on 2016/7/28. | |||||
| * </pre> | |||||
| * | |||||
| */ | |||||
| public class TtPayServiceApacheHttpImpl extends BaseTtPayServiceImpl { | |||||
| @Override | |||||
| public String postV2(String url, String requestStr) throws TtPayException { | |||||
| CloseableHttpClient httpClient = this.createApiV2HttpClient(); | |||||
| HttpPost httpPost = this.createHttpPost(url, requestStr); | |||||
| httpPost.addHeader("Accept", "application/json"); | |||||
| httpPost.addHeader("Content-Type", "application/json"); | |||||
| try (CloseableHttpResponse response = httpClient.execute(httpPost)) { | |||||
| //v3已经改为通过状态码判断200 204 成功 | |||||
| int statusCode = response.getStatusLine().getStatusCode(); | |||||
| //post方法有可能会没有返回值的情况 | |||||
| String responseString; | |||||
| if (response.getEntity() == null) { | |||||
| responseString = null; | |||||
| } else { | |||||
| responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); | |||||
| } | |||||
| if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) { | |||||
| this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); | |||||
| return responseString; | |||||
| } else { | |||||
| //有错误提示信息返回 | |||||
| JsonObject jsonObject = GsonParser.parse(responseString); | |||||
| throw convertException(jsonObject); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); | |||||
| throw (e instanceof TtPayException) ? (TtPayException) e : new TtPayException(e.getMessage(), e); | |||||
| } finally { | |||||
| httpPost.releaseConnection(); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public String postV2(String url, HttpPost httpPost) throws TtPayException { | |||||
| return this.requestV2(url, httpPost); | |||||
| } | |||||
| @Override | |||||
| public String requestV2(String url, HttpRequestBase httpRequest) throws TtPayException { | |||||
| httpRequest.setConfig(RequestConfig.custom() | |||||
| .setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout()) | |||||
| .setConnectTimeout(this.getConfig().getHttpConnectionTimeout()) | |||||
| .setSocketTimeout(this.getConfig().getHttpTimeout()) | |||||
| .build()); | |||||
| CloseableHttpClient httpClient = this.createApiV2HttpClient(); | |||||
| try (CloseableHttpResponse response = httpClient.execute(httpRequest)) { | |||||
| //v3已经改为通过状态码判断200 204 成功 | |||||
| int statusCode = response.getStatusLine().getStatusCode(); | |||||
| //post方法有可能会没有返回值的情况 | |||||
| String responseString; | |||||
| if (response.getEntity() == null) { | |||||
| responseString = null; | |||||
| } else { | |||||
| responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); | |||||
| } | |||||
| if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) { | |||||
| this.log.info("\n【请求地址】:{}\n【响应数据】:{}", url, responseString); | |||||
| return responseString; | |||||
| } else { | |||||
| //有错误提示信息返回 | |||||
| JsonObject jsonObject = GsonParser.parse(responseString); | |||||
| throw convertException(jsonObject); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| this.log.error("\n【请求地址】:{}\n【异常信息】:{}", url, e.getMessage()); | |||||
| throw (e instanceof TtPayException) ? (TtPayException) e : new TtPayException(e.getMessage(), e); | |||||
| } finally { | |||||
| httpRequest.releaseConnection(); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public String getV2(String url) throws TtPayException { | |||||
| HttpGet httpGet = new HttpGet(url); | |||||
| httpGet.addHeader("Accept", "application/json"); | |||||
| httpGet.addHeader("Content-Type", "application/json"); | |||||
| return this.requestV2(url.toString(), httpGet); | |||||
| } | |||||
| private CloseableHttpClient createApiV2HttpClient() throws TtPayException { | |||||
| CloseableHttpClient apiV3HttpClient = this.getConfig().getApiV2HttpClient(); | |||||
| if (null == apiV3HttpClient) { | |||||
| return this.getConfig().initApiV2HttpClient(); | |||||
| } | |||||
| return apiV3HttpClient; | |||||
| } | |||||
| private StringEntity createEntry(String requestStr) { | |||||
| try { | |||||
| return new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| //cannot happen | |||||
| this.log.error(e.getMessage(), e); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| private HttpPost createHttpPost(String url, String requestStr) { | |||||
| HttpPost httpPost = new HttpPost(url); | |||||
| httpPost.setEntity(this.createEntry(requestStr)); | |||||
| httpPost.setConfig(RequestConfig.custom() | |||||
| .setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout()) | |||||
| .setConnectTimeout(this.getConfig().getHttpConnectionTimeout()) | |||||
| .setSocketTimeout(this.getConfig().getHttpTimeout()) | |||||
| .build()); | |||||
| return httpPost; | |||||
| } | |||||
| private TtPayException convertException(JsonObject jsonObject) { | |||||
| //todo 这里考虑使用新的适用于V2的异常 | |||||
| JsonElement codeElement = jsonObject.get("code"); | |||||
| String code = codeElement == null ? null : codeElement.getAsString(); | |||||
| String message = jsonObject.get("message").getAsString(); | |||||
| TtPayException ttPayException = new TtPayException(message); | |||||
| ttPayException.setErrCode(code); | |||||
| ttPayException.setErrCodeDes(message); | |||||
| return ttPayException; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,11 @@ | |||||
| package com.iformall.douyin.pay.impl; | |||||
| /** | |||||
| * <pre> | |||||
| * 支付接口请求实现类,默认使用Apache HttpClient实现 | |||||
| * Created by Binary Wang on 2017-7-8. | |||||
| * </pre> | |||||
| * | |||||
| */ | |||||
| public class TtPayServiceImpl extends TtPayServiceApacheHttpImpl { | |||||
| } | |||||
| @@ -0,0 +1,72 @@ | |||||
| package com.iformall.douyin.payv2.auth; | |||||
| import com.iformall.douyin.payv2.util.PemUtils; | |||||
| import me.chanjar.weixin.common.error.WxRuntimeException; | |||||
| import java.io.ByteArrayInputStream; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.nio.charset.StandardCharsets; | |||||
| import java.security.*; | |||||
| import java.util.Base64; | |||||
| public class CertificatesVerifier implements Verifier { | |||||
| private PublicKey apiKey; | |||||
| public CertificatesVerifier(PublicKey apiKey) { | |||||
| this.apiKey = apiKey; | |||||
| } | |||||
| @Override | |||||
| public boolean verify(byte[] message, String signature) { | |||||
| try { | |||||
| Signature sign = Signature.getInstance("SHA256withRSA"); | |||||
| sign.initVerify(this.apiKey); | |||||
| sign.update(message); | |||||
| return sign.verify(Base64.getDecoder().decode(signature.getBytes(StandardCharsets.UTF_8))); | |||||
| } catch (NoSuchAlgorithmException e) { | |||||
| throw new WxRuntimeException("当前Java环境不支持SHA256withRSA", e); | |||||
| } catch (SignatureException e) { | |||||
| throw new WxRuntimeException("签名验证过程发生了错误", e); | |||||
| } catch (InvalidKeyException e) { | |||||
| throw new WxRuntimeException("无效的证书", e); | |||||
| } | |||||
| } | |||||
| // public static void main(String[] args) { | |||||
| // String pubKey = "-----BEGIN PUBLIC KEY-----\n" + | |||||
| // "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv8jSFriZ6l5vv0xVcpFJ\n" + | |||||
| // "NxihPh3j6tVKrU2FBythCstyr/CwdpAp9AGXvcaW2x2kKiOMXXaRDo6OysjggsxK\n" + | |||||
| // "5hh1fWDE3ML4Wi5tfAV64pvj8wn5XeHXGKtXcKD/ASQmUGnMKI0g8i2REm3Q7gzy\n" + | |||||
| // "JH35URh+tU8wI2v8mDY9OCZ7Hmu8ImW3pibyYRYK0CEpa31+65gVaTeoaPlqTKR0\n" + | |||||
| // "rwgxZM5nFcXxGtiTsH0O1GAJBqWpyVeOqH19vEVB/bROEb21bf65ZYhac2Z1lzWq\n" + | |||||
| // "MW+/4knIDg6EH3/xZWFPPwAFZgpfkSQES/twPkN/59cZ8SfTwJ84k/KUOApvkihM\n" + | |||||
| // "uQIDAQAB\n" + | |||||
| // "-----END PUBLIC KEY-----"; | |||||
| // String timestamp = "1653906762"; | |||||
| // String nonce = "pztVmu9EhPgCv9Dvw31t68U9WhMcLXCb"; | |||||
| // String httpBody = "{\"err_no\":0,\"data\":{\"create_order_callback\":\"https://ctest.malls.iformall.com/C/api/order/douyinPushOrder\",\"refund_callback\":\"https://ctest.malls.iformall.com/C/api/order/douyinRefundOrder\",\"delivery_qrcode_redirect\":\"\"},\"resp_extra\":{\"logid\":\"202205301832420101581160381B3C09C0\"},\"err_tips\":\"success\"}"; | |||||
| // String signStr = "pZEQga7EpGI+NXEznLNZROViIBxwWaofnlstthQsu8MZiuTRUtool2SQhfLHkXwYzj5O8yj+luTbFUrhTfX+BzvcR3+fGrqMtgqGWp86a1hAg4e4pvoTHd5PAxUGRDb/gGxPoxLDgrS6cLKusdGi6mmwJbERveD9ThNV1RQGQo/BM3BeImr3fYdJ/ZU67iVkP6SEWkqRiEJhnQMaavy/B4LK3xI0A5BhWlGbhGUIqumLT903tIOhofXGA6PQJbDiU38J5EtMj/Z7l6+IXtbA/KO0IWbIZ96KFs6e8ZE6H18Xn7b0J7KDTjTelMt7iXczrLU2/e3QEcfn2/7+7DIRMQ=="; | |||||
| // | |||||
| // StringBuffer buffer = new StringBuffer(); | |||||
| // buffer.append(timestamp).append("\n"); | |||||
| // buffer.append(nonce).append("\n"); | |||||
| // buffer.append(httpBody).append("\n"); | |||||
| // try { | |||||
| // Signature sign = Signature.getInstance("SHA256withRSA"); | |||||
| // sign.initVerify(PemUtils.loadPublicKey(new ByteArrayInputStream(pubKey.getBytes("utf-8")))); | |||||
| // sign.update(buffer.toString().getBytes(StandardCharsets.UTF_8)); | |||||
| // boolean verify = sign.verify(Base64.getDecoder().decode(signStr.getBytes(StandardCharsets.UTF_8))); | |||||
| // System.out.println("-------"+verify); | |||||
| // } catch (NoSuchAlgorithmException e) { | |||||
| // e.printStackTrace(); | |||||
| // } catch (UnsupportedEncodingException e) { | |||||
| // e.printStackTrace(); | |||||
| // } catch (SignatureException e) { | |||||
| // e.printStackTrace(); | |||||
| // } catch (InvalidKeyException e) { | |||||
| // e.printStackTrace(); | |||||
| // } | |||||
| // } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| package com.iformall.douyin.payv2.auth; | |||||
| import me.chanjar.weixin.common.error.WxRuntimeException; | |||||
| import java.security.*; | |||||
| import java.util.Base64; | |||||
| public class PrivateKeySigner implements Signer { | |||||
| private String certificateSerialNumber; | |||||
| private PrivateKey privateKey; | |||||
| public PrivateKeySigner(String serialNumber, PrivateKey privateKey) { | |||||
| this.certificateSerialNumber = serialNumber; | |||||
| this.privateKey = privateKey; | |||||
| } | |||||
| @Override | |||||
| public SignatureResult sign(byte[] message) { | |||||
| try { | |||||
| Signature sign = Signature.getInstance("SHA256withRSA"); | |||||
| sign.initSign(privateKey); | |||||
| sign.update(message); | |||||
| return new SignatureResult( | |||||
| Base64.getEncoder().encodeToString(sign.sign()), certificateSerialNumber); | |||||
| } catch (NoSuchAlgorithmException e) { | |||||
| throw new WxRuntimeException("当前Java环境不支持SHA256withRSA", e); | |||||
| } catch (SignatureException e) { | |||||
| throw new WxRuntimeException("签名计算失败", e); | |||||
| } catch (InvalidKeyException e) { | |||||
| throw new WxRuntimeException("无效的私钥", e); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| package com.iformall.douyin.payv2.auth; | |||||
| public interface Signer { | |||||
| SignatureResult sign(byte[] message); | |||||
| class SignatureResult { | |||||
| String sign; | |||||
| String certificateSerialNumber; | |||||
| public SignatureResult(String sign, String serialNumber) { | |||||
| this.sign = sign; | |||||
| this.certificateSerialNumber = serialNumber; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,91 @@ | |||||
| package com.iformall.douyin.payv2.auth; | |||||
| import com.iformall.douyin.payv2.util.Credentials; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.http.HttpEntityEnclosingRequest; | |||||
| import org.apache.http.client.methods.HttpRequestWrapper; | |||||
| import org.apache.http.util.EntityUtils; | |||||
| import java.io.IOException; | |||||
| import java.net.URI; | |||||
| import java.nio.charset.StandardCharsets; | |||||
| import java.security.SecureRandom; | |||||
| @Slf4j | |||||
| public class TtPayCredentials implements Credentials { | |||||
| private static final String SYMBOLS = | |||||
| "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |||||
| private static final SecureRandom RANDOM = new SecureRandom(); | |||||
| protected String appId; | |||||
| protected Signer signer; | |||||
| public TtPayCredentials(String appId, Signer signer) { | |||||
| this.appId = appId; | |||||
| this.signer = signer; | |||||
| } | |||||
| public String getAppId() { | |||||
| return appId; | |||||
| } | |||||
| protected long generateTimestamp() { | |||||
| return System.currentTimeMillis() / 1000; | |||||
| } | |||||
| protected String generateNonceStr() { | |||||
| char[] nonceChars = new char[32]; | |||||
| for (int index = 0; index < nonceChars.length; ++index) { | |||||
| nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); | |||||
| } | |||||
| return new String(nonceChars); | |||||
| } | |||||
| @Override | |||||
| public final String getSchema() { | |||||
| return "SHA256-RSA2048"; | |||||
| } | |||||
| @Override | |||||
| public final String getToken(HttpRequestWrapper request) throws IOException { | |||||
| String nonceStr = generateNonceStr(); | |||||
| long timestamp = generateTimestamp(); | |||||
| String message = buildMessage(nonceStr, timestamp, request); | |||||
| log.info("authorization message=[{}]", message); | |||||
| // System.out.println("message---------------------------"+message); | |||||
| Signer.SignatureResult signature = signer.sign(message.getBytes(StandardCharsets.UTF_8)); | |||||
| String token = "appid=\"" + getAppId() + "\"," | |||||
| + "nonce_str=\"" + nonceStr + "\"," | |||||
| + "timestamp=\"" + timestamp + "\"," | |||||
| + "key_version=\"" + signature.certificateSerialNumber + "\"," | |||||
| + "signature=\"" + signature.sign + "\""; | |||||
| log.info("authorization token=[{}]", token); | |||||
| // System.out.println("token---------------------------"+token); | |||||
| return token; | |||||
| } | |||||
| protected final String buildMessage(String nonce, long timestamp, HttpRequestWrapper request) | |||||
| throws IOException { | |||||
| URI uri = request.getURI(); | |||||
| String canonicalUrl = uri.getRawPath(); | |||||
| if (uri.getQuery() != null) { | |||||
| canonicalUrl += "?" + uri.getRawQuery(); | |||||
| } | |||||
| String body = ""; | |||||
| // PATCH,POST,PUT | |||||
| body = EntityUtils.toString(((HttpEntityEnclosingRequest) request).getEntity(),StandardCharsets.UTF_8); | |||||
| return request.getRequestLine().getMethod() + "\n" | |||||
| + canonicalUrl + "\n" | |||||
| + timestamp + "\n" | |||||
| + nonce + "\n" | |||||
| + body + "\n"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,55 @@ | |||||
| package com.iformall.douyin.payv2.auth; | |||||
| import com.iformall.douyin.payv2.util.Validator; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.http.Header; | |||||
| import org.apache.http.HttpEntity; | |||||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||||
| import org.apache.http.entity.ContentType; | |||||
| import org.apache.http.util.EntityUtils; | |||||
| import java.io.IOException; | |||||
| @Slf4j | |||||
| public class TtPayValidator implements Validator { | |||||
| private Verifier verifier; | |||||
| public TtPayValidator(Verifier verifier) { | |||||
| this.verifier = verifier; | |||||
| } | |||||
| @Override | |||||
| public final boolean validate(CloseableHttpResponse response) throws IOException { | |||||
| if (!ContentType.APPLICATION_JSON.getMimeType().equals(ContentType.parse(String.valueOf(response.getFirstHeader("Content-Type").getValue())).getMimeType())) { | |||||
| return true; | |||||
| } | |||||
| Header sign = response.getFirstHeader("Byte-Signature"); | |||||
| Header timestamp = response.getFirstHeader("Byte-Timestamp"); | |||||
| Header nonce = response.getFirstHeader("Byte-Nonce-Str"); | |||||
| // todo: check timestamp | |||||
| if (timestamp == null || nonce == null || sign == null) { | |||||
| return false; | |||||
| } | |||||
| String message = buildMessage(response); | |||||
| return verifier.verify(message.getBytes("utf-8"), sign.getValue()); | |||||
| } | |||||
| protected final String buildMessage(CloseableHttpResponse response) throws IOException { | |||||
| String timestamp = response.getFirstHeader("Byte-Timestamp").getValue(); | |||||
| String nonce = response.getFirstHeader("Byte-Nonce-Str").getValue(); | |||||
| String body = getResponseBody(response); | |||||
| return timestamp + "\n" | |||||
| + nonce + "\n" | |||||
| + body + "\n"; | |||||
| } | |||||
| protected final String getResponseBody(CloseableHttpResponse response) throws IOException { | |||||
| HttpEntity entity = response.getEntity(); | |||||
| return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : ""; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,6 @@ | |||||
| package com.iformall.douyin.payv2.auth; | |||||
| public interface Verifier { | |||||
| boolean verify(byte[] message, String signature); | |||||
| } | |||||
| @@ -0,0 +1,179 @@ | |||||
| package com.iformall.douyin.payv2.config; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import com.iformall.douyin.payv2.auth.CertificatesVerifier; | |||||
| import com.iformall.douyin.payv2.auth.TtPayValidator; | |||||
| import com.iformall.douyin.payv2.auth.Verifier; | |||||
| import com.iformall.douyin.payv2.util.PemUtils; | |||||
| import com.iformall.douyin.payv2.util.TtPayV2HttpClientBuilder; | |||||
| import jodd.util.ResourcesUtil; | |||||
| import lombok.Data; | |||||
| import lombok.SneakyThrows; | |||||
| import org.apache.commons.lang3.RegExUtils; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | |||||
| import java.io.*; | |||||
| import java.net.URL; | |||||
| import java.security.PrivateKey; | |||||
| import java.security.PublicKey; | |||||
| /** | |||||
| * 支付配置 | |||||
| * | |||||
| * @author Binary Wang | |||||
| */ | |||||
| @Data | |||||
| public class TtPayConfig { | |||||
| private static final String DEFAULT_PAY_BASE_URL = "https://developer.toutiao.com"; | |||||
| private static final String PROBLEM_MSG = "证书文件【%s】有问题,请核实!"; | |||||
| private static final String NOT_FOUND_MSG = "证书文件【%s】不存在,请核实!"; | |||||
| /** | |||||
| * 支付接口请求地址域名部分. | |||||
| */ | |||||
| private String payBaseUrl = DEFAULT_PAY_BASE_URL; | |||||
| /** | |||||
| * http请求连接超时时间. | |||||
| */ | |||||
| private int httpConnectionTimeout = 5000; | |||||
| /** | |||||
| * http请求数据读取等待时间. | |||||
| */ | |||||
| private int httpTimeout = 10000; | |||||
| /** | |||||
| * appid. | |||||
| */ | |||||
| private String appId; | |||||
| /** | |||||
| * apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径. | |||||
| */ | |||||
| private String privateKeyPath; | |||||
| /** | |||||
| * api 秘钥值. | |||||
| */ | |||||
| private String apiKey; | |||||
| private Verifier verifier; | |||||
| @SneakyThrows | |||||
| public Verifier getVerifier() { | |||||
| if (verifier == null) { | |||||
| //当改对象为null时,初始化api v3的请求头 | |||||
| initApiV2HttpClient(); | |||||
| } | |||||
| return verifier; | |||||
| } | |||||
| /** | |||||
| * apiV2 证书序列号值 | |||||
| */ | |||||
| private String certSerialNo; | |||||
| private CloseableHttpClient apiV2HttpClient; | |||||
| /** | |||||
| * 私钥信息 | |||||
| */ | |||||
| private PrivateKey privateKey; | |||||
| /** | |||||
| * 返回所设置的微信支付接口请求地址域名. | |||||
| * | |||||
| * @return 微信支付接口请求地址域名 | |||||
| */ | |||||
| public String getPayBaseUrl() { | |||||
| if (StringUtils.isEmpty(this.payBaseUrl)) { | |||||
| return DEFAULT_PAY_BASE_URL; | |||||
| } | |||||
| return this.payBaseUrl; | |||||
| } | |||||
| /** | |||||
| * 初始化api v2请求头 自动签名验签 | |||||
| * | |||||
| * @return org.apache.http.impl.client.CloseableHttpClient | |||||
| * @author doger.wang | |||||
| **/ | |||||
| public CloseableHttpClient initApiV2HttpClient() throws TtPayException { | |||||
| String privateKeyPath = this.getPrivateKeyPath(); | |||||
| String apiKey = this.getApiKey(); | |||||
| if (StringUtils.isBlank(privateKeyPath)) { | |||||
| throw new TtPayException("请确保privateKeyPath已设置"); | |||||
| } | |||||
| if (StringUtils.isBlank(apiKey)) { | |||||
| throw new TtPayException("请确保apiKey值已设置"); | |||||
| } | |||||
| InputStream keyInputStream = this.loadConfigInputStream(privateKeyPath); | |||||
| try { | |||||
| PrivateKey privateKey = PemUtils.loadPrivateKey(keyInputStream); | |||||
| PublicKey publicKey = PemUtils.loadPublicKey(new ByteArrayInputStream(apiKey.getBytes("utf-8"))); | |||||
| CertificatesVerifier certificatesVerifier = new CertificatesVerifier(publicKey); | |||||
| CloseableHttpClient httpClient = TtPayV2HttpClientBuilder.create() | |||||
| .withAppId(appId, certSerialNo, privateKey) | |||||
| .withValidator(new TtPayValidator(certificatesVerifier)) | |||||
| .build(); | |||||
| this.apiV2HttpClient = httpClient; | |||||
| this.privateKey = privateKey; | |||||
| this.verifier = certificatesVerifier; | |||||
| return httpClient; | |||||
| } catch (Exception e) { | |||||
| throw new TtPayException("v2请求构造异常!", e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 从配置路径 加载配置 信息(支持 classpath、本地路径、网络url) | |||||
| * @param configPath 配置路径 | |||||
| * @return | |||||
| * @throws TtPayException | |||||
| */ | |||||
| private InputStream loadConfigInputStream(String configPath) throws TtPayException { | |||||
| InputStream inputStream; | |||||
| final String prefix = "classpath:"; | |||||
| String fileHasProblemMsg = String.format(PROBLEM_MSG, configPath); | |||||
| String fileNotFoundMsg = String.format(NOT_FOUND_MSG, configPath); | |||||
| if (configPath.startsWith(prefix)) { | |||||
| String path = RegExUtils.removeFirst(configPath, prefix); | |||||
| if (!path.startsWith("/")) { | |||||
| path = "/" + path; | |||||
| } | |||||
| try { | |||||
| inputStream = ResourcesUtil.getResourceAsStream(path); | |||||
| if (inputStream == null) { | |||||
| throw new TtPayException(fileNotFoundMsg); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| throw new TtPayException(fileNotFoundMsg, e); | |||||
| } | |||||
| } else if (configPath.startsWith("http://") || configPath.startsWith("https://")) { | |||||
| try { | |||||
| inputStream = new URL(configPath).openStream(); | |||||
| if (inputStream == null) { | |||||
| throw new TtPayException(fileNotFoundMsg); | |||||
| } | |||||
| } catch (IOException e) { | |||||
| throw new TtPayException(fileNotFoundMsg, e); | |||||
| } | |||||
| } else { | |||||
| try { | |||||
| File file = new File(configPath); | |||||
| if (!file.exists()) { | |||||
| throw new TtPayException(fileNotFoundMsg); | |||||
| } | |||||
| inputStream = new FileInputStream(file); | |||||
| } catch (IOException e) { | |||||
| throw new TtPayException(fileHasProblemMsg, e); | |||||
| } | |||||
| } | |||||
| return inputStream; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| package com.iformall.douyin.payv2.request; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @Accessors(chain = true) | |||||
| public class CallBackSettingsRequest implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * https回调地址,预下单请求地址,长度限制<=512字节 | |||||
| */ | |||||
| @SerializedName(value = "create_order_callback") | |||||
| private String createOrderCallback; | |||||
| /** | |||||
| * https回调地址,退款请求地址,长度限制<=512字节 | |||||
| */ | |||||
| @SerializedName(value = "refund_callback") | |||||
| private String refundCallback; | |||||
| /** | |||||
| * https回调地址,长度限制<=256字节。闭环核销方案核销组件上展示的二维码所对应的跳转地址。开发者可使用这个参数设置app_id维度的订单跳转链接。 | |||||
| */ | |||||
| @SerializedName(value = "delivery_qrcode_redirect") | |||||
| private String deliveryQrcodeRedirect; | |||||
| } | |||||
| @@ -0,0 +1,67 @@ | |||||
| package com.iformall.douyin.payv2.request; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.AllArgsConstructor; | |||||
| import lombok.Builder; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 请求分账API请求实体 | |||||
| * | |||||
| * @author pg | |||||
| * @date 2021-6-24 | |||||
| */ | |||||
| @Data | |||||
| @Builder(builderMethodName = "newBuilder") | |||||
| @NoArgsConstructor | |||||
| @AllArgsConstructor | |||||
| public class ProfitSharingRequest implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 开发者侧订单id,长度限制<64字节 | |||||
| */ | |||||
| @SerializedName("out_order_no") | |||||
| private String outOrderNo; | |||||
| /** | |||||
| * 开发者侧分账单id,分账请求的唯一标识,长度限制<64字节 | |||||
| */ | |||||
| @SerializedName("out_settle_no") | |||||
| private String outSettleNo; | |||||
| /** | |||||
| * 分账描述,长度<512字节 | |||||
| */ | |||||
| @SerializedName("settle_desc") | |||||
| private String settleDesc; | |||||
| /** | |||||
| * 其他分账方(除卖家之外的),json字符串,长度<512字节 | |||||
| * - 示例,"[{\"merchant_uid\":\"分账方商户号1\",\"amount\":100}]" | |||||
| * merchant_uid string 是 | |||||
| * 进件商户id(除了卖家以外的其他分账方) | |||||
| * amount int64 是 | |||||
| * 分账金额,单位[分],amount>0 | |||||
| */ | |||||
| @SerializedName("settle_params") | |||||
| private String settleParams; | |||||
| /** | |||||
| * 透传字段,开发者自定义,<=2048字节,不支持二进制 | |||||
| */ | |||||
| @SerializedName("cp_extra") | |||||
| private String cpExtra; | |||||
| /** | |||||
| * 分账结果通知地址,必须是https类型, | |||||
| * 若不填,默认使用在开发者平台-担保交易配置页面设置的回调地址 | |||||
| */ | |||||
| @SerializedName("notify_url") | |||||
| private String notifyUrl; | |||||
| } | |||||
| @@ -0,0 +1,73 @@ | |||||
| package com.iformall.douyin.payv2.request; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 订单推送核销状态请求对象 | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @Accessors(chain = true) | |||||
| public class TtOrderPushDeliveryRequest implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * <pre> | |||||
| * 开发者服务交易单号 | |||||
| * </pre> | |||||
| */ | |||||
| @SerializedName(value = "out_order_no") | |||||
| private String outOrderNo; | |||||
| /** | |||||
| * <pre> | |||||
| * out_order_no所关联的需要核销的商品单信息,详细结构见下表。可使用此参数指定核销整单中的特定商品单。 | |||||
| * 长度<=100 | |||||
| * 注意:只有待使用状态的商品单才能核销,已核销、正退款或已退款的将返回错误。 | |||||
| * </pre> | |||||
| */ | |||||
| @SerializedName(value = "item_order_list") | |||||
| private List<ItemOrder> itemOrderList; | |||||
| /** | |||||
| * 是否整单核销。此参数设为true则将out_order_no的所有商品单核销。use_all和item_list必须有一个有效值,要么整单核销,要么指定商品单核销。 | |||||
| * 注意:此参数设为true时只有out_order_no的所有商品单都为待使用状态才能成功核销,如果有商品单状态不对将导致不能整单核销,会返回错误。 | |||||
| */ | |||||
| @SerializedName(value = "use_all") | |||||
| private Boolean useAll; | |||||
| /** | |||||
| * 核销的商铺poi信息,详细结构见下表,最多1024个字节。 | |||||
| * 注意:此字段为json string | |||||
| * poi_info 结构,poi商品必填所有字段(强校验),小程序商品也尽量传入(不校验) | |||||
| * shop_name string poi商品必填 | |||||
| * 核销店铺名称,参考商铺同步接口中的店铺名称(name) | |||||
| * ext_valid_shop_id string poi商品必填 | |||||
| * 核销门店的外部店铺id,参考商铺同步接口中的接入方店铺id(supplier_ext_id) | |||||
| * valid_poi_id_str string poi商品必填 | |||||
| * 核销门店对应的抖音poi_id,参考商铺同步接口中的抖音poi id(poi_id) | |||||
| */ | |||||
| @SerializedName(value = "poi_info") | |||||
| private String poiInfo; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ItemOrder implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,38 @@ | |||||
| package com.iformall.douyin.payv2.request; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * <pre> | |||||
| * 订单查询请求对象 | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @Accessors(chain = true) | |||||
| public class TtPayOrderQueryV2Request implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * <pre> | |||||
| * 抖音开平内部交易订单号,长度<64byte,开发者在接收到抖音开平发起的下单交易回调请求的时候,由抖音开平传递给开发者服务,开发者必须确保将该id与自己平台生成的交易单号进行唯一关联 | |||||
| * </pre> | |||||
| */ | |||||
| @SerializedName(value = "order_id") | |||||
| private String orderId; | |||||
| /** | |||||
| * <pre> | |||||
| * 开发者系统生成的订单号,与抖音开平交易单号order_id唯一关联,长度<64byte | |||||
| * </pre> | |||||
| */ | |||||
| @SerializedName(value = "out_order_no") | |||||
| private String outOrderNo; | |||||
| } | |||||
| @@ -0,0 +1,36 @@ | |||||
| package com.iformall.douyin.payv2.request; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 微信支付-申请退款请求参数 | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @Accessors(chain = true) | |||||
| public class TtPayRefundQueryV2Request implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 抖音开平内部交易退款单号,长度<= 64byte,开发者必须确保将该id与自己平台生成的交易单号进行唯一关联 | |||||
| */ | |||||
| @SerializedName(value = "refund_id") | |||||
| private String refund_id; | |||||
| /** | |||||
| * 开发者系统生成的退款单号,与抖音开平退款单号refund_id 唯一关联,长度<= 64byte | |||||
| */ | |||||
| @SerializedName(value = "out_refund_no") | |||||
| private String outRefundNo; | |||||
| } | |||||
| @@ -0,0 +1,107 @@ | |||||
| package com.iformall.douyin.payv2.request; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 申请退款请求参数 | |||||
| * </pre> | |||||
| * | |||||
| * @author | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @Accessors(chain = true) | |||||
| public class TtPayRefundV2Request implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 是 | |||||
| * 开发者侧订单号,长度 <= 64 byte | |||||
| */ | |||||
| @SerializedName(value = "out_order_no") | |||||
| private String outOrderNo; | |||||
| /** | |||||
| * 是 | |||||
| * 开发者侧退款单号,长度 <= 64 byte | |||||
| */ | |||||
| @SerializedName(value = "out_refund_no") | |||||
| private String outRefundNo; | |||||
| /** | |||||
| * 否 | |||||
| * 开发者自定义透传字段,不支持二进制,长度 <= 2048 byte | |||||
| */ | |||||
| @SerializedName(value = "cp_extra") | |||||
| private String cpExtra; | |||||
| /** | |||||
| * 是 | |||||
| * 退款单的跳转的schema | |||||
| */ | |||||
| @SerializedName(value = "order_entry_schema") | |||||
| private PageEntry orderEntrySchema; | |||||
| /** | |||||
| * 否 | |||||
| * 退款结果通知地址,必须是https类型, | |||||
| * 若不填,默认使用在开发者平台-担保交易配置页面设置的退款回调地址 | |||||
| */ | |||||
| @SerializedName(value = "notify_url") | |||||
| private String notifyUrl; | |||||
| /** | |||||
| * 否(新订单发起退款必传) | |||||
| * | |||||
| * 需要发起退款的商品单信息(新订单发起退款必传) | |||||
| */ | |||||
| @SerializedName(value = "item_order_detail") | |||||
| private List<OrderDetail> itemOrderDetail; | |||||
| /** | |||||
| * 否(旧订单发起退款必传) | |||||
| * 退款总金额 (旧订单发起退款必传) | |||||
| */ | |||||
| @SerializedName(value = "refund_total_amount") | |||||
| private Integer refundTotalAmount; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class PageEntry implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 路径 没有前导的“/” | |||||
| */ | |||||
| @SerializedName(value = "path") | |||||
| private String path; | |||||
| /** | |||||
| * 参数 自定义的json结构 | |||||
| */ | |||||
| @SerializedName(value = "params") | |||||
| private String params; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class OrderDetail implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 商品单号,参见前文"对于重要id字段的说明" | |||||
| */ | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,456 @@ | |||||
| package com.iformall.douyin.payv2.request; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 统一下单请求参数对象. | |||||
| * 参考文档:https://bytedance.feishu.cn/docx/doxcna1ALcy90AGMNdGLoALBeIH#doxcnUUemGYgUYECi8n92wMQQke | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @Accessors(chain = true) | |||||
| public class TtPayUnifiedOrderV2Request implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 是 | |||||
| * 商品信息,详情见 goods_list说明 | |||||
| */ | |||||
| @SerializedName(value = "goods_list") | |||||
| protected List<Good> goodsList; | |||||
| /** | |||||
| * 是 | |||||
| * 订单总价,单位(分) | |||||
| */ | |||||
| @SerializedName(value = "total_amount") | |||||
| private Integer totalAmount; | |||||
| /** | |||||
| * 否 | |||||
| * 用户手机号 | |||||
| */ | |||||
| @SerializedName(value = "phone_num") | |||||
| private String phoneNum; | |||||
| /** | |||||
| * 否 | |||||
| * 用户姓名 | |||||
| */ | |||||
| @SerializedName(value = "contact_name") | |||||
| private String contactName; | |||||
| /** | |||||
| * 否 | |||||
| * 下单备注信息,长度 <= 2048byte | |||||
| */ | |||||
| @SerializedName(value = "extra") | |||||
| private String extra; | |||||
| /** | |||||
| * 是 | |||||
| * 用户OpenID | |||||
| */ | |||||
| @SerializedName(value = "open_id") | |||||
| private String openId; | |||||
| /** | |||||
| * 否 | |||||
| * 支付结果通知地址,必须是https类型。若不填,默认使用在开发者平台-担保交易配置页面设置的支付回调地址 | |||||
| */ | |||||
| @SerializedName(value = "pay_notify_url") | |||||
| private String payNotifyUrl; | |||||
| /** | |||||
| * 是 | |||||
| * 开发者的单号,长度 <= 64 byte | |||||
| */ | |||||
| @SerializedName(value = "out_order_no") | |||||
| private String outOrderNo; | |||||
| /** | |||||
| * 否 | |||||
| * 支付超时时间,单位秒,例如300表示300秒后过期;不传或传0会使用默认值300 | |||||
| */ | |||||
| @SerializedName(value = "pay_expire_seconds") | |||||
| private Integer payExpireSeconds; | |||||
| /** | |||||
| * 是 | |||||
| * 订单详情页 | |||||
| */ | |||||
| @SerializedName(value = "order_entry_schema") | |||||
| private PageEntry orderEntrySchema; | |||||
| /** | |||||
| * 否 | |||||
| * 开发者自定义透传字段,不支持二进制,长度 <= 2048 byte | |||||
| */ | |||||
| @SerializedName(value = "cp_extra") | |||||
| private PageEntry cpExtra; | |||||
| /** | |||||
| * 否 | |||||
| * 折扣金额,单位(分) | |||||
| */ | |||||
| @SerializedName(value = "discount_amount") | |||||
| private Integer discountAmount; | |||||
| /** | |||||
| * 否 | |||||
| * 营销算价结果信息, | |||||
| */ | |||||
| @SerializedName(value = "price_calculation_detail") | |||||
| private PriceDetail priceCalculationDetail; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class Good implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 否 | |||||
| * - 非poi商品必传 | |||||
| * 商品图片链接,长度 <= 512 byte | |||||
| */ | |||||
| @SerializedName(value = "goods_image") | |||||
| private String goodsImage; | |||||
| /** | |||||
| * 否 | |||||
| * - 非poi商品必传 | |||||
| * 商品标题/商品名称,长度 <= 256 byte | |||||
| */ | |||||
| @SerializedName(value = "goods_title") | |||||
| private String goodsTitle; | |||||
| /** | |||||
| * 否 | |||||
| * - 非poi商品必传 | |||||
| * 商品标签,最多设置三个标签,例如:随时退|免预约|提前3日预约 (“|”是中文类型),详见type的合法值 | |||||
| */ | |||||
| @SerializedName(value = "labels") | |||||
| private String labels; | |||||
| /** | |||||
| * 否 | |||||
| * 使用规则,如 “周一至周日可用”、“周一至周五可用”、“非节假日可用”,默认“周一至周日可用” | |||||
| */ | |||||
| @SerializedName(value = "date_rule") | |||||
| private String dateRule; | |||||
| /** | |||||
| * 否 | |||||
| * - 非poi商品必传 | |||||
| * 商品价格,单位(分) | |||||
| */ | |||||
| @SerializedName(value = "price") | |||||
| private Integer price; | |||||
| /** | |||||
| * 是 | |||||
| * 商品数量 | |||||
| */ | |||||
| @SerializedName(value = "quantity") | |||||
| private Integer quantity; | |||||
| /** | |||||
| * 是 | |||||
| * 商品id | |||||
| */ | |||||
| @SerializedName(value = "goods_id") | |||||
| private String goodsId; | |||||
| /** | |||||
| * 是 | |||||
| * 商品id类别,poi商品传 1,非poi商品传 2 | |||||
| */ | |||||
| @SerializedName(value = "goods_id_type") | |||||
| private Integer goodsIdType; | |||||
| /** | |||||
| * 否 | |||||
| * 商品详情页 | |||||
| */ | |||||
| @SerializedName(value = "goods_page") | |||||
| private PageEntry goodsPage; | |||||
| /** | |||||
| * 否 | |||||
| * - 非poi商品必传 | |||||
| * 券的有效期,注意: | |||||
| * 1. 非poi商品必传,poi商品会从poi库里查询有效期信息,不会使用开发者传的数据 | |||||
| * 2. 如果是非poi商品,每个goods_id都要传券的有效期信息,否则会下单失败 | |||||
| */ | |||||
| @SerializedName(value = "order_valid_time") | |||||
| private OrderValid orderValidTime; | |||||
| /** | |||||
| * 否 | |||||
| * 折扣金额,单位(分) | |||||
| */ | |||||
| @SerializedName(value = "discount_amount") | |||||
| private Integer discountAmount; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class PageEntry implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 路径 没有前导的“/” | |||||
| */ | |||||
| @SerializedName(value = "path") | |||||
| private String path; | |||||
| /** | |||||
| * 参数 自定义的json结构 | |||||
| */ | |||||
| @SerializedName(value = "params") | |||||
| private String params; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class OrderValid implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 券的有效期开始时间,单位毫秒,须大于0 | |||||
| */ | |||||
| @SerializedName(value = "valid_start_time") | |||||
| private Long validStartTime; | |||||
| /** | |||||
| * 券的有效期结束时间,单位毫秒,须大于0,且须大于valid_start_time和当前时间 | |||||
| */ | |||||
| @SerializedName(value = "valid_end_time") | |||||
| private Long validEndTime; | |||||
| /** | |||||
| * 1. 券的相对有效时间,单位毫秒,须大于0 | |||||
| * 2. 与<valid_start_time,valid_end_time>组合,至少回传一个,否则会下单失败 | |||||
| * 3. 都合法优先使用<valid_start_time,valid_end_time>组合 | |||||
| * 4. 当valid_duration 有效时,券的有效期开始时间 S=订单支付完成时间,券的有效期结束时间 E=1天 + 向下按天截断(S+valid_duration) | |||||
| * eg:valid_duration = 86400000ms(一天) S = 2021.1.1 6:00 E = 2021.1.3 00:00 | |||||
| */ | |||||
| @SerializedName(value = "valid_duration") | |||||
| private Long validDuration; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class PriceDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 是 | |||||
| * 算价类型,1-商户单维度,item单价格我们按分摊比例计算, | |||||
| * 2-item单维度,item单价格由开发者计算 | |||||
| */ | |||||
| @SerializedName(value = "calculation_type") | |||||
| private Integer calculationType; | |||||
| /** | |||||
| * 商品算价结果 | |||||
| */ | |||||
| @SerializedName(value = "goods_discount_detail") | |||||
| private List<GoodsDiscountDetail> goodsDiscountDetail; | |||||
| /** | |||||
| * 商品算价结果 | |||||
| */ | |||||
| @SerializedName(value = "order_discount_detail") | |||||
| private OrderDiscountDetail order_discount_detail; | |||||
| /** | |||||
| * 商品算价结果 | |||||
| */ | |||||
| @SerializedName(value = "item_discount_detail") | |||||
| private List<ItemDiscountDetail> item_discount_detail; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class GoodsDiscountDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 是 | |||||
| * 商品id,此处为课程id,注意这里是string类型 | |||||
| */ | |||||
| @SerializedName(value = "goods_id") | |||||
| private String goodsId; | |||||
| /** | |||||
| * 是 | |||||
| * 购买数量 | |||||
| */ | |||||
| @SerializedName(value = "quantity") | |||||
| private Integer quantity; | |||||
| /** | |||||
| * 是 | |||||
| * 商品总价,单位:分 | |||||
| */ | |||||
| @SerializedName(value = "total_amount") | |||||
| private Integer totalAmount; | |||||
| /** | |||||
| * 是 | |||||
| * 该商品总优惠金额,该商品的实付金额=total_amount-discount_amount | |||||
| */ | |||||
| @SerializedName(value = "discountAmount") | |||||
| private Integer discountAmount; | |||||
| /** | |||||
| * 营销明细 | |||||
| */ | |||||
| @SerializedName(value = "marketing_detail") | |||||
| private List<MarketingDetail> marketingDetail; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class OrderDiscountDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 是 | |||||
| * 订单维度总优惠金额,单位: 分 | |||||
| */ | |||||
| @SerializedName(value = "order_total_discount_amount") | |||||
| private Integer orderTotalDiscountAmount; | |||||
| /** | |||||
| * 是 | |||||
| * 商品(sku)维度总优惠金额,单位: 分 | |||||
| */ | |||||
| @SerializedName(value = "goods_total_discount_amount") | |||||
| private Integer goodsTotalDiscountAmount; | |||||
| /** | |||||
| * 营销明细 | |||||
| */ | |||||
| @SerializedName(value = "marketing_detail") | |||||
| private List<MarketingDetail> marketingDetail; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ItemDiscountDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 是 | |||||
| * 商品id,此处为课程id,注意这里是string类型 | |||||
| */ | |||||
| @SerializedName(value = "goods_id") | |||||
| private String goodsId; | |||||
| /** | |||||
| * 是 | |||||
| * 商品总价,单位:分 | |||||
| */ | |||||
| @SerializedName(value = "total_amount") | |||||
| private Integer totalAmount; | |||||
| /** | |||||
| * 是 | |||||
| * 该商品总优惠金额,该商品的实付金额=total_amount-discount_amount | |||||
| */ | |||||
| @SerializedName(value = "discountAmount") | |||||
| private Integer discountAmount; | |||||
| /** | |||||
| * 营销明细 | |||||
| */ | |||||
| @SerializedName(value = "marketing_detail") | |||||
| private List<MarketingDetail> marketingDetail; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class MarketingDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 是 | |||||
| * 营销id(用户身份id,优惠券id,积分id或者活动id) | |||||
| */ | |||||
| @SerializedName(value = "id") | |||||
| private String id; | |||||
| /** | |||||
| * 是 | |||||
| * | |||||
| * 营销类型: | |||||
| * 1: 用户身份 | |||||
| * 2: 优惠券 | |||||
| * 3: 积分(暂不开放) | |||||
| * 4: 活动 | |||||
| */ | |||||
| @SerializedName(value = "type") | |||||
| private Integer type; | |||||
| /** | |||||
| * 是 | |||||
| * 该营销策略优惠金额,单位: 分 | |||||
| */ | |||||
| @SerializedName(value = "discountAmount") | |||||
| private Integer discountAmount; | |||||
| /** | |||||
| * 营销名称 | |||||
| */ | |||||
| @SerializedName(value = "title") | |||||
| private String title; | |||||
| /** | |||||
| * 营销备注 | |||||
| */ | |||||
| @SerializedName(value = "note") | |||||
| private String note; | |||||
| /** | |||||
| * 优惠范围 | |||||
| */ | |||||
| @SerializedName(value = "discount_range") | |||||
| private Integer discountRange; | |||||
| /** | |||||
| * 营销子类型 | |||||
| */ | |||||
| @SerializedName(value = "subtype") | |||||
| private String subtype; | |||||
| /** | |||||
| * 不同type含义不同,若type=3,value则为积分值 | |||||
| */ | |||||
| @SerializedName(value = "value") | |||||
| private Integer value; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,64 @@ | |||||
| package com.iformall.douyin.payv2.request; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 订单推送核销状态请求对象 | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @Accessors(chain = true) | |||||
| public class TtRefundAuditMsgRequest implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 开发者侧退款单号 | |||||
| */ | |||||
| @SerializedName(value = "out_refund_no") | |||||
| private String outRefundNo; | |||||
| /** | |||||
| * 审核状态,1-同意退款 2-不同意退款 | |||||
| */ | |||||
| @SerializedName(value = "refund_audit_status") | |||||
| private Integer refundAuditStatus; | |||||
| /** | |||||
| * 不同意退款信息(不同意退款时必填),长度 <= 512 byte | |||||
| */ | |||||
| @SerializedName(value = "deny_message") | |||||
| private String denyMessage; | |||||
| /** | |||||
| * 核销的商铺poi信息,详细结构见下表,最多1024个字节。 | |||||
| * shop_name string poi商品必填 | |||||
| * 核销店铺名称,参考商铺同步接口中的店铺名称(name) | |||||
| * ext_valid_shop_id string poi商品必填 | |||||
| * 核销门店的外部店铺id,参考商铺同步接口中的接入方店铺id(supplier_ext_id) | |||||
| * valid_poi_id_str string poi商品必填 | |||||
| * 核销门店对应的抖音poi_id,参考商铺同步接口中的抖音poi id(poi_id) | |||||
| */ | |||||
| @SerializedName(value = "poi_info") | |||||
| private Boolean poiInfo; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ItemOrder implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,55 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * <pre> | |||||
| * 结果共用属性类. | |||||
| * Created by Binary Wang on 2016-10-24. | |||||
| * </pre> | |||||
| * | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class BaseTtPayResult<T> implements Serializable { | |||||
| /** | |||||
| * 返回状态码. | |||||
| */ | |||||
| @SerializedName("err_no") | |||||
| protected Integer errNo; | |||||
| public boolean isSuccess() { | |||||
| return errNo.intValue() == 0; | |||||
| } | |||||
| /** | |||||
| * 返回信息. | |||||
| */ | |||||
| @SerializedName("err_tips") | |||||
| protected String errTips; | |||||
| @SerializedName("data") | |||||
| private T data; | |||||
| /** | |||||
| * Gets logger. | |||||
| * | |||||
| * @return the logger | |||||
| */ | |||||
| protected Logger getLogger() { | |||||
| return LoggerFactory.getLogger(this.getClass()); | |||||
| } | |||||
| @Override | |||||
| public String toString() { | |||||
| return WxGsonBuilder.create().toJson(this); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,226 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaGetLiveInfo; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 结果通知. | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class CreateOrderCallback implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 是 | |||||
| * 抖音开平侧生成的订单号 | |||||
| */ | |||||
| @SerializedName(value = "order_id") | |||||
| private String orderId; | |||||
| /** | |||||
| * 是 | |||||
| * 商品信息,详情见 goods参数 部分 | |||||
| */ | |||||
| @SerializedName(value = "goods") | |||||
| private List<Good> goods; | |||||
| /** | |||||
| * 是 | |||||
| * 订单总价格,单位[分] | |||||
| * 用户实付金额=total_amount-discount | |||||
| */ | |||||
| @SerializedName(value = "total_amount") | |||||
| private Integer totalAmount; | |||||
| /** | |||||
| * 是 | |||||
| * 订单折扣,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "discount") | |||||
| private Integer discount; | |||||
| /** | |||||
| * 否 | |||||
| * 预下单时开发者定义的透传信息 | |||||
| */ | |||||
| @SerializedName(value = "cp_extra") | |||||
| private String cpExtra; | |||||
| /** | |||||
| * 是 | |||||
| * 订单创建时间,13位时间戳,毫秒 | |||||
| */ | |||||
| @SerializedName(value = "create_order_time") | |||||
| private Long createOrderTime; | |||||
| /** | |||||
| * 是 | |||||
| * 用户OpenID | |||||
| */ | |||||
| @SerializedName(value = "open_id") | |||||
| private String openId; | |||||
| /** | |||||
| * 否 | |||||
| * 用户手机号 | |||||
| */ | |||||
| @SerializedName(value = "phone_num") | |||||
| private String phoneNum; | |||||
| /** | |||||
| * 否 | |||||
| * 联系人姓名 | |||||
| */ | |||||
| @SerializedName(value = "contact_name") | |||||
| private String contactName; | |||||
| /** | |||||
| * 是 | |||||
| * 小程序id | |||||
| */ | |||||
| @SerializedName(value = "app_id") | |||||
| private String appId; | |||||
| /** | |||||
| * 否 | |||||
| * 用户的 UnionID | |||||
| */ | |||||
| @SerializedName(value = "union_id") | |||||
| private String unionId; | |||||
| /** | |||||
| * 是 | |||||
| * 核销类型,开平告知此订单是否可走闭环核销判断结果。 | |||||
| * 0-非闭环核销,开发者自行处理券码生成及展示,通过push_delivery接口推送核销状态,1-闭环核销,开平负责生券,开发者使用核销组件展示,使用验券准备和验券接口核销。 | |||||
| */ | |||||
| @SerializedName(value = "delivery_type") | |||||
| private Integer deliveryType; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class Good implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 是 | |||||
| * 商品图片链接 | |||||
| */ | |||||
| @SerializedName(value = "img_url") | |||||
| private String imgUrl; | |||||
| /** | |||||
| * 是 | |||||
| * 商品标题 | |||||
| */ | |||||
| @SerializedName(value = "title") | |||||
| private String title; | |||||
| /** | |||||
| * 是 | |||||
| * 商品副标题 | |||||
| */ | |||||
| @SerializedName(value = "sub_title") | |||||
| private String subTitle; | |||||
| /** | |||||
| * 是 | |||||
| * | |||||
| * 商品标签,对应poi多门店SPU同步的sub_title,例如:随时退|免预约|提前3日预约 (“|”是中文类型) | |||||
| */ | |||||
| @SerializedName(value = "labels") | |||||
| private String labels; | |||||
| /** | |||||
| * 是 | |||||
| * 券的可用时间(目前仅用于展示),例如:“周一至周五可用”、“非节假日可用” | |||||
| */ | |||||
| @SerializedName(value = "date_rule") | |||||
| private String dateRule; | |||||
| /** | |||||
| * 是 | |||||
| * 商品原价,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "origin_price") | |||||
| private Integer originPrice; | |||||
| /** | |||||
| * 是 | |||||
| * 商品去掉折扣后的单价,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "price") | |||||
| private Integer price; | |||||
| /** | |||||
| * 是 | |||||
| * 购买的商品数量 | |||||
| */ | |||||
| @SerializedName(value = "quantity") | |||||
| private Integer quantity; | |||||
| /** | |||||
| * 否 | |||||
| * 对应门店的Poi ID | |||||
| */ | |||||
| @SerializedName(value = "poi_id") | |||||
| private String poiId; | |||||
| /** | |||||
| * 是 | |||||
| * 商品id | |||||
| */ | |||||
| @SerializedName(value = "goods_id") | |||||
| private String goodsId; | |||||
| /** | |||||
| * 是 | |||||
| * item_order_id列表,id个数与quantity一致 | |||||
| */ | |||||
| @SerializedName(value = "item_order_id_list") | |||||
| private List<String> itemOrderIdList; | |||||
| /** | |||||
| * 是 | |||||
| * 商品id类别,1:poi商品,2:非poi商品 | |||||
| */ | |||||
| @SerializedName(value = "goods_id_type") | |||||
| private Integer goodsIdType; | |||||
| /** | |||||
| * 是 | |||||
| * 商品item_order信息,详情见 item_order_info_list部分 | |||||
| */ | |||||
| @SerializedName(value = "item_order_info") | |||||
| protected List<ItemOrderInfo> itemOrderInfoList; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ItemOrderInfo implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * item单id | |||||
| */ | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| /** | |||||
| * 商品优惠后价格 | |||||
| */ | |||||
| @SerializedName(value = "price") | |||||
| private Integer price; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,32 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class OriginNotifyResponse implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| @SerializedName(value = "msg") | |||||
| private String msg; | |||||
| /** | |||||
| * 枚举值: | |||||
| * pre_create_order 预下单回调 | |||||
| * pre_create_refund 退款审核回调 | |||||
| */ | |||||
| @SerializedName(value = "type") | |||||
| private String type; | |||||
| /** | |||||
| * 固定值:"2.0" callback版本,用于开发者识别回调参数的变更 | |||||
| */ | |||||
| @SerializedName(value = "version") | |||||
| private String version; | |||||
| } | |||||
| @@ -0,0 +1,112 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 请求分账API返回的分账结果实体 | |||||
| * | |||||
| * @author pg | |||||
| * @date 2021-6-24 | |||||
| */ | |||||
| @Data | |||||
| public class ProfitSharingResult implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 返回状态码. | |||||
| */ | |||||
| @SerializedName("err_no") | |||||
| protected Integer errNo; | |||||
| public boolean isSuccess() { | |||||
| return errNo.intValue() == 0; | |||||
| } | |||||
| /** | |||||
| * 返回信息. | |||||
| */ | |||||
| @SerializedName("err_tips") | |||||
| protected String errTips; | |||||
| /** | |||||
| * 订单的分账结果 | |||||
| */ | |||||
| @SerializedName("data") | |||||
| private List<Receiver> data; | |||||
| @Data | |||||
| public static class Receiver implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 开发者交易订单id,长度<=64byte,数字、ASCII字符组成 | |||||
| */ | |||||
| @SerializedName("out_order_no") | |||||
| private String outOrderNo; | |||||
| /** | |||||
| * 开发者分账单id,长度<=64byte,数字、ASCII字符组成 | |||||
| */ | |||||
| @SerializedName("out_settle_no") | |||||
| private String outSettleNo; | |||||
| /** | |||||
| * 小程序侧交易订单id,长度<=64byte,数字、ASCII字符组成 | |||||
| */ | |||||
| @SerializedName("order_id") | |||||
| private String orderId; | |||||
| /** | |||||
| * 小程序侧分账单id,长度<=64byte,数字、ASCII字符组成 | |||||
| */ | |||||
| @SerializedName("settle_id") | |||||
| private String settleId; | |||||
| /** | |||||
| * 分账金额,单位[分] | |||||
| */ | |||||
| @SerializedName("settle_amount") | |||||
| private Integer settleAmount; | |||||
| /** | |||||
| * 分账状态:INIT,PROCESSING,SUCCESS,FAIL | |||||
| */ | |||||
| @SerializedName("settle_status") | |||||
| private String settleStatus; | |||||
| /** | |||||
| * 分账详情,如“商户号ABC-分成金额(分)100” | |||||
| */ | |||||
| @SerializedName("settle_detail") | |||||
| private String settleDetail; | |||||
| /** | |||||
| * 分账时间,13位时间戳,毫秒 | |||||
| */ | |||||
| @SerializedName("settle_time") | |||||
| private Long settleTime; | |||||
| /** | |||||
| * 手续费,单位[分] | |||||
| */ | |||||
| @SerializedName("rake") | |||||
| private Integer rake; | |||||
| /** | |||||
| * 佣金,单位[分] | |||||
| */ | |||||
| @SerializedName("commission") | |||||
| private Integer commission; | |||||
| /** | |||||
| * 透传字段,开发者自定义,<=2048字节,不支持二进制数据 | |||||
| */ | |||||
| @SerializedName("cp_extra") | |||||
| private String cpExtra; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,138 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 结果通知. | |||||
| * | |||||
| * @author | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class RefundOrderCallback implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 小程序的appid | |||||
| */ | |||||
| @SerializedName(value = "app_id") | |||||
| private String appId; | |||||
| /** | |||||
| * 用户openid | |||||
| */ | |||||
| @SerializedName(value = "open_id") | |||||
| private String openId; | |||||
| /** | |||||
| * 抖音开平侧退款单号 | |||||
| */ | |||||
| @SerializedName(value = "refund_id") | |||||
| private String refundId; | |||||
| /** | |||||
| * 抖音开平侧订单号 | |||||
| */ | |||||
| @SerializedName(value = "order_id") | |||||
| private String orderId; | |||||
| /** | |||||
| * 开发者侧订单号 | |||||
| */ | |||||
| @SerializedName(value = "out_order_no") | |||||
| private String outOrderNo; | |||||
| /** | |||||
| * 退款总金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "refund_total_amount") | |||||
| private Integer refundTotalAmount; | |||||
| /** | |||||
| * 退款审核的最后期限,超过该期限无需商家审核,自动退款,13位时间戳,毫秒 | |||||
| */ | |||||
| @SerializedName(value = "refund_audit_deadline") | |||||
| private Long refundAuditDeadline; | |||||
| /** | |||||
| * 退款创建时间,13位时间戳,毫秒 | |||||
| */ | |||||
| @SerializedName(value = "create_refund_time") | |||||
| private Long createRefundTime; | |||||
| /** | |||||
| * 退款来源:1-用户发起退款 3-过期自动退 | |||||
| */ | |||||
| @SerializedName(value = "refund_source") | |||||
| private Integer refundSource; | |||||
| /** | |||||
| * cp 自定义字段,不支持二进制,长度 <= 2048byte | |||||
| */ | |||||
| @SerializedName(value = "cp_extra") | |||||
| private String cpExtra; | |||||
| /** | |||||
| * 退款原因,退款原因有多个 | |||||
| */ | |||||
| @SerializedName(value = "refund_reason") | |||||
| private List<String> refundReason; | |||||
| /** | |||||
| *退款补充说明 | |||||
| */ | |||||
| @SerializedName(value = "refund_description") | |||||
| private String refundDescription; | |||||
| /** | |||||
| * 退款商品单信息 (新系统订单退款必填) | |||||
| */ | |||||
| @SerializedName(value = "refund_item_detail") | |||||
| private RefundItemDetail refundItemDetail; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class RefundItemDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 用户需要退款多少个商品单 | |||||
| */ | |||||
| @SerializedName(value = "item_order_quantity") | |||||
| private Integer itemOrderQuantity; | |||||
| /** | |||||
| * 本次退款的商品单列表 | |||||
| */ | |||||
| @SerializedName(value = "item_order_detail") | |||||
| private List<ItemOrderDetail> itemOrderDetail; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ItemOrderDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 用户需要退款多少个商品单 | |||||
| */ | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| /** | |||||
| * 用户需要退款多少个商品单 | |||||
| */ | |||||
| @SerializedName(value = "refund_amount") | |||||
| private Integer refundAmount; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,304 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 查询CPS订单 返回结果对象 | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class TtPayCpsOrderQueryV2Result implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 抖音开平侧订单号 | |||||
| */ | |||||
| @SerializedName(value = "order_id") | |||||
| private String orderId; | |||||
| /** | |||||
| * 开发者侧订单号,与order_id一一对应 | |||||
| */ | |||||
| @SerializedName(value = "out_order_no") | |||||
| private String outOrderNo; | |||||
| /** | |||||
| *cps订单支付相关信息 | |||||
| */ | |||||
| @SerializedName(value = "payment_info") | |||||
| private PaymentInfo paymentInfo; | |||||
| /** | |||||
| *cps相关信息 | |||||
| */ | |||||
| @SerializedName(value = "cps_info") | |||||
| private CpsInfo cpsInfo; | |||||
| /** | |||||
| *cps订单已退款记录信息 | |||||
| * - refund_info字段结构(只展示已退款记录,退款失败和退款中不展示) | |||||
| */ | |||||
| @SerializedName(value = "refund_info") | |||||
| private RefundInfo refundInfo; | |||||
| /** | |||||
| *cps订单已核销记录信息 | |||||
| * - delivery_info字段结构(只展示已核销记录) | |||||
| */ | |||||
| @SerializedName(value = "delivery_info") | |||||
| private DeliveryInfo deliveryInfo; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class PaymentInfo implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 订单实际支付金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "total_fee") | |||||
| private Integer totalFee; | |||||
| /** | |||||
| * 订单状态, | |||||
| * INIT 初始状态 | |||||
| * PROCESS 订单处理中 | |||||
| * SUCCESS:成功 | |||||
| * FAIL:失败 | |||||
| * TIMEOUT:用户超时未支付 | |||||
| */ | |||||
| @SerializedName(value = "order_status") | |||||
| private String orderStatus; | |||||
| /** | |||||
| * 支付时间,格式:2021-12-12 00:00:00 | |||||
| */ | |||||
| @SerializedName(value = "pay_time") | |||||
| private String payTime; | |||||
| /** | |||||
| * 支付渠道枚举,1:微信,2:支付宝 | |||||
| */ | |||||
| @SerializedName(value = "pay_channel") | |||||
| private Integer payChannel; | |||||
| /** | |||||
| * 渠道支付单号,如微信的支付单号 | |||||
| */ | |||||
| @SerializedName(value = "channel_pay_id") | |||||
| private String channelPayId; | |||||
| /** | |||||
| * 卖家商户号id | |||||
| */ | |||||
| @SerializedName(value = "seller_uid") | |||||
| private String sellerUid; | |||||
| /** | |||||
| * 预下单时开发者定义的透传信息 | |||||
| */ | |||||
| @SerializedName(value = "cp_extra") | |||||
| private String cpExtra; | |||||
| /** | |||||
| * 结果描述信息,如失败原因 | |||||
| */ | |||||
| @SerializedName(value = "message") | |||||
| private String message; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class CpsInfo implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 订单总佣金,单位分 | |||||
| */ | |||||
| @SerializedName(value = "total_commission_amount") | |||||
| private Integer totalCommissionAmount; | |||||
| /** | |||||
| * 订单状态, | |||||
| * INIT 初始状态 | |||||
| * PROCESS 订单处理中 | |||||
| * SUCCESS:成功 | |||||
| * FAIL:失败 | |||||
| * TIMEOUT:用户超时未支付 | |||||
| */ | |||||
| @SerializedName(value = "cps_item_list") | |||||
| private List<CpsItem> cps_item_list; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class CpsItem implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 分佣比例,万分位 | |||||
| */ | |||||
| @SerializedName(value = "commission_rate") | |||||
| private Integer commissionRate; | |||||
| /** | |||||
| * 分佣用户ID | |||||
| */ | |||||
| @SerializedName(value = "commission_user_id") | |||||
| private Long commissionUserId; | |||||
| /** | |||||
| * 佣金,单位分 | |||||
| */ | |||||
| @SerializedName(value = "commission_amount") | |||||
| private Integer commissionAmount; | |||||
| /** | |||||
| * 分佣类型,1 短视频, 2 直播间 | |||||
| */ | |||||
| @SerializedName(value = "source_type") | |||||
| private Integer sourceType; | |||||
| /** | |||||
| * 短视频/直播间ID | |||||
| */ | |||||
| @SerializedName(value = "item_id") | |||||
| private Long itemId; | |||||
| /** | |||||
| * 售价,单位分 | |||||
| */ | |||||
| @SerializedName(value = "sell_amount") | |||||
| private Integer sellAmount; | |||||
| /** | |||||
| * cps订单状态,交易系统2.0为子单状态 | |||||
| * 0-未支付, | |||||
| * 1-已支付(待使用); | |||||
| * 2-已退款(不分佣); | |||||
| * 3-已核销(已分佣) | |||||
| */ | |||||
| @SerializedName(value = "status") | |||||
| private Integer status; | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class RefundInfo implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 订单退款总金额,单位分,没有已退款记录,为0 | |||||
| */ | |||||
| @SerializedName(value = "total_refund_amount") | |||||
| private Integer total_refund_amount; | |||||
| /** | |||||
| * 分佣用户ID | |||||
| */ | |||||
| @SerializedName(value = "refund_items") | |||||
| private List<RefundItem> refund_items; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class RefundItem implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 开发者系统生成的退款单号,与抖音开平退款单号refund_id 唯一关联 | |||||
| */ | |||||
| @SerializedName(value = "out_refund_no") | |||||
| private String outRefundNo; | |||||
| /** | |||||
| * 退款金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "refund_amount") | |||||
| private Integer refundAmount; | |||||
| /** | |||||
| * 显示退款状态,默认“已退款” | |||||
| */ | |||||
| @SerializedName(value = "refundStatus") | |||||
| private String refundStatus; | |||||
| /** | |||||
| * 退款时间,13位毫秒时间戳,只有已退款才有退款时间 | |||||
| */ | |||||
| @SerializedName(value = "refunded_at") | |||||
| private Long refunded_at; | |||||
| /** | |||||
| * 抖音开平侧的商品单号,只存在交易2.0系统 | |||||
| */ | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class DeliveryInfo implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 订单核销总金额,单位分,没有核销记录,为0 | |||||
| */ | |||||
| @SerializedName(value = "total_delivery_amount") | |||||
| private Integer totalDeliveryAmount; | |||||
| /** | |||||
| * 分佣用户ID | |||||
| */ | |||||
| @SerializedName(value = "delivery_items") | |||||
| private List<DeliveryItem> deliveryItems; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class DeliveryItem implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 核销金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "delivery_amount") | |||||
| private Integer deliveryAmount; | |||||
| /** | |||||
| * 显示核销状态,默认“已核销” | |||||
| */ | |||||
| @SerializedName(value = "delivery_status") | |||||
| private String deliveryStatus; | |||||
| /** | |||||
| * 退款时间,13位毫秒时间戳,只有已退款才有退款时间 | |||||
| */ | |||||
| @SerializedName(value = "delivery_at") | |||||
| private Long deliveryAt; | |||||
| /** | |||||
| * 抖音开平侧的商品单号,只存在交易2.0系统 | |||||
| */ | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,119 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import io.swagger.models.auth.In; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 查询订单 返回结果对象 | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class TtPayOrderQueryV2Result implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 抖音开平侧订单号 | |||||
| */ | |||||
| @SerializedName(value = "order_id") | |||||
| private String orderId; | |||||
| /** | |||||
| * 开发者侧订单号,与order_id一一对应 | |||||
| */ | |||||
| @SerializedName(value = "out_order_no") | |||||
| private String outOrderNo; | |||||
| /** | |||||
| * 已退款金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "refund_amount") | |||||
| private Integer refundAmount; | |||||
| /** | |||||
| * 已分账金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "settle_amount") | |||||
| private Integer settleAmount; | |||||
| /** | |||||
| * 订单实际支付金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "total_fee") | |||||
| private Integer totalFee; | |||||
| /** | |||||
| * 订单状态, | |||||
| * INIT 初始状态 | |||||
| * PROCESS 订单处理中 | |||||
| * SUCCESS:成功 | |||||
| * FAIL:失败 | |||||
| * TIMEOUT:用户超时未支付 | |||||
| */ | |||||
| @SerializedName(value = "order_status") | |||||
| private String orderStatus; | |||||
| /** | |||||
| * 支付时间,格式:2021-12-12 00:00:00 | |||||
| */ | |||||
| @SerializedName(value = "pay_time") | |||||
| private String payTime; | |||||
| /** | |||||
| * 支付渠道枚举,1:微信,2:支付宝 | |||||
| */ | |||||
| @SerializedName(value = "pay_channel") | |||||
| private Integer payChannel; | |||||
| /** | |||||
| * 渠道支付单号,如微信的支付单号 | |||||
| */ | |||||
| @SerializedName(value = "channel_pay_id") | |||||
| private String channelPayId; | |||||
| /** | |||||
| * 卖家商户号id | |||||
| */ | |||||
| @SerializedName(value = "seller_uid") | |||||
| private String sellerUid; | |||||
| /** | |||||
| * 视频id | |||||
| */ | |||||
| @SerializedName(value = "item_id") | |||||
| private String itemId; | |||||
| /** | |||||
| * 预下单时开发者定义的透传信息 | |||||
| */ | |||||
| @SerializedName(value = "cp_extra") | |||||
| private String cpExtra; | |||||
| /** | |||||
| * 结果描述信息,如失败原因 | |||||
| */ | |||||
| @SerializedName(value = "message") | |||||
| private String message; | |||||
| /** | |||||
| * 担保支付单id | |||||
| */ | |||||
| @SerializedName(value = "payment_order_id") | |||||
| private String paymentOrderId; | |||||
| /** | |||||
| * 订单核销类型: | |||||
| * 0-非闭环核销,开发者自行处理券码生成及展示,通过push_delivery接口推送核销状态。 | |||||
| * 1-闭环核销,开平负责生券,开发者使用核销组件展示,使用验券准备和验券接口核销。 | |||||
| */ | |||||
| @SerializedName(value = "delivery_type") | |||||
| private Integer deliveryType; | |||||
| } | |||||
| @@ -0,0 +1,121 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 退款返回结果. | |||||
| * </pre> | |||||
| * | |||||
| * @author | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class TtPayRefundQueryV2Result implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 系统退款单号,开放平台生成的退款单号 | |||||
| */ | |||||
| @SerializedName(value = "refund_id") | |||||
| private String refundId; | |||||
| /** | |||||
| * 开发者系统生成的退款单号,与抖音开平退款单号refund_id 唯一关联 | |||||
| */ | |||||
| @SerializedName(value = "out_refund_no") | |||||
| private String outRefundNo; | |||||
| /** | |||||
| * 退款金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "refund_total_amount") | |||||
| private Integer refundTotalAmount; | |||||
| /** | |||||
| * 退款状态 | |||||
| * 退款中- PROCESSING,已退款- SUCCESS,退款失败- FAIL | |||||
| */ | |||||
| @SerializedName(value = "refund_status") | |||||
| private String refundStatus; | |||||
| /** | |||||
| * 退款时间,13位毫秒时间戳,只有已退款才有退款时间 | |||||
| */ | |||||
| @SerializedName(value = "refund_at") | |||||
| private Long refundAt; | |||||
| /** | |||||
| * 退款结果信息,非商家拒绝退款导致的退款失败,可以通过该字段了解退款失败原因 | |||||
| */ | |||||
| @SerializedName(value = "message") | |||||
| private String message; | |||||
| /** | |||||
| * 系统订单信息,开放平台生成的订单号 | |||||
| */ | |||||
| @SerializedName(value = "order_id") | |||||
| private String orderId; | |||||
| /** | |||||
| * 商品单信息 (新系统订单退款才有的信息) | |||||
| */ | |||||
| @SerializedName(value = "item_order_detail") | |||||
| private List<itemOrderDetail> itemOrderDetail; | |||||
| /** | |||||
| * 退款审核信息(在新系统发起的退款单才有) | |||||
| */ | |||||
| @SerializedName(value = "merchant_audit_detail") | |||||
| private MerchantAuditDetail merchantAuditDetail; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class itemOrderDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 抖音开平侧的商品单号 | |||||
| */ | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| /** | |||||
| * 该商品单退款金额,单位[分] | |||||
| */ | |||||
| @SerializedName(value = "refund_amount") | |||||
| private Integer refundAmount; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class MerchantAuditDetail implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 退款审核的最后期限,过期无需审核,自动退款,13位unix时间戳,精度:毫秒 | |||||
| */ | |||||
| @SerializedName(value = "refund_audit_deadline") | |||||
| private Long refundAuditDeadline; | |||||
| /** | |||||
| * 退款审核状态 | |||||
| * INIT-初始化 TOAUDIT-待审核 AGREE-同意 DENY-拒绝 OVERTIME-超时未审核自动同意 | |||||
| */ | |||||
| @SerializedName(value = "audit_status") | |||||
| private String auditStatus; | |||||
| /** | |||||
| * 不同意退款信息(不同意退款时必填),长度 <= 512 byte | |||||
| */ | |||||
| @SerializedName(value = "deny_message") | |||||
| private String denyMessage; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,33 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * <pre> | |||||
| * 申请退款返回结果. | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class TtPayRefundV2Result implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 抖音开放平台交易系统内部退款单号 | |||||
| */ | |||||
| @SerializedName(value = "refund_id") | |||||
| private String refundId; | |||||
| /** | |||||
| * 退款审核的最后期限,过期无需审核,自动退款,13位unix时间戳,精度:毫秒 | |||||
| */ | |||||
| @SerializedName(value = "refund_audit_deadline") | |||||
| private Long refundAuditDeadline; | |||||
| } | |||||
| @@ -0,0 +1,99 @@ | |||||
| package com.iformall.douyin.payv2.result; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * <pre> | |||||
| * 统一下单请求参数对象. | |||||
| * </pre> | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @Accessors(chain = true) | |||||
| public class TtPayUnifiedOrderV2Result implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 是 | |||||
| * 抖音开平侧生成的订单号 | |||||
| */ | |||||
| @SerializedName(value = "order_id") | |||||
| protected String orderId; | |||||
| /** | |||||
| * 是 | |||||
| * 开发者系统生成的订单号 | |||||
| */ | |||||
| @SerializedName(value = "out_order_no") | |||||
| protected String outOrderNo; | |||||
| /** | |||||
| * 是 | |||||
| * 吊起收银台的支付订单号 | |||||
| */ | |||||
| @SerializedName(value = "pay_order_id") | |||||
| protected String payOrderId; | |||||
| /** | |||||
| * 是 | |||||
| * 吊起收银台的token | |||||
| */ | |||||
| @SerializedName(value = "pay_order_token") | |||||
| protected String payOrderToken; | |||||
| /** | |||||
| * 是 | |||||
| * 商品item_order信息,详情见 item_order_info_list部分 | |||||
| */ | |||||
| @SerializedName(value = "item_order_info_list") | |||||
| protected List<ItemOrderInfo> itemOrderInfoList; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ItemOrderInfo implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| @SerializedName(value = "goods_id") | |||||
| private String goodsId; | |||||
| /** | |||||
| * 是 | |||||
| * item_order_id列表,id个数与下单时对应goods_id的quantity一致 | |||||
| */ | |||||
| @SerializedName(value = "item_order_id_list") | |||||
| private List<String> itemOrderIdList; | |||||
| /** | |||||
| * 是 | |||||
| * 商品item_order详细信息,详情见 item_order_detail部分 | |||||
| */ | |||||
| @SerializedName(value = "item_order_detail") | |||||
| private List<String> itemOrderDetail; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ItemOrderDetail implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * item单id | |||||
| */ | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| /** | |||||
| * 商品优惠后价格 | |||||
| */ | |||||
| @SerializedName(value = "price") | |||||
| private Integer price; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| package com.iformall.douyin.payv2.util; | |||||
| import org.apache.http.client.methods.HttpRequestWrapper; | |||||
| import java.io.IOException; | |||||
| public interface Credentials { | |||||
| String getSchema(); | |||||
| String getToken(HttpRequestWrapper request) throws IOException; | |||||
| } | |||||
| @@ -0,0 +1,89 @@ | |||||
| package com.iformall.douyin.payv2.util; | |||||
| import me.chanjar.weixin.common.error.WxRuntimeException; | |||||
| import sun.misc.BASE64Decoder; | |||||
| import java.io.ByteArrayOutputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.security.KeyFactory; | |||||
| import java.security.NoSuchAlgorithmException; | |||||
| import java.security.PrivateKey; | |||||
| import java.security.PublicKey; | |||||
| import java.security.cert.*; | |||||
| import java.security.spec.InvalidKeySpecException; | |||||
| import java.security.spec.PKCS8EncodedKeySpec; | |||||
| import java.security.spec.X509EncodedKeySpec; | |||||
| import java.util.Base64; | |||||
| public class PemUtils { | |||||
| public static PrivateKey loadPrivateKey(InputStream inputStream) { | |||||
| try { | |||||
| ByteArrayOutputStream array = new ByteArrayOutputStream(); | |||||
| byte[] buffer = new byte[1024]; | |||||
| int length; | |||||
| while ((length = inputStream.read(buffer)) != -1) { | |||||
| array.write(buffer, 0, length); | |||||
| } | |||||
| String privateKey = array.toString("utf-8") | |||||
| .replace("-----BEGIN PRIVATE KEY-----", "") | |||||
| .replace("-----END PRIVATE KEY-----", "") | |||||
| .replaceAll("\\s+", ""); | |||||
| KeyFactory kf = KeyFactory.getInstance("RSA"); | |||||
| return kf.generatePrivate( | |||||
| new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))); | |||||
| } catch (NoSuchAlgorithmException e) { | |||||
| throw new WxRuntimeException("当前Java环境不支持RSA", e); | |||||
| } catch (InvalidKeySpecException e) { | |||||
| throw new WxRuntimeException("无效的密钥格式"); | |||||
| } catch (IOException e) { | |||||
| throw new WxRuntimeException("无效的密钥"); | |||||
| } | |||||
| } | |||||
| public static X509Certificate loadCertificate(InputStream inputStream) { | |||||
| try { | |||||
| CertificateFactory cf = CertificateFactory.getInstance("X509"); | |||||
| X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream); | |||||
| cert.checkValidity(); | |||||
| return cert; | |||||
| } catch (CertificateExpiredException e) { | |||||
| throw new WxRuntimeException("证书已过期", e); | |||||
| } catch (CertificateNotYetValidException e) { | |||||
| throw new WxRuntimeException("证书尚未生效", e); | |||||
| } catch (CertificateException e) { | |||||
| throw new WxRuntimeException("无效的证书", e); | |||||
| } | |||||
| } | |||||
| public static PublicKey loadPublicKey(InputStream inputStream) { | |||||
| try { | |||||
| ByteArrayOutputStream array = new ByteArrayOutputStream(); | |||||
| byte[] buffer = new byte[1024]; | |||||
| int length; | |||||
| while ((length = inputStream.read(buffer)) != -1) { | |||||
| array.write(buffer, 0, length); | |||||
| } | |||||
| String publicKey = array.toString("utf-8") | |||||
| .replace("-----BEGIN PUBLIC KEY-----", "") | |||||
| .replace("-----END PUBLIC KEY-----", "") | |||||
| .replaceAll("\\s+", ""); | |||||
| KeyFactory kf = KeyFactory.getInstance("RSA"); | |||||
| return kf.generatePublic( | |||||
| new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(publicKey))); | |||||
| } catch (NoSuchAlgorithmException e) { | |||||
| throw new WxRuntimeException("当前Java环境不支持RSA", e); | |||||
| } catch (InvalidKeySpecException e) { | |||||
| throw new WxRuntimeException("无效的密钥格式"); | |||||
| } catch (IOException e) { | |||||
| throw new WxRuntimeException("无效的密钥"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,81 @@ | |||||
| package com.iformall.douyin.payv2.util; | |||||
| import org.apache.http.HttpEntity; | |||||
| import org.apache.http.HttpEntityEnclosingRequest; | |||||
| import org.apache.http.HttpException; | |||||
| import org.apache.http.StatusLine; | |||||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||||
| import org.apache.http.client.methods.HttpExecutionAware; | |||||
| import org.apache.http.client.methods.HttpRequestWrapper; | |||||
| import org.apache.http.client.protocol.HttpClientContext; | |||||
| import org.apache.http.conn.routing.HttpRoute; | |||||
| import org.apache.http.entity.BufferedHttpEntity; | |||||
| import org.apache.http.entity.ByteArrayEntity; | |||||
| import org.apache.http.impl.execchain.ClientExecChain; | |||||
| import org.apache.http.util.EntityUtils; | |||||
| import java.io.IOException; | |||||
| public class SignatureExec implements ClientExecChain { | |||||
| final ClientExecChain mainExec; | |||||
| final Credentials credentials; | |||||
| final Validator validator; | |||||
| SignatureExec(Credentials credentials, Validator validator, ClientExecChain mainExec) { | |||||
| this.credentials = credentials; | |||||
| this.validator = validator; | |||||
| this.mainExec = mainExec; | |||||
| } | |||||
| protected HttpEntity newRepeatableEntity(HttpEntity entity) throws IOException { | |||||
| byte[] content = EntityUtils.toByteArray(entity); | |||||
| ByteArrayEntity newEntity = new ByteArrayEntity(content); | |||||
| newEntity.setContentEncoding(entity.getContentEncoding()); | |||||
| newEntity.setContentType(entity.getContentType()); | |||||
| return newEntity; | |||||
| } | |||||
| protected void convertToRepeatableResponseEntity(CloseableHttpResponse response) throws IOException { | |||||
| HttpEntity entity = response.getEntity(); | |||||
| if (entity != null && !entity.isRepeatable()) { | |||||
| response.setEntity(newRepeatableEntity(entity)); | |||||
| } | |||||
| } | |||||
| protected void convertToRepeatableRequestEntity(HttpRequestWrapper request) throws IOException { | |||||
| if (request instanceof HttpEntityEnclosingRequest) { | |||||
| HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); | |||||
| if (entity != null) { | |||||
| ((HttpEntityEnclosingRequest) request).setEntity(new BufferedHttpEntity(entity)); | |||||
| } | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public CloseableHttpResponse execute(HttpRoute route, HttpRequestWrapper request, | |||||
| HttpClientContext context, HttpExecutionAware execAware) throws IOException, HttpException { | |||||
| return executeWithSignature(route, request, context, execAware); | |||||
| } | |||||
| private CloseableHttpResponse executeWithSignature(HttpRoute route, HttpRequestWrapper request, | |||||
| HttpClientContext context, HttpExecutionAware execAware) throws IOException, HttpException { | |||||
| // 添加认证信息 | |||||
| request.addHeader("Byte-Authorization", | |||||
| credentials.getSchema() + " " + credentials.getToken(request)); | |||||
| // 执行 | |||||
| CloseableHttpResponse response = mainExec.execute(route, request, context, execAware); | |||||
| // 对成功应答验签 | |||||
| StatusLine statusLine = response.getStatusLine(); | |||||
| if (statusLine.getStatusCode() >= 200 && statusLine.getStatusCode() < 300) { | |||||
| convertToRepeatableResponseEntity(response); | |||||
| if (!validator.validate(response)) { | |||||
| throw new HttpException("应答的支付签名验证失败"); | |||||
| } | |||||
| } | |||||
| return response; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,70 @@ | |||||
| package com.iformall.douyin.payv2.util; | |||||
| import com.iformall.douyin.payv2.auth.*; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | |||||
| import org.apache.http.impl.client.HttpClientBuilder; | |||||
| import org.apache.http.impl.execchain.ClientExecChain; | |||||
| import java.security.PrivateKey; | |||||
| import java.security.PublicKey; | |||||
| public class TtPayV2HttpClientBuilder extends HttpClientBuilder { | |||||
| private Credentials credentials; | |||||
| private Validator validator; | |||||
| static final String OS = System.getProperty("os.name") + "/" + System.getProperty("os.version"); | |||||
| static final String VERSION = System.getProperty("java.version"); | |||||
| private TtPayV2HttpClientBuilder() { | |||||
| super(); | |||||
| String userAgent = String.format( | |||||
| "WechatPay-Apache-HttpClient/%s (%s) Java/%s", | |||||
| getClass().getPackage().getImplementationVersion(), | |||||
| OS, | |||||
| VERSION == null ? "Unknown" : VERSION); | |||||
| setUserAgent(userAgent); | |||||
| } | |||||
| public static TtPayV2HttpClientBuilder create() { | |||||
| return new TtPayV2HttpClientBuilder(); | |||||
| } | |||||
| public TtPayV2HttpClientBuilder withAppId(String appId, String serialNo, PrivateKey privateKey) { | |||||
| this.credentials = | |||||
| new TtPayCredentials(appId, new PrivateKeySigner(serialNo, privateKey)); | |||||
| return this; | |||||
| } | |||||
| public TtPayV2HttpClientBuilder withCredentials(Credentials credentials) { | |||||
| this.credentials = credentials; | |||||
| return this; | |||||
| } | |||||
| public TtPayV2HttpClientBuilder withPublicKey(PublicKey publicKey) { | |||||
| this.validator = new TtPayValidator(new CertificatesVerifier(publicKey)); | |||||
| return this; | |||||
| } | |||||
| public TtPayV2HttpClientBuilder withValidator(Validator validator) { | |||||
| this.validator = validator; | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public CloseableHttpClient build() { | |||||
| if (credentials == null) { | |||||
| throw new IllegalArgumentException("缺少身份认证信息"); | |||||
| } | |||||
| if (validator == null) { | |||||
| throw new IllegalArgumentException("缺少签名验证信息"); | |||||
| } | |||||
| return super.build(); | |||||
| } | |||||
| @Override | |||||
| protected ClientExecChain decorateProtocolExec(final ClientExecChain requestExecutor) { | |||||
| return new SignatureExec(this.credentials, this.validator, requestExecutor); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| package com.iformall.douyin.payv2.util; | |||||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||||
| import java.io.IOException; | |||||
| public interface Validator { | |||||
| boolean validate(CloseableHttpResponse response) throws IOException; | |||||
| } | |||||
| @@ -0,0 +1,108 @@ | |||||
| package com.iformall.douyin.web.api; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import me.chanjar.weixin.common.WxType; | |||||
| import me.chanjar.weixin.common.error.WxError; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | |||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | |||||
| import me.chanjar.weixin.common.util.http.ResponseHandler; | |||||
| import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.apache.http.HttpHost; | |||||
| import org.apache.http.client.config.RequestConfig; | |||||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||||
| import org.apache.http.client.methods.HttpGet; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import java.io.IOException; | |||||
| import java.util.regex.Matcher; | |||||
| import java.util.regex.Pattern; | |||||
| /** | |||||
| * . | |||||
| * | |||||
| * @author ecoolper | |||||
| * @date 2017/5/4 | |||||
| */ | |||||
| public class TtWebGoodsGetRequestExecutor implements RequestExecutor<String, String> { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| protected RequestHttp<CloseableHttpClient, HttpHost> requestHttp; | |||||
| public TtWebGoodsGetRequestExecutor(RequestHttp requestHttp) { | |||||
| this.requestHttp = requestHttp; | |||||
| } | |||||
| @Override | |||||
| public void execute(String uri, String data, ResponseHandler<String> handler, WxType wxType) throws WxErrorException, IOException { | |||||
| handler.handle(this.execute(uri, data, wxType)); | |||||
| } | |||||
| @Override | |||||
| public String execute(String uri, String queryParam, WxType wxType) throws WxErrorException, IOException { | |||||
| String access_token = handleUrl(uri); | |||||
| if(StringUtils.isBlank(access_token)){ | |||||
| WxError wxError = WxError.fromJson("{\n" + | |||||
| " \"description\": \"未找到access_token\",\n" + | |||||
| " \"error_code\": -1\n" + | |||||
| " }"); | |||||
| throw new WxErrorException(wxError); | |||||
| } | |||||
| if (queryParam != null) { | |||||
| if (uri.indexOf('?') == -1) { | |||||
| uri += '?'; | |||||
| } | |||||
| uri += uri.endsWith("?") ? queryParam : '&' + queryParam; | |||||
| } | |||||
| HttpGet httpGet = new HttpGet(uri); | |||||
| httpGet.addHeader("Content-Type","application/json"); | |||||
| httpGet.addHeader("access-token",access_token); | |||||
| logger.info("get请求地址uri{}"+uri); | |||||
| logger.info("header-----access_token{}"+access_token); | |||||
| if (requestHttp.getRequestHttpProxy() != null) { | |||||
| RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build(); | |||||
| httpGet.setConfig(config); | |||||
| } | |||||
| try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet)) { | |||||
| String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); | |||||
| logger.info("response{}"+responseContent); | |||||
| return responseContent; | |||||
| // JSONObject jsonObject = JSON.parseObject(responseContent); | |||||
| // JSONObject data = jsonObject.getJSONObject("data"); | |||||
| // WxError error = WxError.fromJson(data.toJSONString()); | |||||
| // if (error.getErrorCode() != 0) { | |||||
| // throw new WxErrorException(error); | |||||
| // } | |||||
| // return data.toString(); | |||||
| } finally { | |||||
| httpGet.releaseConnection(); | |||||
| } | |||||
| } | |||||
| //去除链接中access_token 并返回 | |||||
| private String handleUrl(String url){ | |||||
| String access_token = null; | |||||
| Pattern pXM = Pattern.compile("access_token=([^&]*)"); | |||||
| Matcher mXM = pXM.matcher(url); | |||||
| int i = 0; | |||||
| while (mXM.find()) { | |||||
| i++; | |||||
| access_token = mXM.group(1); | |||||
| } | |||||
| if(i > 1){ | |||||
| return null; | |||||
| } | |||||
| // url = url.replaceAll("&?access_token=[^&]*",""); | |||||
| return access_token; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,117 @@ | |||||
| package com.iformall.douyin.web.api; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import me.chanjar.weixin.common.WxType; | |||||
| import me.chanjar.weixin.common.error.WxError; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | |||||
| import me.chanjar.weixin.common.util.http.RequestHttp; | |||||
| import me.chanjar.weixin.common.util.http.ResponseHandler; | |||||
| import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.apache.http.Consts; | |||||
| import org.apache.http.HttpHost; | |||||
| import org.apache.http.client.config.RequestConfig; | |||||
| import org.apache.http.client.methods.CloseableHttpResponse; | |||||
| import org.apache.http.client.methods.HttpPost; | |||||
| import org.apache.http.entity.StringEntity; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import java.io.IOException; | |||||
| import java.util.regex.Matcher; | |||||
| import java.util.regex.Pattern; | |||||
| /** | |||||
| * . | |||||
| * | |||||
| * @author ecoolper | |||||
| * @date 2017/5/4 | |||||
| */ | |||||
| public class TtWebGoodsPostRequestExecutor implements RequestExecutor<String, String> { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| protected RequestHttp<CloseableHttpClient, HttpHost> requestHttp; | |||||
| public TtWebGoodsPostRequestExecutor(RequestHttp requestHttp) { | |||||
| this.requestHttp = requestHttp; | |||||
| } | |||||
| @Override | |||||
| public void execute(String uri, String data, ResponseHandler<String> handler, WxType wxType) | |||||
| throws WxErrorException, IOException { | |||||
| handler.handle(this.execute(uri, data, wxType)); | |||||
| } | |||||
| @Override | |||||
| public String execute(String uri, String postEntity, WxType wxType) throws WxErrorException, IOException { | |||||
| String access_token = handleUrl(uri); | |||||
| if(StringUtils.isBlank(access_token)){ | |||||
| WxError wxError = WxError.fromJson("{\n" + | |||||
| " \"description\": \"未找到access_token\",\n" + | |||||
| " \"error_code\": -1\n" + | |||||
| " }"); | |||||
| throw new WxErrorException(wxError); | |||||
| } | |||||
| HttpPost httpPost = new HttpPost(uri); | |||||
| httpPost.addHeader("Content-Type","application/json"); | |||||
| httpPost.addHeader("access-token",access_token); | |||||
| logger.info("post请求地址uri{}"+uri); | |||||
| logger.info("header-----access_token{}"+access_token); | |||||
| logger.info("请求参数{}"+postEntity); | |||||
| if (requestHttp.getRequestHttpProxy() != null) { | |||||
| RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build(); | |||||
| httpPost.setConfig(config); | |||||
| } | |||||
| if (postEntity != null) { | |||||
| StringEntity entity = new StringEntity(postEntity, Consts.UTF_8); | |||||
| entity.setContentType("application/json; charset=utf-8"); | |||||
| httpPost.setEntity(entity); | |||||
| } | |||||
| try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) { | |||||
| String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); | |||||
| logger.info("response{}"+responseContent); | |||||
| if (responseContent.isEmpty()) { | |||||
| throw new WxErrorException(WxError.builder().errorCode(9999).errorMsg("无响应内容").build()); | |||||
| } | |||||
| return responseContent; | |||||
| // if (responseContent.startsWith("<xml>")) { | |||||
| // //xml格式输出直接返回 | |||||
| // return responseContent; | |||||
| // } | |||||
| // JSONObject jsonObject = JSON.parseObject(responseContent); | |||||
| // JSONObject data = jsonObject.getJSONObject("data"); | |||||
| // WxError error = WxError.fromJson(data.toJSONString()); | |||||
| // if (error.getErrorCode() != 0) { | |||||
| // throw new WxErrorException(error); | |||||
| // } | |||||
| // return data.toString(); | |||||
| } finally { | |||||
| httpPost.releaseConnection(); | |||||
| } | |||||
| } | |||||
| //去除链接中access_token 并返回 | |||||
| private String handleUrl(String url){ | |||||
| String access_token = null; | |||||
| Pattern pXM = Pattern.compile("access_token=([^&]*)"); | |||||
| Matcher mXM = pXM.matcher(url); | |||||
| int i = 0; | |||||
| while (mXM.find()) { | |||||
| i++; | |||||
| access_token = mXM.group(1); | |||||
| } | |||||
| if(i > 1){ | |||||
| return null; | |||||
| } | |||||
| // url = url.replaceAll("&?access_token=[^&]*",""); | |||||
| return access_token; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,144 @@ | |||||
| package com.iformall.douyin.web.api; | |||||
| import com.iformall.douyin.web.bean.*; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 接入商品库 | |||||
| * | |||||
| * @author | |||||
| */ | |||||
| public interface TtWebGoodsService { | |||||
| /** | |||||
| *1 查询商品模板 | |||||
| */ | |||||
| String TEMPLATE_GET = "/life/goods/template/get/"; | |||||
| /** | |||||
| *2 查询商品草稿数据 | |||||
| */ | |||||
| String PRODUCT_DRAFT_GET = "/life/goods/product/draft/get/"; | |||||
| /** | |||||
| *3 查询商品草稿数据列表 | |||||
| */ | |||||
| String PRODUCT_DRAFT_LIST = "/life/goods/product/draft/list/"; | |||||
| /** | |||||
| *4 查询商品线上数据 | |||||
| */ | |||||
| String PRODUCT_ONLINE_GET = "/life/goods/product/online/get/"; | |||||
| /** | |||||
| *5 查询商品线上数据列表 | |||||
| */ | |||||
| String PRODUCT_ONLINE_LIST = "/life/goods/product/online/list/"; | |||||
| /** | |||||
| *6 创建/更新商品 | |||||
| */ | |||||
| String PRODUCT_SAVE = "/life/goods/product/save/"; | |||||
| /** | |||||
| *7 免审修改团购活动 | |||||
| */ | |||||
| String PRODUCT_FREE_AUDIT = "/life/goods/product/free_audit"; | |||||
| /** | |||||
| *8 创建/更新多SKU商品的SKU列表(团购/代金券不用对接这个接口) | |||||
| */ | |||||
| String SKU_BATCH_SAVE = "/life/goods/sku/batch_save/"; | |||||
| /** | |||||
| *9 上下架商品 | |||||
| */ | |||||
| String PRODUCT_OPERATE = "/life/goods/product/operate/"; | |||||
| /** | |||||
| *10 同步库存 | |||||
| */ | |||||
| String STOCK_SYNC = "/life/goods/stock/sync/"; | |||||
| /** | |||||
| * - 查询商品模板,创建商品时的属性列表需与该接口保持一致,否则无法识别 | |||||
| * category_id int TRUE 行业类目;详细见;商品类目表 https://bytedance.feishu.cn/docx/doxcnn02OUCTiKjpmzFR6ItdTye | |||||
| * product_type int TRUE 商品类型 商品类型 1-团购 11-代金券 | |||||
| */ | |||||
| GoodsTemplateGet templateGet(Integer category_id,Integer product_type) throws WxErrorException; | |||||
| /** | |||||
| * - 使用商品ID或外部商品ID查询商品草稿 | |||||
| * - 处于新建审核中、修改审核中、或审核成功、失败的数据可以通过该接口查询到 | |||||
| * - 一次最多查询10个草稿数据 | |||||
| * product_ids string TRUE 商品ID列表(逗号分隔) | |||||
| * out_ids string TRUE 外部商品ID列表(逗号分隔) | |||||
| */ | |||||
| List<Product> productDraftGet(String product_ids, String out_ids) throws WxErrorException ; | |||||
| /** | |||||
| * - 查询本client_key(或绑定的账号)对应的商品草稿列表 | |||||
| * - 处于审核中、或审核成功、失败的数据可以通过该接口查询到 | |||||
| * cursor string FALSE 第一页不传,之后用前一次返回的next_cursor传入进行翻页 | |||||
| * count int FALSE 分页数量,不传默认为5 | |||||
| * status int FALSE 过滤草稿状态,10-审核中 12-审核失败 1-审核通过 | |||||
| * | |||||
| */ | |||||
| ProductPage productDraftListGet(String cursor,Integer count,Integer status) throws WxErrorException ; | |||||
| /** | |||||
| * - - 使用商品ID或外部商品ID查询商品线上数据 | |||||
| * - 线上数据是指:通过审核后可以被用户看到的数据,包括在线、下线状态的数据 | |||||
| * product_ids string TRUE 商品ID列表(逗号分隔) | |||||
| * out_ids string TRUE 外部商品ID列表(逗号分隔) | |||||
| */ | |||||
| List<Product> productOnlineGet(String product_ids, String out_ids) throws WxErrorException ; | |||||
| /** | |||||
| * - 查询本client_key(或绑定的账号)对应的商品线上列表 | |||||
| * - 处于在线、下线、封禁状态的数据可以通过该接口查询到 | |||||
| * cursor string FALSE 第一页不传,之后用前一次返回的next_cursor传入进行翻页 | |||||
| * count int FALSE 分页数量,不传默认为5 | |||||
| * status int FALSE 过滤在线状态 1-在线 2-下线 3-封禁 | |||||
| * | |||||
| */ | |||||
| ProductPage productOnlineListGet(String cursor,Integer count,Integer status) throws WxErrorException ; | |||||
| /** | |||||
| * - 创建或更新商品 | |||||
| * - 对于同一服务商,相同的out_id会被认为是同一商品,重复创建会被覆盖 | |||||
| * - 商品和SKU属性,需要通过模板获取 | |||||
| * return - product_id 创建/更新商品成功后产生,与老接口spu_id一致 | |||||
| */ | |||||
| String productSave(Product product) throws WxErrorException ; | |||||
| /** | |||||
| * - 免审修改团购活动 | |||||
| * product_id string TRUE 商品id (商品id或商品外部id 选其一) | |||||
| * out_id string TRUE 商品外部id (商品id或商品外部id 选其一) | |||||
| * sold_end_time int64 FALSE 售卖结束时间 | |||||
| * stock_qty int64 FALSE 总库存 | |||||
| */ | |||||
| boolean productFreeAudit(String productId,String outId,Long soldEndTime,Integer stockQty) throws WxErrorException ; | |||||
| /** | |||||
| * 创建/更新多SKU商品的SKU列表(团购/代金券不用对接这个接口) | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| boolean skuBatchSave(ProductSku sku) throws WxErrorException ; | |||||
| /** | |||||
| * 上下架商品 | |||||
| * product_id string TRUE 商品id(若有第三方id可不传) | |||||
| * out_id string TRUE 商品第三方id | |||||
| * op_type int64 TRUE 1-上线 2-下线 | |||||
| * @return | |||||
| */ | |||||
| boolean productOperate(String product_id,String out_id,Integer op_type) throws WxErrorException ; | |||||
| /** | |||||
| * 同步库存 | |||||
| * product_id string TRUE 商品id(若有第三方id可不传) | |||||
| * out_id string TRUE 商品第三方id | |||||
| * stock StockStruct TRUE 库存信息 | |||||
| * - limit_type int TRUE 库存上限类型,为2时stock_qty和avail_qty字段无意义 1-有限库存 2-无限库存 | |||||
| * - stock_qty int TRUE 总库存,limit_type=2时无意义 | |||||
| */ | |||||
| boolean stockSync(String product_id,String out_id,Integer stock) throws WxErrorException ; | |||||
| } | |||||
| @@ -110,4 +110,6 @@ public interface TtWebService { | |||||
| */ | */ | ||||
| TtWebProductService getProductService(); | TtWebProductService getProductService(); | ||||
| TtWebGoodsService getGoodsService(); | |||||
| } | } | ||||
| @@ -0,0 +1,254 @@ | |||||
| package com.iformall.douyin.web.api.impl; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.alibaba.fastjson.TypeReference; | |||||
| import com.google.gson.Gson; | |||||
| import com.google.gson.GsonBuilder; | |||||
| import com.google.gson.JsonObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.douyin.pay.exception.TtPayException; | |||||
| import com.iformall.douyin.payv2.request.CallBackSettingsRequest; | |||||
| import com.iformall.douyin.payv2.result.BaseTtPayResult; | |||||
| import com.iformall.douyin.web.api.*; | |||||
| import com.iformall.douyin.web.bean.*; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import lombok.AllArgsConstructor; | |||||
| import me.chanjar.weixin.common.error.WxError; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * | |||||
| */ | |||||
| @AllArgsConstructor | |||||
| public class TtWebGoodsServiceImpl implements TtWebGoodsService { | |||||
| private static final Gson GSON = new GsonBuilder().create(); | |||||
| private TtWebService service; | |||||
| @Override | |||||
| public GoodsTemplateGet templateGet(Integer category_id, Integer product_type) throws WxErrorException { | |||||
| TtWebGoodsGetRequestExecutor getExecutor = new TtWebGoodsGetRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.TEMPLATE_GET; | |||||
| String param = "category_id=" + category_id | |||||
| + "&product_type=" + product_type; | |||||
| String result = this.service.execute(getExecutor, apiUrl, param); | |||||
| BaseGoodsResult<GoodsTemplateGet> baseResult = GSON.fromJson(result, | |||||
| new TypeReference<BaseGoodsResult<GoodsTemplateGet>>(){}.getType()); | |||||
| if(baseResult.isSuccess()){ | |||||
| return baseResult.getData(); | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public List<Product> productDraftGet(String product_ids, String out_ids) throws WxErrorException { | |||||
| TtWebGoodsGetRequestExecutor getExecutor = new TtWebGoodsGetRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.PRODUCT_DRAFT_GET; | |||||
| String param = "" ; | |||||
| if(StringUtils.isNotBlank(product_ids)){ | |||||
| param = "product_ids=" + product_ids; | |||||
| }else if(StringUtils.isNotBlank(out_ids)){ | |||||
| param = "out_ids=" + out_ids; | |||||
| } | |||||
| String result = this.service.execute(getExecutor, apiUrl, param); | |||||
| BaseGoodsResult baseResult = GSON.fromJson(result, BaseGoodsResult.class); | |||||
| if(baseResult.isSuccess()){ | |||||
| Map map = (Map) baseResult.getData(); | |||||
| if(map != null){ | |||||
| Object product_draft_list = map.get("product_draft_list"); | |||||
| List<Product> list = GSON.fromJson(GSON.toJson(product_draft_list), | |||||
| new TypeReference<List<Product>>() {}.getType()); | |||||
| return list; | |||||
| } | |||||
| return null; | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public ProductPage productDraftListGet(String cursor, Integer count, Integer status) throws WxErrorException { | |||||
| TtWebGoodsGetRequestExecutor getExecutor = new TtWebGoodsGetRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.PRODUCT_DRAFT_LIST; | |||||
| String param = "" ; | |||||
| if(count == null){ | |||||
| param = "count=" + 5; | |||||
| }else{ | |||||
| param = "count=" + count; | |||||
| } | |||||
| if(StringUtils.isNotBlank(cursor)){ | |||||
| param += "&cursor=" + cursor; | |||||
| } | |||||
| if(status != null){ | |||||
| param += "&status=" + status; | |||||
| } | |||||
| String result = this.service.execute(getExecutor, apiUrl, param); | |||||
| BaseGoodsResult<ProductPage> baseResult = GSON.fromJson(result, | |||||
| new TypeReference<BaseGoodsResult<ProductPage>>() {}.getType()); | |||||
| if(baseResult.isSuccess()){ | |||||
| return baseResult.getData(); | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public List<Product> productOnlineGet(String product_ids, String out_ids) throws WxErrorException { | |||||
| TtWebGoodsGetRequestExecutor getExecutor = new TtWebGoodsGetRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.PRODUCT_ONLINE_GET; | |||||
| String param = "" ; | |||||
| if(StringUtils.isNotBlank(product_ids)){ | |||||
| param = "product_ids=" + product_ids; | |||||
| }else if(StringUtils.isNotBlank(out_ids)){ | |||||
| param = "out_ids=" + out_ids; | |||||
| } | |||||
| String result = this.service.execute(getExecutor, apiUrl, param); | |||||
| BaseGoodsResult baseResult = GSON.fromJson(result, BaseGoodsResult.class); | |||||
| if(baseResult.isSuccess()){ | |||||
| Map map = (Map) baseResult.getData(); | |||||
| if(map != null){ | |||||
| Object product_online_list = map.get("product_online_list"); | |||||
| List<Product> list = GSON.fromJson(GSON.toJson(product_online_list), | |||||
| new TypeReference<List<Product>>() {}.getType()); | |||||
| return list; | |||||
| } | |||||
| return null; | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public ProductPage productOnlineListGet(String cursor, Integer count, Integer status) throws WxErrorException { | |||||
| TtWebGoodsGetRequestExecutor getExecutor = new TtWebGoodsGetRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.PRODUCT_ONLINE_LIST; | |||||
| String param = "" ; | |||||
| if(count == null){ | |||||
| param = "count=" + 5; | |||||
| }else{ | |||||
| param = "count=" + count; | |||||
| } | |||||
| if(StringUtils.isNotBlank(cursor)){ | |||||
| param += "&cursor=" + cursor; | |||||
| } | |||||
| if(status != null){ | |||||
| param += "&status=" + status; | |||||
| } | |||||
| String result = this.service.execute(getExecutor, apiUrl, param); | |||||
| BaseGoodsResult<ProductPage> baseResult = GSON.fromJson(result, | |||||
| new TypeReference<BaseGoodsResult<ProductPage>>() {}.getType()); | |||||
| if(baseResult.isSuccess()){ | |||||
| return baseResult.getData(); | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public String productSave(Product product) throws WxErrorException { | |||||
| TtWebGoodsPostRequestExecutor postExecutor = new TtWebGoodsPostRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.PRODUCT_SAVE; | |||||
| String result = this.service.execute(postExecutor, apiUrl, GSON.toJson(product)); | |||||
| BaseGoodsResult baseResult = GSON.fromJson(result, BaseGoodsResult.class); | |||||
| if(baseResult.isSuccess()){ | |||||
| Map map = (Map) baseResult.getData(); | |||||
| return map.get("product_id").toString(); | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public boolean productFreeAudit(String productId, String outId, Long soldEndTime, Integer stockQty) throws WxErrorException { | |||||
| TtWebGoodsPostRequestExecutor postExecutor = new TtWebGoodsPostRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.PRODUCT_FREE_AUDIT; | |||||
| Map<String,Object> map = new HashMap<>(); | |||||
| if(StringUtils.isNotBlank(productId)){ | |||||
| map.put("product_id",productId); | |||||
| }else if(StringUtils.isNotBlank(outId)){ | |||||
| map.put("out_id",outId); | |||||
| } | |||||
| if(soldEndTime != null){ | |||||
| map.put("sold_end_time",soldEndTime); | |||||
| } | |||||
| if(stockQty != null){ | |||||
| map.put("stock_qty",stockQty); | |||||
| } | |||||
| String result = this.service.execute(postExecutor, apiUrl, GSON.toJson(map)); | |||||
| BaseGoodsResult baseResult = GSON.fromJson(result, BaseGoodsResult.class); | |||||
| if(baseResult.isSuccess()){ | |||||
| return true; | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public boolean skuBatchSave(ProductSku sku) throws WxErrorException { | |||||
| TtWebGoodsPostRequestExecutor postExecutor = new TtWebGoodsPostRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.SKU_BATCH_SAVE; | |||||
| String result = this.service.execute(postExecutor, apiUrl, GSON.toJson(sku)); | |||||
| BaseGoodsResult baseResult = GSON.fromJson(result, BaseGoodsResult.class); | |||||
| if(baseResult.isSuccess()){ | |||||
| return true; | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public boolean productOperate(String product_id, String out_id, Integer op_type) throws WxErrorException { | |||||
| TtWebGoodsPostRequestExecutor postExecutor = new TtWebGoodsPostRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.PRODUCT_OPERATE; | |||||
| Map<String,Object> map = new HashMap<>(); | |||||
| if(StringUtils.isNotBlank(product_id)){ | |||||
| map.put("product_id",product_id); | |||||
| }else if(StringUtils.isNotBlank(out_id)){ | |||||
| map.put("out_id",out_id); | |||||
| } | |||||
| map.put("op_type",op_type); | |||||
| String result = this.service.execute(postExecutor, apiUrl, GSON.toJson(map)); | |||||
| BaseGoodsResult baseResult = GSON.fromJson(result, BaseGoodsResult.class); | |||||
| if(baseResult.isSuccess()){ | |||||
| return true; | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public boolean stockSync(String product_id, String out_id, Integer stock) throws WxErrorException { | |||||
| TtWebGoodsPostRequestExecutor postExecutor = new TtWebGoodsPostRequestExecutor(this.service.getRequestHttp()); | |||||
| String apiUrl = this.service.getTtWebConfig().getApiBegin().getPrefix() + this.STOCK_SYNC; | |||||
| Map<String,Object> map = new HashMap<>(); | |||||
| if(StringUtils.isNotBlank(product_id)){ | |||||
| map.put("product_id",product_id); | |||||
| }else if(StringUtils.isNotBlank(out_id)){ | |||||
| map.put("out_id",out_id); | |||||
| } | |||||
| Map<String,Integer> stockStruct = new HashMap<>(); | |||||
| if(stock == null || stock < 0){ | |||||
| stockStruct.put("limit_type",2); | |||||
| }else{ | |||||
| stockStruct.put("limit_type",1); | |||||
| stockStruct.put("stock_qty",stock); | |||||
| } | |||||
| map.put("stock",stockStruct); | |||||
| String result = this.service.execute(postExecutor, apiUrl, GSON.toJson(map)); | |||||
| BaseGoodsResult baseResult = GSON.fromJson(result, BaseGoodsResult.class); | |||||
| if(baseResult.isSuccess()){ | |||||
| return true; | |||||
| }else{ | |||||
| throw new WxErrorException(WxError.builder().errorCode(baseResult.getErrCode()).errorMsg(baseResult.getErrMsg()).build()); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | import com.alibaba.fastjson.JSONObject; | ||||
| import com.google.gson.Gson; | import com.google.gson.Gson; | ||||
| import com.google.gson.JsonParser; | import com.google.gson.JsonParser; | ||||
| import com.iformall.douyin.web.api.TtWebGoodsService; | |||||
| import com.iformall.douyin.web.api.TtWebProductService; | import com.iformall.douyin.web.api.TtWebProductService; | ||||
| import com.iformall.douyin.web.api.TtWebService; | import com.iformall.douyin.web.api.TtWebService; | ||||
| import com.iformall.douyin.web.api.TtWebShopMatchService; | import com.iformall.douyin.web.api.TtWebShopMatchService; | ||||
| @@ -51,6 +52,7 @@ public class TtWebServiceImpl implements TtWebService, RequestHttp<CloseableHttp | |||||
| private TtWebShopMatchService shopMatchService = new TtWebShopMatchServiceImpl(this); | private TtWebShopMatchService shopMatchService = new TtWebShopMatchServiceImpl(this); | ||||
| private TtWebProductService productService = new TtWebProductServiceImpl(this); | private TtWebProductService productService = new TtWebProductServiceImpl(this); | ||||
| private TtWebGoodsServiceImpl goodService = new TtWebGoodsServiceImpl(this); | |||||
| private int retrySleepMillis = 1000; | private int retrySleepMillis = 1000; | ||||
| private int maxRetryTimes = 5; | private int maxRetryTimes = 5; | ||||
| @@ -198,7 +200,7 @@ public class TtWebServiceImpl implements TtWebService, RequestHttp<CloseableHttp | |||||
| if (error.getErrorCode() == -1) { | if (error.getErrorCode() == -1) { | ||||
| int sleepMillis = this.retrySleepMillis * (1 << retryTimes); | int sleepMillis = this.retrySleepMillis * (1 << retryTimes); | ||||
| try { | try { | ||||
| log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); | |||||
| log.warn("系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); | |||||
| Thread.sleep(sleepMillis); | Thread.sleep(sleepMillis); | ||||
| } catch (InterruptedException e1) { | } catch (InterruptedException e1) { | ||||
| Thread.currentThread().interrupt(); | Thread.currentThread().interrupt(); | ||||
| @@ -294,4 +296,9 @@ public class TtWebServiceImpl implements TtWebService, RequestHttp<CloseableHttp | |||||
| return this.productService; | return this.productService; | ||||
| } | } | ||||
| @Override | |||||
| public TtWebGoodsService getGoodsService() { | |||||
| return this.goodService; | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,90 @@ | |||||
| package com.iformall.douyin.web.bean; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 商品. | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class BaseGoodsResult<T> implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * | |||||
| */ | |||||
| @SerializedName(value = "base") | |||||
| private BaseResult base; | |||||
| public Integer getErrCode() { | |||||
| if(base.getGatewayCode().intValue() != 0){ | |||||
| return base.getGatewayCode(); | |||||
| }else if(base.getBizCode().intValue() != 0){ | |||||
| return base.getBizCode(); | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| public boolean isSuccess() { | |||||
| if(base.getGatewayCode().intValue() == 0 | |||||
| && base.getBizCode().intValue() == 0){ | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public String getErrMsg() { | |||||
| if(base.getGatewayCode().intValue() != 0){ | |||||
| return base.getGatewayMsg(); | |||||
| }else if(base.getBizCode().intValue() != 0){ | |||||
| return base.getBizMsg(); | |||||
| } | |||||
| return ""; | |||||
| } | |||||
| @SerializedName(value = "data") | |||||
| private T data; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class BaseResult<T> implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 请求日志ID | |||||
| */ | |||||
| @SerializedName(value = "log_id") | |||||
| private String logId; | |||||
| /** | |||||
| * 网关状态码 | |||||
| */ | |||||
| @SerializedName(value = "gateway_code") | |||||
| private Integer gatewayCode; | |||||
| /** | |||||
| * 网关状态信息 | |||||
| */ | |||||
| @SerializedName(value = "gateway_msg") | |||||
| private String gatewayMsg; | |||||
| /** | |||||
| * 业务状态码 | |||||
| */ | |||||
| @SerializedName(value = "biz_code") | |||||
| private Integer bizCode; | |||||
| /** | |||||
| * 业务状态信息 | |||||
| */ | |||||
| @SerializedName(value = "biz_msg") | |||||
| private String bizMsg; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,91 @@ | |||||
| package com.iformall.douyin.web.bean; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 结果通知. | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class GoodsTemplateGet implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 商品属性列表 | |||||
| */ | |||||
| @SerializedName(value = "product_attrs") | |||||
| private List<ProductAttrs> productAttrs; | |||||
| /** | |||||
| * SKU属性列表 | |||||
| */ | |||||
| @SerializedName(value = "sku_attrs") | |||||
| private List<ProductAttrs> skuAttrs; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ProductAttrs implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 属性描述 | |||||
| */ | |||||
| @SerializedName(value = "desc") | |||||
| private String desc; | |||||
| /** | |||||
| * 是否列表 | |||||
| */ | |||||
| @SerializedName(value = "is_multi") | |||||
| private Boolean isMulti; | |||||
| /** | |||||
| * 是否必填 | |||||
| */ | |||||
| @SerializedName(value = "is_required") | |||||
| private Boolean isRequired; | |||||
| /** | |||||
| * 是否展示 | |||||
| */ | |||||
| @SerializedName(value = "is_show") | |||||
| private Boolean isShow; | |||||
| /** | |||||
| * 属性key | |||||
| */ | |||||
| @SerializedName(value = "key") | |||||
| private String key; | |||||
| /** | |||||
| * 属性名称 | |||||
| */ | |||||
| @SerializedName(value = "name") | |||||
| private String name; | |||||
| /** | |||||
| * 属性类型 | |||||
| */ | |||||
| @SerializedName(value = "value_demo") | |||||
| private String valueDemo; | |||||
| /** | |||||
| * 属性样例 | |||||
| */ | |||||
| @SerializedName(value = "value_type") | |||||
| private String valueType; | |||||
| @SerializedName(value = "data") | |||||
| private String data; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,252 @@ | |||||
| package com.iformall.douyin.web.bean; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 商品. | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class Product implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 草稿状态 10-审核中 12-审核失败 1-审核通过 | |||||
| */ | |||||
| @SerializedName(value = "draft_status") | |||||
| private Integer draftStatus; | |||||
| /** | |||||
| * 审核失败原因 | |||||
| */ | |||||
| @SerializedName(value = "audit_msg") | |||||
| private String auditMsg; | |||||
| /** | |||||
| * 在线状态 1-在线 2-下线 3-封禁 | |||||
| */ | |||||
| @SerializedName(value = "online_status") | |||||
| private Integer onlineStatus; | |||||
| /** | |||||
| * 商品 | |||||
| */ | |||||
| @SerializedName(value = "product") | |||||
| private ProductStruct product; | |||||
| /** | |||||
| * 商品 | |||||
| */ | |||||
| @SerializedName(value = "sku") | |||||
| private SkuStruct sku; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class ProductStruct implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 商品Id | |||||
| * 创建时不必填写,更新时如有out_id可不填写 | |||||
| */ | |||||
| @SerializedName(value = "product_id") | |||||
| private String productId; | |||||
| /** | |||||
| * 外部商品id | |||||
| */ | |||||
| @SerializedName(value = "out_id") | |||||
| private String outId; | |||||
| /** | |||||
| * 商品名 | |||||
| */ | |||||
| @SerializedName(value = "product_name") | |||||
| private String productName; | |||||
| /** | |||||
| * 品类全名,保存时不必填写 | |||||
| */ | |||||
| @SerializedName(value = "category_full_name") | |||||
| private String categoryFullName; | |||||
| /** | |||||
| * 品类id | |||||
| */ | |||||
| @SerializedName(value = "category_id") | |||||
| private Integer categoryId; | |||||
| /** | |||||
| * 商品类型 1-团购 11-代金券 | |||||
| */ | |||||
| @SerializedName(value = "product_type") | |||||
| private Integer productType; | |||||
| /** | |||||
| * 业务线 1-闭环自研开发者 3-直连服务商 5-小程序 | |||||
| */ | |||||
| @SerializedName(value = "biz_line") | |||||
| private Integer bizLine; | |||||
| /** | |||||
| * 商家名 | |||||
| */ | |||||
| @SerializedName(value = "account_name") | |||||
| private String accountName; | |||||
| /** | |||||
| * 售卖开始时间 | |||||
| */ | |||||
| @SerializedName(value = "sold_start_time") | |||||
| private Long soldStartTime; | |||||
| /** | |||||
| * 售卖结束时间 | |||||
| */ | |||||
| @SerializedName(value = "sold_end_time") | |||||
| private Long soldEndTime; | |||||
| /** | |||||
| * 创建时间,保存时不必填写 | |||||
| */ | |||||
| @SerializedName(value = "create_time") | |||||
| private Long createTime; | |||||
| /** | |||||
| * 更新时间,保存时不必填写 | |||||
| */ | |||||
| @SerializedName(value = "update_time") | |||||
| private Long updateTime; | |||||
| /** | |||||
| * 第三方跳转链接,小程序商品必填 | |||||
| */ | |||||
| @SerializedName(value = "out_url") | |||||
| private String outUrl; | |||||
| /** | |||||
| * 店铺列表 | |||||
| */ | |||||
| @SerializedName(value = "poi_list") | |||||
| private List<PoiStruct> poiList; | |||||
| /** | |||||
| * 商品属性KV | |||||
| */ | |||||
| @SerializedName(value = "attr_key_value_map") | |||||
| private Map<String,String> attrKeyValueMap; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class PoiStruct implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 接入方店铺id,保存时必传 | |||||
| */ | |||||
| @SerializedName(value = "supplier_ext_id") | |||||
| private String supplierExtId; | |||||
| /** | |||||
| * poi id,保存时不必填写 | |||||
| */ | |||||
| @SerializedName(value = "poi_id") | |||||
| private Long poiId; | |||||
| /** | |||||
| * 店铺id,保存时不必填写 | |||||
| */ | |||||
| @SerializedName(value = "supplier_id") | |||||
| private Long supplierId; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class SkuStruct implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * sku id,创建时不必填写 | |||||
| */ | |||||
| @SerializedName(value = "sku_id") | |||||
| private String skuId; | |||||
| /** | |||||
| * 接入方店铺id,保存时必传 | |||||
| */ | |||||
| @SerializedName(value = "sku_name") | |||||
| private String skuName; | |||||
| /** | |||||
| * 原价,团购创建时可不填,会根据商品搭配计算原价 | |||||
| */ | |||||
| @SerializedName(value = "origin_amount") | |||||
| private Integer originAmount; | |||||
| /** | |||||
| * 实际支付价格 | |||||
| */ | |||||
| @SerializedName(value = "actual_amount") | |||||
| private Integer actualAmount; | |||||
| /** | |||||
| * 库存信息 | |||||
| */ | |||||
| @SerializedName(value = "stock") | |||||
| private StockStruct stock; | |||||
| /** | |||||
| * 第三方id | |||||
| */ | |||||
| @SerializedName(value = "out_sku_id") | |||||
| private String outSkuId; | |||||
| /** | |||||
| * 状态 1-在线 -1-删除 | |||||
| */ | |||||
| @SerializedName(value = "status") | |||||
| private Integer status; | |||||
| /** | |||||
| * sku属性KV | |||||
| */ | |||||
| @SerializedName(value = "attr_key_value_map") | |||||
| private Map<String,String> attrKeyValueMap; | |||||
| } | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public static class StockStruct implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 库存上限类型, | |||||
| * 为2时stock_qty和avail_qty字段无意义 | |||||
| * 1-有限库存 2-无限库存 | |||||
| */ | |||||
| @SerializedName(value = "limit_type") | |||||
| private Integer limitType; | |||||
| /** | |||||
| * 总库存, | |||||
| * limit_type=2时无意义 | |||||
| */ | |||||
| @SerializedName(value = "stock_qty") | |||||
| private Integer stockQty; | |||||
| /** | |||||
| * 可用库存, | |||||
| * limit_type=2时无意义, | |||||
| * 始终保证stock_qty=avail_qty+frozen_qty+sold_qty | |||||
| */ | |||||
| @SerializedName(value = "avail_qty") | |||||
| private Integer availQty; | |||||
| /** | |||||
| * 冻结库存,保存SKU时不填 | |||||
| */ | |||||
| @SerializedName(value = "frozen_qty") | |||||
| private Integer frozenQty; | |||||
| /** | |||||
| * 售卖库存, 退款回滚,保存SKU时不填 | |||||
| */ | |||||
| @SerializedName(value = "sold_qty") | |||||
| private Integer soldQty; | |||||
| /** | |||||
| * 销量,退款不回滚,保存SKU时不填 | |||||
| */ | |||||
| @SerializedName(value = "sold_count") | |||||
| private Integer soldCount; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| package com.iformall.douyin.web.bean; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 商品. | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class ProductPage implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 用于查询下一页 | |||||
| */ | |||||
| @SerializedName(value = "next_cursor") | |||||
| private String nextCursor; | |||||
| /** | |||||
| * 是否还有下一页 | |||||
| */ | |||||
| @SerializedName(value = "has_more") | |||||
| private boolean hasMore; | |||||
| /** | |||||
| * 商品 | |||||
| */ | |||||
| @SerializedName(value = "product_list") | |||||
| private List<Product> productList; | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| package com.iformall.douyin.web.bean; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 商品. | |||||
| * | |||||
| * @author thinsstar | |||||
| */ | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| public class ProductSku implements Serializable { | |||||
| private static final long serialVersionUID = -1L; | |||||
| /** | |||||
| * 商品Id | |||||
| * 创建时不必填写,更新时如有out_id可不填写 | |||||
| */ | |||||
| @SerializedName(value = "product_id") | |||||
| private String productId; | |||||
| /** | |||||
| * 外部商品id | |||||
| */ | |||||
| @SerializedName(value = "out_id") | |||||
| private String outId; | |||||
| /** | |||||
| * 商品 | |||||
| */ | |||||
| @SerializedName(value = "sku_list") | |||||
| private List<Product.SkuStruct> skuList; | |||||
| } | |||||
| @@ -7,8 +7,12 @@ public enum EnumCouponChannelStatus { | |||||
| // 0-草稿/待生效;1-已生效/已发布/已投放;2-已下架; | // 0-草稿/待生效;1-已生效/已发布/已投放;2-已下架; | ||||
| STATUS_BEFORE(-1, "预上线"),//审核用 | |||||
| STATUS_THROW_IN(0, "已上架"), | STATUS_THROW_IN(0, "已上架"), | ||||
| STATUS_TAKE_OFFF(1, "已下架"), | STATUS_TAKE_OFFF(1, "已下架"), | ||||
| STATUS_AFTER(2, "作废"), | |||||
| ; | ; | ||||
| public static EnumCouponChannelStatus getEnum(Integer code) { | public static EnumCouponChannelStatus getEnum(Integer code) { | ||||
| @@ -25,6 +25,8 @@ public enum EnumMsgRecordType { | |||||
| INSIDE_PRODUCT_PUSH(109, "商品状态或库存同步"), | INSIDE_PRODUCT_PUSH(109, "商品状态或库存同步"), | ||||
| MALL_COO_USER_PUSH(110, "猫酷同步会员"), | MALL_COO_USER_PUSH(110, "猫酷同步会员"), | ||||
| INSIDE_ORDER_PUSH_DELIVERY(200, "2.0核销同步"), | |||||
| ; | ; | ||||
| public static EnumMsgRecordType getEnum(Integer code) { | public static EnumMsgRecordType getEnum(Integer code) { | ||||
| @@ -5,10 +5,11 @@ package com.iformall.enums; | |||||
| */ | */ | ||||
| public enum EnumPushType { | public enum EnumPushType { | ||||
| // 1-B端, 2-C端, 3-服务号, 4-订阅号 | |||||
| // | |||||
| SPU_STATUS_SYNC(1, "同步状态"), | SPU_STATUS_SYNC(1, "同步状态"), | ||||
| SPU_STOCK_SYNC(2, "同步库存"), | SPU_STOCK_SYNC(2, "同步库存"), | ||||
| SPU_FREE_AUDIT_SYNC(3, "免审修改"), | |||||
| ; | ; | ||||
| public static EnumPushType getEnum(Integer code) { | public static EnumPushType getEnum(Integer code) { | ||||
| @@ -11,6 +11,7 @@ public enum EnumSpuSyncStatus { | |||||
| sync_pull_off(2, "下架"), | sync_pull_off(2, "下架"), | ||||
| sync_audit_rejection(3, "审核拒绝"), | sync_audit_rejection(3, "审核拒绝"), | ||||
| sync_audit_pass(4, "审核通过"), | sync_audit_pass(4, "审核通过"), | ||||
| sync_audit_disable(5, "封禁"), | |||||
| ; | ; | ||||
| public static EnumSpuSyncStatus getEnum(Integer code) { | public static EnumSpuSyncStatus getEnum(Integer code) { | ||||
| @@ -0,0 +1,52 @@ | |||||
| package com.iformall.enums; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by Stormeye on 2018/08/09. | |||||
| */ | |||||
| public enum EnumTtProductType { | |||||
| //1 : 团购套餐 | |||||
| //3 : 预售券 | |||||
| //4 : 日历房 | |||||
| //5 : 门票 | |||||
| //7 : 旅行跟拍 | |||||
| //8 : 一日游 | |||||
| //11 : 代金券 | |||||
| PRODUCT_TUANGOU(1, "团购套餐"), | |||||
| PRODUCT_YUSHOU(3, "预售券"), | |||||
| PRODUCT_RILI(4, "日历房"),//没用 | |||||
| PRODUCT_MENGPIAO(5, "门票"), | |||||
| PRODUCT_LVPAI(7, "旅行跟拍"), | |||||
| PRODUCT_YIRIYOU(8, "一日游"), | |||||
| PRODUCT_DAIJIN(11, "代金券"), | |||||
| ; | |||||
| public static EnumTtProductType getEnum(Integer code) { | |||||
| for (EnumTtProductType value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumTtProductType(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -13,4 +13,10 @@ public interface TtCouponChannelPoiMapper extends CommonMapper<TtCouponChannelPo | |||||
| List<Long> findIdList(TtCouponChannelPoi record); | List<Long> findIdList(TtCouponChannelPoi record); | ||||
| Integer getPoiPutOnCount(@Param("tenantId")String tenantId, @Param("ids")List<Long> ids); | Integer getPoiPutOnCount(@Param("tenantId")String tenantId, @Param("ids")List<Long> ids); | ||||
| int updateBySpuId(TtCouponChannelPoi couponChannelPoi); | |||||
| TtCouponChannelPoi selectById(@Param("tenantId")String tenantId,@Param("id")Long id); | |||||
| TtCouponChannelPoi selectByChannelId(@Param("tenantId")String tenantId,@Param("couponChannelId")Long couponChannelId); | |||||
| } | } | ||||
| @@ -0,0 +1,13 @@ | |||||
| package com.iformall.mapper; | |||||
| import com.iformall.common.CommonMapper; | |||||
| import com.iformall.domain.po.TtGoodsCategory; | |||||
| import com.iformall.domain.po.WxSubBusiness; | |||||
| import java.util.List; | |||||
| public interface TtGoodsCategoryMapper extends CommonMapper<TtGoodsCategory, String> { | |||||
| List<TtGoodsCategory> findListAll(); | |||||
| } | |||||
| @@ -5,6 +5,7 @@ import com.iformall.common.CommonMapper; | |||||
| import com.iformall.domain.po.WxTopic; | import com.iformall.domain.po.WxTopic; | ||||
| import com.iformall.domain.po.base.TenantEntity; | import com.iformall.domain.po.base.TenantEntity; | ||||
| import com.iformall.domain.po.WxCouponChannel; | import com.iformall.domain.po.WxCouponChannel; | ||||
| import com.iformall.domain.vo.TtCouponChannelVo; | |||||
| import org.apache.ibatis.annotations.Param; | import org.apache.ibatis.annotations.Param; | ||||
| public interface WxCouponChannelMapper extends CommonMapper<WxCouponChannel, String> { | public interface WxCouponChannelMapper extends CommonMapper<WxCouponChannel, String> { | ||||
| @@ -25,13 +26,13 @@ public interface WxCouponChannelMapper extends CommonMapper<WxCouponChannel, Str | |||||
| int updateEndTimeByCouponId(WxCouponChannel wxCouponChannel); | int updateEndTimeByCouponId(WxCouponChannel wxCouponChannel); | ||||
| List<Long> getExpiriedCouponChannelIdsByEndTime(@Param("tenantId")String tenantId);//同步poi状态 | |||||
| List<Long> getExpiriedCouponIdsByEndTime(@Param("tenantId")String tenantId);//同步poi状态 | |||||
| void offExpiriedCouponChannelByEndTime(@Param("tenantId")String tenantId); | void offExpiriedCouponChannelByEndTime(@Param("tenantId")String tenantId); | ||||
| List<Long> getExpiriedCouponChannelIdsByValidDate(@Param("tenantId")String tenantId);//同步poi状态 | |||||
| List<Long> getExpiriedCouponIdsByValidDate(@Param("tenantId")String tenantId);//同步poi状态 | |||||
| void offExpiriedCouponChannelByValidDate(@Param("tenantId")String tenantId); | void offExpiriedCouponChannelByValidDate(@Param("tenantId")String tenantId); | ||||
| List<Long> getExpiriedCouponChannelIdsByCouponStatus(@Param("tenantId")String tenantId);//同步poi状态 | |||||
| List<Long> getExpiriedCouponIdsByCouponStatus(@Param("tenantId")String tenantId);//同步poi状态 | |||||
| void offExpiriedCouponChannelByCouponStatus(@Param("tenantId")String tenantId); | void offExpiriedCouponChannelByCouponStatus(@Param("tenantId")String tenantId); | ||||
| void offExpiriedCouponChannel2ByEndTime(@Param("tenantId")String tenantId); | void offExpiriedCouponChannel2ByEndTime(@Param("tenantId")String tenantId); | ||||
| @@ -50,14 +51,6 @@ public interface WxCouponChannelMapper extends CommonMapper<WxCouponChannel, Str | |||||
| List<WxCouponChannel> newfindCList(WxCouponChannel wxCouponChannel); | List<WxCouponChannel> newfindCList(WxCouponChannel wxCouponChannel); | ||||
| List<WxCouponChannel> liveHomeList(WxCouponChannel wxCouponChannel); | List<WxCouponChannel> liveHomeList(WxCouponChannel wxCouponChannel); | ||||
| /** | |||||
| * 查询已同步的上架卷的Id | |||||
| * @param tenantId | |||||
| * @param id | |||||
| * @return | |||||
| */ | |||||
| List<Long> getPoiProductIdList(@Param("tenantId")String tenantId, @Param("couponId")Long couponId); | |||||
| Integer reduceChannelStock(@Param("id")Long id,@Param("tenantId")String tenantId,@Param("number")Integer number); | Integer reduceChannelStock(@Param("id")Long id,@Param("tenantId")String tenantId,@Param("number")Integer number); | ||||
| @@ -72,4 +65,5 @@ public interface WxCouponChannelMapper extends CommonMapper<WxCouponChannel, Str | |||||
| WxCouponChannel getPriceAndStock(@Param("id")Long id,@Param("tenantId")String tenantId); | WxCouponChannel getPriceAndStock(@Param("id")Long id,@Param("tenantId")String tenantId); | ||||
| List<WxCouponChannel> batGetPriceAndStock(@Param("ids")List<Long> ids,@Param("tenantId")String tenantId); | List<WxCouponChannel> batGetPriceAndStock(@Param("ids")List<Long> ids,@Param("tenantId")String tenantId); | ||||
| List<TtCouponChannelVo> ttChannelList(TtCouponChannelVo ttChannelVo); | |||||
| } | } | ||||