javacodeadmin/ruoyi-system/src/main/java/com/ruoyi/system/controller/ApplePayController.java

1285 lines
59 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ruoyi.system.controller;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.ControllerUtil.*;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 微信支付管理控制器
* 提供微信支付相关的API接口包括
* 1. 微信支付统一下单
* 2. 代付订单创建
* 3. 支付回调处理
* 4. 退款申请处理
* 支持的支付场景:
* - 小程序支付
* - 代付功能
* - 退款处理
* - 支付回调验证
*
* @author Mr. Zhang Pan
* @version 1.0
*/
@RestController
@RequestMapping("/api/pay")
public class ApplePayController extends BaseController {
// ==================== 日志记录 ====================
private static final Logger logger = LoggerFactory.getLogger(ApplePayController.class);
// ==================== 依赖注入 ====================
@Autowired
private IUsersService usersService;
@Autowired
private WechatPayUtil wechatPayUtil;
@Autowired
private IUserAddressService userAddressService;
@Autowired
private ICouponUserService couponUserService;
@Autowired
private IOrderService orderService;
@Autowired
private IServiceGoodsService serviceGoodsService;
@Autowired
private IUserGroupBuyingService userGroupBuyingService;
@Autowired
private IUserMemberRechargeLogService userMemberRechargeLogService;
@Autowired
private IUserMemberRechargeProgramService userMemberRechargeProgramService;
@Autowired
private IOrderLogService orderLogService;
@Autowired
private IGoodsOrderService goodsOrderService;
@Autowired
private WechatPayV3Util wechatPayV3Util;
// ==================== 支付下单相关接口 ====================
@PostMapping("/api/quick-refund")
public AjaxResult quickRefund(
@RequestParam String orderNo,
@RequestParam BigDecimal refundFee,
@RequestParam(required = false) String reason) {
try {
Map<String, Object> result = wechatPayV3Util.quickRefund(orderNo, refundFee, reason);
if ((Boolean) result.get("success")) {
return success(result.get("data"));
} else {
return error((String) result.get("message"));
}
} catch (Exception e) {
return error("快速退款异常:" + e.getMessage());
}
}
/**
* 用户提现
*
* @param openid 用户openid
* @param amount 金额(分)
* @param desc 提现描述
* @param userName 真实姓名(可选,用于实名校验)
* @return 提现结果
*/
@PostMapping("/api/withdraw")
public AjaxResult withdraw(@RequestParam String openid,
@RequestParam int amount,
@RequestParam(required = false) String desc,
@RequestParam(required = false) String userName) {
try {
Map<String, Object> result = wechatPayV3Util.withdraw(openid, amount, desc, userName);
if ((Boolean) result.get("success")) {
return AjaxResult.success("提现申请成功", result.get("data"));
} else {
return AjaxResult.error(result.get("message").toString());
}
} catch (Exception e) {
return AjaxResult.error("提现申请失败: " + e.getMessage());
}
}
/**
* 微信支付统一下单接口
* 创建微信支付订单,用于小程序支付
* 业务逻辑:
* 1. 验证用户登录状态
* 2. 调用微信支付统一下单API
* 3. 返回支付参数供前端调用
* 请求参数:
* - openid: 用户openid
* - orderNo: 商户订单号
* - totalFee: 支付金额(分)
* - body: 商品描述
* - notifyUrl: 支付回调地址
* - attach: 附加数据
*
* @param params 支付参数
* @param request HTTP请求对象需要包含token
* @return 支付结果包含prepayId等微信支付参数
*/
@PostMapping("/unifiedorder")
public AjaxResult createPayOrder(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 验证必要参数
if (params == null || params.get("openid") == null || params.get("orderNo") == null
|| params.get("totalFee") == null || params.get("body") == null
|| params.get("notifyUrl") == null) {
return AppletControllerUtil.appletWarning("支付参数不完整");
}
// 3. 调用微信支付统一下单
Map<String, Object> payResult = wechatPayUtil.unifiedOrder(
(String) params.get("openid"),
(String) params.get("orderNo"),
(Integer) params.get("totalFee"),
(String) params.get("body"),
(String) params.get("notifyUrl"),
(String) params.get("attach")
);
// 4. 返回结果
boolean success = (Boolean) payResult.get("success");
if (success) {
return AppletControllerUtil.appletSuccess(payResult);
} else {
return AppletControllerUtil.appletWarning((String) payResult.get("message"));
}
} catch (Exception e) {
System.err.println("创建支付订单异常:" + e.getMessage());
return AppletControllerUtil.appletError("创建支付订单失败:" + e.getMessage());
}
}
/**
* 创建代付订单接口
* <p>
* 为其他用户代付功能,如师傅代付、团购代付等
* <p>
* 业务逻辑:
* 1. 验证用户登录状态
* 2. 创建代付订单
* 3. 返回支付参数
* <p>
* 请求参数:
* - payerOpenid: 代付人openid
* - orderNo: 商户订单号
* - totalFee: 支付金额(分)
* - body: 商品描述
* - notifyUrl: 支付回调地址
* - remark: 代付备注
*
* @param params 代付参数
* @param request HTTP请求对象需要包含token
* @return 代付结果,包含支付参数
*/
@PostMapping("/payfor")
public AjaxResult createPayForOrder(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 验证必要参数
if (params == null || params.get("payerOpenid") == null || params.get("orderNo") == null
|| params.get("totalFee") == null || params.get("body") == null
|| params.get("notifyUrl") == null) {
return AppletControllerUtil.appletWarning("代付参数不完整");
}
// 3. 创建代付订单
Map<String, Object> payForResult = wechatPayUtil.unifiedOrder(
params.get("payerOpenid").toString(),
params.get("orderNo").toString(),
Integer.parseInt(params.get("totalFee").toString()),
params.get("body").toString(),
params.get("notifyUrl").toString(),
params.get("remark") != null ? params.get("remark").toString() : ""
);
// 4. 返回结果
boolean success = (Boolean) payForResult.get("success");
if (success) {
return AppletControllerUtil.appletSuccess(payForResult);
} else {
return AppletControllerUtil.appletWarning((String) payForResult.get("message"));
}
} catch (Exception e) {
System.err.println("创建代付订单异常:" + e.getMessage());
return AppletControllerUtil.appletError("创建代付订单失败:" + e.getMessage());
}
}
// ==================== 支付回调相关接口 ====================
/**
* 微信支付回调接口
* <p>
* 接收微信支付服务器的支付结果通知
* <p>
* 重要说明:
* 1. 此接口供微信服务器回调使用,不需要用户认证
* 2. 返回格式必须是XML格式用于告知微信处理结果
* 3. 必须在15秒内响应否则微信会重复发送通知
* 4. 需要验证签名确保数据安全
* <p>
* 业务逻辑:
* 1. 接收并验证微信支付回调数据
* 2. 处理支付成功的业务逻辑
* 3. 返回XML格式的响应给微信
*
* @param request HTTP请求对象包含微信回调的XML数据
* @return XML格式的处理结果响应
*/
@PostMapping("/notify")
public String handlePayNotify(HttpServletRequest request) {
try {
// 1. 处理支付回调
Map<String, Object> notifyResult = wechatPayUtil.handlePayNotify(request);
// 2. 获取支付信息
boolean success = (Boolean) notifyResult.get("success");
if (success) {
Map<String, Object> paymentInfo = (Map<String, Object>) notifyResult.get("paymentInfo");
boolean isPayFor = (Boolean) notifyResult.get("isPayFor");
// 3. 根据业务需要处理支付成功逻辑
// 例如:更新订单状态、发送通知、增加积分等
try {
AppletControllerUtil.handlePaymentSuccess(paymentInfo, isPayFor);
System.out.println("支付回调处理成功,订单号:" + paymentInfo.get("orderNo"));
} catch (Exception e) {
System.err.println("支付回调业务处理异常:" + e.getMessage());
// 即使业务处理失败,也要告知微信支付成功,避免重复回调
}
// 4. 返回成功响应给微信
return (String) notifyResult.get("responseXml");
} else {
// 5. 返回失败响应给微信
String errorMsg = (String) notifyResult.get("message");
System.err.println("支付回调验证失败:" + errorMsg);
return (String) notifyResult.get("responseXml");
}
} catch (Exception e) {
// 6. 异常时返回失败响应
System.err.println("支付回调处理异常:" + e.getMessage());
return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理异常]]></return_msg></xml>";
}
}
// ==================== 退款相关接口 ====================
/**
* 申请退款接口
* <p>
* 对已支付的订单申请退款
* <p>
* 业务逻辑:
* 1. 验证用户登录状态
* 2. 验证退款参数
* 3. 调用微信退款API
* 4. 返回退款结果
* <p>
* 请求参数格式:
* {
* "orderNo": "原订单号",
* "refundNo": "退款单号",
* "totalFee": 订单总金额(分),
* "refundFee": 退款金额(分),
* "refundDesc": "退款原因"
* }
* <p>
* 注意事项:
* - 退款金额不能超过原订单金额
* - 退款单号必须唯一
* - 退款成功后资金会原路返回
*
* @param params 退款参数
* @param request HTTP请求对象需要包含token
* @return 退款结果
*/
@PostMapping("/refund")
public AjaxResult refundOrder(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 验证必要参数
if (params == null || params.get("orderNo") == null || params.get("refundNo") == null
|| params.get("totalFee") == null || params.get("refundFee") == null) {
return AppletControllerUtil.appletWarning("退款参数不完整");
}
// 3. 验证退款金额
int totalFee = Integer.parseInt(params.get("totalFee").toString());
int refundFee = Integer.parseInt(params.get("refundFee").toString());
if (refundFee <= 0 || refundFee > totalFee) {
return AppletControllerUtil.appletWarning("退款金额不正确");
}
// 4. 申请退款
Map<String, Object> refundResult = wechatPayUtil.refund(params);
// 5. 返回结果
boolean success = (Boolean) refundResult.get("success");
if (success) {
System.out.println("退款申请成功,订单号:" + params.get("orderNo") +
",退款单号:" + params.get("refundNo") +
",退款金额:" + refundFee + "");
return AppletControllerUtil.appletSuccess(refundResult);
} else {
String errorMsg = (String) refundResult.get("message");
System.err.println("退款申请失败:" + errorMsg);
return AppletControllerUtil.appletWarning(errorMsg);
}
} catch (Exception e) {
System.err.println("申请退款异常:" + e.getMessage());
return AppletControllerUtil.appletError("申请退款失败:" + e.getMessage());
}
}
// ==================== 支付查询相关接口 ====================
/**
* 查询支付结果接口
* <p>
* 主动查询订单的支付状态
* 用于确认支付结果或处理异常情况
* <p>
* 请求参数:
* - orderNo: 商户订单号
*
* @param params 查询参数
* @param request HTTP请求对象需要包含token
* @return 支付状态查询结果
*/
@PostMapping("/query")
public AjaxResult queryPayOrder(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 验证必要参数
if (params == null || params.get("orderNo") == null) {
return AppletControllerUtil.appletWarning("订单号不能为空");
}
// 3. 查询支付结果
// 注意如果WechatPayUtil.queryOrder需要更多参数请根据实际方法签名调整
Map<String, Object> queryResult = new HashMap<>();
queryResult.put("success", true);
queryResult.put("message", "查询功能待实现");
queryResult.put("orderNo", params.get("orderNo"));
queryResult.put("status", "UNKNOWN");
// 4. 返回结果
boolean success = (Boolean) queryResult.get("success");
if (success) {
return AppletControllerUtil.appletSuccess(queryResult);
} else {
return AppletControllerUtil.appletWarning((String) queryResult.get("message"));
}
} catch (Exception e) {
System.err.println("查询支付结果异常:" + e.getMessage());
return AppletControllerUtil.appletError("查询支付结果失败:" + e.getMessage());
}
}
// ==================== 会员充值相关接口 ====================
/**
* 会员充值支付接口
* <p>
* 支持两种充值方式:
* 1. 通过充值套餐ID充值优先级更高
* 2. 通过自定义金额充值
* <p>
* 业务逻辑:
* - 如果id和money都有值优先使用id充值套餐
* - 如果只有money有值使用自定义金额充值
* - 生成充值记录并调用微信支付
*
* @param params 请求参数包含id(充值类目ID)、money(充值金额)
* @param request HTTP请求对象需要包含token
* @return 支付结果包含prepayId等微信支付参数
*/
@PostMapping("/member/recharge/pay")
public AjaxResult memberRechargePay(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 获取用户信息
Users user = (Users) userValidation.get("user");
if (user == null) {
return AppletControllerUtil.appletWarning("用户信息获取失败");
}
// 3. 参数验证逻辑id和money必须有一个有值如果都有值则优先使用id
Object idObj = params.get("id");
Object moneyObj = params.get("money");
boolean idEmpty = (idObj == null || idObj.toString().trim().isEmpty());
boolean moneyEmpty = (moneyObj == null || moneyObj.toString().trim().isEmpty());
if (idEmpty && moneyEmpty) {
return AppletControllerUtil.appletWarning("参数不能为空,类目和金额必须有一个有值");
}
// 如果id和money都有值优先走id逻辑money置空
if (!idEmpty && !moneyEmpty) {
moneyObj = null;
}
// 4. 创建充值记录
String money = "";
UserMemberRechargeLog userMemberRechargeLog = new UserMemberRechargeLog();
userMemberRechargeLog.setUid(Math.toIntExact(user.getId()));
userMemberRechargeLog.setOrderid(GenerateCustomCode.generCreateOrder("DYZ"));
userMemberRechargeLog.setPaytype(0); // 0=微信支付
userMemberRechargeLog.setPaytime(new Date());
if (!idEmpty) {
// 5a. 通过充值套餐ID充值
UserMemberRechargeProgram userMemberRechargeProgram = userMemberRechargeProgramService
.selectUserMemberRechargeProgramById(Integer.valueOf(idObj.toString()));
if (userMemberRechargeProgram != null) {
userMemberRechargeLog.setInmoney(userMemberRechargeProgram.getMoney()); // 应付金额
userMemberRechargeLog.setComemoney(userMemberRechargeProgram.getDiscount()); // 实际到账金额
userMemberRechargeLog.setReamk("购买" + userMemberRechargeProgram.getRechargename()
+ "应付" + userMemberRechargeProgram.getMoney() + "元,应到"
+ userMemberRechargeProgram.getDiscount() + "");
userMemberRechargeLog.setProid(userMemberRechargeProgram.getId());
money = userMemberRechargeProgram.getMoney().toString();
// type大于0表示会员包年充值需要特殊处理
if (userMemberRechargeProgram.getType() > 0) {
userMemberRechargeLog.setIsmember(1); // 会员充值
} else {
userMemberRechargeLog.setIsmember(2); // 普通充值
}
}
} else {
// 5b. 通过自定义金额充值
money = moneyObj.toString();
userMemberRechargeLog.setInmoney(new BigDecimal(money)); // 应付金额
userMemberRechargeLog.setComemoney(new BigDecimal(money)); // 实际到账金额
userMemberRechargeLog.setIsmember(2); // 普通充值
userMemberRechargeLog.setReamk("会员现金充值" + money + "");
}
// 6. 保存充值记录并调用微信支付
if (userMemberRechargeLogService.insertUserMemberRechargeLog(userMemberRechargeLog) > 0) {
// 调用微信支付测试环境使用0.01元)
Map<String, Object> payResult = wechatPayUtil.createBatchOrderAndPay(
user.getOpenid(),
userMemberRechargeLog.getId().toString(),
new BigDecimal("0.01"), // 测试金额
1,
WechatPayUtil.PAY_FH + "api/recharge/pay/notify"); // 使用配置的回调地址
if (payResult != null && Boolean.TRUE.equals(payResult.get("success"))) {
// 构建支付响应数据
Map<String, Object> responseData = new HashMap<>();
responseData.put("mainOrderId", userMemberRechargeLog.getId().toString());
responseData.put("totalAmount", money);
responseData.put("prepayId", payResult.get("prepayId"));
// 合并所有支付参数
responseData.putAll(payResult);
return AppletControllerUtil.appletSuccess(responseData);
} else {
String errorMsg = payResult != null ? (String) payResult.get("message") : "微信支付下单失败";
return AppletControllerUtil.appletWarning("支付下单失败:" + errorMsg);
}
}
return AppletControllerUtil.appletWarning("支付失败");
} catch (Exception e) {
System.err.println("会员充值支付异常:" + e.getMessage());
return AppletControllerUtil.appletError("充值支付失败:" + e.getMessage());
}
}
/**
* 创建服务订单(支持多商品批量下单)
*
* @param params 请求参数,包含多个商品信息、地址信息和预约时间
* @param request HTTP请求对象
* @return 返回创建结果
*/
@PostMapping("/api/service/create/order")
public AjaxResult createServiceOrder(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 获取用户信息
Users user = (Users) userValidation.get("user");
if (user == null) {
return AppletControllerUtil.appletWarning("用户信息获取失败");
}
// 3. 验证订单参数
if (params == null || params.isEmpty()) {
return AppletControllerUtil.appletWarning("订单参数不能为空");
}
// 4. 生成主订单号
String mainOrderId = GenerateCustomCode.generCreateOrder("WXB");
// 5. 存储所有订单信息
List<Map<String, Object>> orderList = new ArrayList<>();
BigDecimal totalAmount = BigDecimal.ZERO; // 总金额
// 6. 遍历所有订单项
for (String key : params.keySet()) {
// 跳过非数字键
if (!key.matches("\\d+")) {
continue;
}
Map<String, Object> orderParams = (Map<String, Object>) params.get(key);
// 验证必要参数
if (orderParams.get("product_id") == null || orderParams.get("address_id") == null) {
return AppletControllerUtil.appletWarning("商品ID或地址ID不能为空");
}
Long productId = Long.valueOf(orderParams.get("product_id").toString());
Long addressId = Long.valueOf(orderParams.get("address_id").toString());
Long num = orderParams.get("num") != null ? Long.valueOf(orderParams.get("num").toString()) : 1L;
// 处理SKU参数
String sku = AppletControllerUtil.processSkuParam(orderParams.get("sku"));
// 查询商品信息
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(productId);
if (serviceGoods == null) {
return AppletControllerUtil.appletWarning("商品ID " + productId + " 不存在");
}
// 查询地址信息(只需要查询一次,假设所有订单使用相同地址)
UserAddress userAddress = userAddressService.selectUserAddressById(addressId);
if (userAddress == null) {
return AppletControllerUtil.appletWarning("地址不存在");
}
// 计算单个订单金额
BigDecimal itemPrice = serviceGoods.getPrice().multiply(BigDecimal.valueOf(num));
totalAmount = totalAmount.add(itemPrice);
// 判断商品类型并创建相应订单
BigDecimal DeductionPrice = new BigDecimal("0");
if (serviceGoods.getType() == 2) {
// 创建服务订单
String coupon_id = orderParams.get("coupon_id") != null ? orderParams.get("coupon_id").toString() : "";
System.out.println("coupon_id:"+coupon_id);
CouponUser coupon=null;
if (coupon_id!=null&& !coupon_id.isEmpty()){
coupon = couponUserService.selectCouponUserById(Long.valueOf(coupon_id));
if (coupon==null){
return AppletControllerUtil.appletWarning("优惠券不存在");
}
if (coupon != null) {
DeductionPrice= new BigDecimal(coupon.getCouponPrice()).divide(new BigDecimal(params.size()),2, RoundingMode.HALF_UP);
}
if (coupon != null) {
coupon.setStatus(2L);
}
couponUserService.updateCouponUser(coupon) ;
}
// 创建商品订单
GoodsOrder goodsOrder = new GoodsOrder();
goodsOrder.setType(2);
goodsOrder.setMainOrderId(mainOrderId);
goodsOrder.setOrderId(GenerateCustomCode.generCreateOrder("B")); // 独立订单号
goodsOrder.setUid(user.getId());
goodsOrder.setProductId(productId);
goodsOrder.setName(userAddress.getName());
goodsOrder.setPhone(userAddress.getPhone());
goodsOrder.setAddress(userAddress.getAddressName());
goodsOrder.setNum(num);
goodsOrder.setTotalPrice(itemPrice);
goodsOrder.setGoodPrice(serviceGoods.getPrice());
goodsOrder.setPayPrice(itemPrice);
goodsOrder.setDeduction(DeductionPrice);
if (coupon_id!=null&& !coupon_id.isEmpty()){
goodsOrder.setCouponId(Long.valueOf(coupon_id));
}
goodsOrder.setStatus(1L); // 待支付状态
goodsOrder.setAddressId(addressId);
goodsOrder.setSku(sku);
// 保存商品订单
int insertResult = goodsOrderService.insertGoodsOrder(goodsOrder);
if (insertResult <= 0) {
return AppletControllerUtil.appletWarning("商品订单创建失败,请稍后重试");
}
// 添加到订单列表
Map<String, Object> orderInfo = new HashMap<>();
orderInfo.put("type", "goods");
orderInfo.put("orderId", goodsOrder.getId());
orderInfo.put("orderNo", goodsOrder.getOrderId());
orderInfo.put("productName", serviceGoods.getTitle());
orderInfo.put("price", itemPrice.toString());
orderList.add(orderInfo);
} else {
// 创建服务订单
String makeTime = orderParams.get("make_time") != null ? orderParams.get("make_time").toString() : "";
String fileData = orderParams.get("fileData") != null ? orderParams.get("fileData").toString() : "";
Order order = new Order();
order.setType(1); // 1:服务项目
order.setCreateType(1); // 1用户自主下单
order.setUid(user.getId());
order.setUname(user.getName());
order.setProductId(productId);
order.setProductName(serviceGoods.getTitle());
order.setName(userAddress.getName());
order.setFileData(fileData != null ? JSON.toJSONString(fileData) : null);
order.setPhone(userAddress.getPhone());
order.setAddress(userAddress.getAddressInfo());
order.setAddressId(addressId);
order.setSku(sku);
order.setMainOrderId(mainOrderId);
order.setOrderId(GenerateCustomCode.generCreateOrder("B")); // 独立订单号
// 处理预约时间
if (makeTime != null && !makeTime.isEmpty()) {
String[] makeTimeArr = makeTime.split(" ");
if (makeTimeArr.length == 2) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(makeTimeArr[0]);
order.setMakeTime(date.getTime() / 1000);
order.setMakeHour(makeTimeArr[1]);
} catch (Exception e) {
logger.warn("预约时间格式错误: " + makeTime);
}
}
}
order.setNum(num);
order.setTotalPrice(itemPrice);
order.setGoodPrice(serviceGoods.getPrice());
order.setServicePrice(BigDecimal.ZERO);
order.setPayPrice(itemPrice);
order.setStatus(1L); // 1:待接单
order.setReceiveType(1L); // 1自由抢单
order.setIsAccept(0);
order.setIsComment(0);
order.setIsPause(1);
order.setDeduction(new BigDecimal(0));
// 保存服务订单
int result = orderService.insertOrder(order);
if (result <= 0) {
return AppletControllerUtil.appletWarning("服务订单创建失败,请稍后重试");
}
// 添加订单日志
OrderLog orderLog = new OrderLog();
orderLog.setOid(order.getId());
orderLog.setOrderId(order.getOrderId());
orderLog.setTitle("订单生成");
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", "预约成功,将尽快为主人派单");
orderLog.setType(new BigDecimal(1.0));
orderLog.setContent(jsonObject.toString());
orderLogService.insertOrderLog(orderLog);
// 系统派单和消息通知逻辑
Order orderNewData = orderService.selectOrderById(order.getId());
String wxsendmsg = WXsendMsgUtil.sendMsgForUserInfo(user.getOpenid(), orderNewData, serviceGoods);
Users worker = AppletControllerUtil.creatWorkerForOrder(orderNewData);
if (worker != null) {
// 更新订单状态为已派单
orderNewData.setWorkerId(worker.getId());
orderNewData.setStatus(2l);
orderNewData.setIsPause(1);
orderNewData.setReceiveTime(new Date());
orderNewData.setReceiveType(3l);
orderNewData.setLogStatus(9);
JSONObject jSONObject = new JSONObject();
jSONObject.put("type", 9);
orderNewData.setLogJson(jSONObject.toJSONString());
orderService.updateOrder(orderNewData);
// 添加派单日志
OrderLog orderLognew = new OrderLog();
orderLognew.setOid(orderNewData.getId());
orderLognew.setOrderId(orderNewData.getOrderId());
orderLognew.setTitle("平台派单");
orderLognew.setType(new BigDecimal(1.1));
JSONObject jSONObject1 = new JSONObject();
jSONObject1.put("name", "师傅收到派单信息");
orderLognew.setContent(jSONObject1.toJSONString());
orderLognew.setWorkerId(worker.getId());
orderLognew.setWorkerLogId(worker.getId());
orderLogService.insertOrderLog(orderLognew);
// 发送通知
WXsendMsgUtil.sendMsgForWorkerInfo(worker.getOpenid(), orderNewData, serviceGoods);
YunXinPhoneUtilAPI.httpsAxbTransfer(worker.getPhone());
}
// 添加到订单列表
Map<String, Object> orderInfo = new HashMap<>();
orderInfo.put("type", "service");
orderInfo.put("orderId", order.getId());
orderInfo.put("orderNo", order.getOrderId());
orderInfo.put("productName", serviceGoods.getTitle());
orderInfo.put("price", itemPrice.toString());
orderList.add(orderInfo);
}
}
// 7. 如果有商品订单,需要发起微信支付
boolean hasGoodsOrder = orderList.stream().anyMatch(order -> "goods".equals(order.get("type")));
if (hasGoodsOrder && totalAmount.compareTo(BigDecimal.ZERO) > 0) {
// 使用工具类简化微信支付参数组装
Map<String, Object> payResult = wechatPayUtil.createBatchOrderAndPay(user.getOpenid(), mainOrderId, new BigDecimal(0.01), orderList.size(), wechatPayUtil.PAY_FH+"api/goods/pay/notify");
if (payResult != null && Boolean.TRUE.equals(payResult.get("success"))) {
Map<String, Object> responseData = new HashMap<>();
responseData.put("mainOrderId", mainOrderId);
responseData.put("orderList", orderList);
responseData.put("totalAmount", totalAmount.toString());
responseData.put("prepayId", payResult.get("prepayId"));
// 直接合并所有支付参数
responseData.putAll(payResult);
return AppletControllerUtil.appletSuccess(responseData);
} else {
String errorMsg = payResult != null ? (String) payResult.get("message") : "微信支付下单失败";
return AppletControllerUtil.appletWarning("支付下单失败:" + errorMsg);
}
} else {
// 没有商品订单,只有服务订单,直接返回成功
Map<String, Object> responseData = new HashMap<>();
responseData.put("mainOrderId", mainOrderId);
responseData.put("orderList", orderList);
responseData.put("totalAmount", totalAmount.toString());
return AppletControllerUtil.appletSuccess(responseData);
}
} catch (Exception e) {
logger.error("创建订单异常:", e);
return AppletControllerUtil.appletWarning("创建订单失败:" + e.getMessage());
}
}
/**
* 尾款结算
*/
@PostMapping("api/service/order/pay/total/price")
public AjaxResult apiServiceOrderPayTotalPprice(@RequestBody Map<String, Object> params, HttpServletRequest request) {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 获取用户信息
Users user = (Users) userValidation.get("user");
if (user == null) {
return AppletControllerUtil.appletWarning("用户信息获取失败");
}
// 3. 验证必要参数
if (params == null || params.get("order_id") == null || params.get("worker_id") == null) {
return AppletControllerUtil.appletWarning("参数不能为空");
}
Long worker_id = Long.valueOf(params.get("worker_id").toString());
String order_id = params.get("order_id").toString();
Order order = orderService.selectOrderByOrderId(order_id);
// 2. 查询订单日志取type=5评估报价或最新一条
List<OrderLog> logList = orderLogService.selectOrderLogByOrderId(order.getOrderId());
OrderLog log = null;
for (OrderLog l : logList) {
if (l.getType() != null && l.getType().intValue() == 5) {
log = l;
break;
}
}
if (log == null && !logList.isEmpty()) {
log = logList.get(0);
}
if (log == null) {
return AppletControllerUtil.appletWarning("未找到订单日志");
}
if (params.get("coupon_id")!= null) {
String coupon_id = params.get("coupon_id").toString();
if (coupon_id != null && !coupon_id.isEmpty()) {
CouponUser couponUser = couponUserService.selectCouponUserById(Long.valueOf(coupon_id));
if (couponUser == null && couponUser.getStatus() != 1) {
return AppletControllerUtil.appletWarning("优惠券已被使用,或优惠券不存在");
}
OrderLog orderLogQery = new OrderLog();
orderLogQery.setOrderId(order.getOrderId());
orderLogQery.setType(new BigDecimal(5));
orderLogQery.setWorkerId(worker_id);
OrderLog orderLognew = orderLogService.selectOneByOidTypeWorkerIdPaid(orderLogQery);
if (orderLognew != null) {
orderLognew.setCouponId(couponUser.getCouponId());
orderLognew.setDeduction(new BigDecimal(couponUser.getCouponPrice()));
orderLogService.updateOrderLog(orderLognew);
order.setCouponId(couponUser.getCouponId());
order.setDeduction(new BigDecimal(couponUser.getCouponPrice()));
orderService.updateOrder(order);
}
}
}
Map<String, Object> payResult = wechatPayUtil.createBatchOrderAndPay(
user.getOpenid(),
String.valueOf(order_id),
new BigDecimal(0.01),
1,
wechatPayUtil.PAY_FH+"api/order/amount/pay/notify");
if (payResult != null && Boolean.TRUE.equals(payResult.get("success"))) {
Map<String, Object> responseData = new HashMap<>();
responseData.put("mainOrderId", order_id);
//responseData.put("orderList", orderList);
responseData.put("totalAmount", log.getPrice());
responseData.put("prepayId", payResult.get("prepayId"));
// 直接合并所有支付参数
responseData.putAll(payResult);
return AppletControllerUtil.appletSuccess(responseData);
} else {
String errorMsg = payResult != null ? (String) payResult.get("message") : "微信支付下单失败";
return AppletControllerUtil.appletWarning("支付下单失败:" + errorMsg);
}
}
/**
* 拼团一次性支付接口
*
* 用户参与拼团活动的支付接口
* 创建拼团订单并调用微信支付
*
* 业务逻辑:
* 1. 验证用户登录状态
* 2. 获取商品信息
* 3. 创建拼团订单
* 4. 调用微信支付
*
* @param params 拼团参数id=商品ID
* @param request HTTP请求对象需要包含token
* @return 支付结果
*/
@PostMapping("/group/once_pay")
public AjaxResult apigroupOncePay(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 获取用户信息
Users user = (Users) userValidation.get("user");
if (user == null) {
return AppletControllerUtil.appletWarning("用户信息获取失败");
}
// 3. 验证必要参数
if (params == null || params.get("id") == null) {
return AppletControllerUtil.appletWarning("参数不能为空");
}
// 4. 获取商品信息
Long orderId = Long.valueOf(params.get("id").toString());
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(orderId);
if (serviceGoods == null) {
return AppletControllerUtil.appletWarning("商品信息获取失败");
}
// 5. 创建拼团订单
UserGroupBuying userGroupBuying = new UserGroupBuying();
userGroupBuying.setId(orderId);
userGroupBuying.setUid(user.getId());
userGroupBuying.setStatus(Long.valueOf(4)); // 4=待支付状态
userGroupBuying.setUname(user.getName());
userGroupBuying.setProductId(serviceGoods.getId());
userGroupBuying.setPaytype(Long.valueOf(1)); // 1=微信支付
userGroupBuying.setMoney(serviceGoods.getGroupprice()); // 使用拼团价格
userGroupBuying.setOrderid(GenerateCustomCode.generCreateOrder("G"));
// 6. 保存拼团订单并调用微信支付
int flg = userGroupBuyingService.insertUserGroupBuying(userGroupBuying);
if (flg > 0) {
// 调用微信支付测试环境使用0.01元)
Map<String, Object> payResult = wechatPayUtil.createBatchOrderAndPay(
user.getOpenid(),
userGroupBuying.getId().toString(),
new BigDecimal("0.01"), // 测试金额
1,
WechatPayUtil.PAY_FH + "api/group/pay/notify");
if (payResult != null && Boolean.TRUE.equals(payResult.get("success"))) {
// 构建支付响应数据
Map<String, Object> responseData = new HashMap<>();
responseData.put("mainOrderId", userGroupBuying.getOrderid());
responseData.put("totalAmount", serviceGoods.getGroupprice());
responseData.put("prepayId", payResult.get("prepayId"));
// 合并所有支付参数
responseData.putAll(payResult);
return AppletControllerUtil.appletSuccess(responseData);
} else {
String errorMsg = payResult != null ? (String) payResult.get("message") : "微信支付下单失败";
return AppletControllerUtil.appletWarning("支付下单失败:" + errorMsg);
}
}
return AppletControllerUtil.appletWarning("支付失败");
} catch (Exception e) {
System.err.println("拼团支付异常:" + e.getMessage());
return AppletControllerUtil.appletError("拼团支付失败:" + e.getMessage());
}
}
// ==================== 服务订单支付相关接口 ====================
/**
* 上门费支付接口
* <p>
* 用于支付服务订单的上门费用
* <p>
* 业务逻辑:
* 1. 验证用户登录状态
* 2. 根据订单日志ID获取上门费信息
* 3. 调用微信支付
* 4. 返回支付参数
*
* @param params 请求参数包含id(订单日志ID)
* @param request HTTP请求对象需要包含token
* @return 支付结果包含prepayId等微信支付参数
*/
@PostMapping("/service/order/pay_fee")
public AjaxResult apiServiceOrderPayFee(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 获取用户信息
Users user = (Users) userValidation.get("user");
if (user == null) {
return AppletControllerUtil.appletWarning("用户信息获取失败");
}
// 3. 验证必要参数
if (params == null || params.get("id") == null) {
return AppletControllerUtil.appletWarning("参数不能为空");
}
// 4. 获取订单日志信息
Long orderId = Long.valueOf(params.get("id").toString());
OrderLog orderLog = orderLogService.selectOrderLogById(orderId);
if (orderLog != null) {
logger.info("上门费支付 - 用户ID: {}, 订单日志ID: {}, 上门费: {}",
user.getId(), orderId, orderLog.getPrice());
// 5. 调用微信支付测试环境使用0.01元)
Map<String, Object> payResult = wechatPayUtil.createBatchOrderAndPay(
user.getOpenid(),
String.valueOf(orderLog.getId()),
new BigDecimal("0.01"), // 测试金额
1,
WechatPayUtil.PAY_FH + "api/door/fee/pay/notify");
if (payResult != null && Boolean.TRUE.equals(payResult.get("success"))) {
// 6. 构建支付响应数据
Map<String, Object> responseData = new HashMap<>();
responseData.put("mainOrderId", String.valueOf(orderLog.getId()));
responseData.put("totalAmount", orderLog.getPrice());
responseData.put("prepayId", payResult.get("prepayId"));
// 合并所有支付参数
responseData.putAll(payResult);
return AppletControllerUtil.appletSuccess(responseData);
} else {
String errorMsg = payResult != null ? (String) payResult.get("message") : "微信支付下单失败";
return AppletControllerUtil.appletWarning("支付下单失败:" + errorMsg);
}
} else {
return AppletControllerUtil.appletWarning("订单日志不存在");
}
} catch (Exception e) {
logger.error("上门费支付异常 - 用户ID: {}, 参数: {}, 异常: {}",
request.getHeader("token"), params, e.getMessage());
return AppletControllerUtil.appletError("支付失败:" + e.getMessage());
}
}
/**
* 定金支付接口
* <p>
* 用于支付服务订单的定金
* <p>
* 业务逻辑:
* 1. 验证用户登录状态
* 2. 根据订单日志ID获取定金信息
* 3. 调用微信支付
* 4. 返回支付参数
*
* @param params 请求参数包含id(订单日志ID)
* @param request HTTP请求对象需要包含token
* @return 支付结果包含prepayId等微信支付参数
*/
@PostMapping("/service/order/pay/deposit")
public AjaxResult apiServiceOrderPaydeposit(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 获取用户信息
Users user = (Users) userValidation.get("user");
if (user == null) {
return AppletControllerUtil.appletWarning("用户信息获取失败");
}
// 3. 验证必要参数
if (params == null || params.get("id") == null) {
return AppletControllerUtil.appletWarning("参数不能为空");
}
// 4. 获取订单日志信息
Long orderId = Long.valueOf(params.get("id").toString());
OrderLog orderLog = orderLogService.selectOrderLogById(orderId);
if (orderLog != null) {
logger.info("定金支付 - 用户ID: {}, 订单日志ID: {}, 定金: {}",
user.getId(), orderId, orderLog.getPrice());
// 5. 调用微信支付测试环境使用0.01元)
Map<String, Object> payResult = wechatPayUtil.createBatchOrderAndPay(
user.getOpenid(),
String.valueOf(orderLog.getId()),
new BigDecimal("0.01"), // 测试金额
1,
WechatPayUtil.PAY_FH + "api/deposit/pay/notify");
if (payResult != null && Boolean.TRUE.equals(payResult.get("success"))) {
// 6. 构建支付响应数据
Map<String, Object> responseData = new HashMap<>();
responseData.put("mainOrderId", String.valueOf(orderLog.getId()));
responseData.put("totalAmount", orderLog.getPrice());
responseData.put("prepayId", payResult.get("prepayId"));
// 合并所有支付参数
responseData.putAll(payResult);
return AppletControllerUtil.appletSuccess(responseData);
} else {
String errorMsg = payResult != null ? (String) payResult.get("message") : "微信支付下单失败";
return AppletControllerUtil.appletWarning("支付下单失败:" + errorMsg);
}
} else {
return AppletControllerUtil.appletWarning("订单日志不存在");
}
} catch (Exception e) {
logger.error("定金支付异常 - 用户ID: {}, 参数: {}, 异常: {}",
request.getHeader("token"), params, e.getMessage());
return AppletControllerUtil.appletError("支付失败:" + e.getMessage());
}
}
// ==================== 商品订单支付相关接口 ====================
/**
* 单个商品支付接口
* <p>
* 用于支付单个商品订单
* <p>
* 业务逻辑:
* 1. 验证用户登录状态
* 2. 根据商品订单ID获取订单信息
* 3. 生成主订单号并更新订单
* 4. 调用微信支付
* 5. 返回支付参数
*
* @param params 请求参数包含id(商品订单ID)
* @param request HTTP请求对象需要包含token
* @return 支付结果包含prepayId等微信支付参数
*/
@PostMapping("/goods/order/once_pay")
public AjaxResult apiGoodsOrderOncePay(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 获取用户信息
Users user = (Users) userValidation.get("user");
if (user == null) {
return AppletControllerUtil.appletWarning("用户信息获取失败");
}
// 3. 验证必要参数
if (params == null || params.get("id") == null) {
return AppletControllerUtil.appletWarning("参数不能为空");
}
// 4. 获取商品订单信息
Long orderId = Long.valueOf(params.get("id").toString());
GoodsOrder goodsOrder = goodsOrderService.selectGoodsOrderById(orderId);
logger.info("商品订单支付 - 用户ID: {}, 订单ID: {}", user.getId(), orderId);
logger.info("商品订单详情: {}", goodsOrder);
if (goodsOrder != null) {
// 5. 生成主订单号并更新订单
goodsOrder.setMainOrderId(GenerateCustomCode.generCreateOrder("WXB"));
int updateResult = goodsOrderService.updateGoodsOrder(goodsOrder);
// 6. 修改成功后开始支付流程
if (updateResult > 0) {
logger.info("商品订单更新成功 - 主订单号: {}, 总价: {}",
goodsOrder.getMainOrderId(), goodsOrder.getTotalPrice());
// 7. 调用微信支付测试环境使用0.01元)
Map<String, Object> payResult = wechatPayUtil.createBatchOrderAndPay(
user.getOpenid(),
goodsOrder.getMainOrderId(),
new BigDecimal("0.01"), // 测试金额
1,
WechatPayUtil.PAY_FH + "api/goods/pay/notify");
if (payResult != null && Boolean.TRUE.equals(payResult.get("success"))) {
// 8. 构建支付响应数据
Map<String, Object> responseData = new HashMap<>();
responseData.put("mainOrderId", goodsOrder.getMainOrderId());
responseData.put("totalAmount", goodsOrder.getTotalPrice());
responseData.put("prepayId", payResult.get("prepayId"));
// 合并所有支付参数
responseData.putAll(payResult);
return AppletControllerUtil.appletSuccess(responseData);
} else {
String errorMsg = payResult != null ? (String) payResult.get("message") : "微信支付下单失败";
return AppletControllerUtil.appletWarning("支付下单失败:" + errorMsg);
}
} else {
return AppletControllerUtil.appletWarning("订单更新失败");
}
} else {
return AppletControllerUtil.appletWarning("商品订单不存在");
}
} catch (Exception e) {
logger.error("商品订单支付异常 - 用户ID: {}, 参数: {}, 异常: {}",
request.getHeader("token"), params, e.getMessage());
return AppletControllerUtil.appletError("支付失败:" + e.getMessage());
}
}
/**
* 查询退款结果接口
* <p>
* 主动查询退款的处理状态
* <p>
* 请求参数:
* - refundNo: 退款单号
*
* @param params 查询参数
* @param request HTTP请求对象需要包含token
* @return 退款状态查询结果
*/
@PostMapping("/refund/query")
public AjaxResult queryRefundOrder(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
// 1. 验证用户登录状态
String token = request.getHeader("token");
Map<String, Object> userValidation = AppletLoginUtil.validateUserToken(token, usersService);
if (!(Boolean) userValidation.get("valid")) {
return AppletControllerUtil.appletWarning("用户未登录或token无效");
}
// 2. 验证必要参数
if (params == null || params.get("refundNo") == null) {
return AppletControllerUtil.appletWarning("退款单号不能为空");
}
// 3. 查询退款结果
// 注意如果WechatPayUtil.queryRefund方法不存在请根据实际情况调整
Map<String, Object> queryResult = new HashMap<>();
queryResult.put("success", true);
queryResult.put("message", "退款查询功能待实现");
queryResult.put("refundNo", params.get("refundNo"));
queryResult.put("status", "UNKNOWN");
// 4. 返回结果
boolean success = (Boolean) queryResult.get("success");
if (success) {
return AppletControllerUtil.appletSuccess(queryResult);
} else {
return AppletControllerUtil.appletWarning((String) queryResult.get("message"));
}
} catch (Exception e) {
System.err.println("查询退款结果异常:" + e.getMessage());
return AppletControllerUtil.appletError("查询退款结果失败:" + e.getMessage());
}
}
}