Added completion on wspay
This commit is contained in:
parent
9440fa9778
commit
b4b0396b30
123
main.go
123
main.go
|
@ -1,7 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
@ -10,6 +13,7 @@ import (
|
|||
"github.com/stripe/stripe-go/v72/checkout/session"
|
||||
"github.com/stripe/stripe-go/v72/paymentintent"
|
||||
"html/template"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"payment-poc/migration"
|
||||
|
@ -39,6 +43,7 @@ func init() {
|
|||
godotenv.Load()
|
||||
|
||||
BackendUrl = envMustExist("BACKEND_URL")
|
||||
|
||||
WsPayShopId = envMustExist("WSPAY_SHOP_ID")
|
||||
WsPayShopSecret = envMustExist("WSPAY_SHOP_SECRET")
|
||||
|
||||
|
@ -493,6 +498,124 @@ func setupWsPayEndpoints(g *gin.RouterGroup, wspayService wspay.Service) {
|
|||
|
||||
c.HTML(200, "wspay.gohtml", gin.H{"Action": wspay.AuthorisationForm, "Form": form})
|
||||
})
|
||||
g.POST("complete/:id", func(c *gin.Context) {
|
||||
id := uuid.MustParse(c.Param("id"))
|
||||
amount, err := strconv.ParseFloat(c.PostForm("amount"), 64)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
entry, err := wspayService.FetchById(id)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
if int64(amount*100) > entry.TotalAmount || int64(amount*100) < 1 {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
if entry.State == state.StateAccepted {
|
||||
var request = wspay.WsPayCompletionRequest{
|
||||
Version: "2.0",
|
||||
WsPayOrderId: entry.ShoppingCartID,
|
||||
ShopId: entry.ShopID,
|
||||
ApprovalCode: entry.ApprovalCode,
|
||||
STAN: entry.STAN,
|
||||
Amount: int64(amount * 100),
|
||||
Signature: wspay.CalculateCompletionSignature(WsPayShopId, WsPayShopSecret, entry.ShoppingCartID, entry.STAN, entry.ApprovalCode, int64(amount*100)),
|
||||
}
|
||||
|
||||
content, _ := json.Marshal(&request)
|
||||
response, err := http.Post("https://test.wspay.biz/api/services/completion", "application/json", bytes.NewBuffer(content))
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if response.StatusCode == http.StatusOK {
|
||||
transactionResponse := wspay.WsPayCompletionResponse{}
|
||||
content, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if err := json.Unmarshal(content, &transactionResponse); err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("Received transaction response: success=%s, errorMessage=%s, approvalCode=%s",
|
||||
transactionResponse.ActionSuccess, transactionResponse.ErrorMessage, transactionResponse.ApprovalCode,
|
||||
)
|
||||
if wspay.CompareCompletionReturnSignature(transactionResponse.Signature, WsPayShopId, WsPayShopSecret, entry.ShoppingCartID, entry.STAN, transactionResponse.ActionSuccess, transactionResponse.ApprovalCode) != nil {
|
||||
entry.TotalAmount = int64(amount * 100)
|
||||
entry.State = state.StateCompleted
|
||||
wspayService.Update(entry)
|
||||
} else {
|
||||
c.AbortWithError(http.StatusInternalServerError, errors.New("received invalid signature"))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.AbortWithError(http.StatusInternalServerError, errors.New("received wrong status, expected 200 received "+strconv.FormatInt(int64(response.StatusCode), 10)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusSeeOther, "/wspay/info/"+id.String())
|
||||
})
|
||||
g.POST("cancel/:id", func(c *gin.Context) {
|
||||
id := uuid.MustParse(c.Param("id"))
|
||||
entry, err := wspayService.FetchById(id)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
if entry.State == state.StateAccepted {
|
||||
var request = wspay.WsPayCompletionRequest{
|
||||
Version: "2.0",
|
||||
WsPayOrderId: entry.ShoppingCartID,
|
||||
ShopId: entry.ShopID,
|
||||
ApprovalCode: entry.ApprovalCode,
|
||||
STAN: entry.STAN,
|
||||
Amount: entry.TotalAmount,
|
||||
Signature: wspay.CalculateCompletionSignature(WsPayShopId, WsPayShopSecret, entry.ShoppingCartID, entry.STAN, entry.ApprovalCode, entry.TotalAmount),
|
||||
}
|
||||
|
||||
content, _ := json.Marshal(&request)
|
||||
response, err := http.Post("https://test.wspay.biz/api/services/void", "application/json", bytes.NewBuffer(content))
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if response.StatusCode == http.StatusOK {
|
||||
transactionResponse := wspay.WsPayCompletionResponse{}
|
||||
content, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if err := json.Unmarshal(content, &transactionResponse); err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("Received transaction response: success=%s, errorMessage=%s, approvalCode=%s",
|
||||
transactionResponse.ActionSuccess, transactionResponse.ErrorMessage, transactionResponse.ApprovalCode,
|
||||
)
|
||||
if wspay.CompareCompletionReturnSignature(transactionResponse.Signature, WsPayShopId, WsPayShopSecret, entry.ShoppingCartID, entry.STAN, transactionResponse.ActionSuccess, transactionResponse.ApprovalCode) != nil {
|
||||
entry.State = state.StateCanceled
|
||||
wspayService.Update(entry)
|
||||
} else {
|
||||
c.AbortWithError(http.StatusInternalServerError, errors.New("received invalid signature"))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.AbortWithError(http.StatusInternalServerError, errors.New("received wrong status, expected 200 received "+strconv.FormatInt(int64(response.StatusCode), 10)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusSeeOther, "/wspay/info/"+id.String())
|
||||
})
|
||||
g.GET("success", func(c *gin.Context) {
|
||||
response := wspay.WsPayFormReturn{}
|
||||
if err := c.ShouldBind(&response); err != nil {
|
||||
|
|
|
@ -45,5 +45,18 @@
|
|||
|
||||
<tr><th>Stanje: </th><td>{{formatState .Entry.State}}</td></tr>
|
||||
</table>
|
||||
|
||||
{{if eq .Entry.State "accepted"}}
|
||||
<form class="mb-3" method="post" action="/wspay/complete/{{.Entry.Id}}">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="amount">Završi transakciju</label>
|
||||
<input class="form-control" id="amount" required name="amount" type="number" value="{{formatCurrency2 .Entry.TotalAmount}}" step="0.01" min="0.01" max="{{formatCurrency2 .Entry.TotalAmount}}">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Završi transakciju</button>
|
||||
</form>
|
||||
<form method="post" action="/wspay/cancel/{{.Entry.Id}}">
|
||||
<button class="btn btn-primary" type="submit">Otkaži transakciju</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
|
@ -74,6 +74,27 @@ func CalculateFormSignature(shopId string, secret string, cartId string, amount
|
|||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
|
||||
func CalculateCompletionSignature(shopId string, secret string, cartId string, stan string, approvalCode string, amount int64) string {
|
||||
/**
|
||||
Represents a signature created from string formatted from following values in a following order using
|
||||
SHA512 algorithm:
|
||||
ShopID
|
||||
WsPayOrderId
|
||||
SecretKey
|
||||
STAN
|
||||
SecretKey
|
||||
ApprovalCode
|
||||
SecretKey
|
||||
Amount
|
||||
SecretKey
|
||||
WsPayOrderId
|
||||
*/
|
||||
signature := shopId + cartId + secret + stan + secret + approvalCode + secret + strconv.FormatInt(amount, 10) + secret + cartId
|
||||
hash := sha512.New()
|
||||
hash.Write([]byte(signature))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
|
||||
func CompareFormReturnSignature(signature string, shopId string, secret string, cartId string, success int, approvalCode string) error {
|
||||
/**
|
||||
Represents a signature created from string formatted from following values in a following order using
|
||||
|
@ -97,3 +118,26 @@ func CompareFormReturnSignature(signature string, shopId string, secret string,
|
|||
return errors.New("signature mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func CompareCompletionReturnSignature(signature string, shopId string, secret string, stan string, actionSuccess string, approvalCode string, cartId string) error {
|
||||
/**
|
||||
Represents a signature created from string formatted from following values in a following order using
|
||||
SHA512 algorithm:
|
||||
ShopID
|
||||
SecretKey
|
||||
STAN
|
||||
ActionSuccess
|
||||
SecretKey
|
||||
ApprovalCode
|
||||
WsPayOrderId
|
||||
Merchant should validate this signature to make sure that the request is originating from WSPayForm.
|
||||
*/
|
||||
calculatedSignature := shopId + secret + stan + actionSuccess + secret + approvalCode + cartId
|
||||
hash := sha512.New()
|
||||
hash.Write([]byte(calculatedSignature))
|
||||
if hex.EncodeToString(hash.Sum(nil)) == signature {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("signature mismatch")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ type WsPayCompletionRequest struct {
|
|||
ShopId string
|
||||
ApprovalCode string
|
||||
STAN string
|
||||
Amount string
|
||||
Amount int64
|
||||
Signature string
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue