From 7c1a0cb534a333443759af109bccea48ba1a10b7 Mon Sep 17 00:00:00 2001 From: Vaishakh GK Date: Thu, 23 Jan 2025 00:08:08 +0530 Subject: [PATCH 1/3] feat: Add Razorpay integration for order page payments --- go.mod | 1 + go.sum | 7 +++++ internal/handler/user.go | 55 ++++++++++++++++++++++++++++++++- models/product.go | 6 ++++ pkg/mysql/order.go | 12 ++++++++ server/server.go | 2 ++ utils/razorpay.go | 31 +++++++++++++++++++ view/user/cart-order.templ | 2 +- view/user/cart-order_templ.go | 32 +++++++++---------- view/user/order.templ | 58 +++++++++++++++++++++++++++++++++-- view/user/order_templ.go | 57 +++++++++++++++++++++++++++++----- 11 files changed, 233 insertions(+), 30 deletions(-) create mode 100644 utils/razorpay.go diff --git a/go.mod b/go.mod index bfe6c18..e64c7d0 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/razorpay/razorpay-go v1.3.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect golang.org/x/net v0.33.0 // indirect diff --git a/go.sum b/go.sum index d60d196..d8a8949 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,7 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/a-h/templ v0.3.819 h1:KDJ5jTFN15FyJnmSmo2gNirIqt7hfvBD2VXVDTySckM= github.com/a-h/templ v0.3.819/go.mod h1:iDJKJktpttVKdWoTkRNNLcllRI+BlpopJc+8au3gOUo= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= @@ -35,6 +36,10 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/razorpay/razorpay-go v1.3.2 h1:6368QznCNkoQNi7bBbxdHUu7lJJW4UxN7W3WftrbFZg= +github.com/razorpay/razorpay-go v1.3.2/go.mod h1:VcljkUylUJAUEvFfGVv/d5ht1to1dUgF4H1+3nv7i+Q= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -53,5 +58,7 @@ golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/handler/user.go b/internal/handler/user.go index a988fd4..1294a0c 100644 --- a/internal/handler/user.go +++ b/internal/handler/user.go @@ -3,6 +3,7 @@ package handler import ( "fmt" "net/http" + "os" "github.com/FulgurCode/stitch/models" "github.com/FulgurCode/stitch/pkg/mysql" @@ -11,6 +12,7 @@ import ( "github.com/FulgurCode/stitch/view/user" "github.com/google/uuid" "github.com/labstack/echo/v4" + "github.com/razorpay/razorpay-go" ) // Home page handler @@ -87,18 +89,40 @@ func OrderPost(c echo.Context) error { } order.ProductId = productId - order.Status = "ordered" + if order.Payment == "online" { + order.Status = "pending" + } else { + order.Status = "ordered" + } if order.Quantity == 0 { order.Quantity = 1 } order.Total = product.Price * order.Quantity var orderId = uuid.New() + order.Id = string(orderId.String()) err = mysql.MakeOrder(order, orderId) if err != nil { fmt.Println(err) } + if order.Payment == "online" { + var key = os.Getenv("RAZORPAY_KEY") + var secret = os.Getenv("RAZORPAY_SECRET") + var client = razorpay.NewClient(key, secret) + var ord = map[string]interface{}{ + "amount": order.Total * 100, + "currency": "INR", + } + body, err := client.Order.Create(ord, nil) + if err != nil { + fmt.Println(err) + } + + var component = user.OnlinePayment(order, body, key) + return utils.Render(c, component) + } + if c.Request().Header.Get("HX-Request") == "true" { c.Response().Header().Set("HX-Location", fmt.Sprintf("/item/%s", productId)) return c.NoContent(http.StatusSeeOther) @@ -199,6 +223,7 @@ func CartOrderPost(c echo.Context) error { var cart = utils.GetSessionAll(c, "cart") var orderId = uuid.New() + var total int = 0 for id, size := range cart { var product, _ = mysql.GetProductById(id.(string)) var order models.Order = body @@ -213,6 +238,7 @@ func CartOrderPost(c echo.Context) error { if err != nil { fmt.Println(err) } + total += order.Total } utils.DeleteSession(c, "cart") @@ -224,3 +250,30 @@ func CartOrderPost(c echo.Context) error { return c.Redirect(http.StatusSeeOther, "/cart") } + +func VerifyOnlinePayment(c echo.Context) error { + var orderId = c.Param("orderId") + var data models.VerifyOrder + var err = c.Bind(&data) + if err != nil { + fmt.Println(err) + } + + if err := utils.RazorPaymentVerification(data); err != nil { + mysql.OrderStatusPayment(orderId, "ordered") + return c.JSON(200, "Ordered Successfully And Payment Verified") + } + + return c.JSON(406, "Payment Verification Failed") +} + +func DeletePendingOrder(c echo.Context) error { + var orderId = c.Param("orderId") + var err = mysql.DeletePendingOrder(orderId) + if err != nil { + fmt.Println(err) + return c.JSON(500, "Failed") + } + + return c.JSON(200, "Order Payment Failed / Cancelled") +} diff --git a/models/product.go b/models/product.go index efa4f55..df13daf 100644 --- a/models/product.go +++ b/models/product.go @@ -39,3 +39,9 @@ type Order struct { Total int `json:"total" form:"total"` Status string `json:"status" form:"status"` } + +type VerifyOrder struct { + OrderId string `json:"orderId" form:"orderId"` + PaymentId string `json:"paymentId" form:"paymentId"` + RazorpaySignature string `json:"razorpaySignature" form:"razorpaySignature"` +} diff --git a/pkg/mysql/order.go b/pkg/mysql/order.go index 892eaba..a23fb9b 100644 --- a/pkg/mysql/order.go +++ b/pkg/mysql/order.go @@ -43,3 +43,15 @@ func DeleteOrder(id string, productId string) error { var _, err = Db.Exec(query, id, productId) return err } + +func OrderStatusPayment(id string, status string) error { + var query = "UPDATE orders SET status = ? WHERE id = ?;" + var _, err = Db.Exec(query, status, id) + return err +} + +func DeletePendingOrder(id string) error { + var query = "DELETE FROM orders WHERE id = ? AND status = 'pending';" + var _, err = Db.Exec(query, id) + return err +} diff --git a/server/server.go b/server/server.go index 5021afb..7bb20ba 100644 --- a/server/server.go +++ b/server/server.go @@ -40,6 +40,8 @@ func Run(port string) { app.POST("/cart/order", handler.CartOrderPost) app.GET("add-to-cart/:productId", handler.AddToCart) app.DELETE("delete-cart/:productId", handler.DeleteFromCart) + app.POST("/payment-verification/:orderId", handler.VerifyOnlinePayment) + app.GET("/delete-order/:orderId", handler.DeletePendingOrder) app.GET("/admin", utils.CheckLogin(handler.Admin)) diff --git a/utils/razorpay.go b/utils/razorpay.go new file mode 100644 index 0000000..48df701 --- /dev/null +++ b/utils/razorpay.go @@ -0,0 +1,31 @@ +package utils + +import ( + "crypto/hmac" + "crypto/sha256" + "crypto/subtle" + "encoding/hex" + "errors" + "os" + + "github.com/FulgurCode/stitch/models" +) + +func RazorPaymentVerification(order models.VerifyOrder) error { + var secret = os.Getenv("RAZORPAY_SECRET") + data := order.OrderId+ "|" + order.PaymentId + + h := hmac.New(sha256.New, []byte(secret)) + + _, err := h.Write([]byte(data)) + if err != nil { + panic(err) + } + + sha := hex.EncodeToString(h.Sum(nil)) + if subtle.ConstantTimeCompare([]byte(sha), []byte(order.RazorpaySignature)) != 1 { + return errors.New("Payment failed") + } else { + return nil + } +} diff --git a/view/user/cart-order.templ b/view/user/cart-order.templ index 9db32f0..bc7a8b5 100644 --- a/view/user/cart-order.templ +++ b/view/user/cart-order.templ @@ -28,7 +28,7 @@ templ CartOrder(products []models.Product) { diff --git a/view/user/cart-order_templ.go b/view/user/cart-order_templ.go index 0525e90..bc2fe17 100644 --- a/view/user/cart-order_templ.go +++ b/view/user/cart-order_templ.go @@ -75,16 +75,12 @@ func CartOrder(products []models.Product) templ.Component { return templ_7745c5c3_Err } for _, product := range products { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } templ_7745c5c3_Err = OrdersCard(product).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -119,85 +115,85 @@ func OrdersCard(product models.Product) templ.Component { templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(product.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 61, Col: 28} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 54, Col: 28} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
₨. ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "

