-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added functionality of creating transactions
- Loading branch information
1 parent
f5c92ee
commit 9943153
Showing
14 changed files
with
329 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,12 @@ | ||
package api | ||
|
||
import db "wss-payment/internal/database" | ||
import ( | ||
db "wss-payment/internal/database" | ||
"wss-payment/pkg/idpay" | ||
) | ||
|
||
// API contains the data needed to operate the endpoints | ||
type API struct { | ||
Database db.PaymentDatabase | ||
Database db.PaymentDatabase | ||
PaymentService idpay.PaymentService | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,53 @@ | ||
package api | ||
|
||
import ( | ||
"errors" | ||
"github.com/gin-gonic/gin" | ||
log "github.com/sirupsen/logrus" | ||
"gorm.io/gorm" | ||
"net/http" | ||
"wss-payment/internal/database" | ||
) | ||
|
||
// GetGoods gets all goods registered in database | ||
func (api *API) GetGoods(c *gin.Context) { | ||
goods, err := api.Database.GetGoods() | ||
if err != nil { | ||
log.WithError(err).Error("cannot get goods") | ||
c.JSON(http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
c.JSON(http.StatusOK, goods) | ||
} | ||
|
||
// AddGood adds a good to server | ||
func (api *API) AddGood(c *gin.Context) { | ||
// Parse body | ||
var body createGoodRequest | ||
err := c.BindJSON(&body) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, err.Error()) | ||
return | ||
} | ||
logger := log.WithField("body", body) | ||
// Create it in database | ||
good := database.Good{ | ||
Name: body.Name, | ||
Price: body.Price, | ||
Description: body.Description, | ||
} | ||
err = api.Database.AddGood(&good) | ||
if err != nil { | ||
if errors.Is(err, gorm.ErrDuplicatedKey) { | ||
logger.Warn("good already exists") | ||
c.JSON(http.StatusConflict, "good already exists") | ||
} else { | ||
logger.WithError(err).Error("cannot insert body in database") | ||
c.JSON(http.StatusInternalServerError, err.Error()) | ||
} | ||
return | ||
} | ||
logger.Info("added good to database") | ||
// Report back to endpoint | ||
c.JSON(http.StatusCreated, creteGoodResponse{good.ID}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,52 @@ | ||
package api | ||
|
||
import "github.com/google/uuid" | ||
|
||
// createTransactionRequest is the request body for create transaction endpoint | ||
type createTransactionRequest struct { | ||
// Who is creating this transaction? | ||
UserID uint64 `json:"user_id" binding:"required"` | ||
// How much this user should pay? | ||
// This value should be more than zero | ||
ToPayAmount uint64 `json:"to_pay_amount" binding:"required,gte=1"` | ||
// How much discount this user had? (this is only stored in database for logs) | ||
Discount uint64 `json:"discount_amount"` | ||
// An optional description | ||
Description string `json:"description"` | ||
// What are the stuff this use is buying? | ||
BuyingGoods []string `json:"buying_goods" binding:"required"` | ||
// Name is only used to send it to payment service | ||
Name string `json:"name"` | ||
// Phone is only used to send it to payment service | ||
Phone string `json:"phone"` | ||
// The mail of user. Only used to send it to payment service | ||
Mail string `json:"mail"` | ||
// Where we should return the user after they have paid? | ||
CallbackURL string `json:"callback_url" binding:"required"` | ||
} | ||
|
||
// The response of create transaction endpoint if everything goes fine | ||
type createTransactionResponse struct { | ||
// The order ID created by us | ||
OrderID uuid.UUID `json:"order_id"` | ||
// The ID returned from idpay | ||
ID string `json:"id"` | ||
// Where should we redirect the user? | ||
RedirectURL string `json:"redirect_url"` | ||
} | ||
|
||
// createTransactionRequest is the request body for creating goods endpoint | ||
type createGoodRequest struct { | ||
// Name of it | ||
Name string `json:"name" binding:"required"` | ||
// The price of this item | ||
Price uint64 `json:"price" binding:"required,gte=1"` | ||
// An optional description about this payment | ||
Description string `json:"description"` | ||
} | ||
|
||
// createTransactionRequest is the result of creating goods endpoint | ||
type creteGoodResponse struct { | ||
// ID of the created good | ||
ID uint32 `json:"id"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package database | ||
|
||
// GoodNotFoundError is returned if a specific good is not found | ||
type GoodNotFoundError struct { | ||
GoodName string | ||
} | ||
|
||
func (err GoodNotFoundError) Error() string { | ||
return "cannot find good: " + err.GoodName | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,53 @@ | ||
package database | ||
|
||
import ( | ||
"github.com/go-faster/errors" | ||
"github.com/google/uuid" | ||
log "github.com/sirupsen/logrus" | ||
"gorm.io/gorm" | ||
) | ||
|
||
// GetGoods gets the list of all goods in database | ||
func (db PaymentDatabase) GetGoods() ([]Good, error) { | ||
var payments []Good | ||
result := db.db.Find(&payments) | ||
return payments, result.Error | ||
} | ||
|
||
// GetGoodsFromName gets the list of all goods from their name in database | ||
func (db PaymentDatabase) GetGoodsFromName(names []string) ([]Good, error) { | ||
// TODO: There SHOULD be a better way | ||
result := make([]Good, len(names)) | ||
for i, name := range names { | ||
if err := db.db.Where("name = ?", name).Find(&result[i]).Error; err != nil { | ||
if errors.Is(err, gorm.ErrRecordNotFound) { | ||
return nil, GoodNotFoundError{GoodName: name} | ||
} else { | ||
return nil, errors.Wrap(err, "cannot query database") | ||
} | ||
} | ||
} | ||
return result, nil | ||
} | ||
|
||
// AddGood adds a good to the table | ||
func (db PaymentDatabase) AddGood(good *Good) error { | ||
return db.db.Create(good).Error | ||
} | ||
|
||
// InitiateTransaction will add the given Payment in database with status set to initialized | ||
func (db PaymentDatabase) InitiateTransaction(payment *Payment) error { | ||
// At first initialize some values | ||
payment.OrderID = uuid.New() | ||
payment.PaymentStatus = PaymentStatusInitiated | ||
// Now insert it in database and pray to God that we have not fucked up anything up | ||
return db.db.Create(payment).Error | ||
} | ||
|
||
// MarkAsFailed will simply mark a payment as failed | ||
func (db PaymentDatabase) MarkAsFailed(orderID uuid.UUID) { | ||
err := db.db.Model(&Payment{OrderID: orderID}).Update("PaymentStatus", PaymentStatusFailed).Error | ||
if err != nil { | ||
log.WithError(err).WithField("OrderID", orderID).Error("cannot mark order as failed") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.