From e159dc21820792d861c32247bfb801419cd899f8 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Fri, 8 Mar 2024 10:46:42 -0300 Subject: [PATCH 01/14] implementation, unit test, integration test and example --- examples/apis/preapproval/create/main.go | 38 ++ examples/apis/preapproval/get/main.go | 28 ++ examples/apis/preapproval/search/main.go | 36 ++ examples/apis/preapproval/update/main.go | 56 +++ pkg/preapproval/client.go | 95 ++++ pkg/preapproval/client_test.go | 458 ++++++++++++++++++ pkg/preapproval/request.go | 36 ++ pkg/preapproval/response.go | 61 +++ pkg/preapproval/search_request.go | 40 ++ pkg/preapproval/search_response.go | 44 ++ pkg/preapproval/update_request.go | 23 + .../mocks/preapproval/create_response.json | 34 ++ resources/mocks/preapproval/get_response.json | 34 ++ .../mocks/preapproval/search_response.json | 31 ++ .../mocks/preapproval/update_response.json | 34 ++ .../preapproval/preapproval_test.go | 150 ++++++ 16 files changed, 1198 insertions(+) create mode 100644 examples/apis/preapproval/create/main.go create mode 100644 examples/apis/preapproval/get/main.go create mode 100644 examples/apis/preapproval/search/main.go create mode 100644 examples/apis/preapproval/update/main.go create mode 100644 pkg/preapproval/client.go create mode 100644 pkg/preapproval/client_test.go create mode 100644 pkg/preapproval/request.go create mode 100644 pkg/preapproval/response.go create mode 100644 pkg/preapproval/search_request.go create mode 100644 pkg/preapproval/search_response.go create mode 100644 pkg/preapproval/update_request.go create mode 100644 resources/mocks/preapproval/create_response.json create mode 100644 resources/mocks/preapproval/get_response.json create mode 100644 resources/mocks/preapproval/search_response.json create mode 100644 resources/mocks/preapproval/update_response.json create mode 100644 test/integration/preapproval/preapproval_test.go diff --git a/examples/apis/preapproval/create/main.go b/examples/apis/preapproval/create/main.go new file mode 100644 index 00000000..0dd75b47 --- /dev/null +++ b/examples/apis/preapproval/create/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "context" + "fmt" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/preapproval" +) + +func main() { + cfg, err := config.New("{{ACCESS_TOKEN}}") + if err != nil { + fmt.Println(err) + return + } + + req := preapproval.Request{ + AutoRecurring: &preapproval.AutoRecurringRequest{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + }, + BackURL: "https://www.yoursite.com", + ExternalReference: "Ref-123", + PayerEmail: "test_user_28355466@testuser.com", + Reason: "Yoga Class", + } + + client := preapproval.NewClient(cfg) + result, err := client.Create(context.Background(), req) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/examples/apis/preapproval/get/main.go b/examples/apis/preapproval/get/main.go new file mode 100644 index 00000000..238296cb --- /dev/null +++ b/examples/apis/preapproval/get/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "context" + "fmt" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/preapproval" +) + +func main() { + cfg, err := config.New("{{ACCESS_TOKEN}}") + if err != nil { + fmt.Println(err) + return + } + + client := preapproval.NewClient(cfg) + + preApprovalID := "123" + + result, err := client.Get(context.Background(), preApprovalID) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/examples/apis/preapproval/search/main.go b/examples/apis/preapproval/search/main.go new file mode 100644 index 00000000..c0a8bf62 --- /dev/null +++ b/examples/apis/preapproval/search/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "context" + "fmt" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/preapproval" +) + +func main() { + cfg, err := config.New("{{ACCESS_TOKEN}}") + if err != nil { + fmt.Println(err) + return + } + + client := preapproval.NewClient(cfg) + + filters := preapproval.SearchRequest{ + Limit: "10", + Offset: "10", + Filters: map[string]string{ + "payer_id": "123123123", + }, + } + + result, err := client.Search(context.Background(), filters) + if err != nil { + fmt.Println(err) + return + } + + for _, plan := range result.Results { + fmt.Println(plan) + } +} diff --git a/examples/apis/preapproval/update/main.go b/examples/apis/preapproval/update/main.go new file mode 100644 index 00000000..392d0be0 --- /dev/null +++ b/examples/apis/preapproval/update/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "context" + "fmt" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/preapproval" +) + +func main() { + cfg, err := config.New("{{ACCESS_TOKEN}}") + if err != nil { + fmt.Println(err) + return + } + + req := preapproval.Request{ + AutoRecurring: &preapproval.AutoRecurringRequest{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + }, + BackURL: "https://www.yoursite.com", + ExternalReference: "Ref-123", + PayerEmail: "test_user_28355466@testuser.com", + Reason: "Yoga Class", + } + + client := preapproval.NewClient(cfg) + result, err := client.Create(context.Background(), req) + if err != nil { + fmt.Println(err) + return + } + + update := preapproval.UpdateRequest{ + AutoRecurring: &preapproval.AutoRecurringRequest{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + }, + BackURL: "https://www.yoursite.com", + ExternalReference: "Ref-123", + Reason: "Yoga Class", + } + + result, err = client.Update(context.Background(), update, result.ID) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/pkg/preapproval/client.go b/pkg/preapproval/client.go new file mode 100644 index 00000000..7785c0e3 --- /dev/null +++ b/pkg/preapproval/client.go @@ -0,0 +1,95 @@ +package preapproval + +import ( + "context" + "fmt" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/internal/baseclient" + "net/url" + "strings" +) + +const ( + urlBase = "https://api.mercadopago.com/preapproval" + urlWithID = urlBase + "/{id}" + urlSearch = urlBase + "/search" +) + +// Client contains the methods to interact with the Pre Approval API. +type Client interface { + // Create creates a new pre-approval. + // It is a post request to the endpoint: https://api.mercadopago.com/preapproval + // Reference: https://www.mercadopago.com/developers/en/reference/subscriptions/_preapproval/post + Create(ctx context.Context, request Request) (*Response, error) + + // Get finds a pre-approval by ID. + // It is a get request to the endpoint: https://api.mercadopago.com/preapproval/{id} + // Reference: https://www.mercadopago.com/developers/en/reference/subscriptions/_preapproval_id/get + Get(ctx context.Context, id string) (*Response, error) + + // Update updates details a pre-approval by ID. + // It is a put request to the endpoint: https://api.mercadopago.com/preapproval/{id} + // Reference: https://www.mercadopago.com/developers/en/reference/subscriptions/_preapproval_id/put + Update(ctx context.Context, request UpdateRequest, id string) (*Response, error) + + // Search finds all pre-approval information generated through specific filters. + // It is a get request to the endpoint: https://api.mercadopago.com/preapproval/search + // Reference: https://www.mercadopago.com/developers/en/reference/subscriptions/_preapproval_search/get + Search(ctx context.Context, request SearchRequest) (*SearchResponse, error) +} + +// client is the implementation of Client. +type client struct { + cfg *config.Config +} + +// NewClient returns a new Pre Approval API Client. +func NewClient(c *config.Config) Client { + return &client{ + cfg: c, + } +} + +func (c *client) Create(ctx context.Context, request Request) (*Response, error) { + result, err := baseclient.Post[*Response](ctx, c.cfg, urlBase, request) + if err != nil { + return nil, err + } + + return result, nil +} + +func (c *client) Get(ctx context.Context, id string) (*Response, error) { + result, err := baseclient.Get[*Response](ctx, c.cfg, strings.Replace(urlWithID, "{id}", id, 1)) + if err != nil { + return nil, err + } + + return result, nil +} + +func (c *client) Update(ctx context.Context, request UpdateRequest, id string) (*Response, error) { + result, err := baseclient.Put[*Response](ctx, c.cfg, strings.Replace(urlWithID, "{id}", id, 1), request) + if err != nil { + return nil, err + } + + return result, nil +} + +func (c *client) Search(ctx context.Context, request SearchRequest) (*SearchResponse, error) { + params := request.Parameters() + + parsedURL, err := url.Parse(urlSearch) + if err != nil { + return nil, fmt.Errorf("error parsing url: %w", err) + } + parsedURL.RawQuery = params + + result, err := baseclient.Get[*SearchResponse](ctx, c.cfg, parsedURL.String()) + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/pkg/preapproval/client_test.go b/pkg/preapproval/client_test.go new file mode 100644 index 00000000..78cf360c --- /dev/null +++ b/pkg/preapproval/client_test.go @@ -0,0 +1,458 @@ +package preapproval + +import ( + "context" + "fmt" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/internal/httpclient" + "io" + "net/http" + "os" + "reflect" + "strings" + "testing" + "time" +) + +var ( + createResponseJSON, _ = os.Open("../../resources/mocks/preapproval/create_response.json") + createResponse, _ = io.ReadAll(createResponseJSON) + getResponseJSON, _ = os.Open("../../resources/mocks/preapproval/get_response.json") + getResponse, _ = io.ReadAll(getResponseJSON) + updateResponseJSON, _ = os.Open("../../resources/mocks/preapproval/update_response.json") + updateResponse, _ = io.ReadAll(updateResponseJSON) + searchResponseJSON, _ = os.Open("../../resources/mocks/preapproval/search_response.json") + searchResponse, _ = io.ReadAll(searchResponseJSON) +) + +func TestCreate(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + request Request + } + tests := []struct { + name string + fields fields + args args + want *Response + wantErr string + }{ + { + name: "should_fail_to_send_request", + fields: fields{ + config: &config.Config{ + Requester: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + return nil, fmt.Errorf("some error") + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "transport level error: some error", + }, + { + name: "should_return_response", + fields: fields{ + config: &config.Config{ + Requester: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(createResponse)) + stringReaderCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReaderCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: &Response{ + ID: "2c938084726fca480172750000000000", + PayerID: 123123123, + PayerEmail: "", + BackURL: "https://www.mercadopago.com.br", + CollectorID: 123123123, + ApplicationID: 123123123, + Status: "pending", + Reason: "reason", + ExternalReference: "Ref-123", + DateCreated: parseDate("2024-03-06T18:10:01.329-04:00"), + LastModified: parseDate("2024-03-06T18:10:01.579-04:00"), + InitPoint: "https://www.mercadopago.com.br/subscriptions/checkout?preapproval_id=2c938084726fca480172750000000000", + AutoRecurring: AutoRecurringResponse{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + FreeTrial: FreeTrialResponse{}, + }, + Summarized: SummarizedResponse{ + Quotas: 0, + ChargedQuantity: 0, + PendingChargeQuantity: 0, + ChargedAmount: 0, + LastChargedDate: nil, + LastChargedAmount: nil, + }, + NextPaymentDate: parseDate("2024-03-06T18:10:01.000-04:00"), + PaymentMethodID: "", + FirstInvoiceOffset: "", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + cfg: tt.fields.config, + } + got, err := c.Create(tt.args.ctx, tt.args.request) + gotErr := "" + if err != nil { + gotErr = err.Error() + } + + if gotErr != tt.wantErr { + t.Errorf("client.Create() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Create() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGet(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + id string + } + tests := []struct { + name string + fields fields + args args + want *Response + wantErr string + }{ + { + name: "should_return_error_when_send_request", + fields: fields{ + config: &config.Config{ + Requester: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + return nil, fmt.Errorf("some error") + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "transport level error: some error", + }, + { + name: "should_return_response", + fields: fields{ + config: &config.Config{ + Requester: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(getResponse)) + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + id: "2c938084726fca480172750000000000", + }, + want: &Response{ + ID: "2c938084726fca480172750000000000", + PayerID: 123123123, + PayerEmail: "", + BackURL: "https://www.mercadopago.com.br", + CollectorID: 123123123, + ApplicationID: 123123123, + Status: "pending", + Reason: "reason", + ExternalReference: "Ref-123", + DateCreated: parseDate("2024-03-06T18:10:01.329-04:00"), + LastModified: parseDate("2024-03-06T18:10:01.579-04:00"), + InitPoint: "https://www.mercadopago.com.br/subscriptions/checkout?preapproval_id=2c938084726fca480172750000000000", + AutoRecurring: AutoRecurringResponse{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + FreeTrial: FreeTrialResponse{}, + }, + Summarized: SummarizedResponse{ + Quotas: 0, + ChargedQuantity: 0, + PendingChargeQuantity: 0, + ChargedAmount: 0, + LastChargedDate: nil, + LastChargedAmount: nil, + }, + NextPaymentDate: parseDate("2024-03-06T18:10:01.000-04:00"), + PaymentMethodID: "", + FirstInvoiceOffset: "", + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + cfg: tt.fields.config, + } + got, err := c.Get(tt.args.ctx, tt.args.id) + gotErr := "" + if err != nil { + gotErr = err.Error() + } + + if gotErr != tt.wantErr { + t.Errorf("client.Get() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("client.Get() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestSearch(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + request SearchRequest + } + tests := []struct { + name string + fields fields + args args + want *SearchResponse + wantErr string + }{ + { + name: "should_return_error_when_send_request", + fields: fields{ + config: &config.Config{ + Requester: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + return nil, fmt.Errorf("some error") + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "transport level error: some error", + }, + { + name: "should_return_response", + fields: fields{ + config: &config.Config{ + Requester: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(searchResponse)) + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + request: SearchRequest{ + Limit: "10", + }, + }, + want: &SearchResponse{ + Paging: PagingResponse{ + Offset: 0, + Limit: 10, + Total: 10, + }, + Results: []SearchResults{ + { + ID: "2c938084726fca480172750000000000", + Status: "pending", + Reason: "Yoga classes", + Summarized: SummarizedResponse{}, + PayerID: 123123123, + BackURL: "https://www.mercadopago.com.br", + CollectorID: 123123123, + ApplicationID: 123123123, + ExternalReference: "Ref-123", + DateCreated: parseDate("2023-10-10T10:00:32.895-04:00"), + LastModified: parseDate("2023-10-10T10:00:32.896-04:00"), + InitPoint: "https://www.mercadopago.com.br/subscriptions/checkout?preapproval_id=2c938084726fca480172750000000000", + AutoRecurring: AutoRecurringResponse{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 10.0, + CurrencyID: "BRL", + }, + PayerFirstName: "Test", + PayerLastName: "", + }, + }, + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + cfg: tt.fields.config, + } + got, err := c.Search(tt.args.ctx, tt.args.request) + gotErr := "" + if err != nil { + gotErr = err.Error() + } + if gotErr != tt.wantErr { + t.Errorf("client.Search() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("client.Search() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestUpdate(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + request UpdateRequest + id string + } + tests := []struct { + name string + fields fields + args args + want *Response + wantErr string + }{ + { + name: "should_return_error_when_send_request", + fields: fields{ + config: &config.Config{ + Requester: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + return nil, fmt.Errorf("some error") + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "transport level error: some error", + }, + { + name: "should_return_response", + fields: fields{ + config: &config.Config{ + Requester: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(updateResponse)) + stringReaderCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReaderCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + id: "2c938084726fca480172750000000000", + }, + want: &Response{ + ID: "2c938084726fca480172750000000000", + PayerID: 123123123, + PayerEmail: "", + BackURL: "https://www.mercadopago.com.br", + CollectorID: 123123123, + ApplicationID: 123123123, + Status: "pending", + Reason: "reason", + ExternalReference: "Ref-123", + DateCreated: parseDate("2024-03-06T18:10:01.329-04:00"), + LastModified: parseDate("2024-03-07T17:48:00.821-04:00"), + InitPoint: "https://www.mercadopago.com.br/subscriptions/checkout?preapproval_id=2c938084726fca480172750000000000", + AutoRecurring: AutoRecurringResponse{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 50.0, + CurrencyID: "BRL", + FreeTrial: FreeTrialResponse{}, + }, + Summarized: SummarizedResponse{ + Quotas: 0, + ChargedQuantity: 0, + PendingChargeQuantity: 0, + ChargedAmount: 0, + Semaphore: "", + LastChargedDate: nil, + LastChargedAmount: nil, + }, + NextPaymentDate: parseDate("2024-03-06T18:10:01.000-04:00"), + PaymentMethodID: "", + FirstInvoiceOffset: "", + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + cfg: tt.fields.config, + } + got, err := c.Update(tt.args.ctx, tt.args.request, tt.args.id) + gotErr := "" + if err != nil { + gotErr = err.Error() + } + if gotErr != tt.wantErr { + t.Errorf("client.Create() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("client.Create() got = %v, want %v", got, tt.want) + } + }) + } +} + +func parseDate(s string) *time.Time { + d, _ := time.Parse(time.RFC3339, s) + return &d +} diff --git a/pkg/preapproval/request.go b/pkg/preapproval/request.go new file mode 100644 index 00000000..d7647570 --- /dev/null +++ b/pkg/preapproval/request.go @@ -0,0 +1,36 @@ +package preapproval + +import "time" + +// Request represents a request for creating a pre approval. +type Request struct { + AutoRecurring *AutoRecurringRequest `json:"auto_recurring,omitempty"` + + CardTokenID string `json:"card_token_id,omitempty"` + PreapprovalPlanID string `json:"preapproval_plan_id,omitempty"` + PayerEmail string `json:"payer_email,omitempty"` + BackURL string `json:"back_url,omitempty"` + CollectorID string `json:"collector_id,omitempty"` + Reason string `json:"reason,omitempty"` + ExternalReference string `json:"external_reference,omitempty"` + Status string `json:"status,omitempty"` +} + +// AutoRecurringRequest represents the recurrence settings. +type AutoRecurringRequest struct { + StartDate *time.Time `json:"start_date,omitempty"` + EndDate *time.Time `json:"end_date,omitempty"` + FreeTrial *FreeTrialRequest `json:"free_trial,omitempty"` + + CurrencyID string `json:"currency_id,omitempty"` + FrequencyType string `json:"frequency_type,omitempty"` + TransactionAmount float64 `json:"transaction_amount,omitempty"` + Frequency int `json:"frequency,omitempty"` +} + +// FreeTrialRequest represents the free trial settings. +type FreeTrialRequest struct { + FrequencyType string `json:"frequency_type"` + Frequency int `json:"frequency"` + FirstInvoiceOffset int `json:"first_invoice_offset"` +} diff --git a/pkg/preapproval/response.go b/pkg/preapproval/response.go new file mode 100644 index 00000000..44b9c171 --- /dev/null +++ b/pkg/preapproval/response.go @@ -0,0 +1,61 @@ +package preapproval + +import "time" + +// Response represents the response from the pre-approval endpoint. +type Response struct { + AutoRecurring AutoRecurringResponse `json:"auto_recurring"` + Summarized SummarizedResponse `json:"summarized"` + DateCreated *time.Time `json:"date_created"` + LastModified *time.Time `json:"last_modified"` + NextPaymentDate *time.Time `json:"next_payment_date"` + + ID string `json:"id"` + PayerEmail string `json:"payer_email"` + Status string `json:"status"` + Reason string `json:"reason"` + ExternalReference string `json:"external_reference"` + InitPoint string `json:"init_point"` + SandBoxInitPoint string `json:"sandbox_init_point"` + PaymentMethodID string `json:"payment_method_id"` + FirstInvoiceOffset string `json:"first_invoice_offset"` + BackURL string `json:"back_url"` + PreapprovalPlan string `json:"preapproval_plan_id"` + CardID int `json:"card_id"` + Version int `json:"version"` + PayerID int `json:"payer_id"` + CollectorID int `json:"collector_id"` + ApplicationID int `json:"application_id"` +} + +// AutoRecurringResponse represents the recurrence settings. +type AutoRecurringResponse struct { + FreeTrial FreeTrialResponse `json:"free_trial"` + StartDate *time.Time `json:"start_date"` + EndDate *time.Time `json:"end_date"` + + CurrencyID string `json:"currency_id"` + FrequencyType string `json:"frequency_type"` + Frequency int `json:"frequency"` + TransactionAmount float64 `json:"transaction_amount"` +} + +// FreeTrialResponse represents the free trial settings. +type FreeTrialResponse struct { + FrequencyType string `json:"frequency_type"` + Frequency int `json:"frequency"` + FirstInvoiceOffset int `json:"first_invoice_offset"` +} + +// SummarizedResponse contains summary information about invoices and subscription charges +type SummarizedResponse struct { + LastChargedDate *time.Time `json:"last_charged_date,omitempty"` + LastChargedAmount *time.Time `json:"last_charged_amount"` + + Quotas int `json:"quotas"` + PendingChargeQuantity int `json:"pending_charge_quantity"` + ChargedQuantity int `json:"charged_quantity"` + PendingChargeAmount float64 `json:"pending_charge_amount"` + ChargedAmount float64 `json:"charged_amount"` + Semaphore string `json:"semaphore"` +} diff --git a/pkg/preapproval/search_request.go b/pkg/preapproval/search_request.go new file mode 100644 index 00000000..2e609ede --- /dev/null +++ b/pkg/preapproval/search_request.go @@ -0,0 +1,40 @@ +package preapproval + +import "net/url" + +// SearchRequest contains filters accepted in search. +// Filters field can receive a lot of parameters. For details, see: +// https://www.mercadopago.com.br/developers/pt/reference/subscriptions/_preapproval_search/get +type SearchRequest struct { + Filters map[string]string + + Limit string + Offset string +} + +// Parameters transforms SearchRequest into url params. +func (s SearchRequest) Parameters() string { + params := url.Values{} + + for k, v := range s.Filters { + params.Add(k, v) + } + + if _, ok := s.Filters["limit"]; !ok { + limit := "30" + if s.Limit != "" { + limit = s.Limit + } + params.Add("limit", limit) + } + + if _, ok := s.Filters["offset"]; !ok { + offset := "0" + if s.Offset != "" { + offset = s.Offset + } + params.Add("offset", offset) + } + + return params.Encode() +} diff --git a/pkg/preapproval/search_response.go b/pkg/preapproval/search_response.go new file mode 100644 index 00000000..6fe0fa10 --- /dev/null +++ b/pkg/preapproval/search_response.go @@ -0,0 +1,44 @@ +package preapproval + +import "time" + +// SearchResponse represents the response from the search endpoint. +type SearchResponse struct { + Results []SearchResults `json:"results"` + Paging PagingResponse `json:"paging"` +} + +// PagingResponse represents the paging information within SearchResponse. +type PagingResponse struct { + Total int `json:"total"` + Limit int `json:"limit"` + Offset int `json:"offset"` +} + +// SearchResults contains the information of a preapproval. +type SearchResults struct { + AutoRecurring AutoRecurringResponse `json:"auto_recurring"` + Summarized SummarizedResponse `json:"summarized"` + DateCreated *time.Time `json:"date_created"` + LastModified *time.Time `json:"last_modified"` + NextPaymentDate *time.Time `json:"next_payment_date"` + + ID string `json:"id"` + PayerEmail string `json:"payer_email"` + Status string `json:"status"` + Reason string `json:"reason"` + ExternalReference string `json:"external_reference"` + InitPoint string `json:"init_point"` + SandBoxInitPoint string `json:"sandbox_init_point"` + PaymentMethodID string `json:"payment_method_id"` + FirstInvoiceOffset string `json:"first_invoice_offset"` + BackURL string `json:"back_url"` + PreApprovalPlanID string `json:"preapproval_plan_id"` + CardID int `json:"card_id"` + PayerID int `json:"payer_id"` + CollectorID int `json:"collector_id"` + ApplicationID int `json:"application_id"` + Version int `json:"version"` + PayerFirstName string `json:"payer_first_name"` + PayerLastName string `json:"payer_last_name"` +} diff --git a/pkg/preapproval/update_request.go b/pkg/preapproval/update_request.go new file mode 100644 index 00000000..704f7445 --- /dev/null +++ b/pkg/preapproval/update_request.go @@ -0,0 +1,23 @@ +package preapproval + +import "time" + +// UpdateRequest represents a request for creating a pre approval. +type UpdateRequest struct { + AutoRecurring *AutoRecurringRequest `json:"auto_recurring,omitempty"` + + CardTokenID string `json:"card_token_id,omitempty"` + PayerEmail string `json:"payer_email,omitempty"` + BackURL string `json:"back_url,omitempty"` + Reason string `json:"reason,omitempty"` + ExternalReference string `json:"external_reference,omitempty"` + Status string `json:"status,omitempty"` +} + +// UpdateAutoRecurringRequest represents the recurrence settings. +type UpdateAutoRecurringRequest struct { + StartDate *time.Time `json:"start_date,omitempty"` + + CurrencyID string `json:"currency_id,omitempty"` + TransactionAmount float64 `json:"transaction_amount,omitempty"` +} diff --git a/resources/mocks/preapproval/create_response.json b/resources/mocks/preapproval/create_response.json new file mode 100644 index 00000000..e920232a --- /dev/null +++ b/resources/mocks/preapproval/create_response.json @@ -0,0 +1,34 @@ +{ + "id": "2c938084726fca480172750000000000", + "payer_id": 123123123, + "payer_email": "", + "back_url": "https://www.mercadopago.com.br", + "collector_id": 123123123, + "application_id": 123123123, + "status": "pending", + "reason": "reason", + "external_reference": "Ref-123", + "date_created": "2024-03-06T18:10:01.329-04:00", + "last_modified": "2024-03-06T18:10:01.579-04:00", + "init_point": "https://www.mercadopago.com.br/subscriptions/checkout?preapproval_id=2c938084726fca480172750000000000", + "auto_recurring": { + "frequency": 1, + "frequency_type": "months", + "transaction_amount": 100, + "currency_id": "BRL", + "free_trial": null + }, + "summarized": { + "quotas": null, + "charged_quantity": null, + "pending_charge_quantity": null, + "charged_amount": null, + "pending_charge_amount": null, + "semaphore": null, + "last_charged_date": null, + "last_charged_amount": null + }, + "next_payment_date": "2024-03-06T18:10:01.000-04:00", + "payment_method_id": null, + "first_invoice_offset": null +} \ No newline at end of file diff --git a/resources/mocks/preapproval/get_response.json b/resources/mocks/preapproval/get_response.json new file mode 100644 index 00000000..f0f1c9f3 --- /dev/null +++ b/resources/mocks/preapproval/get_response.json @@ -0,0 +1,34 @@ +{ + "id": "2c938084726fca480172750000000000", + "payer_id": 123123123, + "payer_email": "", + "back_url": "https://www.mercadopago.com.br", + "collector_id": 123123123, + "application_id": 123123123, + "status": "pending", + "reason": "reason", + "external_reference": "Ref-123", + "date_created": "2024-03-06T18:10:01.329-04:00", + "last_modified": "2024-03-06T18:10:01.579-04:00", + "init_point": "https://www.mercadopago.com.br/subscriptions/checkout?preapproval_id=2c938084726fca480172750000000000", + "auto_recurring": { + "frequency": 1, + "frequency_type": "months", + "transaction_amount": 100.00, + "currency_id": "BRL", + "free_trial": null + }, + "summarized": { + "quotas": null, + "charged_quantity": null, + "pending_charge_quantity": null, + "charged_amount": null, + "pending_charge_amount": null, + "semaphore": null, + "last_charged_date": null, + "last_charged_amount": null + }, + "next_payment_date": "2024-03-06T18:10:01.000-04:00", + "payment_method_id": null, + "first_invoice_offset": null +} \ No newline at end of file diff --git a/resources/mocks/preapproval/search_response.json b/resources/mocks/preapproval/search_response.json new file mode 100644 index 00000000..4570b353 --- /dev/null +++ b/resources/mocks/preapproval/search_response.json @@ -0,0 +1,31 @@ +{ + "paging": { + "offset": 0, + "limit": 10, + "total": 10 + }, + "results": [ + { + "id": "2c938084726fca480172750000000000", + "status": "pending", + "reason": "Yoga classes", + "summarized": {}, + "payer_id": 123123123, + "back_url": "https://www.mercadopago.com.br", + "collector_id": 123123123, + "application_id": 123123123, + "external_reference": "Ref-123", + "date_created": "2023-10-10T10:00:32.895-04:00", + "last_modified": "2023-10-10T10:00:32.896-04:00", + "init_point": "https://www.mercadopago.com.br/subscriptions/checkout?preapproval_id=2c938084726fca480172750000000000", + "auto_recurring": { + "frequency": 1, + "frequency_type": "months", + "transaction_amount": 10.0, + "currency_id": "BRL" + }, + "payer_first_name": "Test", + "payer_last_name": "" + } + ] +} \ No newline at end of file diff --git a/resources/mocks/preapproval/update_response.json b/resources/mocks/preapproval/update_response.json new file mode 100644 index 00000000..c1a46546 --- /dev/null +++ b/resources/mocks/preapproval/update_response.json @@ -0,0 +1,34 @@ +{ + "id": "2c938084726fca480172750000000000", + "payer_id": 123123123, + "payer_email": "", + "back_url": "https://www.mercadopago.com.br", + "collector_id": 123123123, + "application_id": 123123123, + "status": "pending", + "reason": "reason", + "external_reference": "Ref-123", + "date_created": "2024-03-06T18:10:01.329-04:00", + "last_modified": "2024-03-07T17:48:00.821-04:00", + "init_point": "https://www.mercadopago.com.br/subscriptions/checkout?preapproval_id=2c938084726fca480172750000000000", + "auto_recurring": { + "frequency": 1, + "frequency_type": "months", + "transaction_amount": 50.0, + "currency_id": "BRL", + "free_trial": null + }, + "summarized": { + "quotas": null, + "charged_quantity": null, + "pending_charge_quantity": null, + "charged_amount": null, + "pending_charge_amount": null, + "semaphore": null, + "last_charged_date": null, + "last_charged_amount": null + }, + "next_payment_date": "2024-03-06T18:10:01.000-04:00", + "payment_method_id": null, + "first_invoice_offset": null +} \ No newline at end of file diff --git a/test/integration/preapproval/preapproval_test.go b/test/integration/preapproval/preapproval_test.go new file mode 100644 index 00000000..2057f5cb --- /dev/null +++ b/test/integration/preapproval/preapproval_test.go @@ -0,0 +1,150 @@ +package integration + +import ( + "context" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/preapproval" + "os" + "testing" +) + +func TestPreApproval(t *testing.T) { + t.Run("should_create_preapproval", func(t *testing.T) { + cfg, err := config.New(os.Getenv("ACCESS_TOKEN")) + if err != nil { + t.Fatal(err) + } + + client := preapproval.NewClient(cfg) + + req := preapproval.Request{ + AutoRecurring: &preapproval.AutoRecurringRequest{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + }, + BackURL: "https://www.yoursite.com", + ExternalReference: "Ref-123", + PayerEmail: "test_user_28355466@testuser.com", + Reason: "Yoga Class", + } + + result, err := client.Create(context.Background(), req) + if result == nil || result.ID == "" { + t.Error("preapproval can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) + + t.Run("should_get_preapproval", func(t *testing.T) { + cfg, err := config.New(os.Getenv("ACCESS_TOKEN")) + if err != nil { + t.Fatal(err) + } + + client := preapproval.NewClient(cfg) + + req := preapproval.Request{ + AutoRecurring: &preapproval.AutoRecurringRequest{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + }, + BackURL: "https://www.yoursite.com", + ExternalReference: "Ref-123", + PayerEmail: "test_user_28355466@testuser.com", + Reason: "Yoga Class", + } + + result, err := client.Create(context.Background(), req) + if result == nil { + t.Error("preapproval can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + return + } + + result, err = client.Get(context.Background(), result.ID) + if result == nil || result.ID == "" { + t.Error("preapproval can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) + + t.Run("should_update_preapproval", func(t *testing.T) { + cfg, err := config.New(os.Getenv("ACCESS_TOKEN")) + if err != nil { + t.Fatal(err) + } + + client := preapproval.NewClient(cfg) + + req := preapproval.Request{ + AutoRecurring: &preapproval.AutoRecurringRequest{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + }, + BackURL: "https://www.yoursite.com", + ExternalReference: "Ref-123", + PayerEmail: "test_user_28355466@testuser.com", + Reason: "Yoga Class", + } + + result, err := client.Create(context.Background(), req) + if result == nil { + t.Error("preapproval can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + return + } + + update := preapproval.UpdateRequest{ + AutoRecurring: &preapproval.AutoRecurringRequest{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 50.0, + CurrencyID: "BRL", + }, + } + + result, err = client.Update(context.Background(), update, result.ID) + if result == nil { + t.Error("preapproval can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) + + t.Run("should_search_preapproval", func(t *testing.T) { + cfg, err := config.New(os.Getenv("ACCESS_TOKEN")) + if err != nil { + t.Fatal(err) + } + + filters := preapproval.SearchRequest{ + Limit: "10", + Offset: "10", + } + + client := preapproval.NewClient(cfg) + result, err := client.Search(context.Background(), filters) + + if result == nil || result.Results[0].ID == "" { + t.Error("preapproval can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) +} From f083681b0cc2e2cb6c22fdc0127b043603c79d88 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Fri, 8 Mar 2024 17:19:46 -0300 Subject: [PATCH 02/14] refactoring to adapt to merge --- pkg/preapproval/client.go | 50 ++++++++++++++++++++++--------- pkg/preapproval/client_test.go | 8 ++++- pkg/preapproval/search_request.go | 41 +++++++++++-------------- 3 files changed, 60 insertions(+), 39 deletions(-) diff --git a/pkg/preapproval/client.go b/pkg/preapproval/client.go index 7785c0e3..a81ec3d8 100644 --- a/pkg/preapproval/client.go +++ b/pkg/preapproval/client.go @@ -2,11 +2,9 @@ package preapproval import ( "context" - "fmt" "github.com/mercadopago/sdk-go/pkg/config" - "github.com/mercadopago/sdk-go/pkg/internal/baseclient" - "net/url" - "strings" + "github.com/mercadopago/sdk-go/pkg/internal/httpclient" + "net/http" ) const ( @@ -51,7 +49,12 @@ func NewClient(c *config.Config) Client { } func (c *client) Create(ctx context.Context, request Request) (*Response, error) { - result, err := baseclient.Post[*Response](ctx, c.cfg, urlBase, request) + requestData := httpclient.RequestData{ + Body: request, + Method: http.MethodPost, + URL: urlBase, + } + result, err := httpclient.DoRequest[*Response](ctx, c.cfg, requestData) if err != nil { return nil, err } @@ -60,7 +63,16 @@ func (c *client) Create(ctx context.Context, request Request) (*Response, error) } func (c *client) Get(ctx context.Context, id string) (*Response, error) { - result, err := baseclient.Get[*Response](ctx, c.cfg, strings.Replace(urlWithID, "{id}", id, 1)) + pathParams := map[string]string{ + "id": id, + } + + requestData := httpclient.RequestData{ + PathParams: pathParams, + Method: http.MethodGet, + URL: urlWithID, + } + result, err := httpclient.DoRequest[*Response](ctx, c.cfg, requestData) if err != nil { return nil, err } @@ -69,7 +81,18 @@ func (c *client) Get(ctx context.Context, id string) (*Response, error) { } func (c *client) Update(ctx context.Context, request UpdateRequest, id string) (*Response, error) { - result, err := baseclient.Put[*Response](ctx, c.cfg, strings.Replace(urlWithID, "{id}", id, 1), request) + pathParams := map[string]string{ + "id": id, + } + + requestData := httpclient.RequestData{ + Body: request, + PathParams: pathParams, + Method: http.MethodPut, + URL: urlWithID, + } + + result, err := httpclient.DoRequest[*Response](ctx, c.cfg, requestData) if err != nil { return nil, err } @@ -78,15 +101,14 @@ func (c *client) Update(ctx context.Context, request UpdateRequest, id string) ( } func (c *client) Search(ctx context.Context, request SearchRequest) (*SearchResponse, error) { - params := request.Parameters() + queryParams := request.GetParams() - parsedURL, err := url.Parse(urlSearch) - if err != nil { - return nil, fmt.Errorf("error parsing url: %w", err) + requestData := httpclient.RequestData{ + QueryParams: queryParams, + Method: http.MethodGet, + URL: urlSearch, } - parsedURL.RawQuery = params - - result, err := baseclient.Get[*SearchResponse](ctx, c.cfg, parsedURL.String()) + result, err := httpclient.DoRequest[*SearchResponse](ctx, c.cfg, requestData) if err != nil { return nil, err } diff --git a/pkg/preapproval/client_test.go b/pkg/preapproval/client_test.go index 78cf360c..e1961ea3 100644 --- a/pkg/preapproval/client_test.go +++ b/pkg/preapproval/client_test.go @@ -3,6 +3,7 @@ package preapproval import ( "context" "fmt" + "github.com/google/uuid" "github.com/mercadopago/sdk-go/pkg/config" "github.com/mercadopago/sdk-go/pkg/internal/httpclient" "io" @@ -107,6 +108,7 @@ func TestCreate(t *testing.T) { PaymentMethodID: "", FirstInvoiceOffset: "", }, + wantErr: "", }, } for _, tt := range tests { @@ -287,7 +289,11 @@ func TestSearch(t *testing.T) { args: args{ ctx: context.Background(), request: SearchRequest{ - Limit: "10", + Limit: 10, + Offset: 10, + Filters: map[string]string{ + "iD": uuid.NewString(), + }, }, }, want: &SearchResponse{ diff --git a/pkg/preapproval/search_request.go b/pkg/preapproval/search_request.go index 2e609ede..cff7bd0f 100644 --- a/pkg/preapproval/search_request.go +++ b/pkg/preapproval/search_request.go @@ -1,6 +1,9 @@ package preapproval -import "net/url" +import ( + "strconv" + "strings" +) // SearchRequest contains filters accepted in search. // Filters field can receive a lot of parameters. For details, see: @@ -8,33 +11,23 @@ import "net/url" type SearchRequest struct { Filters map[string]string - Limit string - Offset string + Limit int + Offset int } -// Parameters transforms SearchRequest into url params. -func (s SearchRequest) Parameters() string { - params := url.Values{} - - for k, v := range s.Filters { - params.Add(k, v) - } - - if _, ok := s.Filters["limit"]; !ok { - limit := "30" - if s.Limit != "" { - limit = s.Limit - } - params.Add("limit", limit) +// GetParams creates map to build query parameters. Keys will be changed to lower case. +func (sr SearchRequest) GetParams() map[string]string { + params := map[string]string{} + for k, v := range sr.Filters { + key := strings.ToLower(k) + params[key] = v } - if _, ok := s.Filters["offset"]; !ok { - offset := "0" - if s.Offset != "" { - offset = s.Offset - } - params.Add("offset", offset) + if sr.Limit == 0 { + sr.Limit = 30 } + params["limit"] = strconv.Itoa(sr.Limit) + params["offset"] = strconv.Itoa(sr.Offset) - return params.Encode() + return params } From c7a5842eb81537cd44d7cba9a4c93654b1bff28f Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Fri, 8 Mar 2024 17:25:16 -0300 Subject: [PATCH 03/14] refactor type at integration test --- test/integration/preapproval/preapproval_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/preapproval/preapproval_test.go b/test/integration/preapproval/preapproval_test.go index 2057f5cb..e7bbf2d4 100644 --- a/test/integration/preapproval/preapproval_test.go +++ b/test/integration/preapproval/preapproval_test.go @@ -133,8 +133,8 @@ func TestPreApproval(t *testing.T) { } filters := preapproval.SearchRequest{ - Limit: "10", - Offset: "10", + Limit: 10, + Offset: 10, } client := preapproval.NewClient(cfg) From a382d2e9696941fb337bc15a4e5e992dcec3387f Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 11:43:20 -0300 Subject: [PATCH 04/14] edit comment --- pkg/preapproval/response.go | 2 +- pkg/preapproval/search_request.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/preapproval/response.go b/pkg/preapproval/response.go index 44b9c171..3dd65541 100644 --- a/pkg/preapproval/response.go +++ b/pkg/preapproval/response.go @@ -47,7 +47,7 @@ type FreeTrialResponse struct { FirstInvoiceOffset int `json:"first_invoice_offset"` } -// SummarizedResponse contains summary information about invoices and subscription charges +// SummarizedResponse contains summary information about invoices and subscription charges. type SummarizedResponse struct { LastChargedDate *time.Time `json:"last_charged_date,omitempty"` LastChargedAmount *time.Time `json:"last_charged_amount"` diff --git a/pkg/preapproval/search_request.go b/pkg/preapproval/search_request.go index cff7bd0f..473350de 100644 --- a/pkg/preapproval/search_request.go +++ b/pkg/preapproval/search_request.go @@ -7,7 +7,7 @@ import ( // SearchRequest contains filters accepted in search. // Filters field can receive a lot of parameters. For details, see: -// https://www.mercadopago.com.br/developers/pt/reference/subscriptions/_preapproval_search/get +// https://www.mercadopago.com/developers/en/reference/subscriptions/_preapproval_search/get type SearchRequest struct { Filters map[string]string From 6e4269fe64967ad5e5c8976e1af5e1a8c6febf34 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 14:18:54 -0300 Subject: [PATCH 05/14] remove blank line --- pkg/preapproval/client.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/preapproval/client.go b/pkg/preapproval/client.go index a81ec3d8..8dc3aedf 100644 --- a/pkg/preapproval/client.go +++ b/pkg/preapproval/client.go @@ -91,7 +91,6 @@ func (c *client) Update(ctx context.Context, request UpdateRequest, id string) ( Method: http.MethodPut, URL: urlWithID, } - result, err := httpclient.DoRequest[*Response](ctx, c.cfg, requestData) if err != nil { return nil, err From f0d15c6b1954a0645fc2de1ad6502b959bd567a3 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 14:20:56 -0300 Subject: [PATCH 06/14] add omitempy to FreeTrialRequest --- pkg/preapproval/request.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/preapproval/request.go b/pkg/preapproval/request.go index d7647570..b11acf3b 100644 --- a/pkg/preapproval/request.go +++ b/pkg/preapproval/request.go @@ -30,7 +30,7 @@ type AutoRecurringRequest struct { // FreeTrialRequest represents the free trial settings. type FreeTrialRequest struct { - FrequencyType string `json:"frequency_type"` - Frequency int `json:"frequency"` - FirstInvoiceOffset int `json:"first_invoice_offset"` + FrequencyType string `json:"frequency_type,omitempty"` + Frequency int `json:"frequency,omitempty"` + FirstInvoiceOffset int `json:"first_invoice_offset,omitempty"` } From ec365eeb04e551798de99c344d9d0f9993680a0d Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 14:24:16 -0300 Subject: [PATCH 07/14] refactor field name --- pkg/preapproval/response.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/preapproval/response.go b/pkg/preapproval/response.go index 3dd65541..90075d2d 100644 --- a/pkg/preapproval/response.go +++ b/pkg/preapproval/response.go @@ -20,7 +20,7 @@ type Response struct { PaymentMethodID string `json:"payment_method_id"` FirstInvoiceOffset string `json:"first_invoice_offset"` BackURL string `json:"back_url"` - PreapprovalPlan string `json:"preapproval_plan_id"` + PreapprovalPlanID string `json:"preapproval_plan_id"` CardID int `json:"card_id"` Version int `json:"version"` PayerID int `json:"payer_id"` From 0347c14d9d0595b4a41f0052302fbf7c60b30206 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 14:25:14 -0300 Subject: [PATCH 08/14] remove omitempty --- pkg/preapproval/response.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/preapproval/response.go b/pkg/preapproval/response.go index 90075d2d..dad2913a 100644 --- a/pkg/preapproval/response.go +++ b/pkg/preapproval/response.go @@ -49,7 +49,7 @@ type FreeTrialResponse struct { // SummarizedResponse contains summary information about invoices and subscription charges. type SummarizedResponse struct { - LastChargedDate *time.Time `json:"last_charged_date,omitempty"` + LastChargedDate *time.Time `json:"last_charged_date"` LastChargedAmount *time.Time `json:"last_charged_amount"` Quotas int `json:"quotas"` From 15cecf87844d8182285b9c6edca18765f9eb91a1 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 14:27:32 -0300 Subject: [PATCH 09/14] rename variable name --- pkg/preapproval/search_response.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/preapproval/search_response.go b/pkg/preapproval/search_response.go index 6fe0fa10..1bcf861b 100644 --- a/pkg/preapproval/search_response.go +++ b/pkg/preapproval/search_response.go @@ -29,7 +29,7 @@ type SearchResults struct { Reason string `json:"reason"` ExternalReference string `json:"external_reference"` InitPoint string `json:"init_point"` - SandBoxInitPoint string `json:"sandbox_init_point"` + SandboxInitPoint string `json:"sandbox_init_point"` PaymentMethodID string `json:"payment_method_id"` FirstInvoiceOffset string `json:"first_invoice_offset"` BackURL string `json:"back_url"` From dc06710d04b7ac523c814f47d4af5f2213f9a5a0 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 14:29:13 -0300 Subject: [PATCH 10/14] rename variable name --- pkg/preapproval/search_response.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/preapproval/search_response.go b/pkg/preapproval/search_response.go index 1bcf861b..e8e4423e 100644 --- a/pkg/preapproval/search_response.go +++ b/pkg/preapproval/search_response.go @@ -33,7 +33,7 @@ type SearchResults struct { PaymentMethodID string `json:"payment_method_id"` FirstInvoiceOffset string `json:"first_invoice_offset"` BackURL string `json:"back_url"` - PreApprovalPlanID string `json:"preapproval_plan_id"` + PreapprovalPlanID string `json:"preapproval_plan_id"` CardID int `json:"card_id"` PayerID int `json:"payer_id"` CollectorID int `json:"collector_id"` From ebb8c4ffa5cf5443b91f6a21e2b20bb5e1986533 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 14:30:17 -0300 Subject: [PATCH 11/14] rename variable name --- pkg/preapproval/response.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/preapproval/response.go b/pkg/preapproval/response.go index dad2913a..f3c13057 100644 --- a/pkg/preapproval/response.go +++ b/pkg/preapproval/response.go @@ -16,7 +16,7 @@ type Response struct { Reason string `json:"reason"` ExternalReference string `json:"external_reference"` InitPoint string `json:"init_point"` - SandBoxInitPoint string `json:"sandbox_init_point"` + SandboxInitPoint string `json:"sandbox_init_point"` PaymentMethodID string `json:"payment_method_id"` FirstInvoiceOffset string `json:"first_invoice_offset"` BackURL string `json:"back_url"` From b9fb75debfffa6e251f06320c49caa4a9996cec0 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 14:31:15 -0300 Subject: [PATCH 12/14] refactor comment --- pkg/preapproval/update_request.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/preapproval/update_request.go b/pkg/preapproval/update_request.go index 704f7445..662f6d8b 100644 --- a/pkg/preapproval/update_request.go +++ b/pkg/preapproval/update_request.go @@ -2,7 +2,7 @@ package preapproval import "time" -// UpdateRequest represents a request for creating a pre approval. +// UpdateRequest represents a request for updating a pre approval. type UpdateRequest struct { AutoRecurring *AutoRecurringRequest `json:"auto_recurring,omitempty"` From 05d3638ce50718ae68037e2d2393920befe501b0 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Mon, 11 Mar 2024 15:15:47 -0300 Subject: [PATCH 13/14] refactor preapproval search IT --- .../preapproval/preapproval_test.go | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/test/integration/preapproval/preapproval_test.go b/test/integration/preapproval/preapproval_test.go index e7bbf2d4..fd4e5af1 100644 --- a/test/integration/preapproval/preapproval_test.go +++ b/test/integration/preapproval/preapproval_test.go @@ -132,16 +132,38 @@ func TestPreApproval(t *testing.T) { t.Fatal(err) } + client := preapproval.NewClient(cfg) + + req := preapproval.Request{ + AutoRecurring: &preapproval.AutoRecurringRequest{ + Frequency: 1, + FrequencyType: "months", + TransactionAmount: 100, + CurrencyID: "BRL", + }, + BackURL: "https://www.yoursite.com", + ExternalReference: "Ref-123", + PayerEmail: "test_user_28355466@testuser.com", + Reason: "Yoga Class", + } + + createResult, err := client.Create(context.Background(), req) + if createResult == nil { + t.Error("preapproval can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + return + } + filters := preapproval.SearchRequest{ Limit: 10, Offset: 10, } - client := preapproval.NewClient(cfg) result, err := client.Search(context.Background(), filters) - - if result == nil || result.Results[0].ID == "" { - t.Error("preapproval can't be nil") + if result == nil { + t.Error("result can't be nil") } if err != nil { t.Errorf(err.Error()) From 91cae3f98028bb2fe98ae444abae505d62659403 Mon Sep 17 00:00:00 2001 From: Bruna Campos Date: Tue, 12 Mar 2024 10:46:59 -0300 Subject: [PATCH 14/14] refactor searchResponse --- pkg/preapproval/client_test.go | 2 +- pkg/preapproval/response.go | 2 ++ pkg/preapproval/search_response.go | 34 ++---------------------------- 3 files changed, 5 insertions(+), 33 deletions(-) diff --git a/pkg/preapproval/client_test.go b/pkg/preapproval/client_test.go index e1961ea3..884dfa47 100644 --- a/pkg/preapproval/client_test.go +++ b/pkg/preapproval/client_test.go @@ -302,7 +302,7 @@ func TestSearch(t *testing.T) { Limit: 10, Total: 10, }, - Results: []SearchResults{ + Results: []Response{ { ID: "2c938084726fca480172750000000000", Status: "pending", diff --git a/pkg/preapproval/response.go b/pkg/preapproval/response.go index f3c13057..3f8d471e 100644 --- a/pkg/preapproval/response.go +++ b/pkg/preapproval/response.go @@ -26,6 +26,8 @@ type Response struct { PayerID int `json:"payer_id"` CollectorID int `json:"collector_id"` ApplicationID int `json:"application_id"` + PayerFirstName string `json:"payer_first_name"` + PayerLastName string `json:"payer_last_name"` } // AutoRecurringResponse represents the recurrence settings. diff --git a/pkg/preapproval/search_response.go b/pkg/preapproval/search_response.go index e8e4423e..5549f9b8 100644 --- a/pkg/preapproval/search_response.go +++ b/pkg/preapproval/search_response.go @@ -1,11 +1,9 @@ package preapproval -import "time" - // SearchResponse represents the response from the search endpoint. type SearchResponse struct { - Results []SearchResults `json:"results"` - Paging PagingResponse `json:"paging"` + Results []Response `json:"results"` + Paging PagingResponse `json:"paging"` } // PagingResponse represents the paging information within SearchResponse. @@ -14,31 +12,3 @@ type PagingResponse struct { Limit int `json:"limit"` Offset int `json:"offset"` } - -// SearchResults contains the information of a preapproval. -type SearchResults struct { - AutoRecurring AutoRecurringResponse `json:"auto_recurring"` - Summarized SummarizedResponse `json:"summarized"` - DateCreated *time.Time `json:"date_created"` - LastModified *time.Time `json:"last_modified"` - NextPaymentDate *time.Time `json:"next_payment_date"` - - ID string `json:"id"` - PayerEmail string `json:"payer_email"` - Status string `json:"status"` - Reason string `json:"reason"` - ExternalReference string `json:"external_reference"` - InitPoint string `json:"init_point"` - SandboxInitPoint string `json:"sandbox_init_point"` - PaymentMethodID string `json:"payment_method_id"` - FirstInvoiceOffset string `json:"first_invoice_offset"` - BackURL string `json:"back_url"` - PreapprovalPlanID string `json:"preapproval_plan_id"` - CardID int `json:"card_id"` - PayerID int `json:"payer_id"` - CollectorID int `json:"collector_id"` - ApplicationID int `json:"application_id"` - Version int `json:"version"` - PayerFirstName string `json:"payer_first_name"` - PayerLastName string `json:"payer_last_name"` -}