Skip to content

Commit

Permalink
Getting ready for zarinpal
Browse files Browse the repository at this point in the history
Added a fuckton of logs=
  • Loading branch information
HirbodBehnam committed Jan 12, 2024
1 parent bf5dc06 commit 6a1f3f5
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 118 deletions.
4 changes: 2 additions & 2 deletions payment/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package api

import (
db "wss-payment/internal/database"
"wss-payment/pkg/idpay"
"wss-payment/pkg/payment"
)

// API contains the data needed to operate the endpoints
type API struct {
Database db.PaymentDatabase
PaymentService idpay.PaymentService
PaymentService payment.Service
}
76 changes: 40 additions & 36 deletions payment/api/idpay.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"gorm.io/gorm"
"net/http"
"wss-payment/internal/database"
"wss-payment/pkg/idpay"
"wss-payment/pkg/payment"
)

// CreateTransaction initiates a transaction for a user
Expand All @@ -21,6 +21,7 @@ func (api *API) CreateTransaction(c *gin.Context) {
return
}
logger := log.WithField("body", body)
logger.Trace("creating transaction")
// If buying goods is zero, something's up...
if len(body.BuyingGoods) == 0 {
logger.Warn("empty buying_goods")
Expand All @@ -32,25 +33,26 @@ func (api *API) CreateTransaction(c *gin.Context) {
for i := range body.BuyingGoods {
goods[i] = database.Good{Name: body.BuyingGoods[i]}
}
payment := database.Payment{
databasePayment := database.Payment{
UserID: body.UserID,
ToPayAmount: body.ToPayAmount,
Discount: body.Discount,
Description: body.Description,
BoughtGoods: goods,
}
err = api.Database.InitiateTransaction(&payment)
err = api.Database.InitiateTransaction(&databasePayment)
if err != nil {
logger.WithError(err).Error("cannot put the transaction in database")
c.JSON(http.StatusInternalServerError, "cannot put the transaction in database: "+err.Error())
return
}
// Initiate the request in idpay
idpayResult, err := api.PaymentService.CreateTransaction(c.Request.Context(), idpay.TransactionCreationRequest{
OrderID: payment.OrderID.String(),
Name: body.Name,
Phone: body.Phone,
Mail: body.Mail,
logger = logger.WithField("orderID", databasePayment.OrderID)
logger.Debug("created transaction in database")
// Initiate the request in payment service
paymentResult, err := api.PaymentService.CreateTransaction(c.Request.Context(), payment.TransactionCreationRequest{
OrderID: databasePayment.OrderID.String(),
UsersPhone: body.Phone,
UsersMail: body.Mail,
Description: body.Description,
Callback: body.CallbackURL,
Amount: body.ToPayAmount,
Expand All @@ -59,16 +61,16 @@ func (api *API) CreateTransaction(c *gin.Context) {
logger.WithError(err).Error("cannot start idpay transaction")
c.JSON(http.StatusInternalServerError, "cannot start idpay transaction: "+err.Error())
// Mark the transaction in database as failed
api.Database.MarkAsFailed(payment.OrderID)
api.Database.MarkAsFailed(databasePayment.OrderID)
return
}
// Now we return back the order ID and link and stuff to the other service
c.JSON(http.StatusCreated, createTransactionResponse{
OrderID: payment.OrderID,
ID: idpayResult.ID,
RedirectURL: idpayResult.Link,
OrderID: databasePayment.OrderID,
ID: paymentResult.ServiceOrderID,
RedirectURL: paymentResult.RedirectLink,
})
return
logger.WithField("result", paymentResult).Info("created transaction")
}

// GetTransaction verifies a transaction if not already and then returns the transaction
Expand All @@ -87,9 +89,10 @@ func (api *API) GetTransaction(c *gin.Context) {
return
}
logger := log.WithField("OrderID", body.OrderID)
logger.Trace("getting transaction")
// Now get the transaction from database
payment := database.Payment{OrderID: orderUUID}
err = api.Database.GetPayment(&payment)
databasePayment := database.Payment{OrderID: orderUUID}
err = api.Database.GetPayment(&databasePayment)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
logger.Warn("payment not found")
Expand All @@ -101,22 +104,24 @@ func (api *API) GetTransaction(c *gin.Context) {
return
}
// Check if it's verified and verify it
if payment.PaymentStatus == database.PaymentStatusInitiated {
if databasePayment.PaymentStatus == database.PaymentStatusInitiated {
logger.Debug("verifying transaction")
// Send the verification request
result, err := api.PaymentService.VerifyTransaction(c.Request.Context(), idpay.TransactionVerificationRequest{
OrderID: payment.OrderID.String(),
ID: payment.ID.String,
result, err := api.PaymentService.VerifyTransaction(c.Request.Context(), payment.TransactionVerificationRequest{
OrderID: databasePayment.OrderID.String(),
ServiceOrderID: databasePayment.ServiceOrderID.String,
})
if err != nil {
logger.WithError(err).Error("cannot verify transaction")
c.JSON(http.StatusInternalServerError, "cannot verify transaction: "+err.Error())
return
}
logger.WithField("verification-result", result).Info("transaction verification complete")
// Check the result and update database
if result.PaymentOK {
err = api.Database.MarkPaymentAsOK(&payment, result.TrackID, result.PaymentTrackID)
err = api.Database.MarkPaymentAsOK(&databasePayment, result.TrackID)
} else {
err = api.Database.MarkPaymentAsFailed(&payment)
err = api.Database.MarkPaymentAsFailed(&databasePayment)
}
if err != nil {
// NIGGA
Expand All @@ -127,21 +132,20 @@ func (api *API) GetTransaction(c *gin.Context) {
}
// Return the converted struct
result := getTransactionResponse{
OrderID: payment.OrderID,
UserID: payment.UserID,
ToPayAmount: payment.ToPayAmount,
Discount: payment.Discount,
Description: payment.Description,
ID: payment.ID.String,
TrackID: payment.TrackID.String,
PaymentTrackID: payment.PaymentTrackID.String,
PaymentStatus: payment.PaymentStatus,
BoughtGoods: make([]string, len(payment.BoughtGoods)),
CreatedAt: payment.CreatedAt,
VerifiedAt: payment.VerifiedAt.Time,
OrderID: databasePayment.OrderID,
UserID: databasePayment.UserID,
ToPayAmount: databasePayment.ToPayAmount,
Discount: databasePayment.Discount,
Description: databasePayment.Description,
ID: databasePayment.ServiceOrderID.String,
TrackID: databasePayment.TrackID.String,
PaymentStatus: databasePayment.PaymentStatus,
BoughtGoods: make([]string, len(databasePayment.BoughtGoods)),
CreatedAt: databasePayment.CreatedAt,
VerifiedAt: databasePayment.VerifiedAt.Time,
}
for i := range payment.BoughtGoods {
result.BoughtGoods[i] = payment.BoughtGoods[i].Name
for i := range databasePayment.BoughtGoods {
result.BoughtGoods[i] = databasePayment.BoughtGoods[i].Name
}
c.JSON(http.StatusOK, result)
}
6 changes: 2 additions & 4 deletions payment/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,10 @@ type getTransactionResponse struct {
Discount uint64 `json:"discount"`
// An optional description about this payment
Description string `json:"description,omitempty"`
// The ID which is returned from idpay after we have initiated the transaction
// The ID which is returned from payment service after we have initiated the transaction
ID string `json:"id,omitempty"`
// The track ID which idpay returns to us after verification
// The track ID which payment service returns to us after verification
TrackID string `json:"track_id,omitempty"`
// The payment track ID which idpay returns to us after verification
PaymentTrackID string `json:"payment_track_id,omitempty"`
// What is the status of this payment?
PaymentStatus database.PaymentStatus `json:"payment_status"`
// List of the Goos which this user has bought in this payment
Expand Down
3 changes: 2 additions & 1 deletion payment/cmd/payment/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ import (
"wss-payment/api"
db "wss-payment/internal/database"
"wss-payment/pkg/idpay"
"wss-payment/pkg/payment"
)

func main() {
// Create the data needed
endpointApi := new(api.API)
endpointApi.Database = setupDatabase()
endpointApi.PaymentService = idpay.Mock{ // TODO: remove
endpointApi.PaymentService = payment.ServiceMock{ // TODO: remove
FailCreation: false,
FailVerification: false,
PaymentVerificationOk: false,
Expand Down
14 changes: 7 additions & 7 deletions payment/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/gin-gonic/gin v1.9.1
github.com/go-faster/errors v0.7.1
github.com/google/uuid v1.5.0
github.com/sirupsen/logrus v1.9.3
gorm.io/driver/postgres v1.5.4
gorm.io/gorm v1.25.5
)
Expand Down Expand Up @@ -35,15 +36,14 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.6.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
26 changes: 12 additions & 14 deletions payment/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqR
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
Expand Down Expand Up @@ -92,26 +91,25 @@ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
12 changes: 5 additions & 7 deletions payment/internal/database/payment.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,19 @@ func (db PaymentDatabase) GetPayment(payment *Payment) error {
return db.db.Model(&Payment{}).Preload("BoughtGoods").First(payment).Error
}

// MarkPaymentAsOK will mark a payment as successful and then updates its track ID, payment track ID and verified at time.
// MarkPaymentAsOK will mark a payment as successful and then updates its track ID and verified at time.
// This function will also update the values in payment argument to the ones which will be inserted in database.
func (db PaymentDatabase) MarkPaymentAsOK(payment *Payment, trackID string, paymentTrackID string) error {
func (db PaymentDatabase) MarkPaymentAsOK(payment *Payment, trackID string) error {
verifiedAt := sql.NullTime{Valid: true, Time: time.Now()}
err := db.db.Model(&Payment{OrderID: payment.OrderID}).Updates(&Payment{
TrackID: sql.NullString{Valid: true, String: trackID},
PaymentTrackID: sql.NullString{Valid: true, String: paymentTrackID},
PaymentStatus: PaymentStatusSuccess,
VerifiedAt: verifiedAt,
TrackID: sql.NullString{Valid: true, String: trackID},
PaymentStatus: PaymentStatusSuccess,
VerifiedAt: verifiedAt,
}).Error
if err != nil {
return err
}
payment.TrackID = sql.NullString{Valid: true, String: trackID}
payment.PaymentTrackID = sql.NullString{Valid: true, String: paymentTrackID}
payment.PaymentStatus = PaymentStatusSuccess
payment.VerifiedAt = verifiedAt
return nil
Expand Down
8 changes: 3 additions & 5 deletions payment/internal/database/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,10 @@ type Payment struct {
Discount uint64 `gorm:"not null"`
// An optional description about this payment
Description string `gorm:"not null"`
// The ID which is returned from idpay after we have initiated the transaction
ID sql.NullString
// The track ID which idpay returns to us after verification
// The Order ID which is returned from payment service after we have initiated the transaction
ServiceOrderID sql.NullString
// The track ID which payment service returns to us after verification
TrackID sql.NullString
// The payment track ID which idpay returns to us after verification
PaymentTrackID sql.NullString
// What is the status of this payment?
PaymentStatus PaymentStatus `gorm:"not null"`
// List of the Goos which this user has bought in this payment
Expand Down
38 changes: 0 additions & 38 deletions payment/pkg/idpay/mock.go

This file was deleted.

37 changes: 37 additions & 0 deletions payment/pkg/payment/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package payment

import (
"context"
"github.com/go-faster/errors"
"wss-payment/pkg/util"
)

// ServiceMock is a mock for a payment service
type ServiceMock struct {
FailCreation bool
FailVerification bool
PaymentVerificationOk bool
}

func (service ServiceMock) CreateTransaction(context.Context, TransactionCreationRequest) (TransactionCreationResult, error) {
if service.FailCreation {
return TransactionCreationResult{}, errors.New("mock failed!")
}
id := util.RandomID()
return TransactionCreationResult{
ServiceOrderID: id,
RedirectLink: "https://example.com/" + id,
}, nil

}

// VerifyTransaction will verify a previously made transaction and report errors if there was a problem with it
func (service ServiceMock) VerifyTransaction(context.Context, TransactionVerificationRequest) (TransactionVerificationResult, error) {
if service.FailVerification {
return TransactionVerificationResult{}, errors.New("mock failed!")
}
return TransactionVerificationResult{
TrackID: util.RandomID(),
PaymentOK: service.PaymentVerificationOk,
}, nil
}
Loading

0 comments on commit 6a1f3f5

Please sign in to comment.