Fix Chapa verify JSON parsing when amount is numeric.
Accept string or number for amount in verify and webhook payloads so GET /payments/verify can complete successfully. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
632371c3d0
commit
a83745fd93
|
|
@ -1,5 +1,41 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ChapaFlexibleString unmarshals JSON string or number (Chapa verify/webhook payloads vary).
|
||||
type ChapaFlexibleString string
|
||||
|
||||
func (s *ChapaFlexibleString) UnmarshalJSON(data []byte) error {
|
||||
if len(data) == 0 || string(data) == "null" {
|
||||
*s = ""
|
||||
return nil
|
||||
}
|
||||
switch data[0] {
|
||||
case '"':
|
||||
var v string
|
||||
if err := json.Unmarshal(data, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
*s = ChapaFlexibleString(v)
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
|
||||
var n json.Number
|
||||
if err := json.Unmarshal(data, &n); err != nil {
|
||||
return err
|
||||
}
|
||||
*s = ChapaFlexibleString(n.String())
|
||||
default:
|
||||
return fmt.Errorf("chapa flexible string: unsupported json type %q", data[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s ChapaFlexibleString) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// ChapaInitializeRequest is sent to POST /transaction/initialize.
|
||||
type ChapaInitializeRequest struct {
|
||||
Amount string `json:"amount"`
|
||||
|
|
@ -32,13 +68,13 @@ type ChapaVerifyResponse struct {
|
|||
}
|
||||
|
||||
type ChapaTransactionData struct {
|
||||
TxRef string `json:"tx_ref"`
|
||||
Reference string `json:"reference"`
|
||||
Amount string `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
Status string `json:"status"`
|
||||
PaymentMethod string `json:"payment_method"`
|
||||
Mode string `json:"mode"`
|
||||
TxRef string `json:"tx_ref"`
|
||||
Reference string `json:"reference"`
|
||||
Amount ChapaFlexibleString `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
Status string `json:"status"`
|
||||
PaymentMethod string `json:"payment_method"`
|
||||
Mode string `json:"mode"`
|
||||
}
|
||||
|
||||
// ChapaWebhookPayload is the body POSTed to the webhook URL.
|
||||
|
|
@ -48,7 +84,7 @@ type ChapaWebhookPayload struct {
|
|||
TxRef string `json:"tx_ref"`
|
||||
Reference string `json:"reference"`
|
||||
Status string `json:"status"`
|
||||
Amount string `json:"amount"`
|
||||
Amount ChapaFlexibleString `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
PaymentMethod string `json:"payment_method"`
|
||||
Mode string `json:"mode"`
|
||||
|
|
|
|||
44
internal/domain/chapa_test.go
Normal file
44
internal/domain/chapa_test.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestChapaFlexibleString_UnmarshalJSON(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
raw string
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "string amount", raw: `"500.00"`, want: "500.00"},
|
||||
{name: "number amount", raw: `500`, want: "500"},
|
||||
{name: "float amount", raw: `499.99`, want: "499.99"},
|
||||
{name: "null", raw: `null`, want: ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var s ChapaFlexibleString
|
||||
err := json.Unmarshal([]byte(tt.raw), &s)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Fatalf("err=%v wantErr=%v", err, tt.wantErr)
|
||||
}
|
||||
if s.String() != tt.want {
|
||||
t.Fatalf("got %q want %q", s.String(), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChapaVerifyResponse_UnmarshalNumberAmount(t *testing.T) {
|
||||
raw := `{"status":"success","message":"ok","data":{"tx_ref":"tx-1","reference":"ref-1","amount":500,"currency":"ETB","status":"success","payment_method":"telebirr"}}`
|
||||
var resp ChapaVerifyResponse
|
||||
if err := json.Unmarshal([]byte(raw), &resp); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if resp.Data.Amount.String() != "500" {
|
||||
t.Fatalf("amount=%q want 500", resp.Data.Amount.String())
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user