Commit db5a65e2 authored by shiyu's avatar shiyu

问题修复

parent 5e67ad0d
......@@ -22,7 +22,7 @@ dts:
#分销业务,公众号消息点击后跳转到小程序页面的链接
distribution-msg-url: pages/saleOrderDetail/index
#分销拍卖业务,众号消息点击后跳转到小程序页面的链接
auction-msg-url: pages/saleOrderDetail/index
auction-msg-url: pages/saleAuctionDetail/index
# 商户证书文件路径
# 请参考“商户证书”一节 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3
......
......@@ -13,6 +13,8 @@ dts:
msg-url: pages/consignNodeDetail/index
#分销业务,公众号消息点击后跳转到小程序页面的链接
distribution-msg-url: pages/saleOrderDetail/index
#分销拍卖业务,众号消息点击后跳转到小程序页面的链接
auction-msg-url: pages/saleAuctionDetail/index
# 商户证书文件路径
# 请参考“商户证书”一节 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3
key-path: xxxxx
......
......@@ -86,7 +86,12 @@ public class AuctionRecordDaoImpl implements AuctionRecordDao {
@Override
public AuctionRecord findFirstRecord(long itemId, long userId) {
return null;
AuctionRecordExample example = new AuctionRecordExample();
AuctionRecordExample.Criteria criteria = example.createCriteria();
criteria.andItemIdEqualTo(itemId);
criteria.andUserIdEqualTo(userId);
example.setOrderByClause("create_time asc");
return auctionRecordMapper.selectOneByExample(example);
}
@Override
......@@ -107,6 +112,7 @@ public class AuctionRecordDaoImpl implements AuctionRecordDao {
criteria.andUserIdEqualTo(userId);
criteria.andCreateTimeGreaterThanOrEqualTo(startTime);
criteria.andCreateTimeLessThanOrEqualTo(endTime);
example.setOrderByClause("create_time desc");
return auctionRecordMapper.selectByExample(example);
}
}
......@@ -138,10 +138,19 @@ public class WxPayCallbackController {
//查询系统中订单现在的状态,避免重复更新
DistributionOrder distributionOrder = distributionOrderDao.findById(distributionOrderId);
if (distributionOrder.getState() == DistributionEnum.DistributionOrderStateEnum.PRE_PAY.getCode()) {
//一口价处理逻辑
if (distributionOrder.getType() == DistributionEnum.DistributionTypeEnum.FIXED_PRICE.getCode()) {
Result updateResult = updateOrderStateAndInsertProfit(transaction);
if (!updateResult.getSuccess()) {
return JsonUtils.from(returnMap);
}
} else {
//竞拍订单处理
Result updateResult = handleAuctionOrder(transaction);
if (!updateResult.getSuccess()) {
return JsonUtils.from(returnMap);
}
}
}
}
returnMap.put("code", "SUCCESS");
......@@ -224,6 +233,52 @@ public class WxPayCallbackController {
public Result handleAuctionOrder(Transaction transaction) {
try {
//商户订单号,分销订单号
String distributionOrderId = transaction.getOutTradeNo();
//微信支付交易id
String transactionId = transaction.getTransactionId();
//支付成功时间
String payTime = transaction.getSuccessTime();
//支付成功,更新订单状态为待发货
DistributionOrder distributionOrderDto = new DistributionOrder();
distributionOrderDto.setDistributionOrderId(distributionOrderId);
distributionOrderDto.setTransactionId(transactionId);
distributionOrderDto.setPayTime(TimeUtil.wxTimeConvertToDate(payTime));
distributionOrderDto.setState(DistributionEnum.DistributionOrderStateEnum.PRE_SEND.getCode());
distributionOrderDao.update(distributionOrderDto);
//用户付款成功后,把分销商利润的记录更新为有效,因为未付款前只是创建了预计利润记录,但并未生效
distributorProfitDao.updateValidState(distributionOrderId, true);
DistributionOrder distributionOrder = distributionOrderDao.findById(distributionOrderId);
SupplierItem supplierItem = supplierItemDao.findById(distributionOrder.getItemId());
//更新库存
supplierItemService.reduceStock(distributionOrder.getItemId(), distributionOrder.getItemNum());
logger.info(">>>>>>>>>>>> 微信支付回调通知处理成功,更新拍卖订单状态和商品库存 <<<<<<<<<<<<");
//用户首次购买的话,即绑定该分销商
boolean isExisted = distributorBindDao.isExisted(distributionOrder.getBuyerId());
if (!isExisted) {
Date now = new Date();
DistributorBind distributorBind = new DistributorBind();
distributorBind.setUserId(distributionOrder.getBuyerId());
distributorBind.setDistributorId(distributionOrder.getSellerId());
distributorBind.setCreateTime(now);
distributorBind.setUpdateTime(now);
distributorBind.setBindShareId(distributionOrder.getShareRecordId());
distributorBind.setIsValid(true);
distributorBindDao.insert(distributorBind);
}
return Result.success();
} catch (Exception e) {
logger.error(">>>>>>>>>>>> 微信支付回调通知处理失败 error :{}", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return Result.failed();
}
/**
* 获取请求体
*
......
......@@ -2,12 +2,13 @@ package com.wwdz.ch.wx.entity;
import com.xxdxxs.entity.Entity;
import lombok.Data;
import java.util.Date;
@Data
public class AuctionOfferNoticeMsg implements Entity {
private String openId;
private String templetId;
/**
......@@ -15,6 +16,16 @@ public class AuctionOfferNoticeMsg implements Entity {
*/
private String distributionOrderId;
/**
* 拍卖分享id
*/
private String shareRecordId;
/**
* 商品id
*/
private String itemId;
/**
* 商品名称
*/
......@@ -26,7 +37,21 @@ public class AuctionOfferNoticeMsg implements Entity {
private String amount;
/**
* 签收时间
* 拍卖结束时间
*/
private Date auctionEndTime;
/**
* 拍卖当前价
*/
private String currentPrice;
/**
* 用户名称
*/
private Date signedTime;
private String userName;
}
......@@ -12,11 +12,15 @@ import com.wwdz.ch.core.util.PriceUtil;
import com.wwdz.ch.db.dao.OfficialAccountSubscribeRecordDao;
import com.wwdz.ch.db.dao.UserDao;
import com.wwdz.ch.db.dao.distribution.*;
import com.wwdz.ch.db.domain.OfficialAccountSubscribeRecord;
import com.wwdz.ch.db.domain.User;
import com.wwdz.ch.db.domain.distribution.*;
import com.wwdz.ch.db.dto.request.distribution.AuctionRecordRequestDto;
import com.wwdz.ch.wx.entity.AuctionOfferNoticeMsg;
import com.wwdz.ch.wx.entity.vo.distribution.AuctionRecordRowVo;
import com.wwdz.ch.wx.entity.vo.distribution.AuctionRecordVo;
import com.wwdz.ch.wx.service.distribution.AuctionRecordService;
import com.wwdz.ch.wx.service.distribution.SendMsgService;
import com.xxdxxs.utils.EntityMapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
......@@ -72,6 +76,9 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
@Autowired
OfficialAccountSubscribeRecordDao officialAccountSubscribeRecordDao;
@Autowired
SendMsgService sendMsgService;
@Override
@Transactional
......@@ -80,7 +87,7 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
String itemIdKey = CommConsts.AUCTION_LOCK_KEY_PRE + itemId;
RLock lock = redissonClient.getLock(itemIdKey);
try {
if (lock.tryLock(5, 5, TimeUnit.SECONDS)) {
if (lock.tryLock(0, 10, TimeUnit.SECONDS)) {
Date now = new Date();
//查询竞拍配置信息
AuctionConfig auctionConfig = auctionConfigDao.findByItemId(itemId);
......@@ -94,7 +101,8 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
}
String shareRecordId = dto.getShareRecordId();
DistributorShareRecord distributorShareRecord = distributorShareRecordDao.findById(shareRecordId);
if (!distributorShareRecord.getEnabled()) {
if (distributorShareRecord == null || !distributorShareRecord.getEnabled()) {
logger.info("======== 拍卖出价,对应分享id = {}, 无效 ========", shareRecordId);
return Result.failed("该商品分享链接已失效");
}
......@@ -109,23 +117,23 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
//把上次的最高价记录改为落后
auctionRecordDao.updateNotLeadById(auctionRecord.getId());
//发送模板消息,提示用户出价被超越
/* User user = userDao.queryById(userId);
User user = userDao.queryById(auctionRecord.getUserId());
String unionId = user.getWeixinUnionid();
OfficialAccountSubscribeRecord officialAccountSubscribeRecord = officialAccountSubscribeRecordDao.findOne(unionId);
//没有订阅
if (officialAccountSubscribeRecord == null || officialAccountSubscribeRecord.getEnabled().intValue() == 0) {
logger.info(">>>>>>>>>> 用户 unionId = {} ,尚未订阅公众号,无法推送消息 <<<<<<<<<<<");
logger.info(">>>>>>>>>> 用户id = {}, unionId = {} ,尚未订阅公众号,无法推送消息 <<<<<<<<<<<", auctionRecord.getUserId(), unionId);
//发送短信
} else {
SupplierItem supplierItem = supplierItemDao.findById(auctionRecord.getItemId());
String openId = officialAccountSubscribeRecord.getOpenid();
SupplierItem supplierItem = supplierItemDao.findById(itemId);
String itemName = supplierItem.getName();
String content = "您的出价被超越";
ConsignSaleSubscribeMsg consignSaleSubscribeMsg = ConsignSaleSubscribeMsg.of(itemName.substring(0,10), content, new Date());
consignSaleSubscribeMsg.setPageTitle("拍卖出价被超越");
officialAccountApi.sendModelMsg(openId, consignSaleSubscribeMsg);
}*/
AuctionOfferNoticeMsg auctionOfferNoticeMsg = new AuctionOfferNoticeMsg();
auctionOfferNoticeMsg.setItemName(supplierItem.getName());
auctionOfferNoticeMsg.setCurrentPrice(PriceUtil.convertPriceFenToYuan(price));
auctionOfferNoticeMsg.setOpenId(openId);
sendMsgService.sendAuctionOfferOutMsg(auctionOfferNoticeMsg);
}
}
//插入最新出价记录
AuctionRecord addRecord = new AuctionRecord();
......@@ -149,10 +157,10 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
}
return Result.success();
} else {
return Result.failed("出价者较多,稍后再试");
return Result.failed("出价者较多,请刷新出价记录");
}
} catch (Exception e) {
logger.error("扣减库存失败 error : {}", e);
logger.error("拍卖出价失败 error : {}", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
} finally {
if (lock != null && lock.isHeldByCurrentThread()) {
......@@ -296,10 +304,8 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
auctionRecordVo.setStartTime(startTime);
auctionRecordVo.setRealEndTime(realEndTime);
//出价记录对应展示的按钮
if (CollectionUtils.isEmpty(auctionRecordList)) {
auctionRecordVo.setUserState(DistributionEnum.AuctionUserStateEnum.PROCESS.getCode());
auctionRecordVo.setUserStateName(DistributionEnum.AuctionUserStateEnum.PROCESS.getDes());
}
if (now.after(realEndTime)) {
//如果最高价是自己出的,用户状态显示已领先
if (lastedRecord.getUserId().longValue() == dto.getUserId().longValue()) {
......
......@@ -200,12 +200,13 @@ public class DistributionOrderServiceImpl implements DistributionOrderService {
if (auctionRecord.getUserId().longValue() != dto.getBuyerId().longValue()) {
return Result.failed("下单信息错误");
}
//查询该中拍用户第一次出价关联的分享记录id
String shareRecordId = auctionRecord.getShareRecordId();
AuctionConfig auctionConfig = auctionConfigDao.findByItemId(dto.getItemId());
//查询用户第一次出价对应的分销商
AuctionRecord firstAuctionRecord = auctionRecordDao.findFirstRecord(dto.getItemId(), auctionRecord.getUserId());
String shareRecordId = firstAuctionRecord.getShareRecordId();
DistributorShareRecord distributorShareRecord = distributorShareRecordDao.findById(shareRecordId);
SupplierItem supplierItem = supplierItemDao.findById(dto.getItemId());
//SupplierItem supplierItem = supplierItemDao.findById(dto.getItemId());
DistributionOrder distributionOrder = new DistributionOrder();
distributionOrder.setItemId(dto.getItemId());
distributionOrder.setItemNum(1);
......@@ -214,7 +215,7 @@ public class DistributionOrderServiceImpl implements DistributionOrderService {
distributionOrder.setBuyerId(auctionRecord.getUserId());
distributionOrder.setBuyerOpenid(auctionRecord.getUserOpenId());
distributionOrder.setShopId(distributorShareRecord.getShopId());
distributionOrder.setSellerId(distributorShareRecord.getDistributorId());
distributionOrder.setSellerId(firstAuctionRecord.getDistributorId());
distributionOrder.setAmount(auctionRecord.getPrice());
distributionOrder.setCreateTime(new Date());
distributionOrder.setUpdateTime(new Date());
......@@ -232,11 +233,31 @@ public class DistributionOrderServiceImpl implements DistributionOrderService {
distributorProfit.setItemId(distributionOrder.getItemId());
distributorProfit.setItemNum(distributionOrder.getItemNum());
distributorProfit.setAmount(distributionOrder.getAmount());
distributorProfit.setItemCost(supplierItem.getDistributionPrice());
distributorProfit.setItemCost(auctionConfig.getStartPrice());
distributorProfit.setProfit((long) Math.floor(profit));
distributorProfit.setCreateTime(new Date());
distributorProfit.setIsValid(false);
distributorProfitDao.insert(distributorProfit);
//查询参与出价的所有用户所对应的分销商,可以评分成交额的3%的利润
List<AuctionRecord> auctionRecordList = auctionRecordDao.findByItemId(dto.getItemId());
List<AuctionRecord> filterRecordList = auctionRecordList.stream().filter(a -> a.getUserId().longValue() != auctionRecord.getUserId()).collect(Collectors.toList());
for (AuctionRecord record : filterRecordList) {
Double allProfit = distributionOrder.getAmount().doubleValue() * 0.03;
int peopleNum = filterRecordList.size();
double averageProfit = allProfit / peopleNum;
DistributorProfit averageProfitRecord = new DistributorProfit();
averageProfitRecord.setDistributionOrderId(distributionOrderId);
averageProfitRecord.setDistributorId(record.getDistributorId());
averageProfitRecord.setItemId(distributionOrder.getItemId());
averageProfitRecord.setItemNum(distributionOrder.getItemNum());
averageProfitRecord.setAmount(distributionOrder.getAmount());
averageProfitRecord.setItemCost(0L);
averageProfitRecord.setProfit((long) Math.floor(averageProfit));
averageProfitRecord.setCreateTime(new Date());
averageProfitRecord.setIsValid(false);
distributorProfitDao.insert(averageProfitRecord);
}
//把该拍卖配置信息改为已处理
auctionConfigDao.setDeal(dto.getItemId());
//发送中拍信息给用户
......
......@@ -7,18 +7,24 @@ import com.wwdz.ch.db.dao.OfficialAccountSubscribeRecordDao;
import com.wwdz.ch.db.dao.UserDao;
import com.wwdz.ch.db.domain.OfficialAccountSubscribeRecord;
import com.wwdz.ch.db.domain.User;
import com.wwdz.ch.wx.entity.AuctionOfferNoticeMsg;
import com.wwdz.ch.wx.entity.DeliveryNoticeMsg;
import com.wwdz.ch.wx.entity.PayNoticeMsg;
import com.wwdz.ch.wx.entity.SignedNoticeMsg;
import com.wwdz.ch.wx.service.distribution.SendMsgService;
import com.xxdxxs.utils.DateUtils;
import com.xxdxxs.utils.JsonUtils;
import com.xxdxxs.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
/**
......@@ -46,6 +52,9 @@ public class SendMsgServiceImpl implements SendMsgService {
@Value("${dts.wx.distribution-msg-url}")
private String DISTRIBUTION_MSG_URL;
@Value("${dts.wx.auction-msg-url}")
private String AUCTION_MSG_URL;
@Autowired
OfficialAccountApi officialAccountApi;
......@@ -116,18 +125,6 @@ public class SendMsgServiceImpl implements SendMsgService {
return Result.success();
}
@Override
public Result sendAuctionOfferOutMsg(String openId, SignedNoticeMsg signedNoticeMsg) {
return null;
}
@Override
public Result auctionSuccessMsg(String openId, SignedNoticeMsg signedNoticeMsg) {
return null;
}
@Override
public Result sendSignedTempletMsg(String openId, SignedNoticeMsg signedNoticeMsg) {
String token = officialAccountApi.getAccessToken();
......@@ -158,6 +155,69 @@ public class SendMsgServiceImpl implements SendMsgService {
return Result.success();
}
@Override
public Result sendAuctionOfferOutMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg) {
String openId =auctionOfferNoticeMsg.getOpenId();
String token = officialAccountApi.getAccessToken();
String url = SEND_MSG_URL + "?access_token=" + token;
OkHttpUtil okHttpUtil = OkHttpUtil.builder().url(url);
Map<String, Object> map = new HashMap<>();
map.put("touser", openId);
map.put("template_id", "lO-SF3tbPEbC7bDZxRk-x6lcwp1FrNP7T3SGd160uYM");
Map<String, Object> miniprogramMap = new HashMap<>();
miniprogramMap.put("appid", APPLET_APPID);
StringBuffer stringBuffer = new StringBuffer(AUCTION_MSG_URL);
stringBuffer.append("?itemId=" + auctionOfferNoticeMsg.getItemId());
if (StringUtils.hasLength(auctionOfferNoticeMsg.getShareRecordId())) {
stringBuffer.append("&shareRecordId=" + auctionOfferNoticeMsg.getShareRecordId());
}
miniprogramMap.put("pagepath", stringBuffer.toString());
map.put("miniprogram", miniprogramMap);
Map<String, Object> paramMap = new LinkedHashMap<>();
paramMap.put("thing4", new HashMap(){{put("value", auctionOfferNoticeMsg.getItemName());}});
paramMap.put("amount5", new HashMap(){{put("value", auctionOfferNoticeMsg.getCurrentPrice());}});
map.put("data", paramMap);
logger.info("============ 拍卖出价被超越通知模板消息内容 : {}", JsonUtils.fromMap(map));
okHttpUtil.addParams(map);
okHttpUtil.post(true);
String responseStr = okHttpUtil.async();
logger.info("openid : {}, 发送拍卖出价被超越通知模板消息 response :{}", openId, responseStr);
String errorCode = JsonUtils.getValueByPath(responseStr, "errcode");
String errmsg = JsonUtils.getValueByPath(responseStr, "errmsg");
if (!"0".equals(errorCode)) {
logger.error("openid : {}, 发送拍卖出价被超越通知模板消息, errorCode : {}, errmsg : {} ", openId, errorCode, errmsg);
return Result.failed();
}
logger.info("=============发送拍卖出价被超越通知模板消息成功 ===========");
return Result.success();
}
@Override
public Result auctionSuccessMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg) {
return null;
}
@Override
public Result prePayMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg) {
return null;
}
@Override
public Result auctionSuccessForDistributorMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg) {
return null;
}
@Override
public Result aboutToEndMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg) {
return null;
}
@Override
public Result auctionEndMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg) {
return null;
}
@Override
public String getOpenIdByUserId(long userId) {
//先查询寄售单用户信息
......
......@@ -2,6 +2,7 @@ package com.wwdz.ch.wx.service.distribution;
import com.wwdz.ch.core.entity.AbstractSubscribeMsg;
import com.wwdz.ch.core.type.Result;
import com.wwdz.ch.wx.entity.AuctionOfferNoticeMsg;
import com.wwdz.ch.wx.entity.DeliveryNoticeMsg;
import com.wwdz.ch.wx.entity.PayNoticeMsg;
import com.wwdz.ch.wx.entity.SignedNoticeMsg;
......@@ -16,20 +17,51 @@ public interface SendMsgService {
/**
* 出价被超越通知用户
* @param openId
* @param signedNoticeMsg
* @param auctionOfferNoticeMsg
* @return
*/
Result sendAuctionOfferOutMsg(String openId, SignedNoticeMsg signedNoticeMsg);
Result sendAuctionOfferOutMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg);
/**
* 竞拍成功通知
* @param openId
* @param signedNoticeMsg
* @param auctionOfferNoticeMsg
* @return
*/
Result auctionSuccessMsg(String openId, SignedNoticeMsg signedNoticeMsg);
Result auctionSuccessMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg);
/**
* 催付款通知
* 给中拍用户发送
* @param auctionOfferNoticeMsg
* @return
*/
Result prePayMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg);
/**
* 竞拍成功通知所有参与的分销商
* @param auctionOfferNoticeMsg
* @return
*/
Result auctionSuccessForDistributorMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg);
/**
* 竞拍快结束通知
* 给所有出过价的用户发送
* @param auctionOfferNoticeMsg
* @return
*/
Result aboutToEndMsg(AuctionOfferNoticeMsg auctionOfferNoticeMsg);
/**
* 竞拍结束通知
* 给所有出过价的用户发送
* @param auctionOfferNoticeMsg
* @return
*/
Result auctionEndMsg( AuctionOfferNoticeMsg auctionOfferNoticeMsg);
String getOpenIdByUserId(long userId);
}
......@@ -42,7 +42,7 @@ public class AuctionRecordController {
@PostMapping("/refreshOffer")
public Result refreshOffer(@RequestBody AuctionRecordRequestDto dto) {
logger.info("刷新出价记录,请求参数:{}", JSON.toJSONString(dto));
if (dto.getItemId() == null) {
if (dto.getItemId() == null || dto.getUserId() == null) {
return Result.failed(ResultCode.PARAM_ERROR);
}
return auctionRecordService.refreshOffer(dto);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment