diff --git a/internal/api/connections_test.go b/internal/api/connections_test.go index 87d94941..f8ac170d 100644 --- a/internal/api/connections_test.go +++ b/internal/api/connections_test.go @@ -182,8 +182,8 @@ func TestServer_CreateConnection(t *testing.T) { reqBytes, err := json.Marshal(tc.body) require.NoError(t, err) req, err := http.NewRequest(http.MethodPost, parsedURL.String(), bytes.NewBuffer(reqBytes)) - req.SetBasicAuth(tc.auth()) require.NoError(t, err) + req.SetBasicAuth(tc.auth()) handler.ServeHTTP(rr, req) diff --git a/internal/api/payment.go b/internal/api/payment.go index b9ee7f85..163a7be0 100644 --- a/internal/api/payment.go +++ b/internal/api/payment.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -10,6 +11,7 @@ import ( comm "github.com/iden3/iden3comm/v2" "github.com/polygonid/sh-id-platform/internal/log" + "github.com/polygonid/sh-id-platform/internal/repositories" ) // GetPaymentOptions is the controller to get payment options @@ -50,6 +52,9 @@ func (s *Server) CreatePaymentOption(ctx context.Context, request CreatePaymentO id, err := s.paymentService.CreatePaymentOption(ctx, issuerDID, request.Body.Name, request.Body.Description, request.Body.Config) if err != nil { log.Error(ctx, "creating payment option", "err", err, "issuer", issuerDID, "request", request.Body) + if errors.Is(err, repositories.ErrIdentityNotFound) { + return CreatePaymentOption400JSONResponse{N400JSONResponse{Message: "invalid issuer did"}}, nil + } return CreatePaymentOption500JSONResponse{N500JSONResponse{Message: fmt.Sprintf("can't create payment-option: <%s>", err.Error())}}, nil } return CreatePaymentOption201JSONResponse{Id: id.String()}, nil diff --git a/internal/api/payment_test.go b/internal/api/payment_test.go index a8d38954..be6a18f4 100644 --- a/internal/api/payment_test.go +++ b/internal/api/payment_test.go @@ -1,16 +1,54 @@ package api import ( + "bytes" "context" "encoding/json" + "fmt" "net/http" "net/http/httptest" "testing" + "github.com/iden3/go-iden3-core/v2/w3c" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/polygonid/sh-id-platform/internal/core/ports" ) +const paymentOptionConfigurationTesting = ` +{ + "Chains": [ + { + "ChainId": 137, + "Recipient": "0x..", + "SigningKeyId": "", + "Iden3PaymentRailsRequestV1": { + "Amount": "0.01", + "Currency": "POL" + }, + "Iden3PaymentRailsERC20RequestV1": { + "USDT": { + "Amount": "3" + }, + "USDC": { + "Amount": "3" + } + } + }, + { + "ChainId": 1101, + "Recipient": "0x..", + "SigningKeyId": "", + "Iden3PaymentRailsRequestV1": { + "Amount": "0.5", + "Currency": "ETH" + } + } + ] +} +` + func TestServer_GetPaymentSettings(t *testing.T) { ctx := context.Background() @@ -27,3 +65,105 @@ func TestServer_GetPaymentSettings(t *testing.T) { var response GetPaymentSettings200JSONResponse require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response)) } + +func TestServer_CreatePaymentOption(t *testing.T) { + const ( + method = "polygonid" + blockchain = "polygon" + network = "amoy" + BJJ = "BJJ" + ) + + var config map[string]interface{} + ctx := context.Background() + + server := newTestServer(t, nil) + handler := getHandler(ctx, server) + + iden, err := server.Services.identity.Create(ctx, "polygon-test", &ports.DIDCreationOptions{Method: method, Blockchain: blockchain, Network: network, KeyType: BJJ}) + require.NoError(t, err) + issuerDID, err := w3c.ParseDID(iden.Identifier) + require.NoError(t, err) + + otherDID, err := w3c.ParseDID("did:polygonid:polygon:amoy:2qRYvPBNBTkPaHk1mKBkcLTequfAdsHzXv549ktnL5") + require.NoError(t, err) + + require.NoError(t, json.Unmarshal([]byte(paymentOptionConfigurationTesting), &config)) + + type expected struct { + httpCode int + msg string + } + + for _, tc := range []struct { + name string + issuerDID w3c.DID + auth func() (string, string) + body CreatePaymentOptionJSONRequestBody + expected expected + }{ + { + name: "no auth header", + auth: authWrong, + issuerDID: *issuerDID, + body: CreatePaymentOptionJSONRequestBody{ + Config: config, + Description: "Payment Option explanation", + Name: "1 POL Payment", + }, + expected: expected{ + httpCode: http.StatusUnauthorized, + msg: "Unauthorized", + }, + }, + { + name: "Happy Path", + auth: authOk, + issuerDID: *issuerDID, + body: CreatePaymentOptionJSONRequestBody{ + Config: config, + Description: "Payment Option explanation", + Name: "1 POL Payment", + }, + expected: expected{ + httpCode: http.StatusCreated, + }, + }, + { + name: "Not existing issuerDID", + auth: authOk, + issuerDID: *otherDID, + body: CreatePaymentOptionJSONRequestBody{ + Config: config, + Description: "Payment Option explanation", + Name: "1 POL Payment", + }, + expected: expected{ + httpCode: http.StatusBadRequest, + msg: "invalid issuer did", + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + rr := httptest.NewRecorder() + payload, err := json.Marshal(tc.body) + require.NoError(t, err) + url := fmt.Sprintf("/v2/identities/%s/payment/options", tc.issuerDID.String()) + req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payload)) + assert.NoError(t, err) + req.SetBasicAuth(tc.auth()) + + handler.ServeHTTP(rr, req) + require.Equal(t, tc.expected.httpCode, rr.Code) + switch tc.expected.httpCode { + case http.StatusCreated: + var response CreatePaymentOption201JSONResponse + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response)) + case http.StatusBadRequest: + var response CreatePaymentOption400JSONResponse + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response)) + assert.Equal(t, tc.expected.msg, response.Message) + } + }) + } +} diff --git a/internal/repositories/payment.go b/internal/repositories/payment.go index 06a913f8..5155dc47 100644 --- a/internal/repositories/payment.go +++ b/internal/repositories/payment.go @@ -13,8 +13,8 @@ import ( "github.com/polygonid/sh-id-platform/internal/db" ) -// PaymentOptionNotFound error -var PaymentOptionNotFound = errors.New("payment option not found") +// ErrPaymentOptionNotFound error +var ErrPaymentOptionNotFound = errors.New("payment option not found") // Payment repository type Payment struct { @@ -35,7 +35,9 @@ VALUES ($1, $2, $3, $4, $5, $6, $7); _, err := p.conn.Pgx.Exec(ctx, query, opt.ID, opt.IssuerDID.String(), opt.Name, opt.Description, opt.Config, opt.CreatedAt, opt.UpdatedAt) if err != nil { - return uuid.Nil, err + if strings.Contains(err.Error(), "violates foreign key constraint") { + return uuid.Nil, ErrIdentityNotFound + } } return opt.ID, nil } @@ -85,7 +87,7 @@ AND issuer_did = $2;` err := p.conn.Pgx.QueryRow(ctx, query, id, issuerDID.String()).Scan(&opt.ID, &strIssuerDID, &opt.Name, &opt.Description, &opt.Config, &opt.CreatedAt, &opt.UpdatedAt) if err != nil { if strings.Contains(err.Error(), "no rows in result set") { - return nil, PaymentOptionNotFound + return nil, ErrPaymentOptionNotFound } return nil, err }