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.

218 lines
5.6 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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, 'f', -1, 64)
param.Subject = order.Subject
token := utils.Md5(order.OrderNo + strconv.Itoa(order.UserId) + strconv.FormatInt(time.Now().Unix(), 10))
param.NotifyURL = global.Config.Server.Domain + "/notify"
param.ReturnURL = global.Config.Server.Domain + "/return?token=" + token
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())
order.PayUrl = result.String()
order.Token = token
global.DB.Save(&order)
data := utils.Data{
"pay_url": global.Config.Server.Domain + "/payment?token=" + token,
}
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
}
client.LoadAliPayPublicKey(global.Config.Alipay.AliPublicKey)
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 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
}
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) {
token := c.Query("token")
order := model.Order{}
tx := global.DB.Where("token = ?", token).First(&order)
if tx.Error != nil {
c.Writer.WriteHeader(http.StatusOK)
c.Writer.Write([]byte("订单不存在"))
return
}
c.Redirect(http.StatusMovedPermanently, order.ReturnUrl)
}
func Payment(c *gin.Context) {
token := c.Query("token")
order := model.Order{}
tx := global.DB.Where("token = ?", token).First(&order)
fmt.Println(tx)
if tx.Error != nil {
fmt.Println(tx.Error)
c.Writer.WriteHeader(http.StatusOK)
c.Writer.Write([]byte("订单不存在"))
return
}
c.Redirect(http.StatusMovedPermanently, order.PayUrl)
}