微信支付
This commit is contained in:
@@ -2,7 +2,9 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -19,12 +21,12 @@ import (
|
||||
|
||||
// FinanceHandler 财务HTTP处理器
|
||||
type FinanceHandler struct {
|
||||
appService finance.FinanceApplicationService
|
||||
invoiceAppService finance.InvoiceApplicationService
|
||||
adminInvoiceAppService finance.AdminInvoiceApplicationService
|
||||
responseBuilder interfaces.ResponseBuilder
|
||||
validator interfaces.RequestValidator
|
||||
logger *zap.Logger
|
||||
appService finance.FinanceApplicationService
|
||||
invoiceAppService finance.InvoiceApplicationService
|
||||
adminInvoiceAppService finance.AdminInvoiceApplicationService
|
||||
responseBuilder interfaces.ResponseBuilder
|
||||
validator interfaces.RequestValidator
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewFinanceHandler 创建财务HTTP处理器
|
||||
@@ -201,6 +203,123 @@ func (h *FinanceHandler) HandleAlipayCallback(c *gin.Context) {
|
||||
c.String(200, "success")
|
||||
}
|
||||
|
||||
// HandleWechatPayCallback 处理微信支付回调
|
||||
// @Summary 微信支付回调
|
||||
// @Description 处理微信支付异步通知
|
||||
// @Tags 支付管理
|
||||
// @Accept application/json
|
||||
// @Produce text/plain
|
||||
// @Success 200 {string} string "success"
|
||||
// @Failure 400 {string} string "fail"
|
||||
// @Router /api/v1/pay/wechat/callback [post]
|
||||
func (h *FinanceHandler) HandleWechatPayCallback(c *gin.Context) {
|
||||
// 记录回调请求信息
|
||||
h.logger.Info("收到微信支付回调请求",
|
||||
zap.String("method", c.Request.Method),
|
||||
zap.String("url", c.Request.URL.String()),
|
||||
zap.String("remote_addr", c.ClientIP()),
|
||||
zap.String("user_agent", c.GetHeader("User-Agent")),
|
||||
zap.String("content_type", c.GetHeader("Content-Type")),
|
||||
)
|
||||
|
||||
// 读取请求体内容用于调试(注意:读取后需要重新设置,否则后续解析会失败)
|
||||
bodyBytes, err := c.GetRawData()
|
||||
if err == nil && len(bodyBytes) > 0 {
|
||||
h.logger.Info("微信支付回调请求体",
|
||||
zap.String("body", string(bodyBytes)),
|
||||
zap.Int("body_size", len(bodyBytes)),
|
||||
)
|
||||
// 重新设置请求体,供后续解析使用
|
||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
}
|
||||
|
||||
// 通过应用服务处理微信支付回调
|
||||
err = h.appService.HandleWechatPayCallback(c.Request.Context(), c.Request)
|
||||
if err != nil {
|
||||
h.logger.Error("微信支付回调处理失败",
|
||||
zap.Error(err),
|
||||
zap.String("remote_addr", c.ClientIP()),
|
||||
)
|
||||
c.String(400, "fail")
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("微信支付回调处理成功", zap.String("remote_addr", c.ClientIP()))
|
||||
// 返回成功响应(微信要求返回success)
|
||||
c.String(200, "success")
|
||||
}
|
||||
|
||||
// HandleWechatRefundCallback 处理微信退款回调
|
||||
// @Summary 微信退款回调
|
||||
// @Description 处理微信退款异步通知
|
||||
// @Tags 支付管理
|
||||
// @Accept application/json
|
||||
// @Produce text/plain
|
||||
// @Success 200 {string} string "success"
|
||||
// @Failure 400 {string} string "fail"
|
||||
// @Router /api/v1/wechat/refund_callback [post]
|
||||
func (h *FinanceHandler) HandleWechatRefundCallback(c *gin.Context) {
|
||||
// 记录回调请求信息
|
||||
h.logger.Info("收到微信退款回调请求",
|
||||
zap.String("method", c.Request.Method),
|
||||
zap.String("url", c.Request.URL.String()),
|
||||
zap.String("remote_addr", c.ClientIP()),
|
||||
zap.String("user_agent", c.GetHeader("User-Agent")),
|
||||
)
|
||||
|
||||
// 通过应用服务处理微信退款回调
|
||||
err := h.appService.HandleWechatRefundCallback(c.Request.Context(), c.Request)
|
||||
if err != nil {
|
||||
h.logger.Error("微信退款回调处理失败", zap.Error(err))
|
||||
c.String(400, "fail")
|
||||
return
|
||||
}
|
||||
|
||||
// 返回成功响应(微信要求返回success)
|
||||
c.String(200, "success")
|
||||
}
|
||||
|
||||
// GetWechatOrderStatus 获取微信订单状态
|
||||
// @Summary 获取微信订单状态
|
||||
// @Description 根据商户订单号查询微信订单状态
|
||||
// @Tags 钱包管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param out_trade_no query string true "商户订单号"
|
||||
// @Success 200 {object} responses.WechatOrderStatusResponse "获取订单状态成功"
|
||||
// @Failure 400 {object} map[string]interface{} "请求参数错误"
|
||||
// @Failure 401 {object} map[string]interface{} "未认证"
|
||||
// @Failure 404 {object} map[string]interface{} "订单不存在"
|
||||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||||
// @Router /api/v1/finance/wallet/wechat-order-status [get]
|
||||
func (h *FinanceHandler) GetWechatOrderStatus(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
if userID == "" {
|
||||
h.responseBuilder.Unauthorized(c, "用户未登录")
|
||||
return
|
||||
}
|
||||
|
||||
outTradeNo := c.Query("out_trade_no")
|
||||
if outTradeNo == "" {
|
||||
h.responseBuilder.BadRequest(c, "缺少商户订单号")
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.appService.GetWechatOrderStatus(c.Request.Context(), outTradeNo)
|
||||
if err != nil {
|
||||
h.logger.Error("获取微信订单状态失败",
|
||||
zap.String("user_id", userID),
|
||||
zap.String("out_trade_no", outTradeNo),
|
||||
zap.Error(err),
|
||||
)
|
||||
h.responseBuilder.BadRequest(c, "获取订单状态失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.responseBuilder.Success(c, result, "获取订单状态成功")
|
||||
}
|
||||
|
||||
// HandleAlipayReturn 处理支付宝同步回调
|
||||
// @Summary 支付宝同步回调
|
||||
// @Description 处理支付宝同步支付通知,跳转到前端成功页面
|
||||
@@ -240,7 +359,7 @@ func (h *FinanceHandler) HandleAlipayReturn(c *gin.Context) {
|
||||
// 通过应用服务处理同步回调,查询订单状态
|
||||
orderStatus, err := h.appService.HandleAlipayReturn(c.Request.Context(), outTradeNo)
|
||||
if err != nil {
|
||||
h.logger.Error("支付宝同步回调处理失败",
|
||||
h.logger.Error("支付宝同步回调处理失败",
|
||||
zap.String("out_trade_no", outTradeNo),
|
||||
zap.Error(err))
|
||||
h.redirectToFailPage(c, outTradeNo, "订单处理失败")
|
||||
@@ -257,7 +376,7 @@ func (h *FinanceHandler) HandleAlipayReturn(c *gin.Context) {
|
||||
switch orderStatus {
|
||||
case "TRADE_SUCCESS":
|
||||
// 支付成功,跳转到前端成功页面
|
||||
successURL := fmt.Sprintf("%s/finance/wallet/success?out_trade_no=%s&trade_no=%s&amount=%s",
|
||||
successURL := fmt.Sprintf("%s/finance/wallet/success?out_trade_no=%s&trade_no=%s&amount=%s",
|
||||
frontendDomain, outTradeNo, tradeNo, totalAmount)
|
||||
c.Redirect(http.StatusFound, successURL)
|
||||
case "WAIT_BUYER_PAY":
|
||||
@@ -275,8 +394,8 @@ func (h *FinanceHandler) redirectToFailPage(c *gin.Context, outTradeNo, reason s
|
||||
if gin.Mode() == gin.DebugMode {
|
||||
frontendDomain = "http://localhost:5173"
|
||||
}
|
||||
|
||||
failURL := fmt.Sprintf("%s/finance/wallet/fail?out_trade_no=%s&reason=%s",
|
||||
|
||||
failURL := fmt.Sprintf("%s/finance/wallet/fail?out_trade_no=%s&reason=%s",
|
||||
frontendDomain, outTradeNo, reason)
|
||||
c.Redirect(http.StatusFound, failURL)
|
||||
}
|
||||
@@ -287,8 +406,8 @@ func (h *FinanceHandler) redirectToProcessingPage(c *gin.Context, outTradeNo, am
|
||||
if gin.Mode() == gin.DebugMode {
|
||||
frontendDomain = "http://localhost:5173"
|
||||
}
|
||||
|
||||
processingURL := fmt.Sprintf("%s/finance/wallet/processing?out_trade_no=%s&amount=%s",
|
||||
|
||||
processingURL := fmt.Sprintf("%s/finance/wallet/processing?out_trade_no=%s&amount=%s",
|
||||
frontendDomain, outTradeNo, amount)
|
||||
c.Redirect(http.StatusFound, processingURL)
|
||||
}
|
||||
@@ -319,7 +438,6 @@ func (h *FinanceHandler) CreateAlipayRecharge(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 调用应用服务进行完整的业务流程编排
|
||||
result, err := h.appService.CreateAlipayRechargeOrder(c.Request.Context(), &cmd)
|
||||
if err != nil {
|
||||
@@ -343,6 +461,53 @@ func (h *FinanceHandler) CreateAlipayRecharge(c *gin.Context) {
|
||||
h.responseBuilder.Success(c, result, "支付宝充值订单创建成功")
|
||||
}
|
||||
|
||||
// CreateWechatRecharge 创建微信充值订单
|
||||
// @Summary 创建微信充值订单
|
||||
// @Description 创建微信充值订单并返回预支付数据
|
||||
// @Tags 钱包管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param request body commands.CreateWechatRechargeCommand true "微信充值请求"
|
||||
// @Success 200 {object} responses.WechatRechargeOrderResponse "创建充值订单成功"
|
||||
// @Failure 400 {object} map[string]interface{} "请求参数错误"
|
||||
// @Failure 401 {object} map[string]interface{} "未认证"
|
||||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||||
// @Router /api/v1/finance/wallet/wechat-recharge [post]
|
||||
func (h *FinanceHandler) CreateWechatRecharge(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
if userID == "" {
|
||||
h.responseBuilder.Unauthorized(c, "用户未登录")
|
||||
return
|
||||
}
|
||||
|
||||
var cmd commands.CreateWechatRechargeCommand
|
||||
cmd.UserID = userID
|
||||
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.appService.CreateWechatRechargeOrder(c.Request.Context(), &cmd)
|
||||
if err != nil {
|
||||
h.logger.Error("创建微信充值订单失败",
|
||||
zap.String("user_id", userID),
|
||||
zap.String("amount", cmd.Amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
h.responseBuilder.BadRequest(c, "创建微信充值订单失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("微信充值订单创建成功",
|
||||
zap.String("user_id", userID),
|
||||
zap.String("out_trade_no", result.OutTradeNo),
|
||||
zap.String("amount", cmd.Amount),
|
||||
zap.String("platform", cmd.Platform),
|
||||
)
|
||||
|
||||
h.responseBuilder.Success(c, result, "微信充值订单创建成功")
|
||||
}
|
||||
|
||||
// TransferRecharge 管理员对公转账充值
|
||||
func (h *FinanceHandler) TransferRecharge(c *gin.Context) {
|
||||
var cmd commands.TransferRechargeCommand
|
||||
@@ -849,8 +1014,6 @@ func (h *FinanceHandler) ApproveInvoiceApplication(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
h.responseBuilder.Success(c, nil, "通过发票申请成功")
|
||||
}
|
||||
|
||||
@@ -932,14 +1095,14 @@ func (h *FinanceHandler) AdminDownloadInvoiceFile(c *gin.Context) {
|
||||
// @Router /api/v1/debug/event-system [post]
|
||||
func (h *FinanceHandler) DebugEventSystem(c *gin.Context) {
|
||||
h.logger.Info("🔍 请求事件系统调试信息")
|
||||
|
||||
|
||||
// 这里可以添加事件系统的状态信息
|
||||
// 暂时返回基本信息
|
||||
debugInfo := map[string]interface{}{
|
||||
"timestamp": time.Now().Format("2006-01-02 15:04:05"),
|
||||
"message": "事件系统调试端点已启用",
|
||||
"handler": "FinanceHandler",
|
||||
"message": "事件系统调试端点已启用",
|
||||
"handler": "FinanceHandler",
|
||||
}
|
||||
|
||||
|
||||
h.responseBuilder.Success(c, debugInfo, "事件系统调试信息")
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -11,9 +13,6 @@ import (
|
||||
"tyapi-server/internal/application/product/dto/queries"
|
||||
"tyapi-server/internal/application/product/dto/responses"
|
||||
"tyapi-server/internal/shared/interfaces"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// ProductAdminHandler 产品管理员HTTP处理器
|
||||
@@ -1338,7 +1337,7 @@ func (h *ProductAdminHandler) ExportAdminWalletTransactions(c *gin.Context) {
|
||||
// @Param page query int false "页码" default(1)
|
||||
// @Param page_size query int false "每页数量" default(10)
|
||||
// @Param user_id query string false "用户ID"
|
||||
// @Param recharge_type query string false "充值类型" Enums(alipay, transfer, gift)
|
||||
// @Param recharge_type query string false "充值类型" Enums(alipay, wechat, transfer, gift)
|
||||
// @Param status query string false "状态" Enums(pending, success, failed)
|
||||
// @Param min_amount query string false "最小金额"
|
||||
// @Param max_amount query string false "最大金额"
|
||||
@@ -1425,7 +1424,7 @@ func (h *ProductAdminHandler) GetAdminRechargeRecords(c *gin.Context) {
|
||||
// @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/csv
|
||||
// @Security Bearer
|
||||
// @Param user_ids query string false "用户ID列表,逗号分隔"
|
||||
// @Param recharge_type query string false "充值类型" Enums(alipay, transfer, gift)
|
||||
// @Param recharge_type query string false "充值类型" Enums(alipay, wechat, transfer, gift)
|
||||
// @Param status query string false "状态" Enums(pending, success, failed)
|
||||
// @Param start_time query string false "开始时间" format(date-time)
|
||||
// @Param end_time query string false "结束时间" format(date-time)
|
||||
|
||||
Reference in New Issue
Block a user