Authored by chenjian

ufo门店购买

... ... @@ -3,10 +3,12 @@ package com.yohoufo.order.charge;
import com.yoho.core.common.utils.YHMath;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohobuy.ufo.model.order.constants.OrderConstant;
import com.yohobuy.ufo.model.promotion.UserCouponsBo;
import com.yohoufo.order.charge.model.*;
import com.yohoufo.order.service.support.DeliveryWayCostSupport;
import com.yohoufo.order.service.proxy.CouponProxyService;
import com.yohoufo.order.service.support.ShoppingSupport;
import com.yohoufo.order.utils.LoggerUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
... ... @@ -33,6 +35,9 @@ public class ChargeService {
@Autowired
private DeliveryWayCostSupport deliveryWayCostSupport;
@Autowired
private ShoppingSupport shoppingSupport;
/**
* 算费
... ... @@ -87,9 +92,12 @@ public class ChargeService {
*/
private void calculateShippingAmount(ChargeContext chargeContext) {
double deliveryWayCost = deliveryWayCostSupport.getCostOfSf();
//如果是门店自提,则免运费
double deliveryWayCost = shoppingSupport.isDeliveryWayByStore(chargeContext.getChargeParam().getDeliveryWay()) ?
0 : deliveryWayCostSupport.getCostOfSf();
//运费
chargeContext.getChargeResult().setDeliveryWay(chargeContext.getChargeParam().getDeliveryWay());
chargeContext.getChargeResult().setShippingAmount(deliveryWayCost);
ChargeResult chargeResult = chargeContext.getChargeResult();
... ... @@ -98,8 +106,9 @@ public class ChargeService {
//包括运费
double newFinalAmount = YHMath.add(oldFinalAmount, deliveryWayCost);
chargeResult.setFinalAmount(newFinalAmount);
logger.info("[{}] step shipping charge,sfExpressAmount:{},oldFinalAmount:{},newFinalAmount:{}",
logger.info("[{}] step shipping charge, deliveryWay:{},sfExpressAmount:{},oldFinalAmount:{},newFinalAmount:{}",
chargeContext.getChargeParam().getUid(),
chargeContext.getChargeParam().getDeliveryWay(),
chargeResult.getShippingAmount(),
oldFinalAmount,
chargeResult.getFinalAmount());
... ...
... ... @@ -15,5 +15,6 @@ import java.util.List;
@Builder
public class ChargeParam {
private int uid;
private int deliveryWay;
private List<String> couponCodes;
}
... ...
... ... @@ -20,6 +20,11 @@ public class ChargeResult {
*/
private double shippingAmount;
/**
* 发货方式
*/
private int deliveryWay;
/**
* 优惠券支付结果
... ...
package com.yohoufo.order.controller;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.order.model.request.OfflineShoppingRequest;
import com.yohoufo.order.model.response.OrderSubmitResponse;
import com.yohoufo.order.service.IOfflineShoppingService;
import com.yohoufo.order.utils.CouponCodeUtils;
import com.yohoufo.order.utils.LoggerUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/shopping")
public class OfflineShoppingController {
private Logger logger = LoggerUtils.getBuyerOrderLogger();
@Autowired
IOfflineShoppingService offlineShoppingService;
/**
* 提交订单成功
* @return
*/
@RequestMapping(params = "method=ufo.order.offlineSubmit")
public ApiResponse submit(@RequestParam(name = "uid") int uid,
@RequestParam(name = "skup") int skup,
@RequestParam(name = "coupon_code",required = false) String couponCode,
@RequestParam(name = "channelNo", required = false) String channelNo,
//@RequestParam(name = "addressId") String addressId,
@RequestParam(name = "store_id") Integer storeId,
@RequestParam(name = "user_longitude") Double userLongitude,
@RequestParam(name = "user_latitude") Double userLatitude,
@RequestParam(name = "client_type", required = false) String clientType){
if(StringUtils.isBlank(channelNo)){
channelNo = "2919";
}
//ShoppingRequest request = ShoppingRequest.builder().uid(uid).skup(skup).couponCodes(CouponCodeUtils.asList(couponCode)).channelNo(channelNo).clientType(clientType).addressId(addressId).build();
OfflineShoppingRequest request = new OfflineShoppingRequest();
request.setUid(uid);
request.setSkup(skup);
request.setCouponCodes(CouponCodeUtils.asList(couponCode));
request.setChannelNo(channelNo);
request.setAddressId("0"); //门店自提,不需addressId
request.setStoreId(storeId);
request.setUserLongitude(userLongitude);
request.setUserLatitude(userLatitude);
request.setClientType(clientType);
logger.info("in ufo.order.offlineSubmit, req {}", request);
OrderSubmitResponse submitResponse = offlineShoppingService.offlineSubmit(request);
logger.info("out ufo.order.offlineSubmit,resp:{}", submitResponse);
return new ApiResponse.ApiResponseBuilder().code(200).data(submitResponse).message("提交订单SUCCESS").build();
}
}
... ...
package com.yohoufo.order.model.request;
import lombok.Data;
import lombok.ToString;
@Data
@ToString(callSuper = true)
public class OfflineShoppingRequest extends ShoppingRequest {
private Integer storeId;
private Double userLongitude;
private Double userLatitude;
}
... ...
package com.yohoufo.order.model.response;
import lombok.Data;
import lombok.ToString;
@Data
@ToString(callSuper = true)
public class OfflinePaymentResponse extends PaymentResponse {
private String storeName;
private String storeAddress;
public static OfflinePaymentResponse wrap(PaymentResponse paymentResponse) {
OfflinePaymentResponse offlinePaymentResponse = new OfflinePaymentResponse();
offlinePaymentResponse.setAmount(paymentResponse.getAmount());
offlinePaymentResponse.setGood(paymentResponse.getGood());
offlinePaymentResponse.setPaymentWay(paymentResponse.getPaymentWay());
offlinePaymentResponse.setDeliveryWay(paymentResponse.getDeliveryWay());
offlinePaymentResponse.setPromotionFormulaList(paymentResponse.getPromotionFormulaList());
offlinePaymentResponse.setDamagesDesc(paymentResponse.getDamagesDesc());
return offlinePaymentResponse;
}
}
... ...
package com.yohoufo.order.service;
import com.yohoufo.order.model.request.OfflineShoppingRequest;
import com.yohoufo.order.model.response.ComputeResponse;
import com.yohoufo.order.model.response.OfflinePaymentResponse;
import com.yohoufo.order.model.response.OrderSubmitResponse;
public interface IOfflineShoppingService {
/**
* 结算页数据
* @param request
* @return
*/
OfflinePaymentResponse offlinePayment(OfflineShoppingRequest request);
/**
* 重新结算
* @param request
* @return
*/
ComputeResponse offlineCompute(OfflineShoppingRequest request);
/**
* 提交订单
* @param shoppingRequest
* @return
*/
OrderSubmitResponse offlineSubmit(OfflineShoppingRequest shoppingRequest);
}
... ...
package com.yohoufo.order.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.yoho.tools.common.beans.ApiResponse;
import com.yohobuy.ufo.model.order.common.OrderAttributes;
import com.yohobuy.ufo.model.order.constants.OrderConstant;
import com.yohobuy.ufo.model.order.vo.AddressInfo;
import com.yohobuy.ufo.model.response.store.StoreInfoBo;
import com.yohoufo.common.caller.UfoServiceCaller;
import com.yohoufo.common.exception.UfoServiceException;
import com.yohoufo.order.model.request.OfflineShoppingRequest;
import com.yohoufo.order.model.request.ShoppingRequest;
import com.yohoufo.order.model.response.ComputeResponse;
import com.yohoufo.order.model.response.OfflinePaymentResponse;
import com.yohoufo.order.model.response.OrderSubmitResponse;
import com.yohoufo.order.model.response.PaymentResponse;
import com.yohoufo.order.service.IOfflineShoppingService;
import com.yohoufo.order.utils.LoggerUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("offlineShoppingService")
public class OfflineShoppingServiceImpl extends ShoppingServiceImpl implements IOfflineShoppingService {
private final Logger logger = LoggerUtils.getBuyerOrderLogger();
@Autowired
UfoServiceCaller ufoServiceCaller;
@Override
public OfflinePaymentResponse offlinePayment(OfflineShoppingRequest request) {
StoreInfoBo storeInfoBo = queryStoreInfo(request.getStoreId());
if(storeInfoBo == null) {
logger.warn("storeId from goods not invalid, req: {}", request);
throw new UfoServiceException(500, "商品门店信息为空");
}
PaymentResponse paymentResponse = super.payment(request);
return buildOfflinePaymentResponse(paymentResponse, storeInfoBo);
}
private OfflinePaymentResponse buildOfflinePaymentResponse(PaymentResponse paymentResponse, StoreInfoBo storeInfoBo) {
OfflinePaymentResponse offlinePaymentResponse = OfflinePaymentResponse.wrap(paymentResponse);
offlinePaymentResponse.setStoreName(storeInfoBo.getStoreName());
offlinePaymentResponse.setStoreAddress(storeInfoBo.getStoreAddress());
return offlinePaymentResponse;
}
@Override
public ComputeResponse offlineCompute(OfflineShoppingRequest request) {
return super.compute(request);
}
@Override
public OrderSubmitResponse offlineSubmit(OfflineShoppingRequest offlineRequest) {
if(!checkLocationInStore(offlineRequest.getStoreId(), offlineRequest.getUserLongitude(), offlineRequest.getUserLatitude())) {
logger.warn("user not location in the store, req: {}", offlineRequest);
throw new UfoServiceException(500, "定位不在门店内,不允许购买");
}
return super.submit(offlineRequest);
}
private boolean checkLocationInStore(int storeId, double userLongitude, double userLatitude) {
ApiResponse resp = ufoServiceCaller.call("ufo.store.isLocationInStore", ApiResponse.class, storeId, userLongitude, userLatitude);
if (resp != null && resp.getCode()==200) {
if (resp.getData() != null) {
JSONObject json = (JSONObject)resp.getData();
return json.getBoolean("isInRange");
}
}
logger.warn("check location failed: {}", resp);
throw new UfoServiceException(500, "校验定位信息失败");
}
//查询门店信息
private StoreInfoBo queryStoreInfo(int storeId) {
ApiResponse resp = ufoServiceCaller.call("ufo.store.queryStoreInfoById", ApiResponse.class, storeId);
if (resp != null && resp.getCode()==200) {
if (resp.getData() != null) {
return (StoreInfoBo)resp.getData();
}
}
return null;
}
@Override
protected Pair<AddressInfo, AddressInfo> getAndCheckAddressInfo(ShoppingRequest shoppingRequest) {
OfflineShoppingRequest offlineShoppingRequest = (OfflineShoppingRequest) shoppingRequest;
StoreInfoBo storeInfoBo = queryStoreInfo(offlineShoppingRequest.getStoreId());
if(storeInfoBo == null) {
logger.warn("storeInfo not exist, req: {}", offlineShoppingRequest);
throw new UfoServiceException(500, "门店信息不存在");
}
AddressInfo storeAddress = new AddressInfo();
storeAddress.setAddress_id(0);
storeAddress.setUid(offlineShoppingRequest.getUid());
storeAddress.setAddress(storeInfoBo.getStoreAddress());
return Pair.of(storeAddress, storeAddress);
}
@Override
protected OrderAttributes buildOrderArrtribute() {
return OrderAttributes.OFFLINE;
}
@Override
protected int buildDeliveryWay() {
return OrderConstant.DELIVERY_WAY_STORE;
}
}
... ...
... ... @@ -43,6 +43,7 @@ import com.yohoufo.order.utils.AddressHelper;
import com.yohoufo.order.utils.LoggerUtils;
import com.yohoufo.order.utils.MathUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import java.math.BigDecimal;
... ... @@ -119,7 +120,7 @@ public class ShoppingServiceImpl implements IShoppingService {
PaymentResponse response = new PaymentResponse();
response.setPaymentWay(shoppingSupport.getPaymentWay());
response.setDeliveryWay(shoppingSupport.getDeliverWay(chargeContext.getChargeResult().getShippingAmount()));
response.setDeliveryWay(shoppingSupport.getDeliverWay(chargeContext.getChargeResult()));
response.setGood(shoppingSupport.getGoodsInfo(skupGood));
response.setPromotionFormulaList(shoppingSupport.getPromotionFormula(chargeResult));
response.setAmount(MathUtils.formatStr(chargeResult.getFinalAmount()));
... ... @@ -149,8 +150,12 @@ public class ShoppingServiceImpl implements IShoppingService {
}
private ChargeContext buildChargeContext(ShoppingRequest request, SellerOrderGoods skupInfo) {
ChargeParam chargeParam = ChargeParam.builder().uid(request.getUid())
.deliveryWay(buildDeliveryWay())
.couponCodes(request.getCouponCodes()).build();
return ChargeContext.builder()
.chargeParam(ChargeParam.builder().uid(request.getUid()).couponCodes(request.getCouponCodes()).build())
.chargeParam(chargeParam)
.chargeGoods(ChargeGoods.builder().goodsPrice(skupInfo.getGoodsPrice()).productId(skupInfo.getProductId()).skup(skupInfo.getId()).build()).build();
}
... ... @@ -230,22 +235,11 @@ public class ShoppingServiceImpl implements IShoppingService {
throw new ServiceException(ServiceError.ORDER_REQUEST_PARM_IS_EMPTY);
}
// 检查地址是否合法
int addressId = AddressUtil.getDecryptStr(shoppingRequest.getAddressId());
if (addressId < 0){
logger.warn("submit addressId invalidate, uid is {}, skup is {}, addressId is {}", shoppingRequest.getUid(),
shoppingRequest.getSkup(), shoppingRequest.getAddressId());
throw new ServiceException(ServiceError.ORDER_ADDRESSID_INVALIDATE);
}
//查询并校验用户地址
Pair<AddressInfo, AddressInfo> userAddressPair = getAndCheckAddressInfo(shoppingRequest);
// 检查skup是否可售
SellerOrderGoods skup = checkSkupSellOrNot(shoppingRequest.getSkup());
AddressInfo addressInfo = userProxyService.getAddressInfoNotHidden(shoppingRequest.getUid(), addressId);
if(AddressHelper.isNeedUpdate(addressInfo)){
logger.warn("submit addressId need update, uid is {}, skup is {}, addressId is {}", shoppingRequest.getUid(),
shoppingRequest.getSkup(), shoppingRequest.getAddressId());
throw new ServiceException(ServiceError.ORDER_ADDRESS_NEED_UPDATE);
}
//算费
ChargeContext chargeContext = buildChargeContext(shoppingRequest,skup);
... ... @@ -258,8 +252,6 @@ public class ShoppingServiceImpl implements IShoppingService {
logger.info("generate new orderCode:{}",orderCode);
AddressInfo hiddenAddress = userProxyService.getHiddenAddressInfo(shoppingRequest.getUid(), addressId);
// 减库存,skup更新成不可售,入库
//BigDecimal shipFee = new BigDecimal(delivery_way_sf_cost);
int uid;
... ... @@ -269,7 +261,7 @@ public class ShoppingServiceImpl implements IShoppingService {
.orderCode(orderCode)
.productId(skup.getProductId())
.paymentType(OrderConstant.PAYMENT_ONLINE)
.deliverWay(OrderConstant.DELIVERY_WAY_SF)
.deliverWay(buildDeliveryWay())
.channelNo(shoppingRequest.getChannelNo())
.amount(BigDecimal.valueOf(chargeResult.getFinalAmount()))
.shipFee(BigDecimal.valueOf(chargeResult.getShippingAmount()))
... ... @@ -277,10 +269,10 @@ public class ShoppingServiceImpl implements IShoppingService {
.couponAmount(BigDecimal.valueOf(chargeResult.getCouponPayResult().getCouponAmount()))
.build()
)
.hiddenAddressInfo(hiddenAddress)
.addressInfo(addressInfo)
.hiddenAddressInfo(userAddressPair.getRight())
.addressInfo(userAddressPair.getLeft())
.clientType(shoppingRequest.getClientType())
.attributes(OrderAttributes.COMMON_IN_STOCK.getCode())
.attributes(buildOrderArrtribute().getCode()) //1,普通;2,线下店;3,急速发货
.build();
BuyerOrderSubmitResult submitResult = ordeCreationService.doSumbitOrder(orderBuilder);
... ... @@ -323,6 +315,43 @@ public class ShoppingServiceImpl implements IShoppingService {
}
/**
* 查询并校验用户地址(left: 用户地址; right: 脱敏的用户地址)
*
* @return
*/
protected Pair<AddressInfo, AddressInfo> getAndCheckAddressInfo(ShoppingRequest shoppingRequest) {
// 检查地址是否合法
int addressId = AddressUtil.getDecryptStr(shoppingRequest.getAddressId());
if (addressId < 0){
logger.warn("submit addressId invalidate, uid is {}, skup is {}, addressId is {}", shoppingRequest.getUid(),
shoppingRequest.getSkup(), shoppingRequest.getAddressId());
throw new ServiceException(ServiceError.ORDER_ADDRESSID_INVALIDATE);
}
AddressInfo addressInfo = userProxyService.getAddressInfoNotHidden(shoppingRequest.getUid(), addressId);
if(AddressHelper.isNeedUpdate(addressInfo)){
logger.warn("submit addressId need update, uid is {}, skup is {}, addressId is {}", shoppingRequest.getUid(),
shoppingRequest.getSkup(), shoppingRequest.getAddressId());
throw new ServiceException(ServiceError.ORDER_ADDRESS_NEED_UPDATE);
}
//脱敏的用户地址
AddressInfo hiddenAddress = userProxyService.getHiddenAddressInfo(shoppingRequest.getUid(), addressId);
return Pair.of(addressInfo, hiddenAddress);
}
/**
* 获取订单attribute属性
* @return
*/
protected OrderAttributes buildOrderArrtribute() {
return OrderAttributes.COMMON_IN_STOCK;
}
protected int buildDeliveryWay() {
return OrderConstant.DELIVERY_WAY_SF;
}
}
... ...
... ... @@ -39,16 +39,25 @@ public class ShoppingSupport {
* 配送方式
* @return
*/
public PaymentResponse.DeliveryWay getDeliverWay(double deliveryWayCost) {
public PaymentResponse.DeliveryWay getDeliverWay(final ChargeResult chargeResult) {
// 快递方式
PaymentResponse.DeliveryWay deliveryWay = new PaymentResponse.DeliveryWay();
deliveryWay.setDeliveryWayId(OrderConstant.DELIVERY_WAY_SF);
deliveryWay.setDeliveryWayCost(OrderConstant.MONEY_SIGN + deliveryWayCost);
deliveryWay.setDeliveryWayName(OrderConstant.DELIVERY_WAY_SF_NAME);
deliveryWay.setDeliveryWayId(chargeResult.getDeliveryWay());
deliveryWay.setDeliveryWayCost(OrderConstant.MONEY_SIGN + chargeResult.getShippingAmount());
deliveryWay.setDeliveryWayName(getDeliveryWayStr(chargeResult.getDeliveryWay()));
return deliveryWay;
}
private String getDeliveryWayStr(int deliveryWay) {
return deliveryWay == OrderConstant.DELIVERY_WAY_STORE ? OrderConstant.DELIVERY_WAY_STORE_NAME : OrderConstant.DELIVERY_WAY_SF_NAME;
}
public boolean isDeliveryWayByStore(int deliveryWay) {
return deliveryWay == OrderConstant.DELIVERY_WAY_STORE;
}
/**
* 商品情报
* @param skup
... ...