Просмотр исходного кода

//tt pay v2

release_toaliyun_real
xhxu 4 лет назад
Родитель
Сommit
0024179c2d
25 измененных файлов: 1399 добавлений и 37 удалений
  1. +2
    -0
      mallinkAdmin/src/main/java/com/iformall/config/ShiroConfig.java
  2. +24
    -5
      mallinkAdmin/src/main/java/com/iformall/controller/market/WxCouponController.java
  3. +114
    -20
      mallinkCApi/src/main/java/com/iformall/controller/WxOrderController.java
  4. +1
    -0
      mallinkCallback/src/main/java/com/iformall/config/ShiroConfig.java
  5. +59
    -0
      mallinkCallback/src/main/java/com/iformall/controller/callback/TtWebController.java
  6. +1
    -1
      mallinkService/src/main/java/com/iformall/domain/dto/PlatPushOrderSaveDto.java
  7. +26
    -0
      mallinkService/src/main/java/com/iformall/douyin/payv2/result/CreateOrderCallback.java
  8. +108
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/api/TtWebGoodsGetRequestExecutor.java
  9. +117
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/api/TtWebGoodsPostRequestExecutor.java
  10. +144
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/api/TtWebGoodsService.java
  11. +2
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/api/TtWebService.java
  12. +254
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/api/impl/TtWebGoodsServiceImpl.java
  13. +8
    -1
      mallinkService/src/main/java/com/iformall/douyin/web/api/impl/TtWebServiceImpl.java
  14. +90
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/bean/BaseGoodsResult.java
  15. +82
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/bean/GoodsTemplateGet.java
  16. +252
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/bean/Product.java
  17. +40
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/bean/ProductPage.java
  18. +40
    -0
      mallinkService/src/main/java/com/iformall/douyin/web/bean/ProductSku.java
  19. +16
    -3
      mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java
  20. +4
    -0
      mallinkService/src/main/java/com/iformall/service/order/entity/WxComposeOrder.java
  21. +1
    -1
      mallinkService/src/main/java/com/iformall/service/order/impl/SingleOrderAdapterService.java
  22. +11
    -3
      mallinkService/src/main/java/com/iformall/service/order/impl/batch/BaseBatchOrderAdapterService.java
  23. +1
    -1
      mallinkService/src/main/java/com/iformall/service/order/impl/batch/CouponPackageOrderAdapterService.java
  24. +1
    -1
      mallinkService/src/main/java/com/iformall/service/order/impl/batch/MulityNumberOneOrderBatchOrderAdapterService.java
  25. +1
    -1
      mallinkService/src/main/java/com/iformall/service/order/impl/batch/OneNumberOneOrderBatchOrderAdapterService.java

+ 2
- 0
mallinkAdmin/src/main/java/com/iformall/config/ShiroConfig.java Просмотреть файл

@@ -149,6 +149,8 @@ public class ShiroConfig {
//商场初始化init
filterChainDefinitionMap.put("/wxProjectConfig/**", "anon");

// filterChainDefinitionMap.put("/wxCoupon/goods/**", "anon");

// //test
// filterChainDefinitionMap.put("/merchantPoi/spuSync", "anon");
// filterChainDefinitionMap.put("/merchantPoi/spuGet", "anon");


+ 24
- 5
mallinkAdmin/src/main/java/com/iformall/controller/market/WxCouponController.java Просмотреть файл

@@ -14,13 +14,10 @@ import com.iformall.domain.po.WxCouponPassword;
import com.iformall.domain.po.WxPayAccount;
import com.iformall.domain.po.base.TenantEntity;
import com.iformall.domain.vo.WxCouponStatisVo;
import com.iformall.douyin.web.bean.GoodsTemplateGet;
import com.iformall.enums.*;
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.utils.DateUtils;
import com.iformall.utils.RedisLock;
@@ -29,6 +26,7 @@ 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.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
@@ -60,6 +58,8 @@ public class WxCouponController extends BaseController {
@Autowired
private WxMallService wxMallService;
@Autowired
private TtMerchantPoiService ttMerchantPoiService;
@Autowired
RedisLock redisLock;
@Autowired
@@ -543,4 +543,23 @@ public class WxCouponController extends BaseController {
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());
}

}

}

