package api import ( "bytes" "encoding/json" "fmt" "github.com/gin-gonic/gin" "github.com/smartwalle/alipay/v3" "io" "jypay/errors" "jypay/global" "jypay/model" "jypay/request" "jypay/utils" "log" "net/http" "strconv" "time" ) func Index(c *gin.Context) (utils.Data, error) { return utils.Data{"hello": "elf"}, nil } func Error(c *gin.Context) (utils.Data, error) { return nil, errors.NewBusinessError("测试", "1122") } func Pay(c *gin.Context) (utils.Data, error) { req := request.OrderRequest{} err := c.BindJSON(&req) if err != nil { fmt.Printf("bind json err:%v", err) return nil, errors.NewBusinessError("参数错误") } order, err := saveOrder(req) if err != nil { return nil, err } var param = alipay.TradeWapPay{} param.OutTradeNo = order.OrderNo param.TotalAmount = strconv.FormatFloat(order.PayAmount, 'E', -1, 64) param.Subject = order.Subject param.NotifyURL = global.Config.Server.Domain + "/notify" param.ReturnURL = global.Config.Server.Domain + "/return" client, err := alipay.New(global.Config.Alipay.AppId, global.Config.Alipay.PrivateKey, true) if err != nil { return nil, errors.NewBusinessError("初始化支付宝失败") } result, err := client.TradeWapPay(param) if err != nil { return nil, errors.NewBusinessError("请求支付宝失败:" + err.Error()) } fmt.Println(result.String()) data := utils.Data{ "pay_url": result.String(), } return data, nil } func saveOrder(req request.OrderRequest) (*model.Order, error) { if req.OrderNo == "" { return nil, errors.NewBusinessError("订单号[orderNo]不能为空") } order := model.Order{} global.DB.Where("order_no = ?", req.OrderNo).First(&order) order.OrderNo = req.OrderNo order.UserId = req.UserId order.UserAccount = req.UserAccount order.GameId = req.GameId order.GameName = req.GameName order.ServerId = req.ServerId order.ServerName = req.ServerName order.Subject = req.Subject order.RoleId = req.RoleId order.RoleName = req.RoleName order.PayAmount = float64(req.PayAmount) / 100 order.NotifyUrl = req.NotifyUrl order.ReturnUrl = req.ReturnUrl order.PromoteId = req.PromoteId order.PromoteAccount = req.PromoteAccount order.PayStatus = 0 result := global.DB.Create(&order) if result.Error != nil { return nil, errors.NewBusinessError("数据异常") } return &order, nil } func Notify(c *gin.Context) { err := c.Request.ParseForm() if err != nil { log.Printf("参数错误:%v", err) return } client, err := alipay.New(global.Config.Alipay.AppId, global.Config.Alipay.PrivateKey, true) if err != nil { log.Printf("初始化支付宝失败:%v", err) return } notification, err := client.DecodeNotification(c.Request.Form) if err != nil { log.Printf("解析异步通知发生错误:%v", err) return } order := model.Order{} tx := global.DB.Where("order_no = ?", notification.OutTradeNo).First(&order) if tx.Error != nil { log.Printf("订单不存在:%s", notification.OutTradeNo) return } now := time.Now() if notification.TradeStatus == "TRADE_SUCCESS" || notification.TradeStatus == "TRADE_FINISHED" { order.PayStatus = 1 order.PayTime = &now tx := global.DB.Save(order) if tx.Error != nil { log.Printf("更新订单失败:%s", notification.OutTradeNo) return } } notifyData := make(map[string]interface{}) notifyData["trade_no"] = notification.TradeNo notifyData["out_trade_no"] = notification.OutTradeNo notifyData["trade_status"] = notification.TradeStatus notifyData["total_amount"] = notification.TotalAmount notifyResult := postToSdk(order.NotifyUrl, notifyData) if notifyResult == "success" { client.ACKNotification(c.Writer) } } func postToSdk(url string, data map[string]interface{}) string { content, err := json.Marshal(data) if err != nil { log.Fatalf("无法编码JSON数据:%v", err) return "fail" } client := &http.Client{} req, err := http.NewRequest("POST", url, bytes.NewBuffer(content)) if err != nil { log.Fatalf("无法创建新的请求:%v", err) return "fail" } req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { log.Fatalf("无法发送POST请求:%v", err) return "fail" } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { log.Fatalf("无法读取响应体内容:%v", err) return "fail" } return string(body) } func Return(c *gin.Context) { var req request.ReturnRequest // 将路由参数绑定到结构体中 if err := c.ShouldBindUri(&req); err != nil { c.Writer.WriteHeader(http.StatusOK) c.Writer.Write([]byte("参数错误")) return } order := model.Order{} tx := global.DB.Where("order_no = ?", req.OrderNo).First(&order) if tx.Error != nil { c.Writer.WriteHeader(http.StatusOK) c.Writer.Write([]byte("订单不存在")) return } c.Redirect(http.StatusFound, order.ReturnUrl) }