₨. ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", product.Price)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 62, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 55, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" hx-target=\"body\">View Product
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/view/user/order.templ b/view/user/order.templ index ad77479..148ac5b 100644 --- a/view/user/order.templ +++ b/view/user/order.templ @@ -10,6 +10,7 @@ import ( templ Order(product models.Product, size string) { @layout.User() { +

Place Order

@@ -21,7 +22,7 @@ templ Order(product models.Product, size string) {

₨. {fmt.Sprintf("%d",product.Price)}

-
+ @@ -32,11 +33,64 @@ templ Order(product models.Product, size string) {
} +} + +templ OnlinePayment(order models.Order,ord map[string]interface{},key string) { + @templ.JSONScript("order-data", order) + @templ.JSONScript("ord-data", ord) + @templ.JSONScript("key-data", key) + + + + + + } \ No newline at end of file diff --git a/view/user/order_templ.go b/view/user/order_templ.go index 364d1a2..62d4b21 100644 --- a/view/user/order_templ.go +++ b/view/user/order_templ.go @@ -48,7 +48,7 @@ func Order(product models.Product, size string) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -77,7 +77,7 @@ func Order(product models.Product, size string) templ.Component { var templ_7745c5c3_Var5 string templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs("/static/images/" + product.Id + "-main") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/order.templ`, Line: 18, Col: 66} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/order.templ`, Line: 19, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { @@ -90,7 +90,7 @@ func Order(product models.Product, size string) templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(product.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/order.templ`, Line: 20, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/order.templ`, Line: 21, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -103,7 +103,7 @@ func Order(product models.Product, size string) templ.Component { var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", product.Price)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/order.templ`, Line: 21, Col: 83} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/order.templ`, Line: 22, Col: 83} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -116,26 +116,26 @@ func Order(product models.Product, size string) templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/order/%s", product.Id)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/order.templ`, Line: 24, Col: 66} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/order.templ`, Line: 25, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\"> ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\"> ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -149,4 +149,45 @@ func Order(product models.Product, size string) templ.Component { }) } +func OnlinePayment(order models.Order, ord map[string]interface{}, key string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var10 := templ.GetChildren(ctx) + if templ_7745c5c3_Var10 == nil { + templ_7745c5c3_Var10 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.JSONScript("order-data", order).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.JSONScript("ord-data", ord).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.JSONScript("key-data", key).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + var _ = templruntime.GeneratedTemplate From 4213827e86c86317867058f9526214b214c4f33b Mon Sep 17 00:00:00 2001 From: Vaishakh GK Date: Fri, 24 Jan 2025 00:58:37 +0530 Subject: [PATCH 2/3] fix: Order status update when payment verification fails * Set POST request content type to 'application/json' for payment verification. * Prevent payment status from changing to 'ordered' when verification fails due to wrong condition check. --- internal/handler/user.go | 3 ++- view/user/order.templ | 2 +- view/user/order_templ.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/handler/user.go b/internal/handler/user.go index 1294a0c..c8aa5a9 100644 --- a/internal/handler/user.go +++ b/internal/handler/user.go @@ -259,11 +259,12 @@ func VerifyOnlinePayment(c echo.Context) error { fmt.Println(err) } - if err := utils.RazorPaymentVerification(data); err != nil { + if err := utils.RazorPaymentVerification(data); err == nil { mysql.OrderStatusPayment(orderId, "ordered") return c.JSON(200, "Ordered Successfully And Payment Verified") } + fmt.Println(err) return c.JSON(406, "Payment Verification Failed") } diff --git a/view/user/order.templ b/view/user/order.templ index 148ac5b..6b1ae9f 100644 --- a/view/user/order.templ +++ b/view/user/order.templ @@ -66,7 +66,7 @@ templ OnlinePayment(order models.Order,ord map[string]interface{},key string) { handler: async function (response) { var url = "/payment-verification/" + order.id var body = JSON.stringify({"orderId": response.razorpay_order_id, "paymentId": response.razorpay_payment_id, "razorpaySignature": response.razorpay_signature}) - var res = await fetch(url,{method: "POST", body:body}) + var res = await fetch(url,{method: "POST", headers: {"Content-Type": "application/json"}, body:body}) if (res.ok) { var json = await res.json() alert(json) diff --git a/view/user/order_templ.go b/view/user/order_templ.go index 62d4b21..11744fb 100644 --- a/view/user/order_templ.go +++ b/view/user/order_templ.go @@ -182,7 +182,7 @@ func OnlinePayment(order models.Order, ord map[string]interface{}, key string) t if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } From b839e612ffefb3ddcde48ac118db701254c9ac7c Mon Sep 17 00:00:00 2001 From: Vaishakh GK Date: Fri, 24 Jan 2025 01:20:15 +0530 Subject: [PATCH 3/3] feat: Add Razorpay integration for cart-order page payments --- internal/handler/user.go | 24 ++++++++++++-- view/user/cart-order.templ | 61 ++++++++++++++++++++++++++++++++++- view/user/cart-order_templ.go | 57 +++++++++++++++++++++++++++----- 3 files changed, 131 insertions(+), 11 deletions(-) diff --git a/internal/handler/user.go b/internal/handler/user.go index c8aa5a9..b00b770 100644 --- a/internal/handler/user.go +++ b/internal/handler/user.go @@ -223,13 +223,18 @@ func CartOrderPost(c echo.Context) error { var cart = utils.GetSessionAll(c, "cart") var orderId = uuid.New() + body.Id = orderId.String() var total int = 0 for id, size := range cart { var product, _ = mysql.GetProductById(id.(string)) var order models.Order = body order.ProductId = product.Id - order.Status = "ordered" + if body.Payment == "online" { + order.Status = "pending" + } else { + order.Status = "ordered" + } order.Quantity = 1 order.Total = product.Price order.Size = size.(string) @@ -240,8 +245,23 @@ func CartOrderPost(c echo.Context) error { } total += order.Total } + if body.Payment == "online" { + var key = os.Getenv("RAZORPAY_KEY") + var secret = os.Getenv("RAZORPAY_SECRET") + var client = razorpay.NewClient(key, secret) + var ord = map[string]interface{}{ + "amount": total * 100, + "currency": "INR", + } + order, err := client.Order.Create(ord, nil) + if err != nil { + fmt.Println(err) + } + fmt.Println("submit cart") - utils.DeleteSession(c, "cart") + var component = user.OnlinePaymentCart(body, order, key) + return utils.Render(c, component) + } if c.Request().Header.Get("HX-Request") == "true" { c.Response().Header().Set("HX-Location", "/cart") diff --git a/view/user/cart-order.templ b/view/user/cart-order.templ index bc7a8b5..efc16ce 100644 --- a/view/user/cart-order.templ +++ b/view/user/cart-order.templ @@ -10,6 +10,7 @@ import ( templ CartOrder(products []models.Product) { @layout.User() { +

Place Order

@@ -19,7 +20,7 @@ templ CartOrder(products []models.Product) { @OrdersCard(product) }
-
+ @@ -59,4 +60,62 @@ templ OrdersCard(product models.Product) { +} + +templ OnlinePaymentCart(order models.Order,ord map[string]interface{},key string) { + @templ.JSONScript("order-data", order) + @templ.JSONScript("ord-data", ord) + @templ.JSONScript("key-data", key) + + + + + + } \ No newline at end of file diff --git a/view/user/cart-order_templ.go b/view/user/cart-order_templ.go index bc2fe17..93aeb7b 100644 --- a/view/user/cart-order_templ.go +++ b/view/user/cart-order_templ.go @@ -48,7 +48,7 @@ func CartOrder(products []models.Product) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -80,7 +80,7 @@ func CartOrder(products []models.Product) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -122,7 +122,7 @@ func OrdersCard(product models.Product) templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("/static/images/" + product.Id + "-main") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 52, Col: 54} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 53, Col: 54} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -135,7 +135,7 @@ func OrdersCard(product models.Product) templ.Component { var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(product.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 54, Col: 28} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 55, Col: 28} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -148,7 +148,7 @@ func OrdersCard(product models.Product) templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", product.Price)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 55, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 56, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -161,7 +161,7 @@ func OrdersCard(product models.Product) templ.Component { var templ_7745c5c3_Var9 string templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/delete-cart/%s", product.Id)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 58, Col: 96} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 59, Col: 96} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { @@ -174,7 +174,7 @@ func OrdersCard(product models.Product) templ.Component { var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/item/%s", product.Id)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 59, Col: 88} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 60, Col: 88} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { @@ -187,7 +187,7 @@ func OrdersCard(product models.Product) templ.Component { var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/item/%s", product.Id)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 59, Col: 138} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/cart-order.templ`, Line: 60, Col: 138} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { @@ -201,4 +201,45 @@ func OrdersCard(product models.Product) templ.Component { }) } +func OnlinePaymentCart(order models.Order, ord map[string]interface{}, key string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var12 := templ.GetChildren(ctx) + if templ_7745c5c3_Var12 == nil { + templ_7745c5c3_Var12 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.JSONScript("order-data", order).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.JSONScript("ord-data", ord).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.JSONScript("key-data", key).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + var _ = templruntime.GeneratedTemplate