2025-07-13 14:28:15 +08:00
|
|
|
|
package edu.whut.trigger.http;
|
2025-07-16 14:01:48 +08:00
|
|
|
|
import com.alibaba.fastjson.JSON;
|
2025-07-13 14:28:15 +08:00
|
|
|
|
import com.alipay.api.AlipayApiException;
|
|
|
|
|
import com.alipay.api.internal.util.AlipaySignature;
|
|
|
|
|
import edu.whut.api.IPayService;
|
2025-08-04 22:18:47 +08:00
|
|
|
|
import edu.whut.api.dto.*;
|
2025-07-13 14:28:15 +08:00
|
|
|
|
import edu.whut.api.response.Response;
|
2025-08-04 22:18:47 +08:00
|
|
|
|
import edu.whut.domain.order.model.entity.OrderEntity;
|
2025-07-13 14:28:15 +08:00
|
|
|
|
import edu.whut.domain.order.model.entity.PayOrderEntity;
|
|
|
|
|
import edu.whut.domain.order.model.entity.ShopCartEntity;
|
2025-07-15 14:38:02 +08:00
|
|
|
|
import edu.whut.domain.order.model.valobj.MarketTypeVO;
|
2025-07-13 14:28:15 +08:00
|
|
|
|
import edu.whut.domain.order.service.IOrderService;
|
|
|
|
|
import edu.whut.types.common.Constants;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
2025-07-16 14:01:48 +08:00
|
|
|
|
import java.text.ParseException;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
2025-07-13 14:28:15 +08:00
|
|
|
|
import java.util.HashMap;
|
2025-08-04 22:18:47 +08:00
|
|
|
|
import java.util.List;
|
2025-07-13 14:28:15 +08:00
|
|
|
|
import java.util.Map;
|
2025-08-04 22:18:47 +08:00
|
|
|
|
import java.util.stream.Collectors;
|
2025-07-13 14:28:15 +08:00
|
|
|
|
|
|
|
|
|
@Slf4j
|
|
|
|
|
@RestController()
|
|
|
|
|
@CrossOrigin("*")
|
|
|
|
|
@RequiredArgsConstructor
|
|
|
|
|
@RequestMapping("/api/v1/alipay")
|
|
|
|
|
public class AliPayController implements IPayService {
|
|
|
|
|
|
|
|
|
|
@Value("${alipay.alipay_public_key}")
|
|
|
|
|
private String alipayPublicKey;
|
|
|
|
|
|
|
|
|
|
private final IOrderService orderService;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {
|
|
|
|
|
* "userId": "10001",
|
|
|
|
|
* "productId": "10001"
|
|
|
|
|
* }
|
|
|
|
|
*/
|
|
|
|
|
@PostMapping("/create_pay_order")
|
|
|
|
|
@Override
|
|
|
|
|
public Response<String> createPayOrder(@RequestBody CreatePayRequestDTO createPayRequestDTO) {
|
|
|
|
|
try {
|
|
|
|
|
log.info("商品下单,根据商品ID创建支付单开始 userId:{} productId:{}", createPayRequestDTO.getUserId(), createPayRequestDTO.getUserId());
|
|
|
|
|
String userId = createPayRequestDTO.getUserId();
|
|
|
|
|
String productId = createPayRequestDTO.getProductId();
|
2025-07-15 14:38:02 +08:00
|
|
|
|
String teamId = createPayRequestDTO.getTeamId();
|
|
|
|
|
Integer marketType = createPayRequestDTO.getMarketType();
|
2025-07-13 14:28:15 +08:00
|
|
|
|
// 下单
|
|
|
|
|
PayOrderEntity payOrderEntity = orderService.createOrder(ShopCartEntity.builder()
|
|
|
|
|
.userId(userId)
|
|
|
|
|
.productId(productId)
|
2025-07-15 14:38:02 +08:00
|
|
|
|
.teamId(teamId)
|
|
|
|
|
.marketTypeVO(MarketTypeVO.valueOf(marketType))
|
2025-07-16 17:12:35 +08:00
|
|
|
|
.activityId(createPayRequestDTO.getActivityId())
|
2025-07-13 14:28:15 +08:00
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
log.info("商品下单,根据商品ID创建支付单完成 userId:{} productId:{} orderId:{}", userId, productId, payOrderEntity.getOrderId());
|
|
|
|
|
return Response.<String>builder()
|
|
|
|
|
.code(Constants.ResponseCode.SUCCESS.getCode())
|
|
|
|
|
.info(Constants.ResponseCode.SUCCESS.getInfo())
|
|
|
|
|
.data(payOrderEntity.getPayUrl())
|
|
|
|
|
.build();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("商品下单,根据商品ID创建支付单失败 userId:{} productId:{}", createPayRequestDTO.getUserId(), createPayRequestDTO.getUserId(), e);
|
|
|
|
|
return Response.<String>builder()
|
|
|
|
|
.code(Constants.ResponseCode.UN_ERROR.getCode())
|
|
|
|
|
.info(Constants.ResponseCode.UN_ERROR.getInfo())
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-16 14:01:48 +08:00
|
|
|
|
/**
|
|
|
|
|
* 拼团完成(目标人数已达成)后的回调地址,由group_buy_market调用
|
2025-08-04 22:18:47 +08:00
|
|
|
|
* 仅HTTP方式下触发,MQ方式下不会触发。
|
2025-07-16 14:01:48 +08:00
|
|
|
|
*/
|
|
|
|
|
@PostMapping("/group_buy_notify")
|
|
|
|
|
@Override
|
|
|
|
|
public String groupBuyNotify(@RequestBody NotifyRequestDTO requestDTO) {
|
|
|
|
|
log.info("拼团回调,组队完成,结算开始 {}", JSON.toJSONString(requestDTO));
|
|
|
|
|
try {
|
|
|
|
|
// 营销结算
|
|
|
|
|
orderService.changeOrderMarketSettlement(requestDTO.getOutTradeNoList());
|
|
|
|
|
return "success";
|
|
|
|
|
} catch (Exception e) {
|
2025-07-20 22:10:23 +08:00
|
|
|
|
log.error("拼团回调,组队完成,结算失败 {}", JSON.toJSONString(requestDTO));
|
2025-07-16 14:01:48 +08:00
|
|
|
|
return "error";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 用户支付成功后的回调地址
|
|
|
|
|
*/
|
2025-07-13 14:28:15 +08:00
|
|
|
|
@PostMapping("/alipay_notify_url")
|
2025-07-16 14:01:48 +08:00
|
|
|
|
public String payNotify(HttpServletRequest request) throws AlipayApiException, ParseException {
|
2025-07-13 14:28:15 +08:00
|
|
|
|
log.info("支付回调,消息接收 {}", request.getParameter("trade_status"));
|
|
|
|
|
|
|
|
|
|
if (!request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
|
|
|
|
|
return "false";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<String, String> params = new HashMap<>();
|
|
|
|
|
Map<String, String[]> requestParams = request.getParameterMap();
|
|
|
|
|
for (String name : requestParams.keySet()) {
|
|
|
|
|
params.put(name, request.getParameter(name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String tradeNo = params.get("out_trade_no");
|
|
|
|
|
String gmtPayment = params.get("gmt_payment");
|
|
|
|
|
String alipayTradeNo = params.get("trade_no");
|
|
|
|
|
|
|
|
|
|
String sign = params.get("sign");
|
|
|
|
|
String content = AlipaySignature.getSignCheckContentV1(params);
|
|
|
|
|
boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, alipayPublicKey, "UTF-8"); // 验证签名
|
|
|
|
|
// 支付宝验签
|
|
|
|
|
if (!checkSignature) {
|
|
|
|
|
return "false";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验签通过
|
|
|
|
|
log.info("支付回调,交易名称: {}", params.get("subject"));
|
|
|
|
|
log.info("支付回调,交易状态: {}", params.get("trade_status"));
|
|
|
|
|
log.info("支付回调,支付宝交易凭证号: {}", params.get("trade_no"));
|
|
|
|
|
log.info("支付回调,商户订单号: {}", params.get("out_trade_no"));
|
|
|
|
|
log.info("支付回调,交易金额: {}", params.get("total_amount"));
|
|
|
|
|
log.info("支付回调,买家在支付宝唯一id: {}", params.get("buyer_id"));
|
|
|
|
|
log.info("支付回调,买家付款时间: {}", params.get("gmt_payment"));
|
|
|
|
|
log.info("支付回调,买家付款金额: {}", params.get("buyer_pay_amount"));
|
|
|
|
|
log.info("支付回调,支付回调,更新订单 {}", tradeNo);
|
|
|
|
|
|
2025-07-16 14:01:48 +08:00
|
|
|
|
// 后续处理,更新订单状态...进入下一阶段:如发货
|
|
|
|
|
orderService.changeOrderPaySuccess(tradeNo, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(params.get("gmt_payment")));
|
2025-07-13 14:28:15 +08:00
|
|
|
|
return "success";
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-04 22:18:47 +08:00
|
|
|
|
@RequestMapping(value = "query_user_order_list", method = RequestMethod.POST)
|
|
|
|
|
@Override
|
|
|
|
|
public Response<QueryOrderListResponseDTO> queryUserOrderList(@RequestBody QueryOrderListRequestDTO requestDTO) {
|
|
|
|
|
try {
|
|
|
|
|
log.info("查询用户订单列表开始 userId:{} lastId:{} pageSize:{}", requestDTO.getUserId(), requestDTO.getLastId(), requestDTO.getPageSize());
|
|
|
|
|
|
|
|
|
|
String userId = requestDTO.getUserId();
|
|
|
|
|
Long lastId = requestDTO.getLastId();
|
|
|
|
|
Integer pageSize = requestDTO.getPageSize();
|
|
|
|
|
|
|
|
|
|
// 查询订单列表,多查询一条用于判断是否还有更多数据
|
|
|
|
|
List<OrderEntity> orderList = orderService.queryUserOrderList(userId, lastId, pageSize + 1);
|
|
|
|
|
|
|
|
|
|
// 判断是否还有更多数据
|
|
|
|
|
boolean hasMore = orderList.size() > pageSize;
|
|
|
|
|
if (hasMore) {
|
|
|
|
|
orderList = orderList.subList(0, pageSize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 转换为响应对象
|
|
|
|
|
List<QueryOrderListResponseDTO.OrderInfo> orderInfoList = orderList.stream().map(order -> {
|
|
|
|
|
QueryOrderListResponseDTO.OrderInfo orderInfo = new QueryOrderListResponseDTO.OrderInfo();
|
|
|
|
|
orderInfo.setId(order.getId());
|
|
|
|
|
orderInfo.setUserId(order.getUserId());
|
|
|
|
|
orderInfo.setProductId(order.getProductId());
|
|
|
|
|
orderInfo.setProductName(order.getProductName());
|
|
|
|
|
orderInfo.setOrderId(order.getOrderId());
|
|
|
|
|
orderInfo.setOrderTime(order.getOrderTime());
|
|
|
|
|
orderInfo.setTotalAmount(order.getTotalAmount());
|
|
|
|
|
orderInfo.setStatus(order.getOrderStatusVO() != null ? order.getOrderStatusVO().getCode() : null);
|
|
|
|
|
orderInfo.setPayUrl(order.getPayUrl());
|
|
|
|
|
orderInfo.setMarketType(order.getMarketType());
|
|
|
|
|
orderInfo.setMarketDeductionAmount(order.getMarketDeductionAmount());
|
|
|
|
|
orderInfo.setPayAmount(order.getPayAmount());
|
|
|
|
|
orderInfo.setPayTime(order.getPayTime());
|
|
|
|
|
return orderInfo;
|
|
|
|
|
}).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
QueryOrderListResponseDTO responseDTO = new QueryOrderListResponseDTO();
|
|
|
|
|
responseDTO.setOrderList(orderInfoList);
|
|
|
|
|
responseDTO.setHasMore(hasMore);
|
|
|
|
|
responseDTO.setLastId(!orderList.isEmpty() ? orderList.get(orderList.size() - 1).getId() : null);
|
|
|
|
|
|
|
|
|
|
log.info("查询用户订单列表完成 userId:{} 返回订单数量:{} hasMore:{}", userId, orderInfoList.size(), hasMore);
|
|
|
|
|
return Response.<QueryOrderListResponseDTO>builder()
|
|
|
|
|
.code(Constants.ResponseCode.SUCCESS.getCode())
|
|
|
|
|
.info(Constants.ResponseCode.SUCCESS.getInfo())
|
|
|
|
|
.data(responseDTO)
|
|
|
|
|
.build();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("查询用户订单列表失败 userId:{}", requestDTO.getUserId(), e);
|
|
|
|
|
return Response.<QueryOrderListResponseDTO>builder()
|
|
|
|
|
.code(Constants.ResponseCode.UN_ERROR.getCode())
|
|
|
|
|
.info(Constants.ResponseCode.UN_ERROR.getInfo())
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* http://localhost:8080/api/v1/alipay/refund_order
|
|
|
|
|
* <p>
|
|
|
|
|
* {
|
|
|
|
|
* "userId": "xfg02",
|
|
|
|
|
* "orderId": "928263928388"
|
|
|
|
|
* }
|
|
|
|
|
*/
|
|
|
|
|
@RequestMapping(value = "refund_order", method = RequestMethod.POST)
|
|
|
|
|
@Override
|
|
|
|
|
public Response<RefundOrderResponseDTO> refundOrder(@RequestBody RefundOrderRequestDTO requestDTO) {
|
|
|
|
|
try {
|
|
|
|
|
log.info("用户退单开始 userId:{} orderId:{}", requestDTO.getUserId(), requestDTO.getOrderId());
|
|
|
|
|
|
|
|
|
|
String userId = requestDTO.getUserId();
|
|
|
|
|
String orderId = requestDTO.getOrderId();
|
|
|
|
|
|
|
|
|
|
// 执行退单操作
|
|
|
|
|
boolean success = orderService.refundOrder(userId, orderId);
|
|
|
|
|
|
|
|
|
|
RefundOrderResponseDTO responseDTO = new RefundOrderResponseDTO();
|
|
|
|
|
responseDTO.setSuccess(success);
|
|
|
|
|
responseDTO.setOrderId(orderId);
|
|
|
|
|
responseDTO.setMessage(success ? "退单成功" : "退单失败,订单不存在、已关闭或不属于该用户");
|
|
|
|
|
|
|
|
|
|
log.info("用户退单完成 userId:{} orderId:{} success:{}", userId, orderId, success);
|
|
|
|
|
return Response.<RefundOrderResponseDTO>builder()
|
|
|
|
|
.code(Constants.ResponseCode.SUCCESS.getCode())
|
|
|
|
|
.info(Constants.ResponseCode.SUCCESS.getInfo())
|
|
|
|
|
.data(responseDTO)
|
|
|
|
|
.build();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("用户退单失败 userId:{} orderId:{}", requestDTO.getUserId(), requestDTO.getOrderId(), e);
|
|
|
|
|
|
|
|
|
|
RefundOrderResponseDTO responseDTO = new RefundOrderResponseDTO();
|
|
|
|
|
responseDTO.setSuccess(false);
|
|
|
|
|
responseDTO.setOrderId(requestDTO.getOrderId());
|
|
|
|
|
responseDTO.setMessage("退单失败,系统异常");
|
|
|
|
|
|
|
|
|
|
return Response.<RefundOrderResponseDTO>builder()
|
|
|
|
|
.code(Constants.ResponseCode.UN_ERROR.getCode())
|
|
|
|
|
.info(Constants.ResponseCode.UN_ERROR.getInfo())
|
|
|
|
|
.data(responseDTO)
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 14:28:15 +08:00
|
|
|
|
}
|