Skip to content

Commit

Permalink
Merge pull request #16 from RianIhsan/feature/midtrans-create-transac…
Browse files Browse the repository at this point in the history
…tion

feature:midtrans create transaction
  • Loading branch information
RianIhsan authored Oct 28, 2023
2 parents 453628e + 9c82b83 commit e2f6a59
Show file tree
Hide file tree
Showing 13 changed files with 182 additions and 9 deletions.
5 changes: 4 additions & 1 deletion .env-example
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ CLOUDINARY_URL=

SMTP_PASS=
SMTP_USER=
SMTP_PORT=
SMTP_PORT=

MSERVER=
MCLIENT=
2 changes: 2 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@ jobs:
-e SMTP_PASS=${{ secrets.SMTP_PASS }} \
-e SMTP_USER=${{ secrets.SMTP_USER }} \
-e SMTP_PORT=${{ secrets.SMTP_PORT }} \
-e MSERVER=${{ secrets.MSERVER }}
-e MCLIENT=${{ secrets.MCLIENT}
${{ secrets.DOCKERHUB_USERNAME }}/yondev
7 changes: 3 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@ require (
github.com/alexedwards/argon2id v0.0.0-20230305115115-4b3c3280a736
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/joho/godotenv v1.5.1
github.com/stretchr/testify v1.8.4
github.com/midtrans/midtrans-go v1.3.7
github.com/veritrans/go-midtrans v0.0.0-20210616100512-16326c5eeb00
github.com/wneessen/go-mail v0.4.0
)

require (
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 // indirect
github.com/creasty/defaults v1.5.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/gorilla/schema v1.2.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)

Expand Down
7 changes: 6 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
Expand Down Expand Up @@ -73,6 +75,8 @@ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/midtrans/midtrans-go v1.3.7 h1:3vL9ydlVqp9VfRHDzOG17w1D6X9241jj6LQdPTxVE/g=
github.com/midtrans/midtrans-go v1.3.7/go.mod h1:5hN2oiZDP3/SwSBxHPTg8eC/RVoRE9DXQOY1Ah9au10=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand All @@ -86,7 +90,6 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand All @@ -101,6 +104,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/veritrans/go-midtrans v0.0.0-20210616100512-16326c5eeb00 h1:iCcVFY2mUdalvtpNN0M/vcf7+OYHGKXwzG5JLZgjwQU=
github.com/veritrans/go-midtrans v0.0.0-20210616100512-16326c5eeb00/go.mod h1:21mwYsDK+z+5kR2fvUB8n2yijZZm504Vjzk1s0rNQJg=
github.com/wneessen/go-mail v0.4.0 h1:Oo4HLIV8My7G9JuZkoOX6eipXQD+ACvIqURYeIzUc88=
github.com/wneessen/go-mail v0.4.0/go.mod h1:zxOlafWCP/r6FEhAaRgH4IC1vg2YXxO0Nar9u0IScZ8=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand Down
25 changes: 25 additions & 0 deletions handler/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,28 @@ func (h *transactionHandler) GetUserTransactions(c *gin.Context) {
response := helper.ResponseWithData("User's transaction", transaction.FormatUserTransactions(transactions))
c.JSON(http.StatusOK, response)
}

func (h *transactionHandler) CreateTransaction(c *gin.Context) {
var input transaction.CreateTransactionInput

err := c.ShouldBindJSON(&input)
if err != nil {
errors := helper.FormatValidationError(err)
response := helper.ErrorResponse("Failed to create transaction", errors)
c.JSON(http.StatusBadRequest, response)
return
}

currentUser := c.MustGet("CurrentUser").(user.User)
input.User = currentUser

newTransaction, err := h.service.CreateTransaction(input)
if err != nil {
response := helper.ErrorResponse("Failed to create transaction", err.Error())
c.JSON(http.StatusBadRequest, response)
return
}
response := helper.ResponseWithData("Success to create transaction", transaction.FormatTransaction(newTransaction))
c.JSON(http.StatusOK, response)

}
6 changes: 6 additions & 0 deletions payment/entity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package payment

type Transaction struct {
ID int
Amount int
}
46 changes: 46 additions & 0 deletions payment/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package payment

import (
"github.com/RianIhsan/raise-unity/user"
"github.com/veritrans/go-midtrans"
"os"
"strconv"
)

type service struct {
}

type Service interface {
GetPaymentURL(transaction Transaction, user user.User) (string, error)
}

func NewService() *service {
return &service{}
}
func (s *service) GetPaymentURL(transaction Transaction, user user.User) (string, error) {
midclient := midtrans.NewClient()
server := os.Getenv("MSERVER")
client := os.Getenv("MCLIENT")
midclient.ServerKey = server
midclient.ClientKey = client
midclient.APIEnvType = midtrans.Sandbox
orderID := strconv.Itoa(transaction.ID)
snapGateway := midtrans.SnapGateway{
Client: midclient,
}
snapReq := &midtrans.SnapReq{
CustomerDetail: &midtrans.CustDetail{
Email: user.Email,
FName: user.Name,
},
TransactionDetails: midtrans.TransactionDetails{
OrderID: orderID,
GrossAmt: int64(transaction.Amount),
},
}
snapTokenResp, err := snapGateway.GetToken(snapReq)
if err != nil {
return "", err
}
return snapTokenResp.RedirectURL, nil
}
5 changes: 4 additions & 1 deletion routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/RianIhsan/raise-unity/campaign"
"github.com/RianIhsan/raise-unity/handler"
"github.com/RianIhsan/raise-unity/middleware"
"github.com/RianIhsan/raise-unity/payment"
"github.com/RianIhsan/raise-unity/transaction"
"github.com/RianIhsan/raise-unity/user"
"github.com/RianIhsan/raise-unity/utils/database"
Expand All @@ -20,7 +21,8 @@ func SetupRoute(router *gin.Engine) {
authService := auth.NewService()
userService := user.NewService(userRepository)
campService := campaign.NewService(campRepository)
transactionService := transaction.NewService(transactionRepository, campRepository)
paymentService := payment.NewService()
transactionService := transaction.NewService(transactionRepository, campRepository, paymentService)

userHandler := handler.NewUserHandler(userService, authService)
campHandler := handler.NewCampaignHandler(campService)
Expand All @@ -43,4 +45,5 @@ func SetupRoute(router *gin.Engine) {

api.GET("/campaigns/:id/transactions", middleware.AuthMiddleware(authService, userService), transactionHandler.GetCampaignTransactions)
api.GET("/transactions", middleware.AuthMiddleware(authService, userService), transactionHandler.GetUserTransactions)
api.POST("/transactions", middleware.AuthMiddleware(authService, userService), transactionHandler.CreateTransaction)
}
1 change: 1 addition & 0 deletions transaction/entitiy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Transaction struct {
Amount int `json:"amount"`
Status string `json:"status"`
Code string `json:"code"`
PaymentURL string `json:"payment_url" gorm:"type:varchar(255)"`
User user.User `json:"user"`
Campaign campaign.Campaign `json:"campaign"`
CreatedAt time.Time `json:"created_at"`
Expand Down
22 changes: 22 additions & 0 deletions transaction/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,25 @@ func FormatUserTransactions(transactions []Transaction) []UserTransactionFormatt

return transactionFormatter
}

type TransactionFormatter struct {
ID int `json:"id"`
CampaignID int `json:"campaign_id"`
UserID int `json:"user_id"`
Amount int `json:"amount"`
Status string `json:"status"`
Code string `json:"code"`
PaymentURL string `json:"payment_url"`
}

func FormatTransaction(transaction Transaction) TransactionFormatter {
formatter := TransactionFormatter{}
formatter.ID = transaction.ID
formatter.CampaignID = transaction.CampaignID
formatter.UserID = transaction.UserID
formatter.Amount = transaction.Amount
formatter.Status = transaction.Status
formatter.Code = transaction.Code
formatter.PaymentURL = transaction.PaymentURL
return formatter
}
6 changes: 6 additions & 0 deletions transaction/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ type GetCampaignTransactionInput struct {
ID int `uri:"id" binding:"required"`
User user.User
}

type CreateTransactionInput struct {
Amount int `json:"amount" binding:"required"`
CampaignID int `json:"campaign_id" binding:"required"`
User user.User
}
17 changes: 17 additions & 0 deletions transaction/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type repository struct {
type Repository interface {
GetByCampaignID(campaignID int) ([]Transaction, error)
GetByUserID(userID int) ([]Transaction, error)
Save(transaction Transaction) (Transaction, error)
Update(transaction Transaction) (Transaction, error)
}

func NewRepository(db *gorm.DB) *repository {
Expand All @@ -35,3 +37,18 @@ func (r *repository) GetByUserID(userID int) ([]Transaction, error) {
}
return transactions, nil
}

func (r *repository) Save(transaction Transaction) (Transaction, error) {
err := r.db.Create(&transaction).Error
if err != nil {
return transaction, err
}
return transaction, nil
}
func (r *repository) Update(transaction Transaction) (Transaction, error) {
err := r.db.Save(&transaction).Error
if err != nil {
return transaction, err
}
return transaction, nil
}
42 changes: 40 additions & 2 deletions transaction/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@ package transaction
import (
"errors"
"github.com/RianIhsan/raise-unity/campaign"
"github.com/RianIhsan/raise-unity/helper"
"github.com/RianIhsan/raise-unity/payment"
"strconv"
)

type service struct {
repository Repository
campaignRepository campaign.Repository
paymentService payment.Service
}

type Service interface {
GetTransactionByCampaignID(input GetCampaignTransactionInput) ([]Transaction, error)
GetTransactionByUserID(userID int) ([]Transaction, error)
CreateTransaction(input CreateTransactionInput) (Transaction, error)
}

func NewService(repository Repository, campaignRepository campaign.Repository) *service {
return &service{repository, campaignRepository}
func NewService(repository Repository, campaignRepository campaign.Repository, paymentService payment.Service) *service {
return &service{repository, campaignRepository, paymentService}
}

func (s *service) GetTransactionByCampaignID(input GetCampaignTransactionInput) ([]Transaction, error) {
Expand All @@ -42,3 +47,36 @@ func (s *service) GetTransactionByUserID(userID int) ([]Transaction, error) {
}
return transactions, nil
}

func (s *service) CreateTransaction(input CreateTransactionInput) (Transaction, error) {
transaction := Transaction{}
transaction.CampaignID = input.CampaignID
transaction.Amount = input.Amount
transaction.UserID = input.User.ID
transaction.Status = "pending"

//Mapping struct transaction to transaction
Random := helper.GenerateRandomOTP(5)
atoi, err := strconv.Atoi(Random)
if err != nil {
return Transaction{}, err
}
paymentTransaction := payment.Transaction{
ID: atoi,
Amount: transaction.Amount,
}
var paymentURL string
paymentURL, err = s.paymentService.GetPaymentURL(paymentTransaction, input.User)
if err != nil {
return transaction, err
}
transaction.PaymentURL = paymentURL
transaction.Code = strconv.Itoa(paymentTransaction.ID)

newTransaction, err := s.repository.Save(transaction)
if err != nil {
return newTransaction, err
}

return newTransaction, nil
}

0 comments on commit e2f6a59

Please sign in to comment.