| @@ -149,6 +149,8 @@ public class ShiroConfig { | |||||
| //商场初始化init | //商场初始化init | ||||
| filterChainDefinitionMap.put("/wxProjectConfig/**", "anon"); | filterChainDefinitionMap.put("/wxProjectConfig/**", "anon"); | ||||
| // filterChainDefinitionMap.put("/wxCoupon/goods/**", "anon"); | |||||
| // //test | // //test | ||||
| // filterChainDefinitionMap.put("/merchantPoi/spuSync", "anon"); | // filterChainDefinitionMap.put("/merchantPoi/spuSync", "anon"); | ||||
| // filterChainDefinitionMap.put("/merchantPoi/spuGet", "anon"); | // filterChainDefinitionMap.put("/merchantPoi/spuGet", "anon"); | ||||
| @@ -14,13 +14,10 @@ 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.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 +26,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; | ||||
| @@ -60,6 +58,8 @@ public class WxCouponController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private WxMallService wxMallService; | private WxMallService wxMallService; | ||||
| @Autowired | @Autowired | ||||
| private TtMerchantPoiService ttMerchantPoiService; | |||||
| @Autowired | |||||
| RedisLock redisLock; | RedisLock redisLock; | ||||
| @Autowired | @Autowired | ||||
| @@ -543,4 +543,23 @@ public class WxCouponController extends BaseController { | |||||
| return result; | return result; | ||||
| } | } | ||||
| @ApiOperation("根据类目获取商品模板") | |||||
| @GetMapping("/goods/getTemplate") | |||||
| @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||||
| @SystemControllerLog(description = "根据类目获取商品模板") | |||||
| public ResultData getGoodsTemplate(Integer categoryId,Integer productType) { | |||||
| logger.debug("[" + getIpAddr() + "] WxCouponController::getGoodsTemplate"); | |||||
| if(productType == null){ | |||||
| productType = 1; | |||||
| } | |||||
| try { | |||||
| GoodsTemplateGet goodsTemplateGet = ttMerchantPoiService.getTtWebService(getTenantInfo()).getGoodsService().templateGet(categoryId, productType); | |||||
| return new ResultData(goodsTemplateGet); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| return new ResultData(ErrorCode.SYS_SERVER_ERROR.getCode(),e.getMessage()); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -1,5 +1,7 @@ | |||||
| package com.iformall.controller; | package com.iformall.controller; | ||||
| import com.alibaba.fastjson.JSON; | |||||
| 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.binarywang.wxpay.bean.ecommerce.SignatureHeader; | ||||
| import com.github.pagehelper.PageInfo; | import com.github.pagehelper.PageInfo; | ||||
| @@ -13,16 +15,22 @@ import com.iformall.domain.dto.OrderSaveDto; | |||||
| import com.iformall.domain.dto.PlatPushOrderSaveDto; | 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.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.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.utils.Constant; | import com.iformall.utils.Constant; | ||||
| 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; | ||||
| @@ -55,6 +63,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; | ||||
| @@ -76,6 +87,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; | ||||
| @@ -144,6 +158,8 @@ public class WxOrderController extends BaseController { | |||||
| @ApiOperation(value = "抖音支付2.0与下单回调推送订单", notes = "{\"couponChannelId\":\"String\",\"couponId\":\"String\",\"press\":\"String\",\"orderGroupId\":\"String\",\"formId\":\"String\"}") | @ApiOperation(value = "抖音支付2.0与下单回调推送订单", notes = "{\"couponChannelId\":\"String\",\"couponId\":\"String\",\"press\":\"String\",\"orderGroupId\":\"String\",\"formId\":\"String\"}") | ||||
| @PostMapping("douyinPushOrder") | @PostMapping("douyinPushOrder") | ||||
| public Map<String,Object> douyinPushOrder(HttpServletRequest request) { | public Map<String,Object> douyinPushOrder(HttpServletRequest request) { | ||||
| Map<String, Object> map = new HashMap(); | |||||
| SignatureHeader header = new SignatureHeader(); | SignatureHeader header = new SignatureHeader(); | ||||
| header.setTimeStamp(request.getHeader("Byte-Timestamp")); | header.setTimeStamp(request.getHeader("Byte-Timestamp")); | ||||
| header.setNonce(request.getHeader("Byte-Nonce-Str")); | header.setNonce(request.getHeader("Byte-Nonce-Str")); | ||||
| @@ -154,27 +170,105 @@ public class WxOrderController extends BaseController { | |||||
| String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); | String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); | ||||
| logger.info("支付2.0预下单回调---body{}"+body); | logger.info("支付2.0预下单回调---body{}"+body); | ||||
| Map<String, Object> map = new HashMap(); | |||||
| map.put("err_no",1000); | |||||
| map.put("err_tips","库存不足"); | |||||
| return map; | |||||
| JSONObject jsonObject = JSONObject.parseObject(body); | |||||
| String app_id = jsonObject.getString("app_id"); | |||||
| String open_id = jsonObject.getString("open_id"); | |||||
| //验证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; | |||||
| } | |||||
| //验证用户 | |||||
| Long memberId = null; | |||||
| TtCUser cuser = (TtCUser) cuserFactory.getCUserService(EnumAppPlat.TOUTIAO).getByOpenId(open_id, appinfo.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; | |||||
| } | |||||
| // Long memberId; | |||||
| // try { | |||||
| // memberId = getMemberId(); | |||||
| // } catch (Exception e) { | |||||
| // return new ResultData(Result.ERROR,e.getMessage()); | |||||
| // } | |||||
| // | |||||
| // List<PlatPushOrderSaveDto> list = new ArrayList<>(); | |||||
| // PlatPushOrderSaveDto dto = new PlatPushOrderSaveDto(); | |||||
| // /** | |||||
| // * TODO 从抖音推送的订单中取信息,每个订单里面有extParam,用来放第三方平台匹配的参数信息 | |||||
| // * 注意,wx_batch_order中要存allExtParam, wx_order,wx_coupon_order中存储每个订单的参数信息,需要自己根据总参数信息进行拆分 | |||||
| // */ | |||||
| // list.add(dto); | |||||
| // String allExtParam = "[]"; | |||||
| // return wxOrderService.platPushSaveOrder(false,EnumComposeOrder.ONE_NUMBER_ORDER_BATCH,allExtParam,list,memberId,getPayWay(),getTenantInfo()); | |||||
| try { | |||||
| 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(good.getGoodsId())); | |||||
| dto.setCount(good.getQuantity()); | |||||
| dto.setExtParam(good.getItemOrderInfoList().toString()); | |||||
| list.add(dto); | |||||
| } | |||||
| ResultData resultData = wxOrderService.platPushSaveOrder(false, EnumComposeOrder.ONE_NUMBER_ORDER_BATCH, allExtParam.toString(), list, memberId, EnumPayWay.PAY_WAY_TT, getTenantInfo()); | |||||
| if(resultData.code == 200){ | |||||
| WxComposeOrder order = (WxComposeOrder) resultData.data; | |||||
| Map<String, Object> data = new HashMap<>(); | |||||
| data.put("out_order_no",order.getMainOrderId()); | |||||
| data.put("order_entry_schema",getOrderEntrySchema(order.getMainOrderId())); | |||||
| List<Map<String,Object>> goodsValid = new ArrayList<>(); | |||||
| for (Long goodId:order.getCouponChannelMap().keySet()) { | |||||
| Map<String,Object> goodsValidMap = new HashMap<>(); | |||||
| goodsValidMap.put("goods_id",goodId.toString()); | |||||
| WxCouponChannel couponChannel = order.getCouponChannelMap().get(goodId); | |||||
| 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); | |||||
| 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; | |||||
| } | |||||
| } | |||||
| private Map<String,String> getOrderEntrySchema(Long batchOrderId){ | |||||
| Map<String,String> map = new HashMap<>(); | |||||
| map.put("path", Constant.mainPageUrl); | |||||
| Map<String,Object> paramMap = new HashMap<>(); | |||||
| paramMap.put("type","dt"); | |||||
| paramMap.put("orderId",batchOrderId); | |||||
| map.put("params", JSON.toJSONString(paramMap)); | |||||
| return map; | |||||
| } | } | ||||
| @@ -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"); | ||||
| @@ -0,0 +1,59 @@ | |||||
| package com.iformall.controller.callback; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.controller.base.BaseController; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| 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()); | |||||
| /** | |||||
| * { | |||||
| * "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"); | |||||
| Map<String,Object> resultMap = new HashMap<>(); | |||||
| // String body = ((BodyReaderHttpServletRequestWrapper) request).getBody(); | |||||
| logger.info("抖音开放平台通知-----parameterMap{}"+parameterMap); | |||||
| try { | |||||
| String header = request.getHeader("X-Douyin-Signature"); | |||||
| logger.info("抖音开放平台通知-----header.X-Douyin-Signature{}"+parameterMap); | |||||
| // Map<String, Object> parameterMap = JSONObject.parseObject(body, Map.class); | |||||
| String event = (String) parameterMap.get("event"); | |||||
| logger.info("抖音开放平台通知-----event{}"+event); | |||||
| String client_key = (String) parameterMap.get("client_key"); | |||||
| logger.info("抖音开放平台通知-----client_key{}"+client_key); | |||||
| JSONObject content = (JSONObject) parameterMap.get("content"); | |||||
| logger.info("抖音开放平台通知-----content{}"+content.toString()); | |||||
| String challenge = content.getString("challenge"); | |||||
| logger.info("抖音开放平台通知-----content.challenge{}"+challenge); | |||||
| resultMap.put("challenge",challenge); | |||||
| return resultMap; | |||||
| } catch (Exception e){ | |||||
| logger.error(e.getMessage()); | |||||
| resultMap.put("err_tips","error"); | |||||
| return resultMap; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -24,7 +24,7 @@ public class PlatPushOrderSaveDto implements Serializable { | |||||
| Integer shippingType = 0;//EnumOrderShopingType【传入参数】配送类型 | Integer shippingType = 0;//EnumOrderShopingType【传入参数】配送类型 | ||||
| UserBasicInfoAddress address;//【传入参数】配送地址 | UserBasicInfoAddress address;//【传入参数】配送地址 | ||||
| String extParam;//【传入参数】json,额外的信息,可能每个平台不一样 | |||||
| String extParam;//数组格式长度与数量一致(一个券一个订单时)【传入参数】json,额外的信息,可能每个平台不一样 | |||||
| WxCoupon wxCoupon;//【非传入参数】。 | WxCoupon wxCoupon;//【非传入参数】。 | ||||
| WxCouponChannel wxCouponChannel;//【非传入参数】。 | WxCouponChannel wxCouponChannel;//【非传入参数】。 | ||||
| @@ -195,6 +195,32 @@ public class CreateOrderCallback implements Serializable { | |||||
| @SerializedName(value = "goods_id_type") | @SerializedName(value = "goods_id_type") | ||||
| private Integer goodsIdType; | private Integer goodsIdType; | ||||
| /** | |||||
| * 是 | |||||
| * 商品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; | |||||
| /** | |||||
| * item单id | |||||
| */ | |||||
| @SerializedName(value = "item_order_id") | |||||
| private String itemOrderId; | |||||
| /** | |||||
| * 商品优惠后价格 | |||||
| */ | |||||
| @SerializedName(value = "price") | |||||
| private Integer price; | |||||
| } | } | ||||
| } | } | ||||
| @@ -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()){ | |||||
| JsonObject object = (JsonObject) baseResult.getData(); | |||||
| if(object != null){ | |||||
| JsonObject product_draft_list = object.getAsJsonObject("product_draft_list"); | |||||
| List<Product> list = GSON.fromJson(product_draft_list.toString(), | |||||
| 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()){ | |||||
| JsonObject object = (JsonObject) baseResult.getData(); | |||||
| if(object != null){ | |||||
| JsonObject product_online_list = object.getAsJsonObject("product_online_list"); | |||||
| List<Product> list = GSON.fromJson(product_online_list.toString(), | |||||
| 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()){ | |||||
| JsonObject data = (JsonObject) baseResult.getData(); | |||||
| return GsonHelper.getString(data,"product_id"); | |||||
| }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,82 @@ | |||||
| 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; | |||||
| /** | |||||
| * 属性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; | |||||
| } | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| @@ -16,6 +16,7 @@ import java.util.stream.Collectors; | |||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
| import com.alibaba.fastjson.JSONArray; | |||||
| import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
| import com.iformall.common.Result; | import com.iformall.common.Result; | ||||
| import com.iformall.domain.po.*; | import com.iformall.domain.po.*; | ||||
| @@ -2796,10 +2797,22 @@ public class WxOrderServiceImpl implements WxOrderService { | |||||
| //券一个数量创建一个订单 | //券一个数量创建一个订单 | ||||
| boolean isOneNumberOneOrder = orderAdapterService.isOneNumberOneOrder(); | boolean isOneNumberOneOrder = orderAdapterService.isOneNumberOneOrder(); | ||||
| if (isOneNumberOneOrder) { | if (isOneNumberOneOrder) { | ||||
| JSONArray jsonArray = new JSONArray(); | |||||
| if(StringUtils.isNotBlank(orderdto.getExtParam())){ | |||||
| try{ | |||||
| jsonArray = JSONArray.parseArray(orderdto.getExtParam()); | |||||
| }catch(Exception e){ | |||||
| logger.error(e.getMessage()); | |||||
| } | |||||
| } | |||||
| for (int j = 0; j < orderdto.getCount(); j++) { | for (int j = 0; j < orderdto.getCount(); j++) { | ||||
| lastOrder = proxy.handleSaveOrderForCouponSingle(orderDate,allowUnPayOrder,composeOrder, user, orderdto.getWxCoupon(), 1, | |||||
| orderdto.isPress(),orderdto.getOrderGroupId(),orderdto.getFormId(),orderdto.getShippingType(),orderdto.getAddress(),orderdto.getExtParam(), | |||||
| orderdto.getWxCouponChannel(), payWay); | |||||
| String extParam = ""; | |||||
| if(jsonArray != null && !jsonArray.isEmpty()){ | |||||
| extParam = jsonArray.get(j).toString(); | |||||
| } | |||||
| lastOrder = proxy.handleSaveOrderForCouponSingle(orderDate,allowUnPayOrder,composeOrder, user, orderdto.getWxCoupon(), 1, | |||||
| orderdto.isPress(),orderdto.getOrderGroupId(),orderdto.getFormId(),orderdto.getShippingType(),orderdto.getAddress(),extParam, | |||||
| orderdto.getWxCouponChannel(), payWay); | |||||
| } | } | ||||
| }else { | }else { | ||||
| lastOrder = proxy.handleSaveOrderForCouponSingle(orderDate,allowUnPayOrder,composeOrder, user, orderdto.getWxCoupon(), orderdto.getCount(), | lastOrder = proxy.handleSaveOrderForCouponSingle(orderDate,allowUnPayOrder,composeOrder, user, orderdto.getWxCoupon(), orderdto.getCount(), | ||||
| @@ -1,8 +1,10 @@ | |||||
| package com.iformall.service.order.entity; | package com.iformall.service.order.entity; | ||||
| import java.util.List; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import com.iformall.domain.po.WxBatchOrder; | import com.iformall.domain.po.WxBatchOrder; | ||||
| import com.iformall.domain.po.WxCoupon; | |||||
| import com.iformall.domain.po.WxCouponChannel; | import com.iformall.domain.po.WxCouponChannel; | ||||
| import com.iformall.domain.po.WxOrder; | import com.iformall.domain.po.WxOrder; | ||||
| import com.iformall.domain.po.base.TenantEntity; | import com.iformall.domain.po.base.TenantEntity; | ||||
| @@ -34,5 +36,7 @@ public class WxComposeOrder extends TenantEntity{ | |||||
| private WxBatchOrder mainOrder;//真正的主订单对象,批量下单时才有 | private WxBatchOrder mainOrder;//真正的主订单对象,批量下单时才有 | ||||
| private Map<Long,WxCouponChannel> couponChannelMap; | private Map<Long,WxCouponChannel> couponChannelMap; | ||||
| private Map<Long,WxCoupon> couponMap; | |||||
| } | } | ||||
| @@ -49,7 +49,7 @@ public class SingleOrderAdapterService extends BaseBatchOrderAdapterService { | |||||
| @Override | @Override | ||||
| public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment, | public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment, | ||||
| EnumPayWay payWay) { | EnumPayWay payWay) { | ||||
| return super.createDBMainOrder(tenantEntity,user, payment,null, payWay, EnumComposeOrder.SINGLE,null); | |||||
| return super.createDBMainOrder(tenantEntity,user, payment,null, payWay, EnumComposeOrder.SINGLE,null,null); | |||||
| } | } | ||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | ||||
| @@ -79,6 +79,7 @@ public abstract class BaseBatchOrderAdapterService implements OrderAdapterServic | |||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | ||||
| protected WxComposeOrder createDBMainOrder(TenantEntity tenantEntity,WxCUserBasicInfo user,List<OrderComposeSaveDto> orderSave,EnumPayWay payWay,EnumComposeOrder composeOrderType) { | protected WxComposeOrder createDBMainOrder(TenantEntity tenantEntity,WxCUserBasicInfo user,List<OrderComposeSaveDto> orderSave,EnumPayWay payWay,EnumComposeOrder composeOrderType) { | ||||
| int payment = 0; | int payment = 0; | ||||
| Map<Long,WxCoupon> couponMap = new HashMap<Long,WxCoupon>(); | |||||
| Map<Long,WxCouponChannel> couponChannelMap = new HashMap<Long,WxCouponChannel>(); | Map<Long,WxCouponChannel> couponChannelMap = new HashMap<Long,WxCouponChannel>(); | ||||
| for (OrderComposeSaveDto ocsd : orderSave) { | for (OrderComposeSaveDto ocsd : orderSave) { | ||||
| WxCouponChannel wxCouponChannel = wxCouponChannelService.getById(ocsd.getSignleOrder().getCouponChannelId(),tenantEntity.getTenantId()); | WxCouponChannel wxCouponChannel = wxCouponChannelService.getById(ocsd.getSignleOrder().getCouponChannelId(),tenantEntity.getTenantId()); | ||||
| @@ -88,15 +89,17 @@ public abstract class BaseBatchOrderAdapterService implements OrderAdapterServic | |||||
| boolean isPress = ocsd.getSignleOrder().isPressOrder(); | boolean isPress = ocsd.getSignleOrder().isPressOrder(); | ||||
| WxComposeChildOrderPrice price = getChildCouponOrderPrice(ocsd,ocsd.getWxCoupon(),wxCouponChannel, isPress, ocsd.getSignleOrder().getOrderGroupId(), ocsd.getCount()); | WxComposeChildOrderPrice price = getChildCouponOrderPrice(ocsd,ocsd.getWxCoupon(),wxCouponChannel, isPress, ocsd.getSignleOrder().getOrderGroupId(), ocsd.getCount()); | ||||
| payment = payment+price.getRealPayMent(); | payment = payment+price.getRealPayMent(); | ||||
| couponMap.put(ocsd.getWxCoupon().getId(),ocsd.getWxCoupon()); | |||||
| couponChannelMap.put(wxCouponChannel.getId(), wxCouponChannel); | couponChannelMap.put(wxCouponChannel.getId(), wxCouponChannel); | ||||
| } | } | ||||
| return createDBMainOrder(tenantEntity, user, payment, null,payWay, composeOrderType,couponChannelMap); | |||||
| return createDBMainOrder(tenantEntity, user, payment, null,payWay, composeOrderType,couponChannelMap,couponMap); | |||||
| } | } | ||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | ||||
| protected WxComposeOrder createDBMainOrderForPushOrders(TenantEntity tenantEntity,WxCUserBasicInfo user,String allExtParam,List<PlatPushOrderSaveDto> platPushOrderList,EnumPayWay payWay,EnumComposeOrder composeOrderType) { | protected WxComposeOrder createDBMainOrderForPushOrders(TenantEntity tenantEntity,WxCUserBasicInfo user,String allExtParam,List<PlatPushOrderSaveDto> platPushOrderList,EnumPayWay payWay,EnumComposeOrder composeOrderType) { | ||||
| int payment = 0; | int payment = 0; | ||||
| Map<Long,WxCoupon> couponMap = new HashMap<Long,WxCoupon>(); | |||||
| Map<Long,WxCouponChannel> couponChannelMap = new HashMap<Long,WxCouponChannel>(); | Map<Long,WxCouponChannel> couponChannelMap = new HashMap<Long,WxCouponChannel>(); | ||||
| for (PlatPushOrderSaveDto ocsd : platPushOrderList) { | for (PlatPushOrderSaveDto ocsd : platPushOrderList) { | ||||
| WxCouponChannel wxCouponChannel = wxCouponChannelService.getById(ocsd.getCouponChannelId(),tenantEntity.getTenantId()); | WxCouponChannel wxCouponChannel = wxCouponChannelService.getById(ocsd.getCouponChannelId(),tenantEntity.getTenantId()); | ||||
| @@ -106,14 +109,16 @@ public abstract class BaseBatchOrderAdapterService implements OrderAdapterServic | |||||
| boolean isPress = ocsd.isPress(); | boolean isPress = ocsd.isPress(); | ||||
| WxComposeChildOrderPrice price = getChildCouponOrderPrice(ocsd.getShippingType(),ocsd.getWxCoupon(),wxCouponChannel, isPress, ocsd.getOrderGroupId(), ocsd.getCount()); | WxComposeChildOrderPrice price = getChildCouponOrderPrice(ocsd.getShippingType(),ocsd.getWxCoupon(),wxCouponChannel, isPress, ocsd.getOrderGroupId(), ocsd.getCount()); | ||||
| payment = payment+price.getRealPayMent(); | payment = payment+price.getRealPayMent(); | ||||
| couponMap.put(ocsd.getWxCoupon().getId(),ocsd.getWxCoupon()); | |||||
| couponChannelMap.put(wxCouponChannel.getId(), wxCouponChannel); | couponChannelMap.put(wxCouponChannel.getId(), wxCouponChannel); | ||||
| } | } | ||||
| return createDBMainOrder(tenantEntity, user, payment, allExtParam,payWay, composeOrderType,couponChannelMap); | |||||
| return createDBMainOrder(tenantEntity, user, payment, allExtParam,payWay, composeOrderType,couponChannelMap,couponMap); | |||||
| } | } | ||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | ||||
| protected WxComposeOrder createDBMainOrder(TenantEntity tenantEntity,WxCUserBasicInfo user,int payment,String allExtParam,EnumPayWay payWay,EnumComposeOrder composeOrderType,Map<Long,WxCouponChannel> couponChannelMap) { | |||||
| protected WxComposeOrder createDBMainOrder(TenantEntity tenantEntity,WxCUserBasicInfo user,int payment,String allExtParam,EnumPayWay payWay,EnumComposeOrder composeOrderType, | |||||
| Map<Long,WxCouponChannel> couponChannelMap,Map<Long,WxCoupon> couponMap) { | |||||
| //判断是否poi订单 | //判断是否poi订单 | ||||
| Integer isTtPoiOrder = null; | Integer isTtPoiOrder = null; | ||||
| try{ | try{ | ||||
| @@ -140,6 +145,9 @@ public abstract class BaseBatchOrderAdapterService implements OrderAdapterServic | |||||
| if (null != couponChannelMap) { | if (null != couponChannelMap) { | ||||
| composeOrder.setCouponChannelMap(couponChannelMap); | composeOrder.setCouponChannelMap(couponChannelMap); | ||||
| } | } | ||||
| if (null != couponMap){ | |||||
| composeOrder.setCouponMap(couponMap); | |||||
| } | |||||
| return composeOrder; | return composeOrder; | ||||
| } | } | ||||
| @@ -39,7 +39,7 @@ public class CouponPackageOrderAdapterService extends BaseBatchOrderAdapterServi | |||||
| @Override | @Override | ||||
| public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment, | public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment, | ||||
| EnumPayWay payWay) { | EnumPayWay payWay) { | ||||
| return super.createDBMainOrder(tenantEntity, user, payment,null, payWay, EnumComposeOrder.PACKAGECOUPON,null); | |||||
| return super.createDBMainOrder(tenantEntity, user, payment,null, payWay, EnumComposeOrder.PACKAGECOUPON,null,null); | |||||
| } | } | ||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | ||||
| @@ -40,7 +40,7 @@ public class MulityNumberOneOrderBatchOrderAdapterService extends BaseBatchOrder | |||||
| @Override | @Override | ||||
| public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment, | public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment, | ||||
| EnumPayWay payWay) { | EnumPayWay payWay) { | ||||
| return super.createDBMainOrder(tenantEntity,user, payment, null, payWay, EnumComposeOrder.MULITY_NUMBER_ORDER_BATCH,null); | |||||
| return super.createDBMainOrder(tenantEntity,user, payment, null, payWay, EnumComposeOrder.MULITY_NUMBER_ORDER_BATCH,null,null); | |||||
| } | } | ||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | ||||
| @@ -39,7 +39,7 @@ public class OneNumberOneOrderBatchOrderAdapterService extends BaseBatchOrderAda | |||||
| @Override | @Override | ||||
| public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment, | public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment, | ||||
| EnumPayWay payWay) { | EnumPayWay payWay) { | ||||
| return super.createDBMainOrder(tenantEntity,user, payment, null,payWay, EnumComposeOrder.ONE_NUMBER_ORDER_BATCH,null); | |||||
| return super.createDBMainOrder(tenantEntity,user, payment, null,payWay, EnumComposeOrder.ONE_NUMBER_ORDER_BATCH,null,null); | |||||
| } | } | ||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | ||||