Compare commits
No commits in common. "abd8f7aa60802769707138847a539fb86dc85b55" and "090bd7ecbe3e331e9b69f16613265975285b0b8f" have entirely different histories.
abd8f7aa60
...
090bd7ecbe
|
@ -1,68 +0,0 @@
|
||||||
package com.agileboot.admin.controller.shop;
|
|
||||||
|
|
||||||
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
|
|
||||||
import com.agileboot.common.core.base.BaseController;
|
|
||||||
import com.agileboot.common.core.dto.ResponseDTO;
|
|
||||||
import com.agileboot.common.core.page.PageDTO;
|
|
||||||
import com.agileboot.common.enums.common.BusinessTypeEnum;
|
|
||||||
import com.agileboot.domain.common.command.BulkOperationCommand;
|
|
||||||
import com.agileboot.domain.shop.wxuser.WxUserInfoApplicationService;
|
|
||||||
import com.agileboot.domain.shop.wxuser.command.AddWxUserInfoCommand;
|
|
||||||
import com.agileboot.domain.shop.wxuser.command.UpdateWxUserInfoCommand;
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoEntity;
|
|
||||||
import com.agileboot.domain.shop.wxuser.dto.WxUserInfoDTO;
|
|
||||||
import com.agileboot.domain.shop.wxuser.query.SearchWxUserInfoQuery;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/shop/wxuser")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Validated
|
|
||||||
public class WxUserInfoController extends BaseController {
|
|
||||||
|
|
||||||
private final WxUserInfoApplicationService applicationService;
|
|
||||||
|
|
||||||
@Operation(summary = "微信用户列表")
|
|
||||||
@GetMapping
|
|
||||||
public ResponseDTO<PageDTO<WxUserInfoDTO>> list(SearchWxUserInfoQuery<WxUserInfoEntity> query) {
|
|
||||||
PageDTO<WxUserInfoDTO> page = applicationService.getWxUserList(query);
|
|
||||||
return ResponseDTO.ok(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "新增微信用户")
|
|
||||||
@AccessLog(title = "微信用户管理", businessType = BusinessTypeEnum.ADD)
|
|
||||||
@PostMapping
|
|
||||||
public ResponseDTO<Void> add(@Validated @RequestBody AddWxUserInfoCommand command) {
|
|
||||||
applicationService.addWxUser(command);
|
|
||||||
return ResponseDTO.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "修改微信用户")
|
|
||||||
@AccessLog(title = "微信用户管理", businessType = BusinessTypeEnum.MODIFY)
|
|
||||||
@PutMapping("/{id}")
|
|
||||||
public ResponseDTO<Void> edit(@PathVariable Long id, @Validated @RequestBody UpdateWxUserInfoCommand command) {
|
|
||||||
command.setWxUserId(id);
|
|
||||||
applicationService.updateWxUser(command);
|
|
||||||
return ResponseDTO.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "删除微信用户")
|
|
||||||
@AccessLog(title = "微信用户管理", businessType = BusinessTypeEnum.DELETE)
|
|
||||||
@DeleteMapping("/{ids}")
|
|
||||||
public ResponseDTO<Void> remove(@PathVariable @NotNull List<Long> ids) {
|
|
||||||
applicationService.deleteWxUser(new BulkOperationCommand<>(ids));
|
|
||||||
return ResponseDTO.ok();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,6 @@ import com.agileboot.common.exception.ApiException;
|
||||||
import com.agileboot.common.exception.error.ErrorCode;
|
import com.agileboot.common.exception.error.ErrorCode;
|
||||||
import com.agileboot.domain.shop.approval.ReturnApprovalApplicationService;
|
import com.agileboot.domain.shop.approval.ReturnApprovalApplicationService;
|
||||||
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand;
|
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand;
|
||||||
import com.agileboot.domain.shop.approval.db.ReturnApprovalEntity;
|
|
||||||
import com.agileboot.domain.shop.approval.model.ReturnApprovalModel;
|
import com.agileboot.domain.shop.approval.model.ReturnApprovalModel;
|
||||||
import com.agileboot.domain.shop.order.OrderApplicationService;
|
import com.agileboot.domain.shop.order.OrderApplicationService;
|
||||||
import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity;
|
import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity;
|
||||||
|
@ -22,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 审批请求控制器
|
* 审批请求控制器
|
||||||
|
@ -53,25 +51,37 @@ public class ApprovalApiController {
|
||||||
*/
|
*/
|
||||||
@PostMapping("/submit")
|
@PostMapping("/submit")
|
||||||
@ApiOperation(value = "提交退货审批")
|
@ApiOperation(value = "提交退货审批")
|
||||||
public ResponseDTO<ReturnApprovalEntity> submitApproval(@Valid @RequestBody AddReturnApprovalCommand command) {
|
public ResponseDTO<ReturnApprovalModel> submitApproval(@Valid @RequestBody AddReturnApprovalCommand command) {
|
||||||
if (null == command.getOrderGoodsId()) {
|
try {
|
||||||
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "订单商品ID不能为空"));
|
if (null == command.getOrderId()) {
|
||||||
}
|
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "订单ID不能为空"));
|
||||||
if (null == command.getReturnQuantity()) {
|
}
|
||||||
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "归还数量不能为空"));
|
if (null == command.getGoodsId()) {
|
||||||
}
|
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "商品ID不能为空"));
|
||||||
if (StringUtils.isBlank(command.getReturnImages())) {
|
}
|
||||||
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "归还图片不能为空"));
|
if (null == command.getReturnQuantity()) {
|
||||||
}
|
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "归还数量不能为空"));
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(command.getReturnImages())) {
|
||||||
|
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "归还图片不能为空"));
|
||||||
|
}
|
||||||
|
|
||||||
// 查询订单商品信息
|
// 查询订单商品信息
|
||||||
ShopOrderGoodsEntity orderGoods = orderApplicationService.getOrderGoodsById(command.getOrderGoodsId());
|
ShopOrderGoodsEntity orderGoods = orderApplicationService.getOrderGoodsByOrderIdAndGoodsId(command.getOrderId(), command.getGoodsId());
|
||||||
if (null == orderGoods) {
|
if (null == orderGoods) {
|
||||||
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "订单商品不存在"));
|
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "订单商品不存在"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行业务逻辑
|
// 设置商品价格并初始化审批状态
|
||||||
ReturnApprovalEntity returnApproval = approvalApplicationService.submitApproval(command, orderGoods);
|
command.setGoodsPrice(orderGoods.getPrice());
|
||||||
return ResponseDTO.ok(returnApproval);
|
command.setStatus(1);
|
||||||
|
|
||||||
|
// 执行业务逻辑
|
||||||
|
ReturnApprovalModel returnApprovalModel = approvalApplicationService.addApproval(command);
|
||||||
|
return ResponseDTO.ok(returnApprovalModel);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("提交审批失败", e);
|
||||||
|
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "提交审批失败"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,31 @@
|
||||||
package com.agileboot.api.controller;
|
package com.agileboot.api.controller;
|
||||||
|
|
||||||
import com.agileboot.common.constant.PayApiConstants;
|
|
||||||
import com.agileboot.common.core.base.BaseController;
|
import com.agileboot.common.core.base.BaseController;
|
||||||
import com.agileboot.domain.shop.order.dto.CreateOrderResult;
|
import com.agileboot.domain.shop.order.dto.CreateOrderResult;
|
||||||
import com.agileboot.domain.shop.order.dto.GetOrdersByOpenIdDTO;
|
import com.agileboot.domain.shop.order.dto.GetOrdersByOpenIdDTO;
|
||||||
import com.agileboot.domain.shop.order.model.OrderGoodsModelFactory;
|
|
||||||
import com.agileboot.domain.shop.order.model.OrderModel;
|
|
||||||
import com.agileboot.domain.shop.payment.PaymentApplicationService;
|
|
||||||
import com.agileboot.domain.shop.payment.dto.RefundVO;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.agileboot.common.core.dto.ResponseDTO;
|
import com.agileboot.common.core.dto.ResponseDTO;
|
||||||
import com.agileboot.domain.shop.order.OrderApplicationService;
|
import com.agileboot.domain.shop.order.OrderApplicationService;
|
||||||
import com.agileboot.domain.shop.order.command.SubmitOrderCommand;
|
import com.agileboot.domain.shop.order.command.SubmitOrderCommand;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import java.math.BigDecimal;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import java.math.RoundingMode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调度日志操作处理
|
* 调度日志操作处理
|
||||||
*
|
*
|
||||||
* @author valarchie
|
* @author valarchie
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/order")
|
@RequestMapping("/api/order")
|
||||||
public class OrderController extends BaseController {
|
public class OrderController extends BaseController {
|
||||||
|
|
||||||
private final OrderApplicationService orderApplicationService;
|
private final OrderApplicationService orderApplicationService;
|
||||||
private final PaymentApplicationService paymentApplicationService;
|
|
||||||
|
|
||||||
// 新增提交订单接口
|
// 新增提交订单接口
|
||||||
@PostMapping("/submit")
|
@PostMapping("/submit")
|
||||||
|
@ -51,30 +45,4 @@ public class OrderController extends BaseController {
|
||||||
GetOrdersByOpenIdDTO result = orderApplicationService.getOrdersByOpenId(openid);
|
GetOrdersByOpenIdDTO result = orderApplicationService.getOrdersByOpenId(openid);
|
||||||
return ResponseDTO.ok(result);
|
return ResponseDTO.ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/refund/{orderId}")
|
|
||||||
public ResponseDTO<RefundVO> refundOrder(@PathVariable Long orderId, @RequestParam int money) {
|
|
||||||
OrderModel orderModel = orderApplicationService.loadById(orderId);
|
|
||||||
try {
|
|
||||||
// 退款金额对比, 退款金额不能大于订单金额
|
|
||||||
// 金额转换(元转分)并四舍五入
|
|
||||||
BigDecimal amountInFen = orderModel.getTotalAmount()
|
|
||||||
.multiply(new BigDecimal("100"))
|
|
||||||
.setScale(0, RoundingMode.HALF_UP);
|
|
||||||
|
|
||||||
if (money < 0) {
|
|
||||||
throw new IllegalArgumentException("退款金额不能为负数");
|
|
||||||
}
|
|
||||||
BigDecimal moneyDecimal = new BigDecimal(money);
|
|
||||||
if (moneyDecimal.compareTo(amountInFen) > 0) {
|
|
||||||
throw new IllegalArgumentException("退款金额不能超过订单总额");
|
|
||||||
}
|
|
||||||
|
|
||||||
RefundVO refundVO = paymentApplicationService.refund(PayApiConstants.biz_id, PayApiConstants.appkey, orderModel.getBizOrderId(), orderModel.getUcid(), "退还", money);
|
|
||||||
log.info("退款结果:{}", refundVO);
|
|
||||||
return ResponseDTO.ok(refundVO);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import com.agileboot.domain.qywx.user.QyUserApplicationService;
|
||||||
import com.agileboot.domain.qywx.user.db.QyUserEntity;
|
import com.agileboot.domain.qywx.user.db.QyUserEntity;
|
||||||
import com.agileboot.domain.qywx.userQySys.SysUserQyUserApplicationService;
|
import com.agileboot.domain.qywx.userQySys.SysUserQyUserApplicationService;
|
||||||
import com.agileboot.domain.shop.order.OrderApplicationService;
|
import com.agileboot.domain.shop.order.OrderApplicationService;
|
||||||
import com.agileboot.domain.shop.payment.PaymentApplicationService;
|
|
||||||
import com.agileboot.domain.shop.payment.dto.PaymentCallbackRequest;
|
import com.agileboot.domain.shop.payment.dto.PaymentCallbackRequest;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -57,12 +56,12 @@ import org.springframework.web.client.RestTemplate;
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RequestMapping("/api/payment")
|
@RequestMapping("/api/payment")
|
||||||
public class PaymentController {
|
public class PaymentController {
|
||||||
|
private final OrderApplicationService orderApplicationService;
|
||||||
private final AccessTokenApplicationService accessTokenApplicationService;
|
private final AccessTokenApplicationService accessTokenApplicationService;
|
||||||
private final QyUserApplicationService qyUserApplicationService;
|
private final QyUserApplicationService qyUserApplicationService;
|
||||||
private final AuthCorpInfoApplicationService authCorpInfoApplicationService;
|
private final AuthCorpInfoApplicationService authCorpInfoApplicationService;
|
||||||
private final SysUserQyUserApplicationService sysUserQyUserApplicationService;
|
private final SysUserQyUserApplicationService sysUserQyUserApplicationService;
|
||||||
private final MenuApplicationService menuApplicationService;
|
private final MenuApplicationService menuApplicationService;
|
||||||
private final PaymentApplicationService paymentApplicationService;
|
|
||||||
|
|
||||||
// 新增回调接口
|
// 新增回调接口
|
||||||
/**
|
/**
|
||||||
|
@ -79,37 +78,32 @@ public class PaymentController {
|
||||||
public String paymentCallback(HttpServletRequest request, @RequestBody String requestBody) {
|
public String paymentCallback(HttpServletRequest request, @RequestBody String requestBody) {
|
||||||
log.info("支付回调requestBody:{}", requestBody);
|
log.info("支付回调requestBody:{}", requestBody);
|
||||||
try {
|
try {
|
||||||
paymentApplicationService.paymentCallback(requestBody);
|
// 1. 参数解析
|
||||||
return "success";
|
PaymentCallbackRequest callbackReq = parseCallbackRequest(requestBody);
|
||||||
} catch (Exception e) {
|
PaymentCallbackRequest.BizContent bizContent = parseBizContent(callbackReq.getBiz_content());
|
||||||
log.error("支付回调处理失败", e);
|
|
||||||
return "fail";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// 2. 签名验证(需要根据biz_id获取对应的appKey)
|
||||||
* 微信支付退款回调接口
|
String appKey = getAppKeyByBizId(callbackReq.getBiz_id()); // 需要实现根据biz_id获取appKey的逻辑
|
||||||
* @param request HTTP请求对象,用于获取请求头信息
|
boolean signValid = OpenSignUtil.checkOpenSign(appKey, callbackReq.getSign(), requestBody);
|
||||||
* @param requestBody 回调请求体(URL编码格式的XML数据)
|
|
||||||
* @return 处理结果:"success"表示成功处理并停止通知,"fail"表示需要微信重新发起通知
|
if (!signValid) {
|
||||||
* @throws ApiException 当出现以下情况时抛出:
|
log.error("支付回调签名验证失败:{}", requestBody);
|
||||||
* <ul>
|
return "fail";
|
||||||
* <li>签名验证失败</li>
|
}
|
||||||
* <li>数据解密失败</li>
|
|
||||||
* <li>退款状态异常</li>
|
if (bizContent.getTrade_status().equals("SUCCESS")) {
|
||||||
* </ul>
|
// 3. 业务处理(需要实现幂等性校验)
|
||||||
* @apiNote 该接口需要处理以下流程:
|
handlePaymentSuccess(
|
||||||
* 1. 签名验证(使用微信支付API密钥)
|
bizContent.getBiz_order_id(),
|
||||||
* 2. 解密退款结果(如需加密传输)
|
bizContent.getTotal_amount(),
|
||||||
* 3. 退款状态判断(成功/失败)
|
bizContent.getTrade_id(),
|
||||||
* 4. 更新订单退款状态(需保证幂等性)
|
bizContent.getTrade_pay_time()
|
||||||
* 5. 按微信接口规范返回正确处理结果
|
);
|
||||||
*/
|
} else {
|
||||||
@PostMapping("/refund/callback")
|
log.error("支付订单失败requestBody:{}", requestBody);
|
||||||
public String refundCallback(HttpServletRequest request, @RequestBody String requestBody) {
|
}
|
||||||
log.info("退款回调requestBody:{}", requestBody);
|
|
||||||
try {
|
return "success";
|
||||||
return paymentApplicationService.refundCallback(requestBody);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("支付回调处理失败", e);
|
log.error("支付回调处理失败", e);
|
||||||
return "fail";
|
return "fail";
|
||||||
|
@ -261,7 +255,37 @@ public class PaymentController {
|
||||||
return ResponseDTO.ok(response);
|
return ResponseDTO.ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PaymentCallbackRequest parseCallbackRequest(String requestBody) {
|
||||||
|
// 实现将URL参数解析为PaymentCallbackRequest
|
||||||
|
// 示例实现(需要根据实际参数格式调整):
|
||||||
|
Map<String, String> paramMap = new HashMap<>();
|
||||||
|
for (String param : requestBody.split("&")) {
|
||||||
|
String[] pair = param.split("=");
|
||||||
|
if (pair.length == 2) {
|
||||||
|
paramMap.put(pair[0], URLDecoder.decode(pair[1], StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BeanUtil.toBean(paramMap, PaymentCallbackRequest.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PaymentCallbackRequest.BizContent parseBizContent(String bizContent) {
|
||||||
|
// 实现biz_content的JSON解析
|
||||||
|
return JSONUtil.toBean(bizContent, PaymentCallbackRequest.BizContent.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 需要实现的方法(根据业务需求补充)
|
||||||
|
private String getAppKeyByBizId(String bizId) {
|
||||||
|
// 根据biz_id从数据库或配置获取对应的appKey
|
||||||
|
return "wxshop202503081132";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handlePaymentSuccess(String bizOrderId, Integer amount, String tradeId, String tradePayTime) {
|
||||||
|
// 实现订单状态更新和幂等性校验
|
||||||
|
if (StringUtils.isNotBlank(bizOrderId) && bizOrderId.startsWith("wxshop-")) {
|
||||||
|
// 订单号格式为 wxshop-1-time,提取中间的订单号
|
||||||
|
String orderId = bizOrderId.split("-")[1];
|
||||||
|
orderApplicationService.handlePaymentSuccess(Long.valueOf(orderId), amount, tradeId, tradePayTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
package com.agileboot.common.constant;
|
|
||||||
|
|
||||||
public class PayApiConstants {
|
|
||||||
public static final String biz_id = "wxshop";
|
|
||||||
public static final String appkey = "wxshop202503081132";
|
|
||||||
|
|
||||||
}
|
|
|
@ -10,8 +10,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import com.agileboot.common.constant.PayApiConstants;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.codec.digest.Md5Crypt;
|
import org.apache.commons.codec.digest.Md5Crypt;
|
||||||
import org.apache.commons.collections4.MapUtils;
|
import org.apache.commons.collections4.MapUtils;
|
||||||
|
@ -84,7 +82,7 @@ public class OpenSignUtil {
|
||||||
+ "2448492%22%2C%22trade_id%22%3A%221063669415%22%2C%22total_amount%22%3A1%2C%22extra%22%3A%22%22%2C%22trade_pay_time%22%3A%222025-03-20+17%3A20%3A55%22%2C%22trade_status%22%3A%22SUCCESS%22%2C%22pay_type%22%3A%22116%22%2C%22callback_content%22%3A%22%3Cxml%3E%3Cappid%3E%3C%21%5BCDATA%5Bwx9922dfbb0d4cd7bb%5D%5D%3E%3C%2Fappid%3E%5Cn%3Cattach%3E%3C%21%5BCDATA%5B%257B%2522biz_id%2522%253A%2522wxshop%2522%252C%2522trade_id%2522%253A%25221063669415%2522%257D%5D%5D%3E%3C%2Fattach%3E%5Cn%3Cbank_type%3E%3C%21%5BCDATA%5BOTHERS%5D%5D%3E%3C%2Fbank_type%3E%5Cn%3Ccash_fee%3E%3C%21%5BCDATA%5B1%5D%5D%3E%3C%2Fcash_fee%3E%5Cn%3Cfee_type%3E%3C%21%5BCDATA%5BCNY%5D%5D%3E%3C%2Ffee_type%3E%5Cn%3Cis_subscribe%3E%3C%21%5BCDATA%5BN%5D%5D%3E%3C%2Fis_subscribe%3E%5Cn%3Cmch_id%3E%3C%21%5BCDATA%5B1625101806%5D%5D%3E%3C%2Fmch_id%3E%5Cn%3Cnonce_str%3E%3C%21%5BCDATA%5B24NffiTHxNYm0ppw3QE9WezmzJQDnJQV%5D%5D%3E%3C%2Fnonce_str%3E%5Cn%3Copenid%3E%3C%21%5BCDATA%5BoMRxw6Eum0DB1IjI_pEX_yrawBHw%5D%5D%3E%3C%2Fopenid%3E%5Cn%3Cout_trade_no%3E%3C%21%5BCDATA"
|
+ "2448492%22%2C%22trade_id%22%3A%221063669415%22%2C%22total_amount%22%3A1%2C%22extra%22%3A%22%22%2C%22trade_pay_time%22%3A%222025-03-20+17%3A20%3A55%22%2C%22trade_status%22%3A%22SUCCESS%22%2C%22pay_type%22%3A%22116%22%2C%22callback_content%22%3A%22%3Cxml%3E%3Cappid%3E%3C%21%5BCDATA%5Bwx9922dfbb0d4cd7bb%5D%5D%3E%3C%2Fappid%3E%5Cn%3Cattach%3E%3C%21%5BCDATA%5B%257B%2522biz_id%2522%253A%2522wxshop%2522%252C%2522trade_id%2522%253A%25221063669415%2522%257D%5D%5D%3E%3C%2Fattach%3E%5Cn%3Cbank_type%3E%3C%21%5BCDATA%5BOTHERS%5D%5D%3E%3C%2Fbank_type%3E%5Cn%3Ccash_fee%3E%3C%21%5BCDATA%5B1%5D%5D%3E%3C%2Fcash_fee%3E%5Cn%3Cfee_type%3E%3C%21%5BCDATA%5BCNY%5D%5D%3E%3C%2Ffee_type%3E%5Cn%3Cis_subscribe%3E%3C%21%5BCDATA%5BN%5D%5D%3E%3C%2Fis_subscribe%3E%5Cn%3Cmch_id%3E%3C%21%5BCDATA%5B1625101806%5D%5D%3E%3C%2Fmch_id%3E%5Cn%3Cnonce_str%3E%3C%21%5BCDATA%5B24NffiTHxNYm0ppw3QE9WezmzJQDnJQV%5D%5D%3E%3C%2Fnonce_str%3E%5Cn%3Copenid%3E%3C%21%5BCDATA%5BoMRxw6Eum0DB1IjI_pEX_yrawBHw%5D%5D%3E%3C%2Fopenid%3E%5Cn%3Cout_trade_no%3E%3C%21%5BCDATA"
|
||||||
+ "%5Bwxshop-10-1742462448212%5D%5D%3E%3C%2Fout_trade_no%3E%5Cn%3Cresult_code%3E%3C%21%5BCDATA%5BSUCCESS%5D%5D%3E%3C%2Fresult_code%3E%5Cn%3Creturn_code%3E%3C%21%5BCDATA%5BSUCCESS%5D%5D%3E%3C%2Freturn_code%3E%5Cn%3Csign%3E%3C%21%5BCDATA%5B9CE8A123437E591166DDAF92A750C122%5D%5D%3E%3C%2Fsign%3E%5Cn%3Ctime_end%3E%3C%21%5BCDATA%5B20250320172055%5D%5D%3E%3C%2Ftime_end%3E%5Cn%3Ctotal_fee%3E1%3C%2Ftotal_fee%3E%5Cn%3Ctrade_type%3E%3C%21%5BCDATA%5BJSAPI%5D%5D%3E%3C%2Ftrade_type%3E%5Cn%3Ctransaction_id%3E%3C%21%5BCDATA%5B4200002695202503209706830758%5D%5D%3E%3C%2Ftransaction_id%3E%5Cn%3C%2Fxml%3E%22%2C%22title%22%3A%22%E5%95%86%E5%93%81%E8%AE%A2%E5%8D%95%E6%94%AF%E4%BB%98%22%2C%22biz_order_id%22%3A%22wxshop-10-1742462448212%22%7D&nonce_str=6d80bd6b542a499994adf4ee4c1e89c4&sign=f1ffc9cfc61cf60d8a1acbac0399cd0b&biz_id=wxshop&sign_type=MD5&version=1.0×tamp=1742462460390";
|
+ "%5Bwxshop-10-1742462448212%5D%5D%3E%3C%2Fout_trade_no%3E%5Cn%3Cresult_code%3E%3C%21%5BCDATA%5BSUCCESS%5D%5D%3E%3C%2Fresult_code%3E%5Cn%3Creturn_code%3E%3C%21%5BCDATA%5BSUCCESS%5D%5D%3E%3C%2Freturn_code%3E%5Cn%3Csign%3E%3C%21%5BCDATA%5B9CE8A123437E591166DDAF92A750C122%5D%5D%3E%3C%2Fsign%3E%5Cn%3Ctime_end%3E%3C%21%5BCDATA%5B20250320172055%5D%5D%3E%3C%2Ftime_end%3E%5Cn%3Ctotal_fee%3E1%3C%2Ftotal_fee%3E%5Cn%3Ctrade_type%3E%3C%21%5BCDATA%5BJSAPI%5D%5D%3E%3C%2Ftrade_type%3E%5Cn%3Ctransaction_id%3E%3C%21%5BCDATA%5B4200002695202503209706830758%5D%5D%3E%3C%2Ftransaction_id%3E%5Cn%3C%2Fxml%3E%22%2C%22title%22%3A%22%E5%95%86%E5%93%81%E8%AE%A2%E5%8D%95%E6%94%AF%E4%BB%98%22%2C%22biz_order_id%22%3A%22wxshop-10-1742462448212%22%7D&nonce_str=6d80bd6b542a499994adf4ee4c1e89c4&sign=f1ffc9cfc61cf60d8a1acbac0399cd0b&biz_id=wxshop&sign_type=MD5&version=1.0×tamp=1742462460390";
|
||||||
|
|
||||||
Boolean res = checkOpenSign(PayApiConstants.appkey, "f1ffc9cfc61cf60d8a1acbac0399cd0b", body);
|
Boolean res = checkOpenSign("wxshop202503081132", "f1ffc9cfc61cf60d8a1acbac0399cd0b", body);
|
||||||
log.info("res:{}", res);
|
log.info("res:{}", res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,7 @@ import com.agileboot.domain.shop.approval.dto.ReturnApprovalDTO;
|
||||||
import com.agileboot.domain.shop.approval.model.ReturnApprovalModel;
|
import com.agileboot.domain.shop.approval.model.ReturnApprovalModel;
|
||||||
import com.agileboot.domain.shop.approval.model.ReturnApprovalModelFactory;
|
import com.agileboot.domain.shop.approval.model.ReturnApprovalModelFactory;
|
||||||
import com.agileboot.domain.shop.approval.query.SearchReturnApprovalQuery;
|
import com.agileboot.domain.shop.approval.query.SearchReturnApprovalQuery;
|
||||||
import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity;
|
|
||||||
import com.agileboot.domain.shop.order.model.OrderGoodsModel;
|
|
||||||
import com.agileboot.domain.shop.order.model.OrderGoodsModelFactory;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
@ -29,7 +24,6 @@ public class ReturnApprovalApplicationService {
|
||||||
|
|
||||||
private final ReturnApprovalService approvalService;
|
private final ReturnApprovalService approvalService;
|
||||||
private final ReturnApprovalModelFactory modelFactory;
|
private final ReturnApprovalModelFactory modelFactory;
|
||||||
private final OrderGoodsModelFactory orderGoodsModelFactory;
|
|
||||||
|
|
||||||
public PageDTO<ReturnApprovalDTO> getApprovalList(SearchReturnApprovalQuery<ReturnApprovalEntity> query) {
|
public PageDTO<ReturnApprovalDTO> getApprovalList(SearchReturnApprovalQuery<ReturnApprovalEntity> query) {
|
||||||
Page<ReturnApprovalEntity> page = approvalService.getApprovalList(query);
|
Page<ReturnApprovalEntity> page = approvalService.getApprovalList(query);
|
||||||
|
@ -58,29 +52,4 @@ public class ReturnApprovalApplicationService {
|
||||||
model.deleteById();
|
model.deleteById();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReturnApprovalEntity submitApproval(AddReturnApprovalCommand command, ShopOrderGoodsEntity orderGoods) {
|
|
||||||
// 设置商品价格并初始化审批状态
|
|
||||||
command.setGoodsId(orderGoods.getGoodsId());
|
|
||||||
command.setOrderId(orderGoods.getOrderId());
|
|
||||||
command.setGoodsPrice(orderGoods.getPrice());
|
|
||||||
command.setReturnImages(command.getReturnImages());
|
|
||||||
command.setReturnRemark(command.getReturnRemark());
|
|
||||||
command.setStatus(1);
|
|
||||||
command.setCreatorId(0L);
|
|
||||||
command.setCreateTime(new Date());
|
|
||||||
command.setUpdaterId(0L);
|
|
||||||
command.setUpdateTime(new Date());
|
|
||||||
command.setDeleted(false);
|
|
||||||
|
|
||||||
// 执行业务逻辑
|
|
||||||
ReturnApprovalModel returnApprovalModel = addApproval(command);
|
|
||||||
|
|
||||||
// 更新订单商品状态
|
|
||||||
OrderGoodsModel orderGoodsModel = orderGoodsModelFactory.create(orderGoods);
|
|
||||||
orderGoodsModel.setStatus(5);
|
|
||||||
orderGoodsModel.updateById();
|
|
||||||
|
|
||||||
return returnApprovalModel.selectById();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -40,10 +40,6 @@ public class ReturnApprovalEntity extends BaseEntity<ReturnApprovalEntity> {
|
||||||
@TableField("goods_id")
|
@TableField("goods_id")
|
||||||
private Long goodsId;
|
private Long goodsId;
|
||||||
|
|
||||||
@ApiModelProperty("关联订单商品ID")
|
|
||||||
@TableField("order_goods_id")
|
|
||||||
private Long orderGoodsId;
|
|
||||||
|
|
||||||
@ApiModelProperty("归还数量")
|
@ApiModelProperty("归还数量")
|
||||||
@TableField("return_quantity")
|
@TableField("return_quantity")
|
||||||
private Integer returnQuantity;
|
private Integer returnQuantity;
|
||||||
|
|
|
@ -17,7 +17,7 @@ import org.apache.ibatis.annotations.Select;
|
||||||
* @since 2025-04-03
|
* @since 2025-04-03
|
||||||
*/
|
*/
|
||||||
public interface ReturnApprovalMapper extends BaseMapper<ReturnApprovalEntity> {
|
public interface ReturnApprovalMapper extends BaseMapper<ReturnApprovalEntity> {
|
||||||
@Select("SELECT * " +
|
@Select("SELECT approval_id, order_id, goods_id, return_quantity, goods_price, return_amount, return_images, audit_images, return_remark, audit_remark, status " +
|
||||||
"FROM return_approval " +
|
"FROM return_approval " +
|
||||||
"${ew.customSqlSegment}")
|
"${ew.customSqlSegment}")
|
||||||
Page<ReturnApprovalEntity> getApprovalList(
|
Page<ReturnApprovalEntity> getApprovalList(
|
||||||
|
|
|
@ -41,9 +41,6 @@ public class ReturnApprovalDTO {
|
||||||
@ExcelColumn(name = "关联商品ID")
|
@ExcelColumn(name = "关联商品ID")
|
||||||
private Long goodsId;
|
private Long goodsId;
|
||||||
|
|
||||||
@ExcelColumn(name = "关联订单商品ID")
|
|
||||||
private Long orderGoodsId;
|
|
||||||
|
|
||||||
@ExcelColumn(name = "归还数量")
|
@ExcelColumn(name = "归还数量")
|
||||||
private Integer returnQuantity;
|
private Integer returnQuantity;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.agileboot.domain.shop.order;
|
package com.agileboot.domain.shop.order;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import com.agileboot.common.constant.PayApiConstants;
|
|
||||||
import com.agileboot.common.exception.ApiException;
|
import com.agileboot.common.exception.ApiException;
|
||||||
import com.agileboot.common.exception.error.ErrorCode;
|
import com.agileboot.common.exception.error.ErrorCode;
|
||||||
import com.agileboot.domain.cabinet.cell.db.CabinetCellEntity;
|
import com.agileboot.domain.cabinet.cell.db.CabinetCellEntity;
|
||||||
|
@ -161,7 +160,7 @@ public class OrderApplicationService {
|
||||||
WxJsApiPreCreateRequest request = new WxJsApiPreCreateRequest();
|
WxJsApiPreCreateRequest request = new WxJsApiPreCreateRequest();
|
||||||
request.setIp("222.218.10.217");
|
request.setIp("222.218.10.217");
|
||||||
request.setOpenid(orderModel.getOpenid()); //
|
request.setOpenid(orderModel.getOpenid()); //
|
||||||
request.setBiz_order_id(orderModel.getBizOrderId()); // 使用订单唯一编号
|
request.setBiz_order_id("wxshop-" + orderModel.getOrderId() + "-" + new Date().getTime()); // 使用订单唯一编号
|
||||||
// 金额转换(元转分)并四舍五入
|
// 金额转换(元转分)并四舍五入
|
||||||
BigDecimal amountInFen = orderModel.getTotalAmount()
|
BigDecimal amountInFen = orderModel.getTotalAmount()
|
||||||
.multiply(new BigDecimal("100"))
|
.multiply(new BigDecimal("100"))
|
||||||
|
@ -170,7 +169,7 @@ public class OrderApplicationService {
|
||||||
|
|
||||||
request.setTitle("商品订单支付");
|
request.setTitle("商品订单支付");
|
||||||
request.setNotify_url("http://wxshop.ab98.cn/shop-api/api/payment/callback");
|
request.setNotify_url("http://wxshop.ab98.cn/shop-api/api/payment/callback");
|
||||||
request.setBiz_id(PayApiConstants.biz_id);
|
request.setBiz_id("wxshop");
|
||||||
request.setUcid(orderModel.getUcid());
|
request.setUcid(orderModel.getUcid());
|
||||||
request.setExtra("");
|
request.setExtra("");
|
||||||
return request;
|
return request;
|
||||||
|
@ -204,7 +203,6 @@ public class OrderApplicationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新订单总金额
|
// 更新订单总金额
|
||||||
orderModel.setBizOrderId("wxshop-" + orderModel.getOrderId() + "-" + new Date().getTime());
|
|
||||||
orderModel.setTotalAmount(totalAmount);
|
orderModel.setTotalAmount(totalAmount);
|
||||||
orderModel.updateById();
|
orderModel.updateById();
|
||||||
}
|
}
|
||||||
|
@ -254,7 +252,31 @@ public class OrderApplicationService {
|
||||||
|
|
||||||
public void handlePaymentSuccess(Long orderId, Integer amount, String tradeId, String tradePayTime) {
|
public void handlePaymentSuccess(Long orderId, Integer amount, String tradeId, String tradePayTime) {
|
||||||
OrderModel orderModel = orderModelFactory.loadById(orderId);
|
OrderModel orderModel = orderModelFactory.loadById(orderId);
|
||||||
orderModel.handlePaymentSuccess(amount, tradeId, tradePayTime);
|
// 状态校验
|
||||||
|
orderModel.validateStatusTransition(2); // 2代表已支付
|
||||||
|
// 更新订单状态
|
||||||
|
orderModel.setStatus(2);
|
||||||
|
orderModel.setPayStatus(2);
|
||||||
|
orderModel.setTradeId(tradeId);
|
||||||
|
try {
|
||||||
|
// if (tradePayTime.contains("+")) {
|
||||||
|
// tradePayTime = tradePayTime.replace("+", " ");
|
||||||
|
// }
|
||||||
|
orderModel.setPayTime(DateUtil.parse(tradePayTime));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("支付时间转换失败", e);
|
||||||
|
}
|
||||||
|
orderModel.updateById();
|
||||||
|
|
||||||
|
|
||||||
|
// 发送指令
|
||||||
|
// 客户端手动开柜
|
||||||
|
// QueryWrapper<ShopOrderGoodsEntity> orderGoodsQueryWrapper = new QueryWrapper<>();
|
||||||
|
// orderGoodsQueryWrapper.eq("order_id", orderId);
|
||||||
|
// List<ShopOrderGoodsEntity> orderGoods = orderGoodsService.list(orderGoodsQueryWrapper);
|
||||||
|
// orderGoods.forEach(g -> {
|
||||||
|
// openOrderGoodsCabinet(orderId, g.getOrderGoodsId());
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -285,12 +307,4 @@ public class OrderApplicationService {
|
||||||
public ShopOrderGoodsEntity getOrderGoodsByOrderIdAndGoodsId(Long orderId, Long goodsId) {
|
public ShopOrderGoodsEntity getOrderGoodsByOrderIdAndGoodsId(Long orderId, Long goodsId) {
|
||||||
return orderGoodsService.getByOrderIdAndGoodsId(orderId, goodsId);
|
return orderGoodsService.getByOrderIdAndGoodsId(orderId, goodsId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShopOrderGoodsEntity getOrderGoodsById(Long orderGoodsId) {
|
|
||||||
return orderGoodsService.getById(orderGoodsId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OrderModel loadById(Long orderId) {
|
|
||||||
return orderModelFactory.loadById(orderId);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -45,10 +45,6 @@ public class ShopOrderEntity extends BaseEntity<ShopOrderEntity> {
|
||||||
@TableField("trade_id")
|
@TableField("trade_id")
|
||||||
private String tradeId;
|
private String tradeId;
|
||||||
|
|
||||||
@ApiModelProperty("业务系统订单ID(对接外部系统)")
|
|
||||||
@TableField("biz_order_id")
|
|
||||||
private String bizOrderId;
|
|
||||||
|
|
||||||
@ApiModelProperty("订单总金额")
|
@ApiModelProperty("订单总金额")
|
||||||
@TableField("total_amount")
|
@TableField("total_amount")
|
||||||
private BigDecimal totalAmount;
|
private BigDecimal totalAmount;
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class ShopOrderGoodsEntity extends BaseEntity<ShopOrderGoodsEntity> {
|
||||||
@TableField("total_amount")
|
@TableField("total_amount")
|
||||||
private BigDecimal totalAmount;
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
@ApiModelProperty("商品状态(1正常 2已退货 3已换货 4已完成 5审核中 6退货未通过)")
|
@ApiModelProperty("商品状态(1正常 2已退货 3已换货 4已完成)")
|
||||||
@TableField("`status`")
|
@TableField("`status`")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
|
|
@ -11,4 +11,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
* @since 2025-03-10
|
* @since 2025-03-10
|
||||||
*/
|
*/
|
||||||
public interface ShopOrderService extends IService<ShopOrderEntity> {
|
public interface ShopOrderService extends IService<ShopOrderEntity> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.agileboot.domain.shop.order.db;
|
package com.agileboot.domain.shop.order.db;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import com.agileboot.domain.shop.order.model.OrderModel;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@ -15,4 +13,5 @@ import org.springframework.stereotype.Service;
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrderEntity> implements ShopOrderService {
|
public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrderEntity> implements ShopOrderService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.agileboot.domain.shop.order.model;
|
package com.agileboot.domain.shop.order.model;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import com.agileboot.common.config.AgileBootConfig;
|
import com.agileboot.common.config.AgileBootConfig;
|
||||||
import com.agileboot.common.exception.ApiException;
|
import com.agileboot.common.exception.ApiException;
|
||||||
import com.agileboot.common.exception.error.ErrorCode;
|
import com.agileboot.common.exception.error.ErrorCode;
|
||||||
|
@ -12,9 +11,7 @@ import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
public class OrderModel extends ShopOrderEntity {
|
public class OrderModel extends ShopOrderEntity {
|
||||||
|
@ -71,25 +68,4 @@ public class OrderModel extends ShopOrderEntity {
|
||||||
String orderNo = String.valueOf(System.currentTimeMillis() + (int)(Math.random()*1000));
|
String orderNo = String.valueOf(System.currentTimeMillis() + (int)(Math.random()*1000));
|
||||||
this.setUcid(orderNo);
|
this.setUcid(orderNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handlePaymentSuccess(Integer amount, String tradeId, String tradePayTime) {
|
|
||||||
// 状态校验
|
|
||||||
this.validateStatusTransition(2); // 2代表已支付
|
|
||||||
// 更新订单状态
|
|
||||||
this.setStatus(2);
|
|
||||||
this.setPayStatus(2);
|
|
||||||
this.setTradeId(tradeId);
|
|
||||||
try {
|
|
||||||
this.setPayTime(DateUtil.parse(tradePayTime));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("支付时间转换失败", e);
|
|
||||||
}
|
|
||||||
this.updateById();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleRefundSuccess() {
|
|
||||||
// 更新订单状态
|
|
||||||
this.setPayStatus(4);
|
|
||||||
this.updateById();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,38 +1,22 @@
|
||||||
package com.agileboot.domain.shop.payment;
|
package com.agileboot.domain.shop.payment;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import cn.hutool.core.lang.TypeReference;
|
|
||||||
import cn.hutool.core.net.URLDecoder;
|
|
||||||
import cn.hutool.core.util.URLUtil;
|
|
||||||
import cn.hutool.http.ContentType;
|
import cn.hutool.http.ContentType;
|
||||||
import cn.hutool.http.HttpResponse;
|
import cn.hutool.http.HttpResponse;
|
||||||
import cn.hutool.http.HttpStatus;
|
import cn.hutool.http.HttpStatus;
|
||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import cn.hutool.json.JSONObject;
|
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.agileboot.common.constant.PayApiConstants;
|
import com.agileboot.domain.shop.payment.dto.WxJsApiPreCreateRequest;
|
||||||
import com.agileboot.common.utils.OpenSignUtil;
|
import com.agileboot.domain.shop.payment.dto.WxJsApiPreCreateResponse;
|
||||||
import com.agileboot.domain.shop.order.model.OrderModel;
|
|
||||||
import com.agileboot.domain.shop.order.model.OrderModelFactory;
|
|
||||||
import com.agileboot.domain.shop.payment.dto.*;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.Data;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PaymentApplicationService {
|
public class PaymentApplicationService {
|
||||||
private final OrderModelFactory orderModelFactory;
|
|
||||||
private static final Object LOCKER = new Object();
|
|
||||||
|
|
||||||
public WxJsApiPreCreateResponse callJsApiPreCreate(WxJsApiPreCreateRequest request) {
|
public WxJsApiPreCreateResponse callJsApiPreCreate(WxJsApiPreCreateRequest request) {
|
||||||
String gatewayUrl = "http://222.218.10.217:7890/open/trade/wx/jsapi/precreate";
|
String gatewayUrl = "http://222.218.10.217:7890/open/trade/wx/jsapi/precreate";
|
||||||
|
|
||||||
|
@ -77,157 +61,13 @@ public class PaymentApplicationService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void paymentCallback(String requestBody) {
|
// 添加错误响应处理类
|
||||||
|
@Data
|
||||||
// 1. 参数解析
|
private static class PaymentGatewayError {
|
||||||
PaymentCallbackRequest callbackReq = parseCallbackRequest(requestBody);
|
private String timestamp;
|
||||||
PaymentCallbackRequest.BizContent bizContent = parseBizContent(callbackReq.getBiz_content());
|
private Integer status;
|
||||||
|
private String error;
|
||||||
// 2. 签名验证(需要根据biz_id获取对应的appKey)
|
private String message;
|
||||||
String appKey = getAppKeyByBizId(callbackReq.getBiz_id()); // 需要实现根据biz_id获取appKey的逻辑
|
private String path;
|
||||||
boolean signValid = OpenSignUtil.checkOpenSign(appKey, callbackReq.getSign(), requestBody);
|
|
||||||
|
|
||||||
if (!signValid) {
|
|
||||||
log.error("支付回调签名验证失败:{}", requestBody);
|
|
||||||
throw new RuntimeException("支付回调签名验证失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bizContent.getTrade_status().equals("SUCCESS")) {
|
|
||||||
// 3. 业务处理(需要实现幂等性校验)
|
|
||||||
handlePaymentSuccess(
|
|
||||||
bizContent.getBiz_order_id(),
|
|
||||||
bizContent.getTotal_amount(),
|
|
||||||
bizContent.getTrade_id(),
|
|
||||||
bizContent.getTrade_pay_time()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
log.error("支付订单失败requestBody:{}", requestBody);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 退款
|
|
||||||
* @param bizId 支付网关分配的业务应用ID
|
|
||||||
* @param appKey 支付网关分配的业务应用秘钥
|
|
||||||
* @param orderId 支付时的订单ID
|
|
||||||
* @param uid 用户ID
|
|
||||||
* @param reason 退款理由
|
|
||||||
* @param money 退款金额,单位:分
|
|
||||||
*/
|
|
||||||
public RefundVO refund(String bizId, String appKey, String orderId, String uid, String reason, int money) throws Exception {
|
|
||||||
String url = "http://222.218.10.217:7890/open/trade/refund";
|
|
||||||
JSONObject bizContent = new JSONObject();
|
|
||||||
bizContent.set("userId", uid);
|
|
||||||
bizContent.set("bizId", bizId);
|
|
||||||
bizContent.set("orderId", orderId);
|
|
||||||
bizContent.set("refundFee", money);
|
|
||||||
bizContent.set("refundReason", reason);
|
|
||||||
Map<String, String> params = new HashMap<>();
|
|
||||||
params.put("client_id", UUID.randomUUID().toString());
|
|
||||||
params.put("biz_id", bizId);
|
|
||||||
params.put("sign_type", "md5");
|
|
||||||
params.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
||||||
params.put("version", "1.0");
|
|
||||||
params.put("nonce_str", UUID.randomUUID().toString());
|
|
||||||
params.put("biz_content", URLUtil.encode(JSONUtil.toJsonStr(bizContent)));
|
|
||||||
params.put("sign", SignUtils.openSign(appKey, params));
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (String key : params.keySet()) {
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
sb.append("&");
|
|
||||||
}
|
|
||||||
sb.append(key).append("=").append(params.get(key));
|
|
||||||
}
|
|
||||||
String result = HttpUtil.post(url, sb.toString());
|
|
||||||
CommonResponse<RefundVO> res = JSONUtil.toBean(result, new TypeReference<CommonResponse<RefundVO>>(){}, true);
|
|
||||||
if (res.getCode() != CommonErrorCode.OK.getErrorCode()) {
|
|
||||||
throw new Exception(res.getMsg());
|
|
||||||
}
|
|
||||||
return res.getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private PaymentCallbackRequest parseCallbackRequest(String requestBody) {
|
|
||||||
// 实现将URL参数解析为PaymentCallbackRequest
|
|
||||||
// 示例实现(需要根据实际参数格式调整):
|
|
||||||
Map<String, String> paramMap = new HashMap<>();
|
|
||||||
for (String param : requestBody.split("&")) {
|
|
||||||
String[] pair = param.split("=");
|
|
||||||
if (pair.length == 2) {
|
|
||||||
paramMap.put(pair[0], URLDecoder.decode(pair[1], StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BeanUtil.toBean(paramMap, PaymentCallbackRequest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private PaymentCallbackRequest.BizContent parseBizContent(String bizContent) {
|
|
||||||
// 实现biz_content的JSON解析
|
|
||||||
return JSONUtil.toBean(bizContent, PaymentCallbackRequest.BizContent.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 需要实现的方法(根据业务需求补充)
|
|
||||||
private String getAppKeyByBizId(String bizId) {
|
|
||||||
// 根据biz_id从数据库或配置获取对应的appKey
|
|
||||||
return PayApiConstants.appkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handlePaymentSuccess(String bizOrderId, Integer amount, String tradeId, String tradePayTime) {
|
|
||||||
// 实现订单状态更新和幂等性校验
|
|
||||||
if (StringUtils.isNotBlank(bizOrderId) && bizOrderId.startsWith("wxshop-")) {
|
|
||||||
// 订单号格式为 wxshop-1-time,提取中间的订单号
|
|
||||||
String orderId = bizOrderId.split("-")[1];
|
|
||||||
OrderModel orderModel = orderModelFactory.loadById(Long.valueOf(orderId));
|
|
||||||
orderModel.handlePaymentSuccess(amount, tradeId, tradePayTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String refundCallback(String reqBody) {
|
|
||||||
JSONObject res = new JSONObject();
|
|
||||||
System.out.println("退款回调:" + reqBody);
|
|
||||||
CommonRequest<RefundVO> notifyRequest = CommonRequest.build(reqBody, RefundVO.class);
|
|
||||||
if (notifyRequest == null || notifyRequest.getBizContent() == null) {
|
|
||||||
res.set("callback_code", 1);
|
|
||||||
res.set("callback_msg", "请求body或bizcontent为空");
|
|
||||||
System.out.println("退款回调处理失败, 原因:请求body或bizcontent为空");
|
|
||||||
return JSONUtil.toJsonStr(res);
|
|
||||||
}
|
|
||||||
MyError error = checkSign(notifyRequest.getBizId(), notifyRequest.getSign(), reqBody);
|
|
||||||
if (error != null) {
|
|
||||||
res.set("callback_code", 1);
|
|
||||||
res.set("callback_msg", error.getCode());
|
|
||||||
System.out.printf("退款回调处理失败, 原因:%s%n", error.getMsg());
|
|
||||||
return JSONUtil.toJsonStr(res);
|
|
||||||
}
|
|
||||||
RefundVO bizContent = notifyRequest.getBizContent();
|
|
||||||
|
|
||||||
String orderNO = bizContent.getBizOrderId();
|
|
||||||
if (StringUtils.isBlank(orderNO)) {
|
|
||||||
res.put("callback_code", 1);
|
|
||||||
res.put("callback_msg", "缺少退款订单ID");
|
|
||||||
return JSONUtil.toJsonStr(res);
|
|
||||||
}
|
|
||||||
synchronized (LOCKER) {
|
|
||||||
//根据退款订单号 orderNo 做你的业务处理。退款回调可能会
|
|
||||||
//有多次,业务应用要做好幂等处理
|
|
||||||
if (orderNO.startsWith("wxshop-")) {
|
|
||||||
// 订单号格式为 wxshop-1-time,提取中间的订单号
|
|
||||||
String orderId = orderNO.split("-")[1];
|
|
||||||
OrderModel orderModel = orderModelFactory.loadById(Long.valueOf(orderId));
|
|
||||||
orderModel.handleRefundSuccess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.set("callback_code", 0);
|
|
||||||
res.set("callback_msg", "ok");
|
|
||||||
return JSONUtil.toJsonStr(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MyError checkSign(String bizId, String sign, String reqBody) {
|
|
||||||
if (StringUtils.isBlank(bizId)) {
|
|
||||||
return new MyError(CommonErrorCode.BAD_PARAMETER, "bizId is blank");
|
|
||||||
}
|
|
||||||
if (!SignUtils.checkOpenSign(getAppKeyByBizId(bizId), sign, reqBody)) {
|
|
||||||
return new MyError(CommonErrorCode.BAD_PARAMETER, String.format("Invalid sign: %s", sign));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,122 +0,0 @@
|
||||||
package com.agileboot.domain.shop.payment;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.collections4.MapUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public final class SignUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 珊瑚签名计算
|
|
||||||
*/
|
|
||||||
public static String coralSign(String secret, Map<String, Object> params) {
|
|
||||||
return commonSign(secret, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 业务方签名计算
|
|
||||||
*/
|
|
||||||
public static String bizSign(String secret, Map<String, Object> params) {
|
|
||||||
return commonSign(secret, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认签到计算:params根据key进行字典排序,然后将对应值直接拼成字符串(null跳过),再将业务预生成的"secret"拼在最后,用MD5算法生成签名
|
|
||||||
* @param secret appKey/appSecret
|
|
||||||
* @param params 需要签名的参数
|
|
||||||
* @return 签名
|
|
||||||
*/
|
|
||||||
public static String commonSign(String secret, Map<String, Object> params) {
|
|
||||||
Map<String, Object> sortedParams = new TreeMap<>(params);
|
|
||||||
StringBuilder plainText = new StringBuilder();
|
|
||||||
sortedParams.values().stream().filter(Objects::nonNull).forEach(plainText::append);
|
|
||||||
plainText.append(secret);
|
|
||||||
try {
|
|
||||||
return md5(plainText.toString().getBytes("utf-8"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务端接口加签校验,按照Key升序排列,拼接key1=value1&key2=value2(value为null跳过, value需要url encode),在后面拼接上&app_key=xxx,md5生成sign值
|
|
||||||
* @param appKey
|
|
||||||
* @param params
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String openSign(String appKey, Map<String, String> params) {
|
|
||||||
if(MapUtils.isEmpty(params)) {
|
|
||||||
params = new HashMap<String, String>(1);
|
|
||||||
}
|
|
||||||
Map<String, String> sortedParams = new TreeMap<>(params);
|
|
||||||
List<String> kvPairList = getKVList(sortedParams);
|
|
||||||
String sourceText = StringUtils.join(kvPairList, "&");
|
|
||||||
sourceText = sourceText + "&app_key=" + appKey;
|
|
||||||
log.info("sourceText:" + sourceText);
|
|
||||||
try {
|
|
||||||
return md5(sourceText.getBytes("utf-8"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean checkOpenSign(String appKey, String sign, String reqBody) {
|
|
||||||
String[] fields = reqBody.split("&");
|
|
||||||
Map<String, String> fieldMap = new HashMap<>();
|
|
||||||
for (String field : fields) {
|
|
||||||
String[] pair = field.split("=");
|
|
||||||
if (pair.length != 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// sign字段不参与校验,空字段不校验
|
|
||||||
if (!"sign".equals(pair[0]) && StringUtils.isNotBlank(pair[1])) {
|
|
||||||
fieldMap.put(pair[0], pair[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String generateSign = openSign(appKey, fieldMap);
|
|
||||||
return Objects.equals(generateSign, sign);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> getKVList(Map<String, String> params) {
|
|
||||||
if(MapUtils.isEmpty(params)) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
List<String> kvPairs = new ArrayList<>();
|
|
||||||
for(String key : params.keySet()) {
|
|
||||||
String value = params.get(key);
|
|
||||||
if(value == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String kv = key + "=" + value;
|
|
||||||
kvPairs.add(kv);
|
|
||||||
}
|
|
||||||
return kvPairs;
|
|
||||||
}
|
|
||||||
private SignUtils() {}
|
|
||||||
|
|
||||||
private static String md5(byte[] textBytes) {
|
|
||||||
try {
|
|
||||||
if (textBytes == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
|
||||||
byte[] messageDigest = md.digest(textBytes);
|
|
||||||
BigInteger number = new BigInteger(1, messageDigest);
|
|
||||||
|
|
||||||
String hashtext;
|
|
||||||
for(hashtext = number.toString(16); hashtext.length() < 32; hashtext = "0" + hashtext) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hashtext;
|
|
||||||
}
|
|
||||||
} catch (Exception var5) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
package com.agileboot.domain.shop.payment.dto;
|
|
||||||
|
|
||||||
public class CommonErrorCode {
|
|
||||||
// 成功
|
|
||||||
public static final CommonErrorCode OK = new CommonErrorCode(2000000, "OK");
|
|
||||||
// 400
|
|
||||||
public static final CommonErrorCode BAD_PARAMETER = new CommonErrorCode(4000001, "bad parameter: {0}");
|
|
||||||
public static final CommonErrorCode INVALID_REQUEST_BODY = new CommonErrorCode(4000002, "bad reqeust body");
|
|
||||||
// 403
|
|
||||||
public static final CommonErrorCode USER_NOT_LOGIN = new CommonErrorCode(4030001, "user not login");
|
|
||||||
public static final CommonErrorCode INVALID_REQUEST = new CommonErrorCode(4030003, "invalid request");
|
|
||||||
// 404
|
|
||||||
public static final CommonErrorCode REQUEST_NOT_FOUND = new CommonErrorCode(4040001, "request not found, {0}");
|
|
||||||
// 500
|
|
||||||
public static final CommonErrorCode INTERNAL_SERVER_ERROR = new CommonErrorCode(5000000, "internal server error, {0}");
|
|
||||||
public static final CommonErrorCode TAIR_SERVER_ERROR = new CommonErrorCode(5000003, "internal server error");
|
|
||||||
|
|
||||||
private int errorCode;
|
|
||||||
private String messagePattern;
|
|
||||||
|
|
||||||
protected CommonErrorCode() {}
|
|
||||||
|
|
||||||
protected CommonErrorCode(int errorCode, String messagePattern) {
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
this.messagePattern = messagePattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getErrorCode() {
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessagePattern() {
|
|
||||||
return messagePattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void throwMyError(Object... msgArgs) {
|
|
||||||
throw new MyError(this, msgArgs);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,155 +0,0 @@
|
||||||
package com.agileboot.domain.shop.payment.dto;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.URLUtil;
|
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class CommonRequest<T> {
|
|
||||||
private String clientId;
|
|
||||||
|
|
||||||
private String bizId;
|
|
||||||
|
|
||||||
private String sign;
|
|
||||||
|
|
||||||
private String signType;
|
|
||||||
|
|
||||||
private Long timestamp;
|
|
||||||
|
|
||||||
private String version;
|
|
||||||
|
|
||||||
private String nonceStr;
|
|
||||||
|
|
||||||
private T bizContent;
|
|
||||||
|
|
||||||
public CommonRequest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommonRequest(String clientId, String bizId, String nonceStr, T bizContent) {
|
|
||||||
super();
|
|
||||||
this.clientId = clientId;
|
|
||||||
this.bizId = bizId;
|
|
||||||
this.signType = "MD5";
|
|
||||||
this.timestamp = Instant.now().toEpochMilli();
|
|
||||||
this.version = "1.0";
|
|
||||||
this.nonceStr = nonceStr;
|
|
||||||
this.bizContent = bizContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<String, String> getSSMapFromKvPairs(String reqBody) {
|
|
||||||
String[] fields = reqBody.split("&");
|
|
||||||
Map<String, String> fieldMap = new HashMap<>();
|
|
||||||
for (String field : fields) {
|
|
||||||
String[] pair = field.split("=");
|
|
||||||
if (pair.length != 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldMap.put(pair[0], pair[1]);
|
|
||||||
}
|
|
||||||
return fieldMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> CommonRequest<T> build(String reqBody, Class<T> clazz) {
|
|
||||||
if (StringUtils.isBlank(reqBody)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 防止恶意传入&
|
|
||||||
Map<String, String> fieldMap = getSSMapFromKvPairs(reqBody);
|
|
||||||
|
|
||||||
CommonRequest<T> req = new CommonRequest<T>();
|
|
||||||
Optional.ofNullable(fieldMap.get("client_id")).ifPresent(e -> req.setClientId(e));
|
|
||||||
Optional.ofNullable(fieldMap.get("biz_id")).ifPresent(e -> req.setBizId(e));
|
|
||||||
Optional.ofNullable(fieldMap.get("sign")).ifPresent(e -> req.setSign(e));
|
|
||||||
Optional.ofNullable(fieldMap.get("sign_type")).ifPresent(e -> req.setSignType(e));
|
|
||||||
Optional.ofNullable(fieldMap.get("timestamp")).ifPresent(e -> {
|
|
||||||
if (NumberUtils.isNumber(e)) {
|
|
||||||
req.setTimestamp(Long.valueOf(e));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Optional.ofNullable(fieldMap.get("version")).ifPresent(e -> req.setVersion(e));
|
|
||||||
Optional.ofNullable(fieldMap.get("nonce_str")).ifPresent(e -> {
|
|
||||||
req.setNonceStr(URLUtil.decode(e));
|
|
||||||
});
|
|
||||||
Optional.ofNullable(fieldMap.get("biz_content")).ifPresent(e -> {
|
|
||||||
req.setBizContent(JSONUtil.toBean(URLUtil.decode(e), clazz));
|
|
||||||
});
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClientId() {
|
|
||||||
return clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClientId(String clientId) {
|
|
||||||
this.clientId = clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBizId() {
|
|
||||||
return bizId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBizId(String bizId) {
|
|
||||||
this.bizId = bizId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSign() {
|
|
||||||
return sign;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSign(String sign) {
|
|
||||||
this.sign = sign;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignType() {
|
|
||||||
return signType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSignType(String signType) {
|
|
||||||
this.signType = signType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getTimestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimestamp(Long timestamp) {
|
|
||||||
this.timestamp = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVersion() {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVersion(String version) {
|
|
||||||
this.version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNonceStr() {
|
|
||||||
return nonceStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNonceStr(String nonceStr) {
|
|
||||||
this.nonceStr = nonceStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getBizContent() {
|
|
||||||
return bizContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBizContent(T bizContent) {
|
|
||||||
this.bizContent = bizContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return JSONUtil.toJsonStr(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
package com.agileboot.domain.shop.payment.dto;
|
|
||||||
|
|
||||||
public class CommonResponse<T> {
|
|
||||||
private Integer code;
|
|
||||||
|
|
||||||
private String msg;
|
|
||||||
|
|
||||||
private T data;
|
|
||||||
|
|
||||||
public CommonResponse() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommonResponse(Integer code, String msg, T data) {
|
|
||||||
this.code = code;
|
|
||||||
this.msg = msg;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommonResponse(Integer code, String msg) {
|
|
||||||
this.code = code;
|
|
||||||
this.msg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> CommonResponse<T> resultOk(T data) {
|
|
||||||
CommonResponse response = new CommonResponse(CommonErrorCode.OK.getErrorCode(), CommonErrorCode.OK.getMessagePattern(), data);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> CommonResponse<T> resultError(Integer errorCode,String errorMsg) {
|
|
||||||
CommonResponse response = new CommonResponse(errorCode, errorMsg);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCode(Integer code) {
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMsg() {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMsg(String msg) {
|
|
||||||
this.msg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setData(T data) {
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
package com.agileboot.domain.shop.payment.dto;
|
|
||||||
|
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
|
|
||||||
public class MyError extends RuntimeException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private String msg;
|
|
||||||
|
|
||||||
private int code;
|
|
||||||
|
|
||||||
public MyError() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyError(int code, String msg) {
|
|
||||||
super(msg, null, true, true);
|
|
||||||
this.code = code;
|
|
||||||
this.msg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyError(CommonErrorCode errorCode, Object... msgArgs) {
|
|
||||||
this(errorCode.getErrorCode(), MessageFormat.format(errorCode.getMessagePattern(), msgArgs));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void invalidUrl() {
|
|
||||||
throw new MyError(CommonErrorCode.INVALID_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void badParameter(String msg) {
|
|
||||||
throw new MyError(CommonErrorCode.BAD_PARAMETER, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void internalError(String msg) {
|
|
||||||
throw new MyError(CommonErrorCode.INTERNAL_SERVER_ERROR, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void userNotLogin() {
|
|
||||||
throw new MyError(CommonErrorCode.USER_NOT_LOGIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void throwError(CommonErrorCode errorCode, Object ...args) {
|
|
||||||
throw new MyError(errorCode, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMsg() {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMsg(String msg) {
|
|
||||||
this.msg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCode(int code) {
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return JSONUtil.toJsonStr(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.agileboot.domain.shop.payment.dto;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class PaymentGatewayError {
|
|
||||||
private String timestamp;
|
|
||||||
private Integer status;
|
|
||||||
private String error;
|
|
||||||
private String message;
|
|
||||||
private String path;
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package com.agileboot.domain.shop.payment.dto;
|
|
||||||
|
|
||||||
public class RefundVO {
|
|
||||||
private Boolean success;
|
|
||||||
private String msg;
|
|
||||||
private String refundId;
|
|
||||||
private String bizOrderId;
|
|
||||||
private String wxCallbackJson;
|
|
||||||
|
|
||||||
public Boolean getSuccess() {
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSuccess(Boolean success) {
|
|
||||||
this.success = success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMsg() {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMsg(String msg) {
|
|
||||||
this.msg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRefundId() {
|
|
||||||
return refundId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRefundId(String refundId) {
|
|
||||||
this.refundId = refundId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBizOrderId() {
|
|
||||||
return bizOrderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBizOrderId(String bizOrderId) {
|
|
||||||
this.bizOrderId = bizOrderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWxCallbackJson() {
|
|
||||||
return wxCallbackJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWxCallbackJson(String wxCallbackJson) {
|
|
||||||
this.wxCallbackJson = wxCallbackJson;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser;
|
|
||||||
|
|
||||||
import com.agileboot.common.core.page.PageDTO;
|
|
||||||
import com.agileboot.domain.common.command.BulkOperationCommand;
|
|
||||||
import com.agileboot.domain.shop.wxuser.command.AddWxUserInfoCommand;
|
|
||||||
import com.agileboot.domain.shop.wxuser.command.UpdateWxUserInfoCommand;
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoEntity;
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoService;
|
|
||||||
import com.agileboot.domain.shop.wxuser.dto.WxUserInfoDTO;
|
|
||||||
import com.agileboot.domain.shop.wxuser.model.WxUserInfoModel;
|
|
||||||
import com.agileboot.domain.shop.wxuser.model.WxUserInfoModelFactory;
|
|
||||||
import com.agileboot.domain.shop.wxuser.query.SearchWxUserInfoQuery;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class WxUserInfoApplicationService {
|
|
||||||
private final WxUserInfoService wxUserInfoService;
|
|
||||||
private final WxUserInfoModelFactory wxUserInfoModelFactory;
|
|
||||||
|
|
||||||
public PageDTO<WxUserInfoDTO> getWxUserList(SearchWxUserInfoQuery<WxUserInfoEntity> query) {
|
|
||||||
Page<WxUserInfoEntity> page = wxUserInfoService.getWxUserInfoList(query);
|
|
||||||
List<WxUserInfoDTO> dtoList = page.getRecords().stream()
|
|
||||||
.map(WxUserInfoDTO::new)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
return new PageDTO<>(dtoList, page.getTotal());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addWxUser(AddWxUserInfoCommand command) {
|
|
||||||
WxUserInfoModel model = wxUserInfoModelFactory.create();
|
|
||||||
model.loadAddCommand(command);
|
|
||||||
model.insert();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateWxUser(UpdateWxUserInfoCommand command) {
|
|
||||||
WxUserInfoModel model = wxUserInfoModelFactory.loadById(command.getWxUserId());
|
|
||||||
model.loadUpdateCommand(command);
|
|
||||||
model.updateById();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteWxUser(BulkOperationCommand<Long> command) {
|
|
||||||
for (Long id : command.getIds()) {
|
|
||||||
WxUserInfoModel model = wxUserInfoModelFactory.loadById(id);
|
|
||||||
model.deleteById();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.command;
|
|
||||||
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class AddWxUserInfoCommand extends WxUserInfoEntity {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.command;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.validation.constraints.PositiveOrZero;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class UpdateWxUserInfoCommand extends AddWxUserInfoCommand {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@PositiveOrZero
|
|
||||||
private Long wxUserId;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.db;
|
|
||||||
|
|
||||||
import com.agileboot.common.core.base.BaseEntity;
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 微信用户基本信息表
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author valarchie
|
|
||||||
* @since 2025-04-07
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@TableName("wx_user_info")
|
|
||||||
@ApiModel(value = "WxUserInfoEntity对象", description = "微信用户基本信息表")
|
|
||||||
public class WxUserInfoEntity extends BaseEntity<WxUserInfoEntity> {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@ApiModelProperty("微信用户唯一ID")
|
|
||||||
@TableId(value = "wx_user_id", type = IdType.AUTO)
|
|
||||||
private Long wxUserId;
|
|
||||||
|
|
||||||
@ApiModelProperty("微信开放平台唯一标识")
|
|
||||||
@TableField("openid")
|
|
||||||
private String openid;
|
|
||||||
|
|
||||||
@ApiModelProperty("用户昵称")
|
|
||||||
@TableField("nickname")
|
|
||||||
private String nickname;
|
|
||||||
|
|
||||||
@ApiModelProperty("性别(0未知 1男 2女)")
|
|
||||||
@TableField("sex")
|
|
||||||
private Integer sex;
|
|
||||||
|
|
||||||
@ApiModelProperty("手机号码")
|
|
||||||
@TableField("mobile")
|
|
||||||
private String mobile;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Serializable pkVal() {
|
|
||||||
return this.wxUserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.db;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import java.util.List;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 微信用户基本信息表 Mapper 接口
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author valarchie
|
|
||||||
* @since 2025-04-07
|
|
||||||
*/
|
|
||||||
public interface WxUserInfoMapper extends BaseMapper<WxUserInfoEntity> {
|
|
||||||
@Select("SELECT wx_user_id, openid, nickname, sex, mobile " +
|
|
||||||
"FROM wx_user_info " +
|
|
||||||
"${ew.customSqlSegment}")
|
|
||||||
Page<WxUserInfoEntity> getWxUserInfoList(
|
|
||||||
Page<WxUserInfoEntity> page,
|
|
||||||
@Param(Constants.WRAPPER) Wrapper<WxUserInfoEntity> queryWrapper
|
|
||||||
);
|
|
||||||
|
|
||||||
@Select("SELECT * " +
|
|
||||||
"FROM wx_user_info " +
|
|
||||||
"WHERE enable = '1' " +
|
|
||||||
"ORDER BY create_time DESC " +
|
|
||||||
"LIMIT 1")
|
|
||||||
WxUserInfoEntity selectFirstEnabled();
|
|
||||||
|
|
||||||
@Select("SELECT * " +
|
|
||||||
"FROM wx_user_info " +
|
|
||||||
"WHERE enable = '1' " +
|
|
||||||
"ORDER BY create_time DESC")
|
|
||||||
List<WxUserInfoEntity> selectAllEnabled();
|
|
||||||
|
|
||||||
@Select("SELECT * FROM wx_user_info WHERE openid = #{openid} LIMIT 1")
|
|
||||||
WxUserInfoEntity selectByOpenid(String openid);
|
|
||||||
|
|
||||||
@Select("SELECT * FROM wx_user_info WHERE wx_user_id = #{wxUserId} LIMIT 1")
|
|
||||||
WxUserInfoEntity selectByWxUserId(Long wxUserId);
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.db;
|
|
||||||
|
|
||||||
import com.agileboot.common.core.page.AbstractPageQuery;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 微信用户基本信息表 服务类
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author valarchie
|
|
||||||
* @since 2025-04-07
|
|
||||||
*/
|
|
||||||
public interface WxUserInfoService extends IService<WxUserInfoEntity> {
|
|
||||||
Page<WxUserInfoEntity> getWxUserInfoList(AbstractPageQuery<WxUserInfoEntity> query);
|
|
||||||
|
|
||||||
List<WxUserInfoEntity> selectAllEnabled();
|
|
||||||
|
|
||||||
WxUserInfoEntity selectFirstEnabled();
|
|
||||||
|
|
||||||
WxUserInfoEntity selectByOpenid(String openid);
|
|
||||||
|
|
||||||
WxUserInfoEntity selectByWxUserId(Long wxUserId);
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.db;
|
|
||||||
|
|
||||||
import com.agileboot.common.core.page.AbstractPageQuery;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 微信用户基本信息表 服务实现类
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author valarchie
|
|
||||||
* @since 2025-04-07
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class WxUserInfoServiceImpl extends ServiceImpl<WxUserInfoMapper, WxUserInfoEntity> implements WxUserInfoService {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Page<WxUserInfoEntity> getWxUserInfoList(AbstractPageQuery<WxUserInfoEntity> query) {
|
|
||||||
return this.page(query.toPage(), query.toQueryWrapper());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<WxUserInfoEntity> selectAllEnabled() {
|
|
||||||
return baseMapper.selectAllEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxUserInfoEntity selectFirstEnabled() {
|
|
||||||
return baseMapper.selectFirstEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxUserInfoEntity selectByOpenid(String openid) {
|
|
||||||
return baseMapper.selectByOpenid(openid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxUserInfoEntity selectByWxUserId(Long wxUserId) {
|
|
||||||
return baseMapper.selectByWxUserId(wxUserId);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.dto;
|
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import com.agileboot.common.annotation.ExcelColumn;
|
|
||||||
import com.agileboot.common.annotation.ExcelSheet;
|
|
||||||
import com.agileboot.domain.common.cache.CacheCenter;
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoEntity;
|
|
||||||
import com.agileboot.domain.system.user.db.SysUserEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@ExcelSheet(name = "微信用户信息列表")
|
|
||||||
@Data
|
|
||||||
public class WxUserInfoDTO {
|
|
||||||
|
|
||||||
public WxUserInfoDTO(WxUserInfoEntity entity) {
|
|
||||||
if (entity != null) {
|
|
||||||
BeanUtil.copyProperties(entity, this);
|
|
||||||
|
|
||||||
switch (entity.getSex()) {
|
|
||||||
case 1:
|
|
||||||
this.sexStr = "男";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
this.sexStr = "女";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.sexStr = "未知";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExcelColumn(name = "微信用户ID")
|
|
||||||
private Long wxUserId;
|
|
||||||
|
|
||||||
@ExcelColumn(name = "微信开放平台ID")
|
|
||||||
private String openid;
|
|
||||||
|
|
||||||
@ExcelColumn(name = "用户昵称")
|
|
||||||
private String nickname;
|
|
||||||
|
|
||||||
private Integer sex;
|
|
||||||
|
|
||||||
@ExcelColumn(name = "性别")
|
|
||||||
private String sexStr;
|
|
||||||
|
|
||||||
@ExcelColumn(name = "手机号码")
|
|
||||||
private String mobile;
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.model;
|
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoEntity;
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoService;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class WxUserInfoModel extends WxUserInfoEntity {
|
|
||||||
|
|
||||||
private WxUserInfoService wxUserInfoService;
|
|
||||||
|
|
||||||
public WxUserInfoModel(WxUserInfoEntity entity, WxUserInfoService wxUserInfoService) {
|
|
||||||
this(wxUserInfoService);
|
|
||||||
if (entity != null) {
|
|
||||||
BeanUtil.copyProperties(entity, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public WxUserInfoModel(WxUserInfoService wxUserInfoService) {
|
|
||||||
this.wxUserInfoService = wxUserInfoService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadAddCommand(Object addCommand) {
|
|
||||||
if (addCommand != null) {
|
|
||||||
BeanUtil.copyProperties(addCommand, this, "id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadUpdateCommand(Object updateCommand) {
|
|
||||||
if (updateCommand != null) {
|
|
||||||
loadAddCommand(updateCommand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.model;
|
|
||||||
|
|
||||||
import com.agileboot.common.exception.ApiException;
|
|
||||||
import com.agileboot.common.exception.error.ErrorCode;
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoEntity;
|
|
||||||
import com.agileboot.domain.shop.wxuser.db.WxUserInfoService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class WxUserInfoModelFactory {
|
|
||||||
|
|
||||||
private final WxUserInfoService wxUserInfoService;
|
|
||||||
|
|
||||||
public WxUserInfoModel loadById(Long wxUserId) {
|
|
||||||
WxUserInfoEntity entity = wxUserInfoService.getById(wxUserId);
|
|
||||||
if (entity == null) {
|
|
||||||
throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, wxUserId, "微信用户");
|
|
||||||
}
|
|
||||||
return new WxUserInfoModel(entity, wxUserInfoService);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WxUserInfoModel create() {
|
|
||||||
return new WxUserInfoModel(wxUserInfoService);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package com.agileboot.domain.shop.wxuser.query;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.agileboot.common.core.page.AbstractPageQuery;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
||||||
import java.util.Date;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class SearchWxUserInfoQuery<T> extends AbstractPageQuery<T> {
|
|
||||||
|
|
||||||
private Long wxUserId;
|
|
||||||
private String openid;
|
|
||||||
private String nickname;
|
|
||||||
private Integer sex;
|
|
||||||
private String mobile;
|
|
||||||
private Date startTime;
|
|
||||||
private Date endTime;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public QueryWrapper<T> addQueryCondition() {
|
|
||||||
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
|
|
||||||
|
|
||||||
queryWrapper
|
|
||||||
.eq(wxUserId != null, "wx_user_id", wxUserId)
|
|
||||||
.eq(StrUtil.isNotEmpty(openid), "openid", openid)
|
|
||||||
.like(StrUtil.isNotEmpty(nickname), "nickname", nickname)
|
|
||||||
.eq(sex != null, "sex", sex)
|
|
||||||
.eq(StrUtil.isNotEmpty(mobile), "mobile", mobile)
|
|
||||||
.between(startTime != null && endTime != null, "create_time", startTime, endTime);
|
|
||||||
|
|
||||||
this.timeRangeColumn = "create_time";
|
|
||||||
|
|
||||||
return queryWrapper;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?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.agileboot.domain.shop.wxuser.db.WxUserInfoMapper">
|
|
||||||
|
|
||||||
</mapper>
|
|
|
@ -61,7 +61,7 @@ public class CodeGenerator {
|
||||||
//生成的类 放在orm子模块下的/target/generated-code目录底下
|
//生成的类 放在orm子模块下的/target/generated-code目录底下
|
||||||
.module("/agileboot-orm/target/generated-code")
|
.module("/agileboot-orm/target/generated-code")
|
||||||
.parentPackage("com.agileboot")
|
.parentPackage("com.agileboot")
|
||||||
.tableName("wx_user_info")
|
.tableName("return_approval")
|
||||||
// 决定是否继承基类
|
// 决定是否继承基类
|
||||||
.isExtendsFromBaseEntity(true)
|
.isExtendsFromBaseEntity(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -41,12 +41,3 @@ CREATE TABLE `wx_user_info` (
|
||||||
PRIMARY KEY (`wx_user_id`),
|
PRIMARY KEY (`wx_user_id`),
|
||||||
UNIQUE KEY `uk_openid` (`openid`)
|
UNIQUE KEY `uk_openid` (`openid`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='微信用户基本信息表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='微信用户基本信息表';
|
||||||
|
|
||||||
-- 在已有表结构下方添加
|
|
||||||
ALTER TABLE `return_approval`
|
|
||||||
ADD COLUMN `order_goods_id` BIGINT NOT NULL COMMENT '关联订单商品ID' AFTER `goods_id`,
|
|
||||||
ADD KEY `idx_order_goods` (`order_goods_id`),
|
|
||||||
ADD CONSTRAINT `fk_return_order_goods` FOREIGN KEY (`order_goods_id`) REFERENCES `shop_order_goods` (`order_goods_id`);
|
|
||||||
|
|
||||||
ALTER TABLE `shop_order`
|
|
||||||
ADD COLUMN `biz_order_id` VARCHAR(32) NULL COMMENT '业务系统订单ID(对接外部系统)' AFTER `trade_id`;
|
|
Loading…
Reference in New Issue