新增:会员卡功能及支持使用余额支付功能

This commit is contained in:
gxwebsoft
2024-05-30 20:01:06 +08:00
parent bf71971a6c
commit 4d16b04fa5
23 changed files with 683 additions and 70 deletions
@@ -100,7 +100,7 @@ public class PeriodController extends BaseController {
// 查询是否含有未支付订单 // 查询是否含有未支付订单
final User loginUser = getLoginUser(); final User loginUser = getLoginUser();
if(loginUser != null){ if(loginUser != null){
if (orderService.count(new LambdaQueryWrapper<Order>().eq(Order::getPayStatus,0).eq(Order::getOrderStatus,0).eq(Order::getUserId,loginUser.getUserId())) > 0) { if (orderService.count(new LambdaQueryWrapper<Order>().eq(Order::getType,1).eq(Order::getPayStatus,0).eq(Order::getOrderStatus,0).eq(Order::getUserId,loginUser.getUserId())) > 0) {
return fail("您还有未支付订单,请先支付",null); return fail("您还有未支付订单,请先支付",null);
} }
} }
@@ -22,7 +22,7 @@ import java.util.List;
* 会员卡控制器 * 会员卡控制器
* *
* @author 科技小王子 * @author 科技小王子
* @since 2024-05-27 19:58:58 * @since 2024-05-29 14:29:43
*/ */
@Api(tags = "会员卡管理") @Api(tags = "会员卡管理")
@RestController @RestController
@@ -1,22 +1,20 @@
package com.gxwebsoft.booking.entity; package com.gxwebsoft.booking.entity;
import java.math.BigDecimal; import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/** /**
* 会员卡 * 会员卡
* *
* @author 科技小王子 * @author 科技小王子
* @since 2024-05-27 19:58:57 * @since 2024-05-29 14:29:43
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@@ -58,11 +56,14 @@ public class UserCard implements Serializable {
@ApiModelProperty(value = "手机号码") @ApiModelProperty(value = "手机号码")
private String phone; private String phone;
@ApiModelProperty(value = "会员卡图片")
private String image;
@ApiModelProperty(value = "vip购卡价格") @ApiModelProperty(value = "vip购卡价格")
private BigDecimal price; private BigDecimal price;
@ApiModelProperty(value = "会员卡介绍") @ApiModelProperty(value = "会员卡介绍")
private String desc; private String cardDesc;
@ApiModelProperty(value = "会员卡说明") @ApiModelProperty(value = "会员卡说明")
private String info; private String info;
@@ -119,7 +120,10 @@ public class UserCard implements Serializable {
private Integer isInvoice; private Integer isInvoice;
@ApiModelProperty(value = "vip卡到期时间") @ApiModelProperty(value = "vip卡到期时间")
private Date expireTime; private Date expirationTime;
@ApiModelProperty(value = "vip卡到期时间")
private Integer expireTimeOld;
@ApiModelProperty(value = "紧急联系人") @ApiModelProperty(value = "紧急联系人")
private String urgentName; private String urgentName;
@@ -137,13 +141,16 @@ public class UserCard implements Serializable {
private Integer useTime; private Integer useTime;
@ApiModelProperty(value = "创建时间") @ApiModelProperty(value = "创建时间")
private Integer createTime; private Integer createTimeOld;
private Integer updateTime; private Integer updateTimeOld;
@ApiModelProperty(value = "身份证号码") @ApiModelProperty(value = "身份证号码")
private String idCard; private String idCard;
@ApiModelProperty(value = "商户ID")
private Integer merchantId;
@ApiModelProperty(value = "备注") @ApiModelProperty(value = "备注")
private String remark; private String remark;
@@ -153,7 +160,21 @@ public class UserCard implements Serializable {
@ApiModelProperty(value = "排序号") @ApiModelProperty(value = "排序号")
private Integer sortNumber; private Integer sortNumber;
@ApiModelProperty(value = "是否删除, 0否, 1是")
@TableLogic
private Integer deleted;
@ApiModelProperty(value = "租户id") @ApiModelProperty(value = "租户id")
private Integer tenantId; private Integer tenantId;
@ApiModelProperty(value = "注册时间")
private Date createTime;
@ApiModelProperty(value = "修改时间")
private Date updateTime;
@ApiModelProperty(value = "商户头像")
@TableField(exist = false)
private String merchantAvatar;
} }
@@ -12,7 +12,7 @@ import java.util.List;
* 会员卡Mapper * 会员卡Mapper
* *
* @author 科技小王子 * @author 科技小王子
* @since 2024-05-27 19:58:57 * @since 2024-05-29 14:29:43
*/ */
public interface UserCardMapper extends BaseMapper<UserCard> { public interface UserCardMapper extends BaseMapper<UserCard> {
@@ -4,8 +4,9 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.* SELECT a.*,b.merchant_name,b.image as merchant_avatar
FROM booking_user_card a FROM booking_user_card a
LEFT JOIN shop_merchant b ON a.merchant_id = b.merchant_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -43,8 +44,8 @@
<if test="param.price != null"> <if test="param.price != null">
AND a.price = #{param.price} AND a.price = #{param.price}
</if> </if>
<if test="param.desc != null"> <if test="param.cardDesc != null">
AND a.desc LIKE CONCAT('%', #{param.desc}, '%') AND a.card_desc LIKE CONCAT('%', #{param.cardDesc}, '%')
</if> </if>
<if test="param.info != null"> <if test="param.info != null">
AND a.info LIKE CONCAT('%', #{param.info}, '%') AND a.info LIKE CONCAT('%', #{param.info}, '%')
@@ -100,8 +101,11 @@
<if test="param.isInvoice != null"> <if test="param.isInvoice != null">
AND a.is_invoice = #{param.isInvoice} AND a.is_invoice = #{param.isInvoice}
</if> </if>
<if test="param.expireTime != null"> <if test="param.expirationTime != null">
AND a.expire_time = #{param.expireTime} AND a.expiration_time LIKE CONCAT('%', #{param.expirationTime}, '%')
</if>
<if test="param.expireTimeOld != null">
AND a.expire_time_old = #{param.expireTimeOld}
</if> </if>
<if test="param.urgentName != null"> <if test="param.urgentName != null">
AND a.urgent_name LIKE CONCAT('%', #{param.urgentName}, '%') AND a.urgent_name LIKE CONCAT('%', #{param.urgentName}, '%')
@@ -118,11 +122,11 @@
<if test="param.useTime != null"> <if test="param.useTime != null">
AND a.use_time = #{param.useTime} AND a.use_time = #{param.useTime}
</if> </if>
<if test="param.createTimeStart != null"> <if test="param.createTimeOld != null">
AND a.create_time &gt;= #{param.createTimeStart} AND a.create_time_old = #{param.createTimeOld}
</if> </if>
<if test="param.createTimeEnd != null"> <if test="param.updateTimeOld != null">
AND a.create_time &lt;= #{param.createTimeEnd} AND a.update_time_old = #{param.updateTimeOld}
</if> </if>
<if test="param.idCard != null"> <if test="param.idCard != null">
AND a.id_card LIKE CONCAT('%', #{param.idCard}, '%') AND a.id_card LIKE CONCAT('%', #{param.idCard}, '%')
@@ -136,6 +140,18 @@
<if test="param.sortNumber != null"> <if test="param.sortNumber != null">
AND a.sort_number = #{param.sortNumber} AND a.sort_number = #{param.sortNumber}
</if> </if>
<if test="param.deleted != null">
AND a.deleted = #{param.deleted}
</if>
<if test="param.deleted == null">
AND a.deleted = 0
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
) )
@@ -14,7 +14,7 @@ import lombok.EqualsAndHashCode;
* 会员卡查询参数 * 会员卡查询参数
* *
* @author 科技小王子 * @author 科技小王子
* @since 2024-05-27 19:58:57 * @since 2024-05-29 14:29:43
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@@ -65,7 +65,7 @@ public class UserCardParam extends BaseParam {
private BigDecimal price; private BigDecimal price;
@ApiModelProperty(value = "会员卡介绍") @ApiModelProperty(value = "会员卡介绍")
private String desc; private String cardDesc;
@ApiModelProperty(value = "会员卡说明") @ApiModelProperty(value = "会员卡说明")
private String info; private String info;
@@ -136,9 +136,12 @@ public class UserCardParam extends BaseParam {
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer isInvoice; private Integer isInvoice;
@ApiModelProperty(value = "vip卡到期时间")
private String expirationTime;
@ApiModelProperty(value = "vip卡到期时间") @ApiModelProperty(value = "vip卡到期时间")
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private String expireTime; private Integer expireTimeOld;
@ApiModelProperty(value = "紧急联系人") @ApiModelProperty(value = "紧急联系人")
private String urgentName; private String urgentName;
@@ -156,6 +159,13 @@ public class UserCardParam extends BaseParam {
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer useTime; private Integer useTime;
@ApiModelProperty(value = "创建时间")
@QueryField(type = QueryType.EQ)
private Integer createTimeOld;
@QueryField(type = QueryType.EQ)
private Integer updateTimeOld;
@ApiModelProperty(value = "身份证号码") @ApiModelProperty(value = "身份证号码")
private String idCard; private String idCard;
@@ -169,4 +179,8 @@ public class UserCardParam extends BaseParam {
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer sortNumber; private Integer sortNumber;
@ApiModelProperty(value = "是否删除, 0否, 1是")
@QueryField(type = QueryType.EQ)
private Integer deleted;
} }
@@ -11,7 +11,7 @@ import java.util.List;
* 会员卡Service * 会员卡Service
* *
* @author 科技小王子 * @author 科技小王子
* @since 2024-05-27 19:58:57 * @since 2024-05-29 14:29:43
*/ */
public interface UserCardService extends IService<UserCard> { public interface UserCardService extends IService<UserCard> {
@@ -15,7 +15,7 @@ import java.util.List;
* 会员卡Service实现 * 会员卡Service实现
* *
* @author 科技小王子 * @author 科技小王子
* @since 2024-05-27 19:58:57 * @since 2024-05-29 14:29:43
*/ */
@Service @Service
public class UserCardServiceImpl extends ServiceImpl<UserCardMapper, UserCard> implements UserCardService { public class UserCardServiceImpl extends ServiceImpl<UserCardMapper, UserCard> implements UserCardService {
@@ -127,6 +127,15 @@ public class CommonUtil {
return prefix + tenantId + RandomUtil.randomNumbers(2); return prefix + tenantId + RandomUtil.randomNumbers(2);
} }
/**
* 生成会员卡号
* @return
*/
public static String createCardNo() {
String prefix = DateTime.now().toString(DatePattern.PURE_TIME_PATTERN);
return "00" + prefix + RandomUtil.randomNumbers(2);
}
/** /**
* 检查List是否有重复元素 * 检查List是否有重复元素
* *
@@ -3,14 +3,20 @@ package com.gxwebsoft.common.core.utils;
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.security.JwtUtil; import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.system.entity.Role; import com.gxwebsoft.common.system.entity.Role;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.entity.UserRole; import com.gxwebsoft.common.system.entity.UserRole;
import com.gxwebsoft.common.system.param.RoleParam; import com.gxwebsoft.common.system.param.RoleParam;
import com.gxwebsoft.shop.entity.MerchantAccount; import com.gxwebsoft.shop.entity.MerchantAccount;
import com.gxwebsoft.shop.entity.Order;
import org.springframework.http.*;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -20,15 +26,15 @@ public class RequestUtil {
private static String ACCESS_TOKEN; private static String ACCESS_TOKEN;
private static String TENANT_ID; private static String TENANT_ID;
public void setTenantId(String tenantId){ public void setTenantId(String tenantId) {
TENANT_ID = tenantId; TENANT_ID = tenantId;
} }
public void setAccessToken(String token){ public void setAccessToken(String token) {
ACCESS_TOKEN = token; ACCESS_TOKEN = token;
} }
public User getUserByPhone(String phone){ public User getUserByPhone(String phone) {
String path = "/system/user/getByPhone/" + phone; String path = "/system/user/getByPhone/" + phone;
try { try {
// 链式构建请求 // 链式构建请求
@@ -72,18 +78,18 @@ public class RequestUtil {
String path = "/system/user/"; String path = "/system/user/";
try { try {
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
map.put("nickname",merchantAccount.getRealName()); map.put("nickname", merchantAccount.getRealName());
map.put("username", merchantAccount.getPhone()); map.put("username", merchantAccount.getPhone());
map.put("realName",merchantAccount.getRealName()); map.put("realName", merchantAccount.getRealName());
map.put("phone", merchantAccount.getPhone()); map.put("phone", merchantAccount.getPhone());
map.put("password",merchantAccount.getPassword()); map.put("password", merchantAccount.getPassword());
final ArrayList<Object> roles = new ArrayList<>(); final ArrayList<Object> roles = new ArrayList<>();
final UserRole userRole = new UserRole(); final UserRole userRole = new UserRole();
userRole.setUserId(merchantAccount.getUserId()); userRole.setUserId(merchantAccount.getUserId());
userRole.setRoleId(merchantAccount.getRoleId()); userRole.setRoleId(merchantAccount.getRoleId());
userRole.setTenantId(merchantAccount.getTenantId()); userRole.setTenantId(merchantAccount.getTenantId());
roles.add(userRole); roles.add(userRole);
map.put("roles",roles); map.put("roles", roles);
map.put("tenantId", TENANT_ID); map.put("tenantId", TENANT_ID);
// 链式构建请求 // 链式构建请求
String result = HttpRequest.post(host.concat(path)) String result = HttpRequest.post(host.concat(path))
@@ -97,4 +103,20 @@ public class RequestUtil {
} }
return true; return true;
} }
public ApiResult<?> updateUserBalance(String path,User user) {
try {
// 链式构建请求
final String body = HttpRequest.put(host.concat(path))
.header("Authorization", ACCESS_TOKEN)
.header("Tenantid", TENANT_ID)
.body(JSONUtil.toJSONString(user))
.timeout(20000)
.execute().body();
return JSONUtil.parseObject(body, ApiResult.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
} }
@@ -11,6 +11,7 @@ import com.gxwebsoft.booking.entity.UserCard;
import com.gxwebsoft.booking.param.UserCardParam; import com.gxwebsoft.booking.param.UserCardParam;
import com.gxwebsoft.booking.service.CardService; import com.gxwebsoft.booking.service.CardService;
import com.gxwebsoft.booking.service.UserCardService; import com.gxwebsoft.booking.service.UserCardService;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.CommonUtil; import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.entity.OrderInfo; import com.gxwebsoft.shop.entity.OrderInfo;
@@ -33,6 +34,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@@ -82,8 +84,9 @@ public class OrderController extends BaseController {
@PreAuthorize("hasAuthority('sys:order:save')") @PreAuthorize("hasAuthority('sys:order:save')")
@ApiOperation("下单") @ApiOperation("下单")
@PostMapping() @PostMapping()
public ApiResult<?> save(@RequestBody Order order) { public ApiResult<?> save(@RequestBody Order order, HttpServletRequest request) {
System.out.println("order = " + order); System.out.println("order = " + order);
String access_token = JwtUtil.getAccessToken(request);
// 记录当前登录用户id // 记录当前登录用户id
User loginUser = getLoginUser(); User loginUser = getLoginUser();
if (loginUser == null) { if (loginUser == null) {
@@ -98,11 +101,11 @@ public class OrderController extends BaseController {
return fail("商品描述(必填)"); return fail("商品描述(必填)");
} }
// 微信支付(商品金额不能为0) // 微信支付(商品金额不能为0)
if (order.getPayType().equals(1)) { // if (order.getPayType().equals(1)) {
if (order.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) { // if (order.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
return fail("商品金额不能为0"); // return fail("商品金额不能为0");
} // }
} // }
// 已下过订单 // 已下过订单
if(order.getOrderId() != null){ if(order.getOrderId() != null){
@@ -162,17 +165,17 @@ public class OrderController extends BaseController {
if (order.getType().equals(2)) { if (order.getType().equals(2)) {
// 会员卡信息 // 会员卡信息
final Card card = cardService.getByIdRel(Integer.valueOf(order.getCardId())); final Card card = cardService.getByIdRel(Integer.valueOf(order.getCardId()));
System.out.println("card = " + card);
final UserCard userCard = new UserCard(); final UserCard userCard = new UserCard();
userCard.setUserId(loginUser.getUserId()); userCard.setUserId(loginUser.getUserId());
// 适用场馆 // 适用场馆
userCard.setSid(card.getMerchantIds()); userCard.setSid(card.getMerchantIds());
userCard.setCardNum(CommonUtil.randomUUID8()); userCard.setCardNum(CommonUtil.createCardNo());
userCard.setName(card.getCardName()); userCard.setName(card.getCardName());
userCard.setUsername(loginUser.getRealName()); userCard.setUsername(loginUser.getRealName());
userCard.setPhone(loginUser.getPhone()); userCard.setPhone(loginUser.getPhone());
userCard.setPrice(card.getPrice()); userCard.setPrice(card.getPrice());
userCard.setDesc(card.getCardDesc()); userCard.setImage(card.getImage());
userCard.setCardDesc(card.getCardDesc());
userCard.setInfo(card.getComments()); userCard.setInfo(card.getComments());
userCard.setUid(loginUser.getUserId()); userCard.setUid(loginUser.getUserId());
userCard.setVid(0); userCard.setVid(0);
@@ -181,20 +184,25 @@ public class OrderController extends BaseController {
userCard.setDiscount(card.getDiscount()); userCard.setDiscount(card.getDiscount());
userCard.setNumber(1); userCard.setNumber(1);
userCard.setNum(card.getNumber()); userCard.setNum(card.getNumber());
userCard.setTerm(1);
userCard.setTerm(card.getMonth()/12);
userCard.setMonth(card.getMonth()); userCard.setMonth(card.getMonth());
userCard.setMerchantId(card.getMerchantId());
userCard.setPayType(1); userCard.setPayType(1);
userCard.setExpireTime(DateUtil.offset(DateUtil.date(), DateField.MONTH, card.getMonth())); userCard.setTenantId(card.getTenantId());
System.out.println("userCard = " + userCard); userCard.setExpirationTime(DateUtil.offset(DateUtil.date(), DateField.MONTH, card.getMonth()));
return fail("下单失败2",userCard); userCardService.save(userCard);
// userCardService.save(userCard);
} }
// 微信统一下单接口 // 微信统一下单接口
if (order.getPayType().equals(1)) { if (order.getPayType().equals(1)) {
return success("下单成功", orderService.createWxOrder(order)); return success("下单成功", orderService.createWxOrder(order));
} }
// 余额支付
if (order.getPayType().equals(0)) {
order.setAccessToken(access_token);
order.setLoginUser(loginUser);
return success("下单成功", orderService.payByBalance(order));
}
} }
return fail("下单失败"); return fail("下单失败");
} }
@@ -0,0 +1,115 @@
package com.gxwebsoft.shop.controller;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.service.UserBalanceLogService;
import com.gxwebsoft.shop.entity.UserBalanceLog;
import com.gxwebsoft.shop.param.UserBalanceLogParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 用户余额变动明细表控制器
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
*/
@Api(tags = "用户余额变动明细表管理")
@RestController
@RequestMapping("/api/shop/user-balance-log")
public class UserBalanceLogController extends BaseController {
@Resource
private UserBalanceLogService userBalanceLogService;
@ApiOperation("分页查询用户余额变动明细表")
@GetMapping("/page")
public ApiResult<PageResult<UserBalanceLog>> page(UserBalanceLogParam param) {
// 使用关联查询
return success(userBalanceLogService.pageRel(param));
}
@ApiOperation("查询全部用户余额变动明细表")
@GetMapping()
public ApiResult<List<UserBalanceLog>> list(UserBalanceLogParam param) {
// 使用关联查询
return success(userBalanceLogService.listRel(param));
}
@PreAuthorize("hasAuthority('shop:userBalanceLog:list')")
@ApiOperation("根据id查询用户余额变动明细表")
@GetMapping("/{id}")
public ApiResult<UserBalanceLog> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(userBalanceLogService.getByIdRel(id));
}
@ApiOperation("添加用户余额变动明细表")
@PostMapping()
public ApiResult<?> save(@RequestBody UserBalanceLog userBalanceLog) {
// 记录当前登录用户id
User loginUser = getLoginUser();
if (loginUser != null) {
userBalanceLog.setUserId(loginUser.getUserId());
}
if (userBalanceLogService.save(userBalanceLog)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("修改用户余额变动明细表")
@PutMapping()
public ApiResult<?> update(@RequestBody UserBalanceLog userBalanceLog) {
if (userBalanceLogService.updateById(userBalanceLog)) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("删除用户余额变动明细表")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (userBalanceLogService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@ApiOperation("批量添加用户余额变动明细表")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<UserBalanceLog> list) {
if (userBalanceLogService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("批量修改用户余额变动明细表")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<UserBalanceLog> batchParam) {
if (batchParam.update(userBalanceLogService, "log_id")) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("批量删除用户余额变动明细表")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (userBalanceLogService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
}
@@ -10,6 +10,7 @@ import java.util.List;
import com.gxwebsoft.common.core.annotation.QueryField; import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType; import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@@ -190,6 +191,18 @@ public class Order implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String openid; private String openid;
@ApiModelProperty(value = "余额变动场景(10用户充值 20用户消费 30管理员操作 40订单退款)")
@TableField(exist = false)
private Integer scene;
@ApiModelProperty(value = "用于请求主服务器时附加token")
@TableField(exist = false)
private String accessToken;
@ApiModelProperty(value = "当前登录用户")
@TableField(exist = false)
private User loginUser;
@ApiModelProperty(value = "预定信息") @ApiModelProperty(value = "预定信息")
@TableField(exist = false) @TableField(exist = false)
private List<OrderInfo> orderInfoList; private List<OrderInfo> orderInfoList;
@@ -0,0 +1,83 @@
package com.gxwebsoft.shop.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableLogic;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 用户余额变动明细表
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "UserBalanceLog对象", description = "用户余额变动明细表")
@TableName("shop_user_balance_log")
public class UserBalanceLog implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@TableId(value = "log_id", type = IdType.AUTO)
private Integer logId;
@ApiModelProperty(value = "用户ID")
private Integer userId;
@ApiModelProperty(value = "余额变动场景(10用户充值 20用户消费 30管理员操作 40订单退款)")
private Integer scene;
@ApiModelProperty(value = "变动金额")
private BigDecimal money;
@ApiModelProperty(value = "变动后余额")
private BigDecimal balance;
@ApiModelProperty(value = "管理员备注")
private String remark;
@ApiModelProperty(value = "操作人ID")
private Integer adminId;
@ApiModelProperty(value = "订单编号")
private String orderNo;
@ApiModelProperty(value = "商户ID")
private Integer merchantId;
@ApiModelProperty(value = "排序(数字越小越靠前)")
private Integer sortNumber;
@ApiModelProperty(value = "备注")
private String comments;
@ApiModelProperty(value = "状态, 0正常, 1冻结")
private Integer status;
@ApiModelProperty(value = "是否删除, 0否, 1是")
@TableLogic
private Integer deleted;
@ApiModelProperty(value = "商户编码")
private String merchantCode;
@ApiModelProperty(value = "租户id")
private Integer tenantId;
@ApiModelProperty(value = "注册时间")
private Date createTime;
@ApiModelProperty(value = "修改时间")
private Date updateTime;
}
@@ -0,0 +1,37 @@
package com.gxwebsoft.shop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.shop.entity.UserBalanceLog;
import com.gxwebsoft.shop.param.UserBalanceLogParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户余额变动明细表Mapper
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
*/
public interface UserBalanceLogMapper extends BaseMapper<UserBalanceLog> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<UserBalanceLog>
*/
List<UserBalanceLog> selectPageRel(@Param("page") IPage<UserBalanceLog> page,
@Param("param") UserBalanceLogParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<UserBalanceLog> selectListRel(@Param("param") UserBalanceLogParam param);
}
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gxwebsoft.shop.mapper.UserBalanceLogMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM shop_user_balance_log a
<where>
<if test="param.logId != null">
AND a.log_id = #{param.logId}
</if>
<if test="param.userId != null">
AND a.user_id = #{param.userId}
</if>
<if test="param.scene != null">
AND a.scene = #{param.scene}
</if>
<if test="param.money != null">
AND a.money = #{param.money}
</if>
<if test="param.balance != null">
AND a.balance = #{param.balance}
</if>
<if test="param.remark != null">
AND a.remark LIKE CONCAT('%', #{param.remark}, '%')
</if>
<if test="param.sortNumber != null">
AND a.sort_number = #{param.sortNumber}
</if>
<if test="param.comments != null">
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
</if>
<if test="param.status != null">
AND a.status = #{param.status}
</if>
<if test="param.deleted != null">
AND a.deleted = #{param.deleted}
</if>
<if test="param.deleted == null">
AND a.deleted = 0
</if>
<if test="param.merchantCode != null">
AND a.merchant_code LIKE CONCAT('%', #{param.merchantCode}, '%')
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.shop.entity.UserBalanceLog">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.UserBalanceLog">
<include refid="selectSql"></include>
</select>
</mapper>
@@ -0,0 +1,67 @@
package com.gxwebsoft.shop.param;
import java.math.BigDecimal;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 用户余额变动明细表查询参数
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "UserBalanceLogParam对象", description = "用户余额变动明细表查询参数")
public class UserBalanceLogParam extends BaseParam {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@QueryField(type = QueryType.EQ)
private Integer logId;
@ApiModelProperty(value = "用户ID")
@QueryField(type = QueryType.EQ)
private Integer userId;
@ApiModelProperty(value = "余额变动场景(10用户充值 20用户消费 30管理员操作 40订单退款)")
@QueryField(type = QueryType.EQ)
private Integer scene;
@ApiModelProperty(value = "变动金额")
@QueryField(type = QueryType.EQ)
private BigDecimal money;
@ApiModelProperty(value = "变动后余额")
@QueryField(type = QueryType.EQ)
private BigDecimal balance;
@ApiModelProperty(value = "管理员备注")
private String remark;
@ApiModelProperty(value = "排序(数字越小越靠前)")
@QueryField(type = QueryType.EQ)
private Integer sortNumber;
@ApiModelProperty(value = "备注")
private String comments;
@ApiModelProperty(value = "状态, 0正常, 1冻结")
@QueryField(type = QueryType.EQ)
private Integer status;
@ApiModelProperty(value = "是否删除, 0否, 1是")
@QueryField(type = QueryType.EQ)
private Integer deleted;
@ApiModelProperty(value = "商户编码")
private String merchantCode;
}
@@ -2,6 +2,7 @@ package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.entity.Order; import com.gxwebsoft.shop.entity.Order;
import com.gxwebsoft.shop.param.OrderParam; import com.gxwebsoft.shop.param.OrderParam;
@@ -45,4 +46,6 @@ public interface OrderService extends IService<Order> {
Order getByOutTradeNo(String outTradeNo); Order getByOutTradeNo(String outTradeNo);
void updateByOutTradeNo(Order order); void updateByOutTradeNo(Order order);
Boolean payByBalance(Order order);
} }
@@ -0,0 +1,42 @@
package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.UserBalanceLog;
import com.gxwebsoft.shop.param.UserBalanceLogParam;
import java.util.List;
/**
* 用户余额变动明细表Service
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
*/
public interface UserBalanceLogService extends IService<UserBalanceLog> {
/**
* 分页关联查询
*
* @param param 查询参数
* @return PageResult<UserBalanceLog>
*/
PageResult<UserBalanceLog> pageRel(UserBalanceLogParam param);
/**
* 关联查询全部
*
* @param param 查询参数
* @return List<UserBalanceLog>
*/
List<UserBalanceLog> listRel(UserBalanceLogParam param);
/**
* 根据id查询
*
* @param logId 主键ID
* @return UserBalanceLog
*/
UserBalanceLog getByIdRel(Integer logId);
}
@@ -7,20 +7,24 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.config.ConfigProperties; import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.RequestUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.SettingService; import com.gxwebsoft.common.system.service.SettingService;
import com.gxwebsoft.shop.entity.OrderGoods; import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.shop.entity.OrderInfo; import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.entity.Payment;
import com.gxwebsoft.shop.mapper.OrderMapper; import com.gxwebsoft.shop.mapper.OrderMapper;
import com.gxwebsoft.shop.param.OrderInfoParam; import com.gxwebsoft.shop.param.OrderInfoParam;
import com.gxwebsoft.shop.service.OrderGoodsService; import com.gxwebsoft.shop.service.OrderGoodsService;
import com.gxwebsoft.shop.service.OrderInfoService; import com.gxwebsoft.shop.service.OrderInfoService;
import com.gxwebsoft.shop.service.OrderService; import com.gxwebsoft.shop.service.OrderService;
import com.gxwebsoft.shop.entity.Order;
import com.gxwebsoft.shop.param.OrderParam; import com.gxwebsoft.shop.param.OrderParam;
import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.service.UserBalanceLogService;
import com.wechat.pay.java.core.Config; import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAConfig; import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension; import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
@@ -28,11 +32,18 @@ import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer; import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest; import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse; import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.beans.Beans;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -59,6 +70,10 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
@Resource @Resource
private SettingService settingService; private SettingService settingService;
@Resource @Resource
private UserService userService;
@Resource
private UserBalanceLogService userBalanceLogService;
@Resource
private RedisUtil redisUtil; private RedisUtil redisUtil;
public static String privateKeyPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_key.pem"; public static String privateKeyPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_key.pem";
public static String privateCertPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_cert.pem"; public static String privateCertPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_cert.pem";
@@ -71,7 +86,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
page.setDefaultOrder("sort_number asc, create_time desc"); page.setDefaultOrder("sort_number asc, create_time desc");
List<Order> list = baseMapper.selectPageRel(page, param); List<Order> list = baseMapper.selectPageRel(page, param);
if(param.getSceneType() != null){ if (param.getSceneType() != null) {
final Set<Integer> orderIds = list.stream().map(Order::getOrderId).collect(Collectors.toSet()); final Set<Integer> orderIds = list.stream().map(Order::getOrderId).collect(Collectors.toSet());
if (!CollectionUtils.isEmpty(orderIds)) { if (!CollectionUtils.isEmpty(orderIds)) {
// 查询预定订单信息 // 查询预定订单信息
@@ -235,4 +250,35 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
baseMapper.updateByOutTradeNo(order); baseMapper.updateByOutTradeNo(order);
} }
@Override
@Transactional(rollbackFor = {Exception.class})
public Boolean payByBalance(Order order) {
final User loginUser = order.getLoginUser();
if (loginUser.getBalance().compareTo(order.getTotalPrice()) < 0) {
throw new BusinessException("余额不足");
}
// 发起网络请求(更新余额接口)
final RequestUtil requestUtil = new RequestUtil();
requestUtil.setAccessToken(order.getAccessToken());
requestUtil.setTenantId(order.getTenantId().toString());
String api = "/system/user/updateUserBalance"; // 更新余额接口
final BigDecimal subtract = loginUser.getBalance().subtract(order.getTotalPrice());
loginUser.setBalance(subtract);
final ApiResult<?> apiResult = requestUtil.updateUserBalance(api, loginUser);
if (apiResult.getCode().equals(0)) {
// 记录余额明细
final UserBalanceLog balanceLog = new UserBalanceLog();
balanceLog.setUserId(order.getUserId());
balanceLog.setScene(20);
balanceLog.setOrderNo(order.getOrderNo());
balanceLog.setMoney(order.getPayPrice());
balanceLog.setBalance(subtract);
balanceLog.setRemark(order.getComments());
balanceLog.setMerchantId(order.getMerchantId());
userBalanceLogService.save(balanceLog);
return true;
}
return false;
}
} }
@@ -0,0 +1,47 @@
package com.gxwebsoft.shop.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.shop.mapper.UserBalanceLogMapper;
import com.gxwebsoft.shop.service.UserBalanceLogService;
import com.gxwebsoft.shop.entity.UserBalanceLog;
import com.gxwebsoft.shop.param.UserBalanceLogParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 用户余额变动明细表Service实现
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
*/
@Service
public class UserBalanceLogServiceImpl extends ServiceImpl<UserBalanceLogMapper, UserBalanceLog> implements UserBalanceLogService {
@Override
public PageResult<UserBalanceLog> pageRel(UserBalanceLogParam param) {
PageParam<UserBalanceLog, UserBalanceLogParam> page = new PageParam<>(param);
page.setDefaultOrder("sort_number asc, create_time desc");
List<UserBalanceLog> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<UserBalanceLog> listRel(UserBalanceLogParam param) {
List<UserBalanceLog> list = baseMapper.selectListRel(param);
// 排序
PageParam<UserBalanceLog, UserBalanceLogParam> page = new PageParam<>();
page.setDefaultOrder("sort_number asc, create_time desc");
return page.sortRecords(list);
}
@Override
public UserBalanceLog getByIdRel(Integer logId) {
UserBalanceLogParam param = new UserBalanceLogParam();
param.setLogId(logId);
return param.getOne(baseMapper.selectListRel(param));
}
}
+1 -1
View File
@@ -21,5 +21,5 @@ socketio:
# 框架配置 # 框架配置
config: config:
# 开发环境接口 # 开发环境接口
server-url: http://127.0.0.1:9090/api server-url: http://127.0.0.1:9091/api
upload-path: D:\Temp upload-path: D:\Temp
@@ -47,7 +47,7 @@ public class ShopGenerator {
// 需要生成的表 // 需要生成的表
private static final String[] TABLE_NAMES = new String[]{ private static final String[] TABLE_NAMES = new String[]{
// "shop_spec", // "shop_spec",
// "shop_spec_value" // "shop_spec_value",
// "shop_goods", // "shop_goods",
// "shop_goods_spec", // "shop_goods_spec",
// "shop_goods_sku", // "shop_goods_sku",
@@ -57,23 +57,24 @@ public class ShopGenerator {
// "shop_goods_log", // "shop_goods_log",
// "shop_goods_relation", // "shop_goods_relation",
// "shop_goods_comment", // "shop_goods_comment",
// "shop_goods_rule" // "shop_goods_rule",
// "shop_brand", // "shop_brand",
// "shop_merchant", // "shop_merchant",
// "shop_merchant_type", // "shop_merchant_type",
// "shop_merchant_apply", // "shop_merchant_apply",
// "shop_merchant_account", // "shop_merchant_account",
// "shop_chat_message", // "shop_chat_message",
// "shop_chat_conversation" // "shop_chat_conversation",
// "shop_user_collection", // "shop_user_collection",
// "shop_mp_menu" // "shop_mp_menu",
// "shop_order", // "shop_order",
// "shop_order_info", // "shop_order_info",
// "shop_order_info_log", // "shop_order_info_log",
"shop_order_goods", // "shop_order_goods",
// "shop_wechat_deposit" // "shop_wechat_deposit",
// "shop_users", // "shop_users",
// "shop_user_address" // "shop_user_address",
"shop_user_balance_log"
}; };
// 需要去除的表前缀 // 需要去除的表前缀
private static final String[] TABLE_PREFIX = new String[]{ private static final String[] TABLE_PREFIX = new String[]{