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

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