Wallet/pkg/internal/server/api/order_api.go

179 lines
5.5 KiB
Go
Raw Normal View History

2025-02-02 22:20:10 +08:00
package api
import (
"fmt"
"git.solsynth.dev/hypernet/nexus/pkg/nex/sec"
"git.solsynth.dev/hypernet/passport/pkg/authkit"
"git.solsynth.dev/hypernet/wallet/pkg/internal/database"
"git.solsynth.dev/hypernet/wallet/pkg/internal/gap"
"git.solsynth.dev/hypernet/wallet/pkg/internal/models"
"git.solsynth.dev/hypernet/wallet/pkg/internal/server/exts"
"git.solsynth.dev/hypernet/wallet/pkg/internal/services"
"github.com/gofiber/fiber/v2"
"github.com/shopspring/decimal"
2025-02-02 23:17:08 +08:00
"golang.org/x/crypto/bcrypt"
2025-02-02 22:20:10 +08:00
)
func getOrder(c *fiber.Ctx) error {
orderId, _ := c.ParamsInt("orderId")
var order models.Order
if err := database.C.Where("id = ?", orderId).First(&order).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
return c.JSON(order)
}
2025-02-02 22:46:01 +08:00
func createOrder(c *fiber.Ctx) error {
2025-02-02 22:20:10 +08:00
var data struct {
ClientID string `json:"client_id" validate:"required"`
ClientSecret string `json:"client_secret" validate:"required"`
Remark string `json:"remark" validate:"required"`
Amount float64 `json:"amount" validate:"required"`
PayeeID *uint `json:"payee_id"`
PayerID *uint `json:"payer_id"`
}
if err := exts.BindAndValidate(c, &data); err != nil {
return err
}
// Validating client
client, err := authkit.GetThirdClientByAlias(gap.Nx, data.ClientID, &data.ClientSecret)
if err != nil {
return fiber.NewError(fiber.StatusForbidden, fmt.Sprintf("could not get client info: %v", err))
}
order := models.Order{
Status: models.OrderStatusPending,
Remark: data.Remark,
Amount: decimal.NewFromFloat(data.Amount),
ClientID: &client.ID,
}
// System client, spec payee was not allowed
if client.AccountID != nil && data.PayeeID != nil {
var payee models.Wallet
if err := database.C.Where("id = ? AND account_id = ?", data.PayeeID, client.AccountID).First(&payee).Error; err != nil {
2025-02-02 22:20:10 +08:00
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("payee id %d not found", data.PayeeID))
} else {
order.Payee = &payee
order.PayeeID = &payee.ID
}
}
if data.PayerID != nil {
var payer models.Wallet
if err := database.C.Where("id = ?", data.PayerID).First(&payer).Error; err != nil {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("payer id %d not found", data.PayerID))
} else {
order.Payer = &payer
order.PayerID = &payer.ID
}
}
if err := database.C.Create(&order).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
return c.JSON(order)
}
func payOrder(c *fiber.Ctx) error {
if err := sec.EnsureAuthenticated(c); err != nil {
return err
}
2025-02-03 00:30:58 +08:00
user := c.Locals("nex_user").(*sec.UserInfo)
2025-02-02 22:20:10 +08:00
orderId, _ := c.ParamsInt("orderId")
2025-02-02 23:17:08 +08:00
var data struct {
WalletPassword string `json:"wallet_password" validate:"required"`
}
if err := exts.BindAndValidate(c, &data); err != nil {
return err
}
2025-02-02 22:20:10 +08:00
var order models.Order
if err := database.C.Where("id = ?", orderId).First(&order).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
var payer *models.Wallet
if order.PayerID != nil {
if err := database.C.Where("id = ?", order.PayerID).First(&payer).Error; err != nil {
return fiber.NewError(fiber.StatusBadRequest, "order payer wallet was not found")
} else if payer.AccountID != user.ID {
return fiber.NewError(fiber.StatusForbidden, "the order cannot paid by you")
}
} else {
2025-02-03 00:34:51 +08:00
if err := database.C.Where("account_id = ?", user.ID).First(&payer).Error; err != nil {
2025-02-02 22:20:10 +08:00
return fiber.NewError(fiber.StatusBadRequest, "account wallet was not found")
}
}
2025-02-02 23:17:08 +08:00
if payer != nil {
if bcrypt.CompareHashAndPassword([]byte(payer.Password), []byte(data.WalletPassword)) != nil {
return fiber.NewError(fiber.StatusForbidden, "invalid wallet password")
}
}
2025-02-02 22:20:10 +08:00
var payee *models.Wallet
if order.PayeeID != nil {
if err := database.C.Where("id = ?", order.PayeeID).First(&payee).Error; err != nil {
return fiber.NewError(fiber.StatusBadRequest, "order payee wallet was not found")
}
}
if tran, err := services.MakeTransaction(order.Amount.InexactFloat64(), order.Remark, payer, payee); err != nil {
return fiber.NewError(fiber.StatusPaymentRequired, err.Error())
} else {
if err := database.C.Model(&order).Updates(&models.Order{
Status: models.OrderStatusPaid,
TransactionID: &tran.ID,
}).Error; err != nil {
// Do refund
_, _ = services.MakeTransaction(
order.Amount.InexactFloat64(),
fmt.Sprintf("%s - #%d Refund", order.Remark, order.ID),
payee,
payer,
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
}
return c.JSON(order)
}
2025-02-03 13:23:45 +08:00
func cancelOrder(c *fiber.Ctx) error {
var data struct {
ClientID string `json:"client_id" validate:"required"`
ClientSecret string `json:"client_secret" validate:"required"`
}
orderId, _ := c.ParamsInt("orderId")
if err := exts.BindAndValidate(c, &data); err != nil {
return err
}
// Validating client
client, err := authkit.GetThirdClientByAlias(gap.Nx, data.ClientID, &data.ClientSecret)
if err != nil {
return fiber.NewError(fiber.StatusForbidden, fmt.Sprintf("could not get client info: %v", err))
}
var order models.Order
if err := database.C.Where("id = ? AND client_id = ?", orderId, client.ID).First(&order).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
if err := database.C.Model(&order).Updates(&models.Order{Status: models.OrderStatusCanceled}).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
return c.JSON(order)
}