|
|
|
|
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)
|
|
|
|
|
}
|