From ccb42cbf3a344ba1a729802af01fb1087cb20e8a Mon Sep 17 00:00:00 2001 From: Sudarshan Pathak Date: Wed, 18 Jun 2025 22:27:57 +0545 Subject: [PATCH] feat: add mobile transaction verification functionality for esewa --- esewa/types.go | 26 ++++++++++++++++++++ esewa/verify.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 esewa/verify.go diff --git a/esewa/types.go b/esewa/types.go index e36ccc3..66e08f2 100644 --- a/esewa/types.go +++ b/esewa/types.go @@ -39,3 +39,29 @@ type EsewaConfig struct { signatureMap map[string]string ReponsePayload *EsewaVerifyPayload } + +type VerifyInput struct { + TxnRefId string + ProductId string + Amount string + MerchantId string + MerchantSecret string + Environment string +} + +type EsewaTransactionVerificationResponse struct { + ProductId string `json:"productId"` + ProductName string `json:"productName"` + TotalAmount string `json:"totalAmount"` + Code string `json:"code"` + Message struct { + TechnicalSuccessMessage string `json:"technicalSuccessMessage"` + SuccessMessage string `json:"successMessage"` + } `json:"message"` + TransactionDetails struct { + Date string `json:"date"` + ReferenceId string `json:"referenceId"` + Status string `json:"status"` + } `json:"transactionDetails"` + MerchantName string `json:"merchantName"` +} diff --git a/esewa/verify.go b/esewa/verify.go new file mode 100644 index 0000000..807233e --- /dev/null +++ b/esewa/verify.go @@ -0,0 +1,64 @@ +package esewa + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "net/http" +) + +func VerifyMobileTransaction(input VerifyInput) ([]byte, error) { + if input.TxnRefId == "" && (input.ProductId == "" || input.Amount == "") { + return nil, errors.New("either txnRefId or both productId and amount must be provided") + } + + baseURL := "https://rc.esewa.com.np/mobile/transaction" + if input.Environment == "live" { + baseURL = "https://esewa.com.np/mobile/transaction" + } + var url string + if input.TxnRefId != "" { + url = fmt.Sprintf("%s?txnRefId=%s", baseURL, input.TxnRefId) + } else { + url = fmt.Sprintf("%s?productId=%s&amount=%s", baseURL, input.ProductId, input.Amount) + } + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + // Set merchantId and merchantSecret as headers if provided + if input.MerchantId != "" { + req.Header.Set("merchantId", input.MerchantId) + } + if input.MerchantSecret != "" { + req.Header.Set("merchantSecret", input.MerchantSecret) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return body, fmt.Errorf("verification failed: status %d", resp.StatusCode) + } + + return body, nil +} + +func ParseVerificationResponse(data []byte) ([]EsewaTransactionVerificationResponse, error) { + var resp []EsewaTransactionVerificationResponse + err := json.Unmarshal(data, &resp) + if err != nil { + return nil, err + } + return resp, nil +}