+ 114
- 20
mallinkCApi/src/main/java/com/iformall/controller/WxOrderController.java Просмотреть файл

@@ -1,5 +1,7 @@
package com.iformall.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
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.po.*;
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.WxOrderCouponPressVo;
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.exception.MallinkException;
import com.iformall.interceptor.BodyReaderHttpServletRequestWrapper;
import com.iformall.service.*;
import com.iformall.service.cuser.CUserServiceFactory;
import com.iformall.service.order.OrderFactory;
import com.iformall.service.order.entity.WxComposeOrder;
import com.iformall.utils.Constant;
import com.iformall.utils.MaUtil;
import com.iformall.utils.RedisLock;

import io.swagger.annotations.Api;
@@ -55,6 +63,9 @@ public class WxOrderController extends BaseController {
@Autowired
private WxCouponService wxCouponService;

@Autowired
private CUserServiceFactory cuserFactory;

@Autowired
private WxCUserBasicInfoService wxCUserBasicInfoService;

@@ -76,6 +87,9 @@ public class WxOrderController extends BaseController {
@Autowired
private OrderFactory orderFactory;

@Autowired
private MaUtil maUtil;

@Autowired
@Qualifier("couponDetailRedisTemplate")
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\"}")
@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"));
@@ -154,27 +170,105 @@ public class WxOrderController extends BaseController {
String body = ((BodyReaderHttpServletRequestWrapper) request).getBody();
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;
}


+ 1
- 0
mallinkCallback/src/main/java/com/iformall/config/ShiroConfig.java Просмотреть файл

@@ -112,6 +112,7 @@ public class ShiroConfig {

filterChainDefinitionMap.put("/alipay/notify/**", "anon");
filterChainDefinitionMap.put("/ttPay/notify/**", "anon");
filterChainDefinitionMap.put("/ttweb/notify/**", "anon");

filterChainDefinitionMap.put("/jinmao/notify/**", "anon");



+ 59
- 0
mallinkCallback/src/main/java/com/iformall/controller/callback/TtWebController.java Просмотреть файл

@@ -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;
}
}
}

+ 1
- 1
mallinkService/src/main/java/com/iformall/domain/dto/PlatPushOrderSaveDto.java Просмотреть файл

@@ -24,7 +24,7 @@ public class PlatPushOrderSaveDto implements Serializable {
Integer shippingType = 0;//EnumOrderShopingType【传入参数】配送类型
UserBasicInfoAddress address;//【传入参数】配送地址
String extParam;//【传入参数】json,额外的信息,可能每个平台不一样
String extParam;//数组格式长度与数量一致(一个券一个订单时)【传入参数】json,额外的信息,可能每个平台不一样
WxCoupon wxCoupon;//【非传入参数】。
WxCouponChannel wxCouponChannel;//【非传入参数】。


+ 26
- 0
mallinkService/src/main/java/com/iformall/douyin/payv2/result/CreateOrderCallback.java Просмотреть файл

@@ -195,6 +195,32 @@ public class CreateOrderCallback implements Serializable {
@SerializedName(value = "goods_id_type")
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;

}

}

+ 108
- 0
mallinkService/src/main/java/com/iformall/douyin/web/api/TtWebGoodsGetRequestExecutor.java Просмотреть файл

@@ -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;
}

}

+ 117
- 0
mallinkService/src/main/java/com/iformall/douyin/web/api/TtWebGoodsPostRequestExecutor.java Просмотреть файл

@@ -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;
}
}

+ 144
- 0
mallinkService/src/main/java/com/iformall/douyin/web/api/TtWebGoodsService.java Просмотреть файл

@@ -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 ;

}

+ 2
- 0
mallinkService/src/main/java/com/iformall/douyin/web/api/TtWebService.java Просмотреть файл

@@ -110,4 +110,6 @@ public interface TtWebService {
*/
TtWebProductService getProductService();

TtWebGoodsService getGoodsService();

}

+ 254
- 0
mallinkService/src/main/java/com/iformall/douyin/web/api/impl/TtWebGoodsServiceImpl.java Просмотреть файл

@@ -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());
}
}
}

+ 8
- 1
mallinkService/src/main/java/com/iformall/douyin/web/api/impl/TtWebServiceImpl.java Просмотреть файл

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
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.TtWebService;
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 TtWebProductService productService = new TtWebProductServiceImpl(this);
private TtWebGoodsServiceImpl goodService = new TtWebGoodsServiceImpl(this);

private int retrySleepMillis = 1000;
private int maxRetryTimes = 5;
@@ -198,7 +200,7 @@ public class TtWebServiceImpl implements TtWebService, RequestHttp<CloseableHttp
if (error.getErrorCode() == -1) {
int sleepMillis = this.retrySleepMillis * (1 << retryTimes);
try {
log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1);
log.warn("系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1);
Thread.sleep(sleepMillis);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
@@ -294,4 +296,9 @@ public class TtWebServiceImpl implements TtWebService, RequestHttp<CloseableHttp
return this.productService;
}

@Override
public TtWebGoodsService getGoodsService() {
return this.goodService;
}

}

+ 90
- 0
mallinkService/src/main/java/com/iformall/douyin/web/bean/BaseGoodsResult.java Просмотреть файл

@@ -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;

}

}

+ 82
- 0
mallinkService/src/main/java/com/iformall/douyin/web/bean/GoodsTemplateGet.java Просмотреть файл

@@ -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;

}

}

+ 252
- 0
mallinkService/src/main/java/com/iformall/douyin/web/bean/Product.java Просмотреть файл

@@ -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;

}

}

+ 40
- 0
mallinkService/src/main/java/com/iformall/douyin/web/bean/ProductPage.java Просмотреть файл

@@ -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;

}

+ 40
- 0
mallinkService/src/main/java/com/iformall/douyin/web/bean/ProductSku.java Просмотреть файл

@@ -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
- 3
mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java Просмотреть файл

@@ -16,6 +16,7 @@ import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.iformall.common.Result;
import com.iformall.domain.po.*;
@@ -2796,10 +2797,22 @@ public class WxOrderServiceImpl implements WxOrderService {
//券一个数量创建一个订单
boolean isOneNumberOneOrder = orderAdapterService.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++) {
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 {
lastOrder = proxy.handleSaveOrderForCouponSingle(orderDate,allowUnPayOrder,composeOrder, user, orderdto.getWxCoupon(), orderdto.getCount(),


+ 4
- 0
mallinkService/src/main/java/com/iformall/service/order/entity/WxComposeOrder.java Просмотреть файл

@@ -1,8 +1,10 @@
package com.iformall.service.order.entity;

import java.util.List;
import java.util.Map;

import com.iformall.domain.po.WxBatchOrder;
import com.iformall.domain.po.WxCoupon;
import com.iformall.domain.po.WxCouponChannel;
import com.iformall.domain.po.WxOrder;
import com.iformall.domain.po.base.TenantEntity;
@@ -34,5 +36,7 @@ public class WxComposeOrder extends TenantEntity{
private WxBatchOrder mainOrder;//真正的主订单对象,批量下单时才有
private Map<Long,WxCouponChannel> couponChannelMap;

private Map<Long,WxCoupon> couponMap;
}

+ 1
- 1
mallinkService/src/main/java/com/iformall/service/order/impl/SingleOrderAdapterService.java Просмотреть файл

@@ -49,7 +49,7 @@ public class SingleOrderAdapterService extends BaseBatchOrderAdapterService {
@Override
public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment,
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})


+ 11
- 3
mallinkService/src/main/java/com/iformall/service/order/impl/batch/BaseBatchOrderAdapterService.java Просмотреть файл

@@ -79,6 +79,7 @@ public abstract class BaseBatchOrderAdapterService implements OrderAdapterServic
@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
protected WxComposeOrder createDBMainOrder(TenantEntity tenantEntity,WxCUserBasicInfo user,List<OrderComposeSaveDto> orderSave,EnumPayWay payWay,EnumComposeOrder composeOrderType) {
int payment = 0;
Map<Long,WxCoupon> couponMap = new HashMap<Long,WxCoupon>();
Map<Long,WxCouponChannel> couponChannelMap = new HashMap<Long,WxCouponChannel>();
for (OrderComposeSaveDto ocsd : orderSave) {
WxCouponChannel wxCouponChannel = wxCouponChannelService.getById(ocsd.getSignleOrder().getCouponChannelId(),tenantEntity.getTenantId());
@@ -88,15 +89,17 @@ public abstract class BaseBatchOrderAdapterService implements OrderAdapterServic
boolean isPress = ocsd.getSignleOrder().isPressOrder();
WxComposeChildOrderPrice price = getChildCouponOrderPrice(ocsd,ocsd.getWxCoupon(),wxCouponChannel, isPress, ocsd.getSignleOrder().getOrderGroupId(), ocsd.getCount());
payment = payment+price.getRealPayMent();
couponMap.put(ocsd.getWxCoupon().getId(),ocsd.getWxCoupon());
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})
protected WxComposeOrder createDBMainOrderForPushOrders(TenantEntity tenantEntity,WxCUserBasicInfo user,String allExtParam,List<PlatPushOrderSaveDto> platPushOrderList,EnumPayWay payWay,EnumComposeOrder composeOrderType) {
int payment = 0;
Map<Long,WxCoupon> couponMap = new HashMap<Long,WxCoupon>();
Map<Long,WxCouponChannel> couponChannelMap = new HashMap<Long,WxCouponChannel>();
for (PlatPushOrderSaveDto ocsd : platPushOrderList) {
WxCouponChannel wxCouponChannel = wxCouponChannelService.getById(ocsd.getCouponChannelId(),tenantEntity.getTenantId());
@@ -106,14 +109,16 @@ public abstract class BaseBatchOrderAdapterService implements OrderAdapterServic
boolean isPress = ocsd.isPress();
WxComposeChildOrderPrice price = getChildCouponOrderPrice(ocsd.getShippingType(),ocsd.getWxCoupon(),wxCouponChannel, isPress, ocsd.getOrderGroupId(), ocsd.getCount());
payment = payment+price.getRealPayMent();
couponMap.put(ocsd.getWxCoupon().getId(),ocsd.getWxCoupon());
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})
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订单
Integer isTtPoiOrder = null;
try{
@@ -140,6 +145,9 @@ public abstract class BaseBatchOrderAdapterService implements OrderAdapterServic
if (null != couponChannelMap) {
composeOrder.setCouponChannelMap(couponChannelMap);
}
if (null != couponMap){
composeOrder.setCouponMap(couponMap);
}
return composeOrder;
}



+ 1
- 1
mallinkService/src/main/java/com/iformall/service/order/impl/batch/CouponPackageOrderAdapterService.java Просмотреть файл

@@ -39,7 +39,7 @@ public class CouponPackageOrderAdapterService extends BaseBatchOrderAdapterServi
@Override
public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment,
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})


+ 1
- 1
mallinkService/src/main/java/com/iformall/service/order/impl/batch/MulityNumberOneOrderBatchOrderAdapterService.java Просмотреть файл

@@ -40,7 +40,7 @@ public class MulityNumberOneOrderBatchOrderAdapterService extends BaseBatchOrder
@Override
public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment,
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})


+ 1
- 1
mallinkService/src/main/java/com/iformall/service/order/impl/batch/OneNumberOneOrderBatchOrderAdapterService.java Просмотреть файл

@@ -39,7 +39,7 @@ public class OneNumberOneOrderBatchOrderAdapterService extends BaseBatchOrderAda
@Override
public WxComposeOrder createDBMainOrder(TenantEntity tenantEntity, WxCUserBasicInfo user, int payment,
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})


Загрузка…
Отмена
Сохранить