updates 抖音支付优化

This commit is contained in:
zhouwentao 2024-07-24 19:02:10 +08:00
parent 29288b22b2
commit 6e742a8e06
11 changed files with 217 additions and 22 deletions

View File

@ -3,12 +3,15 @@ package org.jeecg.modules.mini.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.AssertUtils;
import org.jeecg.modules.yx.constant.YxConstant;
import org.jeecg.modules.yx.entity.YxOrder;
import org.jeecg.modules.yx.service.IYxOrderService;
import org.jeecg.modules.yx.util.OrderStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -36,8 +39,13 @@ public class MiniOrderController {
LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
AssertUtils.notNull(loginUser,"未获取到登录信息");
List<YxOrder> orderList = yxOrderService.findListByPaymentUserId(loginUser.getId());
orderList = orderList.stream().filter(o->!"1".equals(o.getOrderStatus())).collect(Collectors.toList());
//orderList = orderList.stream().filter(o->!"1".equals(o.getOrderStatus())).collect(Collectors.toList());
for (YxOrder yxOrder : orderList) {
if (StringUtils.isNotBlank(yxOrder.getOrderStatus())) {
yxOrder.setOrderStatusName(OrderStatusEnum.getStatusNameByStatusCode(Integer.parseInt(yxOrder.getOrderStatus())));
}else{
yxOrder.setOrderStatusName("未知");
}
if (yxOrder.getTotalAmount()!=null) {
yxOrder.setTotalAmount(yxOrder.getTotalAmount().divide(new BigDecimal(100),2, RoundingMode.HALF_UP));
}
@ -56,4 +64,5 @@ public class MiniOrderController {
AssertUtils.notNull(yxOrder,"订单信息未找到!");
return Result.OK(yxOrder);
}
}

View File

@ -2,12 +2,10 @@ package org.jeecg.modules.mini.controller;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.HttpKit;
@ -46,8 +44,8 @@ import org.jeecg.modules.yx.entity.YxOrder;
import org.jeecg.modules.yx.entity.YxVipSku;
import org.jeecg.modules.yx.service.IYxOrderService;
import org.jeecg.modules.yx.service.IYxVipSkuService;
import org.jeecg.modules.yx.util.OrderStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -99,17 +97,19 @@ public class MiniPayApiController {
}
String provider = requestBody.getString("provider");//供应商
String skuCode = requestBody.getString("skuCode");
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
SysUser user = sysUserService.getById(sysUser.getId());
if (user == null) {
LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
SysUser sysUser = sysUserService.getById(loginUser.getId());
if (sysUser == null) {
throw new JeecgBootException("获取用户信息失败,请联系管理员");
}
// 将当前用户的其他未支付订单取消
yxOrderService.cancelByUserId(loginUser.getId());
//获取库存信息
YxVipSku yxVipSku = yxVipSkuService.getBySkuCode(skuCode);
AssertUtils.notNull(yxVipSku, "获取商品信息失败,请联系管理员");
//判断用户是否已购买过该会员
VipDTO userVip = miniUserService.getUserVip(user.getId());
VipDTO userVip = miniUserService.getUserVip(sysUser.getId());
if (userVip != null) {
//如果这个会员已经买过了提示不可重复购买
AssertUtils.notTrue(yxVipSkuService.convertVipLevel(skuCode) <= userVip.getVipLevel(), "该权益您已购买!不可重复购买");
@ -117,7 +117,7 @@ public class MiniPayApiController {
YxOrder yxOrder = new YxOrder();
String orderCode = OrderNumberGenerator.generateOrderNumber();
String openId = user.getWxOpenId();
String openId = sysUser.getWxOpenId();
BigDecimal skuPrice = yxVipSku.getSkuPrice();
BigDecimal totalAmount = skuPrice.multiply(YxConstant.bigDecimal100);
// totalAmount = YxConstant.bigDecimal100;
@ -130,28 +130,42 @@ public class MiniPayApiController {
if (StringUtils.isNotBlank(yxVipSku.getSkuDetail())) {
description = yxVipSku.getSkuDetail();
}
try {
yxOrder.setOrderCode(orderCode);//orderCode
yxOrder.setSkuCode(skuCode);//vip商品Code
yxOrder.setOrderStatus("0");//订单状态
yxOrder.setTotalAmount(totalAmount);//金额
yxOrder.setPaymentUserId(user.getId());//付款人
yxOrder.setOrderStatus("1");
yxOrder.setPaymentUserId(sysUser.getId());//付款人
yxOrder.setOrderStatus(String.valueOf(OrderStatusEnum.getStatusCodeByStatusName("待支付")));
yxOrder.setProvider(provider);
yxOrder.setProgramType(programType);
yxOrder.setCreateTime(new Date());
//判断是抖音平台 还是 微信平台 小程序操作
if ("toutiao".equals(provider)) {
// 同步抖音订单
long createTimeLong = yxOrder.getCreateTime().getTime() / YxConstant.bigDecimal1000;
List<ItemStruct> itemList=new ArrayList<>();
String skuImg = yxVipSku.getSkuImg();
itemList.add(new ItemStruct(yxOrder.getSkuCode(),skuImg,attach,null,1,yxOrder.getTotalAmount().longValue()));
DouYinOrderSyncModel douYinOrderSyncModel = new DouYinOrderSyncModel(orderCode, createTimeLong,
"待支付", 1, totalAmount.longValue(),
"pages/zyb/order/detail?orderCode=" + orderCode, itemList);
//
// 抖音平台
if("体育志愿宝".equals(programType)){
String douyinSign = DouYinUtil.main(douYinTiyuConfig.getAppId(), douYinTiyuConfig.getToken(),douYinTiyuConfig.getNotifyUrl(), douYinTiyuConfig.getSalt(), orderCode, totalAmount.intValue(),attach, description);
yxOrder.setOrderSign(douyinSign);
// 同步
DouYinUtil.orderSyncV1(douYinOrderSyncModel,douYinTiyuConfig.getAppId(),douYinTiyuConfig.getAppSecret(),sysUser.getDyOpenId());
}else{
String douyinSign = DouYinUtil.main(douYinConfig.getAppId(), douYinConfig.getToken(),douYinConfig.getNotifyUrl(), douYinConfig.getSalt(), orderCode, totalAmount.intValue(),attach, description);
yxOrder.setOrderSign(douyinSign);
// 同步
DouYinUtil.orderSyncV1(douYinOrderSyncModel,douYinConfig.getAppId(),douYinConfig.getAppSecret(),sysUser.getDyOpenId());
}
yxOrder.setOpenId(sysUser.getDyOpenId());
}
else {
yxOrder.setOpenId(sysUser.getWxOpenId());
// 微信平台
String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()

View File

@ -46,6 +46,7 @@ import org.jeecg.modules.yx.entity.YxOrder;
import org.jeecg.modules.yx.entity.YxVipSku;
import org.jeecg.modules.yx.service.IYxOrderService;
import org.jeecg.modules.yx.service.IYxVipSkuService;
import org.jeecg.modules.yx.util.OrderStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
@ -189,11 +190,10 @@ public class WxPayApiController {
//==============创建订单信息 Start
yxOrder.setOrderCode(orderCode);//orderCode
yxOrder.setSkuCode(skuCode);//vip商品Code
yxOrder.setOrderStatus("0");//订单状态
yxOrder.setTotalAmount(totalAmount);//金额
yxOrder.setPaymentUserId(user.getId());//付款人
yxOrder.setOrderSign(jsonStr);
yxOrder.setOrderStatus("1");
yxOrder.setOrderStatus(String.valueOf(OrderStatusEnum.getStatusCodeByStatusName("待支付")));
yxOrder.setPaymentType("3");//微信支付
yxOrder.setProgramType(programType);
yxOrderService.save(yxOrder);
@ -234,7 +234,11 @@ public class WxPayApiController {
String tradeState = plainTextJson.getString("trade_state");
if ("SUCCESS".equals(tradeState)) {
//支付成功
yxOrderService.update(new LambdaUpdateWrapper<YxOrder>().eq(YxOrder::getOrderCode,outTradeNo).set(YxOrder::getPaymentTime,new Date()).set(YxOrder::getOrderStatus,"2"));
LambdaUpdateWrapper<YxOrder> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(YxOrder::getOrderCode, outTradeNo);
lambdaUpdateWrapper.set(YxOrder::getPaymentTime, new Date());
lambdaUpdateWrapper.set(YxOrder::getOrderStatus, String.valueOf(OrderStatusEnum.getStatusCodeByStatusName("已支付")));
yxOrderService.update(lambdaUpdateWrapper);
}
//支付成功修改订单信息
response.setStatus(200);

View File

@ -20,6 +20,18 @@ public class DouYinOrderSyncModel implements Serializable {
private String detail_url; //*小程序订单详情页 path长度<=1024 byte (备注该路径需要保证在小程序内配置过相对路径即可
private List<ItemStruct> item_list; //* 子订单商品列表不可为空
public DouYinOrderSyncModel() {
}
public DouYinOrderSyncModel(String order_id, long create_time, String status, long amount, long total_price, String detail_url, List<ItemStruct> item_list) {
this.order_id = order_id;
this.create_time = create_time;
this.status = status;
this.amount = amount;
this.total_price = total_price;
this.detail_url = detail_url;
this.item_list = item_list;
}
public String getOrder_id() {
return order_id;

View File

@ -6,6 +6,7 @@ import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.RestUtil;
import org.jeecg.modules.mini.douyin.model.DouYinOrderSyncModel;
import org.jeecg.modules.yx.util.OrderStatusEnum;
import java.util.*;
@ -72,6 +73,36 @@ public class DouYinUtil {
System.out.println(JSONObject.parseObject(ss));*/
}
/**
* 订单同步v1
*/
public static void orderSyncV1(DouYinOrderSyncModel douYinOrderSyncModel,String appId, String appSecret, String openId){
log.debug("抖音订单同步----订单号:"+douYinOrderSyncModel.getOrder_id());
//文档 https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/server/ecpay/order/order-sync/
String accessToken = getAccessToken(appId, appSecret);
if (StringUtils.isBlank(accessToken)) {
throw new JeecgBootException("获取accessToken失败");
}
// 根据detail_status枚举出订单的order_status
int order_status = OrderStatusEnum.getStatusCodeByStatusName(douYinOrderSyncModel.getStatus());
JSONObject requestJson=new JSONObject();
requestJson.put("access_token",accessToken);
requestJson.put("app_name","douyin");
requestJson.put("open_id",openId);
requestJson.put("order_status",order_status);
requestJson.put("order_type",0);
requestJson.put("update_time",new Date().getTime()/1000);
//详情字段
requestJson.put("order_detail",JSONObject.toJSONString(douYinOrderSyncModel));
JSONObject post = RestUtil.post(orderSyncUrl,requestJson);
if (post!=null && "success".equals(post.getString("err_msg"))) {
//同步成功
log.debug("抖音订单同步成功----订单号:"+douYinOrderSyncModel.getOrder_id());
}else{
log.debug("抖音订单同步失败----订单号:"+douYinOrderSyncModel.getOrder_id()+",错误原因:"+post.toJSONString());
}
}
/**
* 订单同步
*/

View File

@ -13,6 +13,7 @@ import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.yx.entity.*;
import org.jeecg.modules.yx.service.*;
import org.jeecg.modules.yx.util.OrderStatusEnum;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@ -83,7 +84,8 @@ public class MiniUserService {
//判断支付订单中的
if(StringUtils.isBlank(skuCode) || vipDTO.getVipLevel()<2){
List<YxOrder> yxOrderList = yxOrderService.findListByPaymentUserId(userId);
List<YxOrder> paymentOrderList = yxOrderList.stream().filter(y -> "2".equals(y.getOrderStatus())).collect(Collectors.toList());
List<YxOrder> paymentOrderList = yxOrderList.stream().filter(y -> String.valueOf(OrderStatusEnum.getStatusCodeByStatusName("已支付")).equals(y.getOrderStatus())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(paymentOrderList)) {
YxOrder yxOrder = paymentOrderList.get(0);
skuCode = yxOrder.getSkuCode();

View File

@ -114,9 +114,14 @@ public class YxOrder implements Serializable {
@ApiModelProperty(value = "所属程序")
private String programType;
@ApiModelProperty(value = "用户OPENID")
private String openId;
//==================
@TableField(exist = false)
private String skuName;
@TableField(exist = false)
private String skuDetail;
@TableField(exist = false)
private String orderStatusName;
}

View File

@ -6,12 +6,12 @@
SELECT o.*,vsku.sku_name as skuName,vsku.sku_detail as skuDetail FROM yx_order o
LEFT JOIN (select * FROM yx_vip_sku group by sku_code) vsku ON vsku.sku_code = o.sku_code
WHERE o.payment_user_id = #{paymentUserId} AND o.order_code is not null
ORDER BY vsku.sku_code,o.payment_time DESC
ORDER BY o.update_time,o.create_time DESC
</select>
<select id="selectByOrderCode" resultType="org.jeecg.modules.yx.entity.YxOrder">
SELECT o.*,vsku.sku_name as skuName,vsku.sku_detail as skuDetail FROM yx_order o
LEFT JOIN (select * FROM yx_vip_sku group by sku_code) vsku ON vsku.sku_code = o.sku_code
WHERE o.order_code = #{orderCode}
ORDER BY vsku.sku_code,o.payment_time DESC
ORDER BY o.update_time,o.create_time DESC
</select>
</mapper>

View File

@ -35,4 +35,9 @@ public interface IYxOrderService extends IService<YxOrder> {
* @param refundAmount 退款金额
*/
YxOrder updateRefund(String dyOrderCode, String cpRefundNo, String refundNo, BigDecimal refundAmount);
/**
* 取消用户的订单
*/
void cancelByUserId(String userId);
}

View File

@ -1,17 +1,32 @@
package org.jeecg.modules.yx.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.lang.StringUtils;
import org.jeecg.modules.mini.douyin.config.DouYinConfig;
import org.jeecg.modules.mini.douyin.config.DouYinTiyuConfig;
import org.jeecg.modules.mini.douyin.model.DouYinOrderSyncModel;
import org.jeecg.modules.mini.douyin.model.ItemStruct;
import org.jeecg.modules.mini.douyin.util.DouYinUtil;
import org.jeecg.modules.yx.constant.YxConstant;
import org.jeecg.modules.yx.entity.YxOrder;
import org.jeecg.modules.yx.entity.YxVipSku;
import org.jeecg.modules.yx.mapper.YxOrderMapper;
import org.jeecg.modules.yx.mapper.YxVipSkuMapper;
import org.jeecg.modules.yx.service.IYxOrderService;
import org.jeecg.modules.yx.util.OrderStatusEnum;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description: 订单表
@ -21,7 +36,12 @@ import java.util.List;
*/
@Service
public class YxOrderServiceImpl extends ServiceImpl<YxOrderMapper, YxOrder> implements IYxOrderService {
@Resource
private DouYinConfig douYinConfig;
@Resource
private DouYinTiyuConfig douYinTiyuConfig;
@Resource
private YxVipSkuMapper yxVipSkuMapper;
@Override
public List<YxOrder> findListByPaymentUserId(String paymentUserId) {
return baseMapper.findListByPaymentUserId(paymentUserId);
@ -36,7 +56,7 @@ public class YxOrderServiceImpl extends ServiceImpl<YxOrderMapper, YxOrder> impl
lambdaUpdateWrapper.eq(YxOrder::getOrderCode, orderCode);
lambdaUpdateWrapper.set(YxOrder::getPaymentTime, paymentTime);
lambdaUpdateWrapper.set(YxOrder::getPaymentType, paymentType);
lambdaUpdateWrapper.set(YxOrder::getOrderStatus, "2");
lambdaUpdateWrapper.set(YxOrder::getOrderStatus, String.valueOf(OrderStatusEnum.getStatusCodeByStatusName("已支付")));
super.update(lambdaUpdateWrapper);
}
@ -59,9 +79,52 @@ public class YxOrderServiceImpl extends ServiceImpl<YxOrderMapper, YxOrder> impl
yxOrder.setCpRefundNo(cpRefundNo);
yxOrder.setRefundNo(refundNo);
yxOrder.setRefundAmount(refundAmount);
yxOrder.setOrderStatus("8");
yxOrder.setOrderStatus(String.valueOf(OrderStatusEnum.getStatusCodeByStatusName("已退款")));
yxOrder.setRefundTime(new Date());
this.updateById(yxOrder);
return yxOrder;
}
@Override
public void cancelByUserId(String userId) {
LambdaQueryWrapper<YxOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(YxOrder::getPaymentUserId,userId);
lambdaQueryWrapper.eq(YxOrder::getOrderStatus,OrderStatusEnum.PENDING_PAYMENT.getStatusCode());
List<YxOrder> orderList = this.list(lambdaQueryWrapper);
if (CollectionUtil.isNotEmpty(orderList)) {
List<YxVipSku> yxVipSkuList = yxVipSkuMapper.selectList(new LambdaQueryWrapper<>());
Map<String, YxVipSku> skuMap = yxVipSkuList.stream().collect(Collectors.toMap(YxVipSku::getSkuCode, y -> y));
YxVipSku yxVipSku = null;
String skuImg = null;
String attach = null;
String programType = null;
List<ItemStruct> itemList = null;
for (YxOrder yxOrder : orderList) {
programType = yxOrder.getProgramType();
yxVipSku = skuMap.get(yxOrder.getSkuCode());
if (yxVipSku == null || StringUtils.isBlank(yxOrder.getOpenId()) || StringUtils.isBlank(programType)) {
continue;
}
long createTimeLong = yxOrder.getCreateTime().getTime() / YxConstant.bigDecimal1000;
itemList = new ArrayList<>();
skuImg = yxVipSku.getSkuImg();
attach = yxOrder.getProgramType() + yxVipSku.getSkuName();
itemList.add(new ItemStruct(yxOrder.getSkuCode(),skuImg,attach,null,1,yxOrder.getTotalAmount().longValue()));
DouYinOrderSyncModel douYinOrderSyncModel = new DouYinOrderSyncModel(yxOrder.getOrderCode(), createTimeLong,
"已取消", 1, yxOrder.getTotalAmount().longValue(),
"pages/zyb/order/detail?orderCode=" + yxOrder.getOrderCode(), itemList);
if(programType.equals("体育志愿宝")){
DouYinUtil.orderSyncV1(douYinOrderSyncModel,douYinTiyuConfig.getAppId(),douYinTiyuConfig.getAppSecret(),yxOrder.getOpenId());
}else{
DouYinUtil.orderSyncV1(douYinOrderSyncModel,douYinConfig.getAppId(),douYinConfig.getAppSecret(),yxOrder.getOpenId());
}
// 更改该订单状态
yxOrder.setOrderStatus(String.valueOf(OrderStatusEnum.CANCELED.getStatusCode()));
this.updateById(yxOrder);
}
}
}
}

View File

@ -0,0 +1,50 @@
package org.jeecg.modules.yx.util;
/**
* @author ZhouWenTao
* @create 2024-07-24-17:52
*/
public enum OrderStatusEnum {
PENDING_PAYMENT("待支付", 0),
PAID("已支付", 1),
CANCELED("已取消", 2),
REDEEMED("已核销", 4),
REFUNDING("退款中", 5),
REFUNDED("已退款", 6),
REFUND_FAILED("退款失败", 8);
private final String statusName;
private final int statusCode;
OrderStatusEnum(String statusName, int statusCode) {
this.statusName = statusName;
this.statusCode = statusCode;
}
public String getStatusName() {
return statusName;
}
public int getStatusCode() {
return statusCode;
}
public static String getStatusNameByStatusCode(int statusCode) {
for (OrderStatusEnum status : OrderStatusEnum.values()) {
if (status.getStatusCode() == statusCode) {
return status.getStatusName();
}
}
return PENDING_PAYMENT.getStatusName(); // Default or throw exception
}
public static int getStatusCodeByStatusName(String statusName) {
for (OrderStatusEnum status : OrderStatusEnum.values()) {
if (status.getStatusName().equals(statusName)) {
return status.getStatusCode();
}
}
return PENDING_PAYMENT.getStatusCode(); // Default or throw exception
}
}