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());
+ }
+ }
+
+ /**
+ * 创建代付订单接口
+ *
+ * 为其他用户代付功能,如师傅代付、团购代付等
+ *
+ * 业务逻辑:
+ * 1. 验证用户登录状态
+ * 2. 创建代付订单
+ * 3. 返回支付参数
+ *
+ * 请求参数:
+ * - payerOpenid: 代付人openid
+ * - orderNo: 商户订单号
+ * - totalFee: 支付金额(分)
+ * - body: 商品描述
+ * - notifyUrl: 支付回调地址
+ * - remark: 代付备注
+ *
+ * @param params 代付参数
+ * @param request HTTP请求对象(需要包含token)
+ * @return 代付结果,包含支付参数
+ */
+ @PostMapping("/payfor")
+ public AjaxResult createPayForOrder(@RequestBody Map params, HttpServletRequest request) {
+ try {
+ // 1. 验证用户登录状态
+ String token = request.getHeader("token");
+ Map 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 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());
+ }
+ }
+
+ // ==================== 支付回调相关接口 ====================
+
+ /**
+ * 微信支付回调接口
+ *
+ * 接收微信支付服务器的支付结果通知
+ *
+ * 重要说明:
+ * 1. 此接口供微信服务器回调使用,不需要用户认证
+ * 2. 返回格式必须是XML格式,用于告知微信处理结果
+ * 3. 必须在15秒内响应,否则微信会重复发送通知
+ * 4. 需要验证签名确保数据安全
+ *
+ * 业务逻辑:
+ * 1. 接收并验证微信支付回调数据
+ * 2. 处理支付成功的业务逻辑
+ * 3. 返回XML格式的响应给微信
+ *
+ * @param request HTTP请求对象(包含微信回调的XML数据)
+ * @return XML格式的处理结果响应
+ */
+ @PostMapping("/notify")
+ public String handlePayNotify(HttpServletRequest request) {
+ try {
+ // 1. 处理支付回调
+ Map notifyResult = wechatPayUtil.handlePayNotify(request);
+
+ // 2. 获取支付信息
+ boolean success = (Boolean) notifyResult.get("success");
+ if (success) {
+ Map paymentInfo = (Map) 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 "";
+ }
+ }
+
+ // ==================== 退款相关接口 ====================
+
+ /**
+ * 申请退款接口
+ *
+ * 对已支付的订单申请退款
+ *
+ * 业务逻辑:
+ * 1. 验证用户登录状态
+ * 2. 验证退款参数
+ * 3. 调用微信退款API
+ * 4. 返回退款结果
+ *
+ * 请求参数格式:
+ * {
+ * "orderNo": "原订单号",
+ * "refundNo": "退款单号",
+ * "totalFee": 订单总金额(分),
+ * "refundFee": 退款金额(分),
+ * "refundDesc": "退款原因"
+ * }
+ *
+ * 注意事项:
+ * - 退款金额不能超过原订单金额
+ * - 退款单号必须唯一
+ * - 退款成功后资金会原路返回
+ *
+ * @param params 退款参数
+ * @param request HTTP请求对象(需要包含token)
+ * @return 退款结果
+ */
+ @PostMapping("/refund")
+ public AjaxResult refundOrder(@RequestBody Map params, HttpServletRequest request) {
+ try {
+ // 1. 验证用户登录状态
+ String token = request.getHeader("token");
+ Map 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 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());
+ }
+ }
+
+ // ==================== 支付查询相关接口 ====================
+
+ /**
+ * 查询支付结果接口
+ *
+ * 主动查询订单的支付状态
+ * 用于确认支付结果或处理异常情况
+ *
+ * 请求参数:
+ * - orderNo: 商户订单号
+ *
+ * @param params 查询参数
+ * @param request HTTP请求对象(需要包含token)
+ * @return 支付状态查询结果
+ */
+ @PostMapping("/query")
+ public AjaxResult queryPayOrder(@RequestBody Map params, HttpServletRequest request) {
+ try {
+ // 1. 验证用户登录状态
+ String token = request.getHeader("token");
+ Map 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 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());
+ }
+ }
+
+
+ // ==================== 会员充值相关接口 ====================
+
+ /**
+ * 会员充值支付接口
+ *
+ * 支持两种充值方式:
+ * 1. 通过充值套餐ID充值(优先级更高)
+ * 2. 通过自定义金额充值
+ *
+ * 业务逻辑:
+ * - 如果id和money都有值,优先使用id充值套餐
+ * - 如果只有money有值,使用自定义金额充值
+ * - 生成充值记录并调用微信支付
+ *
+ * @param params 请求参数,包含id(充值类目ID)、money(充值金额)
+ * @param request HTTP请求对象(需要包含token)
+ * @return 支付结果,包含prepayId等微信支付参数
+ */
+ @PostMapping("/member/recharge/pay")
+ public AjaxResult memberRechargePay(@RequestBody Map params, HttpServletRequest request) {
+ try {
+ // 1. 验证用户登录状态
+ String token = request.getHeader("token");
+ Map 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 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 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 params, HttpServletRequest request) {
+ try {
+ // 1. 验证用户登录状态
+ String token = request.getHeader("token");
+ Map 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