You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
5.8 KiB
Go

11 months ago
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())
}
11 months ago
11 months ago
fmt.Println(result.String())
11 months ago
order.PayUrl = result.String()
order.Token = utils.Md5(order.OrderNo + strconv.Itoa(order.UserId) + strconv.FormatInt(time.Now().Unix(), 10))
global.DB.Save(order)
11 months ago
data := utils.Data{
11 months ago
"pay_url": global.Config.Server.Domain + "/payment/" + order.Token
11 months ago
}
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)
}
}
11 months ago
func TestPost(c *gin.Context) (utils.Data, error) {
notifyData := make(map[string]interface{})
notifyData["trade_no"] = "112233"
notifyData["out_trade_no"] = "2222222"
notifyData["trade_status"] = "1"
notifyData["total_amount"] = "11.11"
notifyResult := postToSdk("https://api.jianghuifa.cn/callback.php/Notify/kd_callback", notifyData)
return utils.Data{"hello": notifyResult}, nil
}
11 months ago
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)
}
11 months ago
func Payment(c *gin.Context) {
var req request.PaymentRequest
// 将路由参数绑定到结构体中
if err := c.ShouldBindUri(&req); err != nil {
c.Writer.WriteHeader(http.StatusOK)
c.Writer.Write([]byte("参数错误"))
return
}
order := model.Order{}
tx := global.DB.Where("token = ?", req.Token).First(&order)
if tx.Error != nil {
c.Writer.WriteHeader(http.StatusOK)
c.Writer.Write([]byte("订单不存在"))
return
}
c.Redirect(http.StatusFound, order.PayUrl)
}