From 8b2295408fcd70df3bd73979d53fef71443b143a Mon Sep 17 00:00:00 2001 From: gabs Date: Thu, 25 Jan 2024 12:10:42 -0300 Subject: [PATCH 01/25] Update client --- pkg/payment/payment.go | 218 ++++++++++++++++++++ pkg/payment/request.go | 236 +++++++++++++++++++++ pkg/payment/response.go | 304 ++++++++++++++++++++++++++++ pkg/payment/search_request.go | 40 ++++ pkg/payment/search_response.go | 14 ++ pkg/payment/update_request.go | 12 ++ pkg/paymentmethod/payment_method.go | 2 +- 7 files changed, 825 insertions(+), 1 deletion(-) create mode 100644 pkg/payment/payment.go create mode 100644 pkg/payment/request.go create mode 100644 pkg/payment/response.go create mode 100644 pkg/payment/search_request.go create mode 100644 pkg/payment/search_response.go create mode 100644 pkg/payment/update_request.go diff --git a/pkg/payment/payment.go b/pkg/payment/payment.go new file mode 100644 index 00000000..96f780f7 --- /dev/null +++ b/pkg/payment/payment.go @@ -0,0 +1,218 @@ +package payment + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "net/url" + "strconv" + "strings" + + "github.com/mercadopago/sdk-go/pkg/credential" + "github.com/mercadopago/sdk-go/pkg/internal/httpclient" + "github.com/mercadopago/sdk-go/pkg/option" +) + +const ( + postURL = "https://api.mercadopago.com/v1/payments" + searchURL = "https://api.mercadopago.com/v1/payments/search" + getURL = "https://api.mercadopago.com/v1/payments/{id}" + putURL = "https://api.mercadopago.com/v1/payments/{id}" +) + +// Client contains the methods to interact with the Payments API. +type Client interface { + // Create creates a new payment. + // It is a post request to the endpoint: https://api.mercadopago.com/v1/payments + // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments/post/ + Create(ctx context.Context, dto Request) (*Response, error) + + // Search searches for payments. + // It is a get request to the endpoint: https://api.mercadopago.com/v1/payments/search + // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments_search/get/ + Search(ctx context.Context, f Filters) (*SearchResponse, error) + + // Get gets a payment by its ID. + // It is a get request to the endpoint: https://api.mercadopago.com/v1/payments/{id} + // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments_id/get/ + Get(ctx context.Context, id int64) (*Response, error) + + // Cancel cancels a payment by its ID. + // It is a put request to the endpoint: https://api.mercadopago.com/v1/payments/{id} + Cancel(ctx context.Context, id int64) (*Response, error) + + // Capture captures a payment by its ID. + // It is a put request to the endpoint: https://api.mercadopago.com/v1/payments/{id} + Capture(ctx context.Context, id int64) (*Response, error) + + // CaptureAmount captures amount of a payment by its ID. + // It is a put request to the endpoint: https://api.mercadopago.com/v1/payments/{id} + CaptureAmount(ctx context.Context, id int64, amount float64) (*Response, error) +} + +// client is the implementation of Client. +type client struct { + credential *credential.Credential + config *option.ClientOptions +} + +// NewClient returns a new Payments API Client. +func NewClient(cdt *credential.Credential, opts ...option.ClientOption) Client { + c := option.ApplyClientOptions(opts...) + + return &client{ + credential: cdt, + config: c, + } +} + +func (c *client) Create(ctx context.Context, dto Request) (*Response, error) { + body, err := json.Marshal(&dto) + if err != nil { + return nil, fmt.Errorf("error marshaling request body: %w", err) + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, postURL, strings.NewReader(string(body))) + if err != nil { + return nil, fmt.Errorf("error creating request: %w", err) + } + + res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + if err != nil { + return nil, err + } + + formatted := &Response{} + if err := json.Unmarshal(res, &formatted); err != nil { + return nil, fmt.Errorf("error unmarshaling response: %w", err) + } + + return formatted, nil +} + +func (c *client) Search(ctx context.Context, f Filters) (*SearchResponse, error) { + params := url.Values{} + params.Add("sort", f.Sort) + params.Add("criteria", f.Criteria) + params.Add("external_reference", f.ExternalReference) + params.Add("range", f.Range) + params.Add("begin_date", f.BeginDate) + params.Add("end_date", f.EndDate) + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL+"?"+params.Encode(), nil) + if err != nil { + return nil, fmt.Errorf("error creating request: %w", err) + } + + res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + if err != nil { + return nil, err + } + + var formatted *SearchResponse + if err := json.Unmarshal(res, &formatted); err != nil { + return nil, fmt.Errorf("error unmarshaling response: %w", err) + } + + return formatted, nil +} + +func (c *client) Get(ctx context.Context, id int64) (*Response, error) { + conv := strconv.Itoa(int(id)) + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, strings.Replace(getURL, "{id}", conv, 1), nil) + if err != nil { + return nil, fmt.Errorf("error creating request: %w", err) + } + + res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + if err != nil { + return nil, err + } + + formatted := &Response{} + if err := json.Unmarshal(res, &formatted); err != nil { + return nil, fmt.Errorf("error unmarshaling response: %w", err) + } + + return formatted, nil +} + +func (c *client) Cancel(ctx context.Context, id int64) (*Response, error) { + dto := &CancelRequest{Status: "cancelled"} + body, err := json.Marshal(dto) + if err != nil { + return nil, fmt.Errorf("error marshaling request body: %w", err) + } + + conv := strconv.Itoa(int(id)) + req, err := http.NewRequestWithContext(ctx, http.MethodPut, strings.Replace(putURL, "{id}", conv, 1), strings.NewReader(string(body))) + if err != nil { + return nil, fmt.Errorf("error creating request: %w", err) + } + + res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + if err != nil { + return nil, err + } + + formatted := &Response{} + if err := json.Unmarshal(res, &formatted); err != nil { + return nil, fmt.Errorf("error unmarshaling response: %w", err) + } + + return formatted, nil +} + +func (c *client) Capture(ctx context.Context, id int64) (*Response, error) { + dto := &CaptureRequest{Capture: true} + body, err := json.Marshal(dto) + if err != nil { + return nil, fmt.Errorf("error marshaling request body: %w", err) + } + + conv := strconv.Itoa(int(id)) + req, err := http.NewRequestWithContext(ctx, http.MethodPut, strings.Replace(putURL, "{id}", conv, 1), strings.NewReader(string(body))) + if err != nil { + return nil, fmt.Errorf("error creating request: %w", err) + } + + res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + if err != nil { + return nil, err + } + + formatted := &Response{} + if err := json.Unmarshal(res, &formatted); err != nil { + return nil, fmt.Errorf("error unmarshaling response: %w", err) + } + + return formatted, nil +} + +func (c *client) CaptureAmount(ctx context.Context, id int64, amount float64) (*Response, error) { + dto := &CaptureRequest{TransactionAmount: amount, Capture: true} + body, err := json.Marshal(dto) + if err != nil { + return nil, fmt.Errorf("error marshaling request body: %w", err) + } + + conv := strconv.Itoa(int(id)) + req, err := http.NewRequestWithContext(ctx, http.MethodPut, strings.Replace(putURL, "{id}", conv, 1), strings.NewReader(string(body))) + if err != nil { + return nil, fmt.Errorf("error creating request: %w", err) + } + + res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + if err != nil { + return nil, err + } + + formatted := &Response{} + if err := json.Unmarshal(res, &formatted); err != nil { + return nil, fmt.Errorf("error unmarshaling response: %w", err) + } + + return formatted, nil +} diff --git a/pkg/payment/request.go b/pkg/payment/request.go new file mode 100644 index 00000000..0b44a978 --- /dev/null +++ b/pkg/payment/request.go @@ -0,0 +1,236 @@ +package payment + +import ( + "time" +) + +// Request represents a request for creating or updating a payment. +type Request struct { + CallbackURL string `json:"callback_url,omitempty"` + CouponCode string `json:"coupon_code,omitempty"` + Description string `json:"description,omitempty"` + ExternalReference string `json:"external_reference,omitempty"` + IssuerID string `json:"issuer_id,omitempty"` + MerchantAccountID string `json:"merchant_account_id,omitempty"` + NotificationURL string `json:"notification_url,omitempty"` + PaymentMethodID string `json:"payment_method_id,omitempty"` + ProcessingMode string `json:"processing_mode,omitempty"` + Token string `json:"token,omitempty"` + PaymentMethodOptionID string `json:"payment_method_option_id,omitempty"` + StatementDescriptor string `json:"statement_descriptor,omitempty"` + ThreeDSecureMode string `json:"three_d_secure_mode,omitempty"` + Installments int `json:"installments,omitempty"` + CampaignID int64 `json:"campaign_id,omitempty"` + DifferentialPricingID int64 `json:"differential_pricing_id,omitempty"` + SponsorID int64 `json:"sponsor_id,omitempty"` + BinaryMode bool `json:"binary_mode,omitempty"` + Capture bool `json:"capture,omitempty"` + ApplicationFee float64 `json:"application_fee,omitempty"` + CouponAmount float64 `json:"coupon_amount,omitempty"` + NetAmount float64 `json:"net_amount,omitempty"` + TransactionAmount float64 `json:"transaction_amount,omitempty"` + Metadata map[string]any `json:"metadata,omitempty"` + + DateOfExpiration *time.Time `json:"date_of_expiration,omitempty"` + AdditionalInfo *AdditionalInfoRequest `json:"additional_info,omitempty"` + MerchantServices *MerchantServicesRequest `json:"merchant_services,omitempty"` + Order *OrderRequest `json:"order,omitempty"` + Payer *PayerRequest `json:"payer,omitempty"` + TransactionDetails *TransactionDetailsRequest `json:"transaction_details,omitempty"` + PointOfInteraction *PointOfInteractionRequest `json:"point_of_interaction,omitempty"` + PaymentMethod *PaymentMethodRequest `json:"payment_method,omitempty"` + Taxes []TaxRequest `json:"taxes,omitempty"` +} + +// AdditionalInfoRequest represents additional information request within Request. +type AdditionalInfoRequest struct { + IPAddress string `json:"ip_address,omitempty"` + + Payer *AdditionalInfoPayerRequest `json:"payer,omitempty"` + Shipments *ShipmentsRequest `json:"shipments,omitempty"` + Barcode *AdditionalInfoBarcodeRequest `json:"barcode,omitempty"` + Items []ItemRequest `json:"items,omitempty"` +} + +// AdditionalInfoPayerRequest represents payer information request within AdditionalInfoPayerRequest. +type AdditionalInfoPayerRequest struct { + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + AuthenticationType string `json:"authentication_type,omitempty"` + IsPrimeUser bool `json:"is_prime_user,omitempty"` + IsFirstPurchaseOnline bool `json:"is_first_purchase_online,omitempty"` + + RegistrationDate *time.Time `json:"registration_date,omitempty"` + LastPurchase *time.Time `json:"last_purchase,omitempty"` + Phone *PhoneRequest `json:"phone,omitempty"` + Address *AddressRequest `json:"address,omitempty"` +} + +// PhoneRequest represents phone request within AdditionalInfoPayerRequest. +type PhoneRequest struct { + AreaCode string `json:"area_code,omitempty"` + Number string `json:"number,omitempty"` +} + +// AddressRequest represents address request within AdditionalInfoPayerRequest. +type AddressRequest struct { + ZipCode string `json:"zip_code,omitempty"` + StreetName string `json:"street_name,omitempty"` + StreetNumber string `json:"street_number,omitempty"` +} + +// ShipmentsRequest represents shipments request within AdditionalInfoRequest. +type ShipmentsRequest struct { + LocalPickup bool `json:"local_pickup,omitempty"` + ExpressShipment bool `json:"express_shipment,omitempty"` + + ReceiverAddress *ReceiverAddressRequest `json:"receiver_address,omitempty"` +} + +// ReceiverAddressRequest represents receiver address request within ShipmentsRequest. +type ReceiverAddressRequest struct { + StateName string `json:"state_name,omitempty"` + CityName string `json:"city_name,omitempty"` + Floor string `json:"floor,omitempty"` + Apartment string `json:"apartment,omitempty"` + ZipCode string `json:"zip_code,omitempty"` + StreetName string `json:"street_name,omitempty"` + StreetNumber string `json:"street_number,omitempty"` +} + +// AdditionalInfoBarcodeRequest represents barcode request within AdditionalInfoRequest. +type AdditionalInfoBarcodeRequest struct { + Type string `json:"type,omitempty"` + Content string `json:"content,omitempty"` + Width float64 `json:"width,omitempty"` + Height float64 `json:"height,omitempty"` +} + +// ItemRequest represents an item request within AdditionalInfoRequest. +type ItemRequest struct { + ID string `json:"id,omitempty"` + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + PictureURL string `json:"picture_url,omitempty"` + CategoryID string `json:"category_id,omitempty"` + Quantity int `json:"quantity,omitempty"` + UnitPrice float64 `json:"unit_price,omitempty"` + Warranty bool `json:"warranty,omitempty"` + + EventDate *time.Time `json:"event_date,omitempty"` + CategoryDescriptor *CategoryDescriptorRequest `json:"category_descriptor,omitempty"` +} + +// CategoryDescriptorRequest represents category descriptor request within ItemRequest. +type CategoryDescriptorRequest struct { + Passenger *PassengerRequest `json:"passenger,omitempty"` + Route *RouteRequest `json:"route,omitempty"` +} + +// PassengerRequest represents passenger request within CategoryDescriptorRequest. +type PassengerRequest struct { + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + + Identification *IdentificationRequest `json:"identification,omitempty"` +} + +// IdentificationRequest represents identification request within PaymentPassengerRequest. +type IdentificationRequest struct { + Type string `json:"type,omitempty"` + Number string `json:"number,omitempty"` +} + +// RouteRequest represents route request within CategoryDescriptorRequest. +type RouteRequest struct { + Departure string `json:"departure,omitempty"` + Destination string `json:"destination,omitempty"` + Company string `json:"company,omitempty"` + + DepartureDateTime *time.Time `json:"departure_date_time,omitempty"` + ArrivalDateTime *time.Time `json:"arrival_date_time,omitempty"` +} + +// MerchantServicesRequest represents merchant services request within Request. +type MerchantServicesRequest struct { + FraudScoring bool `json:"fraud_scoring,omitempty"` + FraudManualReview bool `json:"fraud_manual_review,omitempty"` +} + +// OrderRequest represents order request within Request. +type OrderRequest struct { + Type string `json:"type,omitempty"` + ID int64 `json:"id,omitempty"` +} + +// PayerRequest represents payer request within Request. +type PayerRequest struct { + Type string `json:"type,omitempty"` + ID string `json:"id,omitempty"` + Email string `json:"email,omitempty"` + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + EntityType string `json:"entity_type,omitempty"` + + Identification *IdentificationRequest `json:"identification,omitempty"` + Address *PayerAddressRequest `json:"address,omitempty"` +} + +// PayerAddressRequest represents payer address request within PayerRequest. +type PayerAddressRequest struct { + Neighborhood string `json:"neighborhood,omitempty"` + City string `json:"city,omitempty"` + FederalUnit string `json:"federal_unit,omitempty"` + ZipCode string `json:"zip_code,omitempty"` + StreetName string `json:"street_name,omitempty"` + StreetNumber string `json:"street_number,omitempty"` +} + +// TransactionDetailsRequest represents transaction details request within Request. +type TransactionDetailsRequest struct { + FinancialInstitution string `json:"financial_institution,omitempty"` +} + +// PointOfInteractionRequest represents point of interaction request within Request. +type PointOfInteractionRequest struct { + LinkedTo string `json:"linked_to,omitempty"` + Type string `json:"type,omitempty"` +} + +// PaymentMethodRequest represents payment method request within Request. +type PaymentMethodRequest struct { + Data *DataRequest `json:"data,omitempty"` +} + +// DataRequest represents payment data request within PaymentMethodRequest. +type DataRequest struct { + Rules *RulesRequest `json:"rules,omitempty"` +} + +// RulesRequest represents payment rules request within DataRequest. +type RulesRequest struct { + Fine *FeeRequest `json:"fine,omitempty"` + Interest *FeeRequest `json:"interest,omitempty"` + Discounts []DiscountRequest `json:"discounts,omitempty"` +} + +// FeeRequest represents fee request within RulesRequest. +type FeeRequest struct { + Type string `json:"type,omitempty"` + Value float64 `json:"value,omitempty"` +} + +// DiscountRequest represents discount request within RulesRequest. +type DiscountRequest struct { + Type string `json:"type,omitempty"` + Value float64 `json:"value,omitempty"` + + LimitDate *time.Time `json:"limit_date,omitempty"` +} + +// TaxRequest represents tax request within Request. +type TaxRequest struct { + Type string `json:"type,omitempty"` + Value float64 `json:"value,omitempty"` + Percentage bool `json:"percentage,omitempty"` +} diff --git a/pkg/payment/response.go b/pkg/payment/response.go new file mode 100644 index 00000000..de0ecaa8 --- /dev/null +++ b/pkg/payment/response.go @@ -0,0 +1,304 @@ +package payment + +import ( + "time" +) + +// Response is the response from the Payments API. +type Response struct { + DifferentialPricingID string `json:"differential_pricing_id,omitempty"` + MoneyReleaseSchema string `json:"money_release_schema,omitempty"` + OperationType string `json:"operation_type,omitempty"` + IssuerID string `json:"issuer_id,omitempty"` + PaymentMethodID string `json:"payment_method_id,omitempty"` + PaymentTypeID string `json:"payment_type_id,omitempty"` + Status string `json:"status,omitempty"` + StatusDetail string `json:"status_detail,omitempty"` + CurrencyID string `json:"currency_id,omitempty"` + Description string `json:"description,omitempty"` + AuthorizationCode string `json:"authorization_code,omitempty"` + IntegratorID string `json:"integrator_id,omitempty"` + PlatformID string `json:"platform_id,omitempty"` + CorporationID string `json:"corporation_id,omitempty"` + NotificationURL string `json:"notification_url,omitempty"` + CallbackURL string `json:"callback_url,omitempty"` + ProcessingMode string `json:"processing_mode,omitempty"` + MerchantAccountID string `json:"merchant_account_id,omitempty"` + MerchantNumber string `json:"merchant_number,omitempty"` + CouponCode string `json:"coupon_code,omitempty"` + ExternalReference string `json:"external_reference,omitempty"` + PaymentMethodOptionID string `json:"payment_method_option_id,omitempty"` + PosID string `json:"pos_id,omitempty"` + StoreID string `json:"store_id,omitempty"` + DeductionSchema string `json:"deduction_schema,omitempty"` + CounterCurrency string `json:"counter_currency,omitempty"` + CallForAuthorizeID string `json:"call_for_authorize_id,omitempty"` + StatementDescriptor string `json:"statement_descriptor,omitempty"` + Installments int `json:"installments,omitempty"` + ID int64 `json:"id,omitempty"` + SponsorID int64 `json:"sponsor_id,omitempty"` + CollectorID int64 `json:"collector_id,omitempty"` + TransactionAmount float64 `json:"transaction_amount,omitempty"` + TransactionAmountRefunded float64 `json:"transaction_amount_refunded,omitempty"` + CouponAmount float64 `json:"coupon_amount,omitempty"` + TaxesAmount float64 `json:"taxes_amount,omitempty"` + ShippingAmount float64 `json:"shipping_amount,omitempty"` + NetAmount float64 `json:"net_amount,omitempty"` + LiveMode bool `json:"live_mode,omitempty"` + Captured bool `json:"captured,omitempty"` + BinaryMode bool `json:"binary_mode,omitempty"` + Metadata map[string]any `json:"metadata,omitempty"` + InternalMetadata map[string]any `json:"internal_metadata,omitempty"` + + DateCreated *time.Time `json:"date_created,omitempty"` + DateApproved *time.Time `json:"date_approved,omitempty"` + DateLastUpdated *time.Time `json:"date_last_updated,omitempty"` + DateOfExpiration *time.Time `json:"date_of_expiration,omitempty"` + MoneyReleaseDate *time.Time `json:"money_release_date,omitempty"` + Payer *PayerResponse `json:"payer,omitempty"` + AdditionalInfo *AdditionalInfoResponse `json:"additional_info,omitempty"` + Order *OrderResponse `json:"order,omitempty"` + TransactionDetails *TransactionDetailsResponse `json:"transaction_details,omitempty"` + Card *CardResponse `json:"card,omitempty"` + PointOfInteraction *PointOfInteractionResponse `json:"point_of_interaction,omitempty"` + PaymentMethod *PaymentMethodResponse `json:"payment_method,omitempty"` + ThreeDSInfo *ThreeDSInfoResponse `json:"three_ds_info,omitempty"` + FeeDetails []FeeDetailResponse `json:"fee_details,omitempty"` + Taxes []TaxResponse `json:"taxes,omitempty"` + Refunds []RefundResponse `json:"refunds,omitempty"` +} + +// PayerResponse represents the payer of the payment. +type PayerResponse struct { + Type string `json:"type,omitempty"` + ID string `json:"id,omitempty"` + Email string `json:"email,omitempty"` + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + EntityType string `json:"entity_type,omitempty"` + + Identification *IdentificationResponse `json:"identification,omitempty"` +} + +// IdentificationResponse represents payer's personal identification. +type IdentificationResponse struct { + Type string `json:"type,omitempty"` + Number string `json:"number,omitempty"` +} + +// AdditionalInfoResponse represents additional information about a payment. +type AdditionalInfoResponse struct { + IPAddress string `json:"ip_address,omitempty"` + + Payer *AdditionalInfoPayerResponse `json:"payer,omitempty"` + Shipments *ShipmentsResponse `json:"shipments,omitempty"` + Items []ItemResponse `json:"items,omitempty"` +} + +// ItemResponse represents an item. +type ItemResponse struct { + ID string `json:"id,omitempty"` + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + PictureURL string `json:"picture_url,omitempty"` + CategoryID string `json:"category_id,omitempty"` + Quantity int `json:"quantity,omitempty"` + UnitPrice float64 `json:"unit_price,omitempty"` +} + +// AdditionalInfoPayerResponse represents payer's additional information. +type AdditionalInfoPayerResponse struct { + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + + RegistrationDate *time.Time `json:"registration_date,omitempty"` + Phone *PhoneResponse `json:"phone,omitempty"` + Address *AddressResponse `json:"address,omitempty"` +} + +// PhoneResponse represents phone information. +type PhoneResponse struct { + AreaCode string `json:"area_code,omitempty"` + Number string `json:"number,omitempty"` +} + +// AddressResponse represents address information. +type AddressResponse struct { + ZipCode string `json:"zip_code,omitempty"` + StreetName string `json:"street_name,omitempty"` + StreetNumber string `json:"street_number,omitempty"` +} + +// ShipmentsResponse represents shipment information. +type ShipmentsResponse struct { + ReceiverAddress *ReceiverAddressResponse `json:"receiver_address,omitempty"` +} + +// ReceiverAddressResponse represents the receiver's address within ShipmentsResponse. +type ReceiverAddressResponse struct { + StateName string `json:"state_name,omitempty"` + CityName string `json:"city_name,omitempty"` + Floor string `json:"floor,omitempty"` + Apartment string `json:"apartment,omitempty"` + + Address *AddressResponse `json:"address,omitempty"` +} + +// OrderResponse represents order information. +type OrderResponse struct { + ID int `json:"id,omitempty"` + Type string `json:"type,omitempty"` +} + +// TransactionDetailsResponse represents transaction details. +type TransactionDetailsResponse struct { + FinancialInstitution string `json:"financial_institution,omitempty"` + ExternalResourceURL string `json:"external_resource_url,omitempty"` + PaymentMethodReferenceID string `json:"payment_method_reference_id,omitempty"` + AcquirerReference string `json:"acquirer_reference,omitempty"` + NetReceivedAmount float64 `json:"net_received_amount,omitempty"` + TotalPaidAmount float64 `json:"total_paid_amount,omitempty"` + InstallmentAmount float64 `json:"installment_amount,omitempty"` + OverpaidAmount float64 `json:"overpaid_amount,omitempty"` +} + +// CardResponse represents card information. +type CardResponse struct { + ID string `json:"id,omitempty"` + LastFourDigits string `json:"last_four_digits,omitempty"` + FirstSixDigits string `json:"first_six_digits,omitempty"` + ExpirationYear int `json:"expiration_year,omitempty"` + ExpirationMonth int `json:"expiration_month,omitempty"` + + DateCreated *time.Time `json:"date_created,omitempty"` + DateLastUpdated *time.Time `json:"date_last_updated,omitempty"` + Cardholder *CardholderResponse `json:"cardholder,omitempty"` +} + +// CardholderResponse represents cardholder information. +type CardholderResponse struct { + Name string `json:"name,omitempty"` + + Identification *IdentificationResponse `json:"identification,omitempty"` +} + +// PointOfInteractionResponse represents point of interaction information. +type PointOfInteractionResponse struct { + Type string `json:"type,omitempty"` + SubType string `json:"sub_type,omitempty"` + LinkedTo string `json:"linked_to,omitempty"` + + ApplicationData *ApplicationDataResponse `json:"application_data,omitempty"` + TransactionData *TransactionDataResponse `json:"transaction_data,omitempty"` +} + +// ApplicationDataResponse represents application data within PointOfInteractionResponse. +type ApplicationDataResponse struct { + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` +} + +// TransactionDataResponse represents transaction data within PointOfInteractionResponse. +type TransactionDataResponse struct { + QRCode string `json:"qr_code,omitempty"` + QRCodeBase64 string `json:"qr_code_base64,omitempty"` + TransactionID string `json:"transaction_id,omitempty"` + TicketURL string `json:"ticket_url,omitempty"` + BankTransferID int64 `json:"bank_transfer_id,omitempty"` + FinancialInstitution int64 `json:"financial_institution,omitempty"` + + BankInfo *BankInfoResponse `json:"bank_info,omitempty"` +} + +// BankInfoResponse represents bank information. +type BankInfoResponse struct { + IsSameBankAccountOwner string `json:"is_same_bank_account_owner,omitempty"` + + Payer *BankInfoPayerResponse `json:"payer,omitempty"` + Collector *BankInfoCollectorResponse `json:"collector,omitempty"` +} + +// BankInfoPayerResponse represents payer information within BankInfoResponse. +type BankInfoPayerResponse struct { + Email string `json:"email,omitempty"` + LongName string `json:"long_name,omitempty"` + AccountID int64 `json:"account_id,omitempty"` +} + +// BankInfoCollectorResponse represents collector information within BankInfoResponse. +type BankInfoCollectorResponse struct { + LongName string `json:"long_name,omitempty"` + AccountID int64 `json:"account_id,omitempty"` +} + +// PaymentMethodResponse represents payment method information. +type PaymentMethodResponse struct { + Data *DataResponse `json:"data,omitempty"` +} + +// DataResponse represents data within PaymentMethodResponse. +type DataResponse struct { + Rules *RulesResponse `json:"rules,omitempty"` +} + +// RulesResponse represents payment rules. +type RulesResponse struct { + Fine *FeeResponse `json:"fine,omitempty"` + Interest *FeeResponse `json:"interest,omitempty"` + Discounts []DiscountResponse `json:"discounts,omitempty"` +} + +// DiscountResponse represents payment discount information. +type DiscountResponse struct { + Type string `json:"type,omitempty"` + Value float64 `json:"value,omitempty"` + + LimitDate *time.Time `json:"limit_date,omitempty"` +} + +// FeeResponse represents payment fee information. +type FeeResponse struct { + Type string `json:"type,omitempty"` + Value float64 `json:"value,omitempty"` +} + +// ThreeDSInfoResponse represents 3DS (Three-Domain Secure) information. +type ThreeDSInfoResponse struct { + ExternalResourceURL string `json:"external_resource_url,omitempty"` + Creq string `json:"creq,omitempty"` +} + +// FeeDetailResponse represents payment fee detail information. +type FeeDetailResponse struct { + Type string `json:"type,omitempty"` + FeePayer string `json:"fee_payer,omitempty"` + Amount float64 `json:"amount,omitempty"` +} + +// TaxResponse represents tax information. +type TaxResponse struct { + Type string `json:"type,omitempty"` + Value float64 `json:"value,omitempty"` +} + +// RefundResponse represents refund information. +type RefundResponse struct { + Status string `json:"status,omitempty"` + RefundMode string `json:"refund_mode,omitempty"` + Reason string `json:"reason,omitempty"` + UniqueSequenceNumber string `json:"unique_sequence_number,omitempty"` + ID int64 `json:"id,omitempty"` + PaymentID int64 `json:"payment_id,omitempty"` + Amount float64 `json:"amount,omitempty"` + AdjustmentAmount float64 `json:"adjustment_amount,omitempty"` + + DateCreated *time.Time `json:"date_created,omitempty"` + Source *SourceResponse `json:"source,omitempty"` +} + +// SourceResponse represents source information. +type SourceResponse struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` +} diff --git a/pkg/payment/search_request.go b/pkg/payment/search_request.go new file mode 100644 index 00000000..b869d9ba --- /dev/null +++ b/pkg/payment/search_request.go @@ -0,0 +1,40 @@ +package payment + +// Filters is the filters to search for payments. +type Filters struct { + // Sort is a field used to sort a list of payments. + // The sort can be done by the following attributes: + // - "date_approved" + // - "date_created" + // - "date_last_updated" + // - "id" + // - "money_release_date" + Sort string + + // Criteria is a field used to define the order of the result list. + // Can be "asc" or "desc". + Criteria string + + // ExternalReference is an external reference of the payment. + // It can be, for example, a hashcode from the Central Bank, working as an identifier of the transaction origin. + ExternalReference string + + // Range is a field used to define the range of the search. + // The Range can be related to the following attributes: + // - "date_created" + // - "date_last_updated" + // - "date_approved" + // - "money_release_date" + // If not informed, it uses "date_created" by default. + Range string + + // BeginDate is a field used to define the start of the search interval. + // Its format can be a relative date - "NOW-XDAYS", "NOW-XMONTHS" - or an absolute date - ISO8601. + // If not informed, it uses "NOW-3MONTHS" by default. + BeginDate string + + // EndDate is a field used to define the end of the search interval. + // Its format can be a relative date - "NOW-XDAYS", "NOW-XMONTHS" - or an absolute date - ISO8601. + // If not informed, it uses "NOW" by default. + EndDate string +} diff --git a/pkg/payment/search_response.go b/pkg/payment/search_response.go new file mode 100644 index 00000000..829d4610 --- /dev/null +++ b/pkg/payment/search_response.go @@ -0,0 +1,14 @@ +package payment + +// SearchResponse represents the response from the search endpoint. +type SearchResponse struct { + Results []Response `json:"results"` + Paging PagingResponse `json:"paging"` +} + +// PagingResponse represents the paging information within SearchResponse. +type PagingResponse struct { + Total int64 `json:"total"` + Limit int64 `json:"limit"` + Offset int64 `json:"offset"` +} diff --git a/pkg/payment/update_request.go b/pkg/payment/update_request.go new file mode 100644 index 00000000..3c6cdf8a --- /dev/null +++ b/pkg/payment/update_request.go @@ -0,0 +1,12 @@ +package payment + +// CancelRequest represents a payment cancellation request. +type CancelRequest struct { + Status string `json:"status,omitempty"` +} + +// CaptureRequest represents a payment capture request. +type CaptureRequest struct { + TransactionAmount float64 `json:"transaction_amount,omitempty"` + Capture bool `json:"capture"` +} diff --git a/pkg/paymentmethod/payment_method.go b/pkg/paymentmethod/payment_method.go index 77c53689..dca192f9 100644 --- a/pkg/paymentmethod/payment_method.go +++ b/pkg/paymentmethod/payment_method.go @@ -50,7 +50,7 @@ func (c *client) List(ctx context.Context) ([]Response, error) { var formatted []Response if err := json.Unmarshal(res, &formatted); err != nil { - return nil, err + return nil, fmt.Errorf("error unmarshaling response: %w", err) } return formatted, nil From 331ffd8de86548e13c3694fb01377280a03a1c0f Mon Sep 17 00:00:00 2001 From: gabs Date: Thu, 25 Jan 2024 15:13:56 -0300 Subject: [PATCH 02/25] Improve structs --- pkg/payment/request.go | 51 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/pkg/payment/request.go b/pkg/payment/request.go index 0b44a978..1da2ae03 100644 --- a/pkg/payment/request.go +++ b/pkg/payment/request.go @@ -60,20 +60,20 @@ type AdditionalInfoPayerRequest struct { IsPrimeUser bool `json:"is_prime_user,omitempty"` IsFirstPurchaseOnline bool `json:"is_first_purchase_online,omitempty"` - RegistrationDate *time.Time `json:"registration_date,omitempty"` - LastPurchase *time.Time `json:"last_purchase,omitempty"` - Phone *PhoneRequest `json:"phone,omitempty"` - Address *AddressRequest `json:"address,omitempty"` + RegistrationDate *time.Time `json:"registration_date,omitempty"` + LastPurchase *time.Time `json:"last_purchase,omitempty"` + Phone *AdditionalInfoPayerPhoneRequest `json:"phone,omitempty"` + Address *AdditionalInfoPayerAddressRequest `json:"address,omitempty"` } -// PhoneRequest represents phone request within AdditionalInfoPayerRequest. -type PhoneRequest struct { +// AdditionalInfoPayerPhoneRequest represents phone request within AdditionalInfoPayerRequest. +type AdditionalInfoPayerPhoneRequest struct { AreaCode string `json:"area_code,omitempty"` Number string `json:"number,omitempty"` } -// AddressRequest represents address request within AdditionalInfoPayerRequest. -type AddressRequest struct { +// AdditionalInfoPayerAddressRequest represents address request within AdditionalInfoPayerRequest. +type AdditionalInfoPayerAddressRequest struct { ZipCode string `json:"zip_code,omitempty"` StreetName string `json:"street_name,omitempty"` StreetNumber string `json:"street_number,omitempty"` @@ -113,7 +113,7 @@ type ItemRequest struct { Description string `json:"description,omitempty"` PictureURL string `json:"picture_url,omitempty"` CategoryID string `json:"category_id,omitempty"` - Quantity int `json:"quantity,omitempty"` + Quantity int64 `json:"quantity,omitempty"` UnitPrice float64 `json:"unit_price,omitempty"` Warranty bool `json:"warranty,omitempty"` @@ -174,6 +174,7 @@ type PayerRequest struct { Identification *IdentificationRequest `json:"identification,omitempty"` Address *PayerAddressRequest `json:"address,omitempty"` + Phone *PayerPhoneRequest `json:"phone,omitempty"` } // PayerAddressRequest represents payer address request within PayerRequest. @@ -186,6 +187,12 @@ type PayerAddressRequest struct { StreetNumber string `json:"street_number,omitempty"` } +// PayerPhoneRequest represents payer phone request within PayerRequest. +type PayerPhoneRequest struct { + AreaCode string `json:"area_code,omitempty"` + Number string `json:"number,omitempty"` +} + // TransactionDetailsRequest represents transaction details request within Request. type TransactionDetailsRequest struct { FinancialInstitution string `json:"financial_institution,omitempty"` @@ -195,6 +202,32 @@ type TransactionDetailsRequest struct { type PointOfInteractionRequest struct { LinkedTo string `json:"linked_to,omitempty"` Type string `json:"type,omitempty"` + + TransactionData *TransactionDataRequest `json:"transaction_data,omitempty"` +} + +type TransactionDataRequest struct { + SubscriptionID string `json:"subscription_id,omitempty"` + BillingDate string `json:"billing_date,omitempty"` + FirstTimeUse bool `json:"first_time_use,omitempty"` + + SubscriptionSequence *SubscriptionSequenceRequest `json:"subscription_sequence,omitempty"` + InvoicePeriod *InvoicePeriodRequest `json:"invoice_period,omitempty"` + PaymentReference *PaymentReferenceRequest `json:"payment_reference,omitempty"` +} + +type SubscriptionSequenceRequest struct { + Number int64 `json:"number,omitempty"` + Total int64 `json:"total,omitempty"` +} + +type InvoicePeriodRequest struct { + Type string `json:"type,omitempty"` + Period int64 `json:"period,omitempty"` +} + +type PaymentReferenceRequest struct { + ID string `json:"id,omitempty"` } // PaymentMethodRequest represents payment method request within Request. From e943ef42711ebff304a31113ad7440c676bc51e9 Mon Sep 17 00:00:00 2001 From: gabs Date: Thu, 25 Jan 2024 15:54:37 -0300 Subject: [PATCH 03/25] Add more fields to response struct --- pkg/payment/response.go | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/pkg/payment/response.go b/pkg/payment/response.go index de0ecaa8..465a6f2e 100644 --- a/pkg/payment/response.go +++ b/pkg/payment/response.go @@ -156,6 +156,7 @@ type TransactionDetailsResponse struct { ExternalResourceURL string `json:"external_resource_url,omitempty"` PaymentMethodReferenceID string `json:"payment_method_reference_id,omitempty"` AcquirerReference string `json:"acquirer_reference,omitempty"` + TransactionID string `json:"transaction_id,omitempty"` NetReceivedAmount float64 `json:"net_received_amount,omitempty"` TotalPaidAmount float64 `json:"total_paid_amount,omitempty"` InstallmentAmount float64 `json:"installment_amount,omitempty"` @@ -204,10 +205,16 @@ type TransactionDataResponse struct { QRCodeBase64 string `json:"qr_code_base64,omitempty"` TransactionID string `json:"transaction_id,omitempty"` TicketURL string `json:"ticket_url,omitempty"` + SubscriptionID string `json:"subscription_id,omitempty"` + BillingDate string `json:"billing_date,omitempty"` BankTransferID int64 `json:"bank_transfer_id,omitempty"` FinancialInstitution int64 `json:"financial_institution,omitempty"` + FirstTimeUse bool `json:"first_time_use,omitempty"` - BankInfo *BankInfoResponse `json:"bank_info,omitempty"` + BankInfo *BankInfoResponse `json:"bank_info,omitempty"` + SubscriptionSequence *SubscriptionSequenceResponse `json:"subscription_sequence,omitempty"` + InvoicePeriod *InvoicePeriodResponse `json:"invoice_period,omitempty"` + PaymentReference *PaymentReferenceResponse `json:"payment_reference,omitempty"` } // BankInfoResponse represents bank information. @@ -218,6 +225,23 @@ type BankInfoResponse struct { Collector *BankInfoCollectorResponse `json:"collector,omitempty"` } +// SubscriptionSequenceResponse represents subscription sequence. +type SubscriptionSequenceResponse struct { + Number int64 `json:"number,omitempty"` + Total int64 `json:"total,omitempty"` +} + +// InvoicePeriodResponse represents invoice period. +type InvoicePeriodResponse struct { + Type string `json:"type,omitempty"` + Period int64 `json:"period,omitempty"` +} + +// PaymentReferenceResponse represents payment reference. +type PaymentReferenceResponse struct { + ID string `json:"id,omitempty"` +} + // BankInfoPayerResponse represents payer information within BankInfoResponse. type BankInfoPayerResponse struct { Email string `json:"email,omitempty"` From cd5fac035505c4f175879e5f7252477a0c31415d Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 09:59:12 -0300 Subject: [PATCH 04/25] Adjust search --- pkg/payment/payment.go | 16 ++------ pkg/payment/search_request.go | 77 ++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/pkg/payment/payment.go b/pkg/payment/payment.go index 96f780f7..6d5b4b98 100644 --- a/pkg/payment/payment.go +++ b/pkg/payment/payment.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "net/http" - "net/url" "strconv" "strings" @@ -31,7 +30,7 @@ type Client interface { // Search searches for payments. // It is a get request to the endpoint: https://api.mercadopago.com/v1/payments/search // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments_search/get/ - Search(ctx context.Context, f Filters) (*SearchResponse, error) + Search(ctx context.Context, dto SearchRequest) (*SearchResponse, error) // Get gets a payment by its ID. // It is a get request to the endpoint: https://api.mercadopago.com/v1/payments/{id} @@ -91,16 +90,9 @@ func (c *client) Create(ctx context.Context, dto Request) (*Response, error) { return formatted, nil } -func (c *client) Search(ctx context.Context, f Filters) (*SearchResponse, error) { - params := url.Values{} - params.Add("sort", f.Sort) - params.Add("criteria", f.Criteria) - params.Add("external_reference", f.ExternalReference) - params.Add("range", f.Range) - params.Add("begin_date", f.BeginDate) - params.Add("end_date", f.EndDate) - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL+"?"+params.Encode(), nil) +func (c *client) Search(ctx context.Context, dto SearchRequest) (*SearchResponse, error) { + params := dto.Parameters() + req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL+"?"+params, nil) if err != nil { return nil, fmt.Errorf("error creating request: %w", err) } diff --git a/pkg/payment/search_request.go b/pkg/payment/search_request.go index b869d9ba..95d1cf04 100644 --- a/pkg/payment/search_request.go +++ b/pkg/payment/search_request.go @@ -1,40 +1,43 @@ package payment -// Filters is the filters to search for payments. -type Filters struct { - // Sort is a field used to sort a list of payments. - // The sort can be done by the following attributes: - // - "date_approved" - // - "date_created" - // - "date_last_updated" - // - "id" - // - "money_release_date" - Sort string - - // Criteria is a field used to define the order of the result list. - // Can be "asc" or "desc". - Criteria string - - // ExternalReference is an external reference of the payment. - // It can be, for example, a hashcode from the Central Bank, working as an identifier of the transaction origin. - ExternalReference string - - // Range is a field used to define the range of the search. - // The Range can be related to the following attributes: - // - "date_created" - // - "date_last_updated" - // - "date_approved" - // - "money_release_date" - // If not informed, it uses "date_created" by default. - Range string - - // BeginDate is a field used to define the start of the search interval. - // Its format can be a relative date - "NOW-XDAYS", "NOW-XMONTHS" - or an absolute date - ISO8601. - // If not informed, it uses "NOW-3MONTHS" by default. - BeginDate string - - // EndDate is a field used to define the end of the search interval. - // Its format can be a relative date - "NOW-XDAYS", "NOW-XMONTHS" - or an absolute date - ISO8601. - // If not informed, it uses "NOW" by default. - EndDate string +import ( + "net/url" + "strings" +) + +// SearchRequest is the request to search services. +// Filters field can receive a lot of paramaters. For details, see: +// https://www.mercadopago.com.br/developers/pt/reference/payments/_payments_search/get. +type SearchRequest struct { + Limit string + Offset string + + Filters map[string]string +} + +// Parameters transforms SearchRequest into url params. +func (s SearchRequest) Parameters() string { + params := url.Values{} + + var limitKey, offsetKey bool + for k, v := range s.Filters { + params.Add(k, v) + + if strings.EqualFold(k, "limit") { + limitKey = true + continue + } + if strings.EqualFold(k, "offset") { + offsetKey = true + } + } + + if !limitKey { + params.Add("limit", s.Limit) + } + if !offsetKey { + params.Add("offset", s.Offset) + } + + return params.Encode() } From 7617d60161b5a55dfbdc55123a32ff2ebf3e05c7 Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 14:00:48 -0300 Subject: [PATCH 05/25] Add some tests --- pkg/internal/httpclient/mock.go | 13 ++ pkg/payment/payment_test.go | 194 +++++++++++++++++++ pkg/payment/response.go | 5 + resources/mocks/payment/create_response.json | 143 ++++++++++++++ 4 files changed, 355 insertions(+) create mode 100644 pkg/internal/httpclient/mock.go create mode 100644 pkg/payment/payment_test.go create mode 100644 resources/mocks/payment/create_response.json diff --git a/pkg/internal/httpclient/mock.go b/pkg/internal/httpclient/mock.go new file mode 100644 index 00000000..7176b3b8 --- /dev/null +++ b/pkg/internal/httpclient/mock.go @@ -0,0 +1,13 @@ +package httpclient + +import ( + "net/http" +) + +type Mock struct { + DoMock func(req *http.Request) (*http.Response, error) +} + +func (m *Mock) Do(req *http.Request) (*http.Response, error) { + return m.DoMock(req) +} diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go new file mode 100644 index 00000000..ac042726 --- /dev/null +++ b/pkg/payment/payment_test.go @@ -0,0 +1,194 @@ +package payment + +import ( + "context" + "fmt" + "io" + "net/http" + "os" + "reflect" + "strings" + "testing" + "time" + + "github.com/mercadopago/sdk-go/pkg/credential" + "github.com/mercadopago/sdk-go/pkg/internal/httpclient" + "github.com/mercadopago/sdk-go/pkg/option" +) + +var ( + cred, _ = credential.New("") + + createResponseJSON, _ = os.Open("../../resources/mocks/payment/create_response.json") + createResponse, _ = io.ReadAll(createResponseJSON) +) + +func TestCreate(t *testing.T) { + type fields struct { + credential *credential.Credential + config *option.ClientOptions + } + type args struct { + ctx context.Context + dto Request + } + tests := []struct { + name string + fields fields + args args + want *Response + wantErr string + }{ + { + name: "should_fail_to_marshal_dto", + fields: fields{ + credential: cred, + config: nil, + }, + args: args{ + ctx: nil, + dto: Request{ + Metadata: map[string]any{ + "fail": make(chan int), + }, + }, + }, + want: nil, + wantErr: "error marshaling request body: json: unsupported type: chan int", + }, + { + name: "should_fail_to_create_request", + fields: fields{ + credential: cred, + config: nil, + }, + args: args{ + ctx: nil, + }, + want: nil, + wantErr: "error creating request: net/http: nil Context", + }, + { + name: "should_fail_to_send_request", + fields: fields{ + credential: cred, + config: option.ApplyClientOptions( + option.WithCustomClient( + &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_fail_to_unmarshaling_response", + fields: fields{ + credential: cred, + config: option.ApplyClientOptions( + option.WithCustomClient( + &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader("invalid json") + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + ), + ), + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + }, + { + name: "should_return_formatted_response", + fields: fields{ + credential: cred, + config: option.ApplyClientOptions( + option.WithCustomClient( + &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(createResponse)) + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + ), + ), + }, + args: args{ + ctx: context.Background(), + }, + want: &Response{ + ID: 1316782634, + DateCreated: func() *time.Time { t := time.Date(2024, 1, 26, 10, 1, 4, 655, time.UTC); return &t }(), + DateLastUpdated: func() *time.Time { t := time.Date(2024, 1, 26, 10, 1, 4, 655, time.UTC); return &t }(), + DateOfExpiration: nil, + MoneyReleaseDate: nil, + MoneyReleaseStatus: "released", + OperationType: "regular_payment", + IssuerID: "162", + PaymentMethodID: "master", + PaymentTypeID: "credit_card", + PaymentMethod: &PaymentMethodResponse{ + ID: "master", + Type: "credit_card", + IssuerID: "162", + }, + // Status: "pending", + // Status_detail: "pending_challenge", + // CurrencyID: "MXN", + // Description: nil, + // LiveMode: false, + // SponsorID: nil, + // authorization_code nil, + // money_release_schema nil, + // taxes_amount 0, + // counter_currency nil, + // brand_id nil, + // shipping_amount 0, + // build_version "54.20.12-hotfix-9", + // pos_id nil, + // store_id nil, + // integrator_id nil, + // platform_id nil, + // corporation_id nil, + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + credential: tt.fields.credential, + config: tt.fields.config, + } + got, err := c.Create(tt.args.ctx, tt.args.dto) + 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() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/payment/response.go b/pkg/payment/response.go index 465a6f2e..61c1dfdd 100644 --- a/pkg/payment/response.go +++ b/pkg/payment/response.go @@ -34,6 +34,7 @@ type Response struct { CounterCurrency string `json:"counter_currency,omitempty"` CallForAuthorizeID string `json:"call_for_authorize_id,omitempty"` StatementDescriptor string `json:"statement_descriptor,omitempty"` + MoneyReleaseStatus string `json:"money_release_status,omitempty"` Installments int `json:"installments,omitempty"` ID int64 `json:"id,omitempty"` SponsorID int64 `json:"sponsor_id,omitempty"` @@ -257,6 +258,10 @@ type BankInfoCollectorResponse struct { // PaymentMethodResponse represents payment method information. type PaymentMethodResponse struct { + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + IssuerID string `json:"issuer_id,omitempty"` + Data *DataResponse `json:"data,omitempty"` } diff --git a/resources/mocks/payment/create_response.json b/resources/mocks/payment/create_response.json new file mode 100644 index 00000000..5023cffe --- /dev/null +++ b/resources/mocks/payment/create_response.json @@ -0,0 +1,143 @@ +{ + "id": 1316782634, + "date_created": "2024-01-26T10:01:04.655-04:00", + "date_approved": null, + "date_last_updated": "2024-01-26T10:01:04.655-04:00", + "date_of_expiration": null, + "money_release_date": null, + "money_release_status": "released", + "operation_type": "regular_payment", + "issuer_id": "162", + "payment_method_id": "master", + "payment_type_id": "credit_card", + "payment_method": { + "id": "master", + "type": "credit_card", + "issuer_id": "162" + }, + "status": "pending", + "status_detail": "pending_challenge", + "currency_id": "MXN", + "description": null, + "live_mode": false, + "sponsor_id": null, + "authorization_code": null, + "money_release_schema": null, + "taxes_amount": 0, + "counter_currency": null, + "brand_id": null, + "shipping_amount": 0, + "build_version": "54.20.12-hotfix-9", + "pos_id": null, + "store_id": null, + "integrator_id": null, + "platform_id": null, + "corporation_id": null, + "payer": { + "identification": { + "number": "32659430", + "type": "DNI" + }, + "entity_type": null, + "phone": { + "number": null, + "extension": null, + "area_code": null + }, + "last_name": null, + "id": "1655897964", + "type": null, + "first_name": null, + "email": "test_user_80507629@testuser.com" + }, + "collector_id": 1227208776, + "marketplace_owner": null, + "metadata": {}, + "additional_info": { + "available_balance": null, + "nsu_processadora": null, + "authentication_code": null + }, + "order": {}, + "external_reference": null, + "transaction_amount": 500, + "transaction_amount_refunded": 0, + "coupon_amount": 0, + "differential_pricing_id": null, + "financing_group": null, + "deduction_schema": null, + "installments": 1, + "transaction_details": { + "payment_method_reference_id": null, + "acquirer_reference": null, + "net_received_amount": 0, + "total_paid_amount": 500, + "overpaid_amount": 0, + "external_resource_url": null, + "installment_amount": 500, + "financial_institution": null, + "payable_deferral_period": null + }, + "fee_details": [], + "charges_details": [ + { + "id": "1316782634-001", + "name": "mercadopago_fee", + "type": "fee", + "accounts": { + "from": "collector", + "to": "mp" + }, + "client_id": 0, + "date_created": "2024-01-26T10:01:04.658-04:00", + "last_updated": "2024-01-26T10:01:04.658-04:00", + "amounts": { + "original": 24.89, + "refunded": 0 + }, + "metadata": {}, + "reserve_id": null, + "refund_charges": [] + } + ], + "captured": true, + "binary_mode": false, + "call_for_authorize_id": null, + "statement_descriptor": null, + "card": { + "id": null, + "first_six_digits": "548392", + "last_four_digits": "4623", + "expiration_month": 11, + "expiration_year": 2025, + "date_created": "2024-01-26T10:01:04.000-04:00", + "date_last_updated": "2024-01-26T10:01:04.000-04:00", + "cardholder": { + "name": "GABS", + "identification": { + "number": null, + "type": null + } + } + }, + "notification_url": null, + "refunds": [], + "processing_mode": "aggregator", + "merchant_account_id": null, + "merchant_number": null, + "acquirer_reconciliation": [], + "point_of_interaction": { + "type": "UNSPECIFIED", + "business_info": { + "unit": "online_payments", + "sub_unit": "default", + "branch": null + } + }, + "accounts_info": null, + "three_ds_info": { + "external_resource_url": "https://api.mercadopago.com/cardholder_authenticator/v2/prod/browser-challenges", + "creq": "" + }, + "tags": null +} \ No newline at end of file From 3a533a2d2b7055b5d3855d58ce2166087bf3b03d Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 19:54:12 -0300 Subject: [PATCH 06/25] Refactor tests --- pkg/payment/payment.go | 25 +++----- pkg/payment/payment_test.go | 78 ++++++++++-------------- pkg/paymentmethod/payment_method_test.go | 2 +- 3 files changed, 42 insertions(+), 63 deletions(-) diff --git a/pkg/payment/payment.go b/pkg/payment/payment.go index 6d5b4b98..0de4e2db 100644 --- a/pkg/payment/payment.go +++ b/pkg/payment/payment.go @@ -8,9 +8,8 @@ import ( "strconv" "strings" - "github.com/mercadopago/sdk-go/pkg/credential" + "github.com/mercadopago/sdk-go/pkg/config" "github.com/mercadopago/sdk-go/pkg/internal/httpclient" - "github.com/mercadopago/sdk-go/pkg/option" ) const ( @@ -52,17 +51,13 @@ type Client interface { // client is the implementation of Client. type client struct { - credential *credential.Credential - config *option.ClientOptions + config *config.Config } // NewClient returns a new Payments API Client. -func NewClient(cdt *credential.Credential, opts ...option.ClientOption) Client { - c := option.ApplyClientOptions(opts...) - +func NewClient(c *config.Config) Client { return &client{ - credential: cdt, - config: c, + config: c, } } @@ -77,7 +72,7 @@ func (c *client) Create(ctx context.Context, dto Request) (*Response, error) { return nil, fmt.Errorf("error creating request: %w", err) } - res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + res, err := httpclient.Send(ctx, c.config, req) if err != nil { return nil, err } @@ -97,7 +92,7 @@ func (c *client) Search(ctx context.Context, dto SearchRequest) (*SearchResponse return nil, fmt.Errorf("error creating request: %w", err) } - res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + res, err := httpclient.Send(ctx, c.config, req) if err != nil { return nil, err } @@ -118,7 +113,7 @@ func (c *client) Get(ctx context.Context, id int64) (*Response, error) { return nil, fmt.Errorf("error creating request: %w", err) } - res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + res, err := httpclient.Send(ctx, c.config, req) if err != nil { return nil, err } @@ -144,7 +139,7 @@ func (c *client) Cancel(ctx context.Context, id int64) (*Response, error) { return nil, fmt.Errorf("error creating request: %w", err) } - res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + res, err := httpclient.Send(ctx, c.config, req) if err != nil { return nil, err } @@ -170,7 +165,7 @@ func (c *client) Capture(ctx context.Context, id int64) (*Response, error) { return nil, fmt.Errorf("error creating request: %w", err) } - res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + res, err := httpclient.Send(ctx, c.config, req) if err != nil { return nil, err } @@ -196,7 +191,7 @@ func (c *client) CaptureAmount(ctx context.Context, id int64, amount float64) (* return nil, fmt.Errorf("error creating request: %w", err) } - res, err := httpclient.Send(ctx, c.credential, c.config.Requester, req) + res, err := httpclient.Send(ctx, c.config, req) if err != nil { return nil, err } diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index ac042726..2255085e 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -11,22 +11,18 @@ import ( "testing" "time" - "github.com/mercadopago/sdk-go/pkg/credential" + "github.com/mercadopago/sdk-go/pkg/config" "github.com/mercadopago/sdk-go/pkg/internal/httpclient" - "github.com/mercadopago/sdk-go/pkg/option" ) var ( - cred, _ = credential.New("") - createResponseJSON, _ = os.Open("../../resources/mocks/payment/create_response.json") createResponse, _ = io.ReadAll(createResponseJSON) ) func TestCreate(t *testing.T) { type fields struct { - credential *credential.Credential - config *option.ClientOptions + config *config.Config } type args struct { ctx context.Context @@ -42,8 +38,7 @@ func TestCreate(t *testing.T) { { name: "should_fail_to_marshal_dto", fields: fields{ - credential: cred, - config: nil, + config: nil, }, args: args{ ctx: nil, @@ -59,8 +54,7 @@ func TestCreate(t *testing.T) { { name: "should_fail_to_create_request", fields: fields{ - credential: cred, - config: nil, + config: nil, }, args: args{ ctx: nil, @@ -71,16 +65,13 @@ func TestCreate(t *testing.T) { { name: "should_fail_to_send_request", fields: fields{ - credential: cred, - config: option.ApplyClientOptions( - option.WithCustomClient( - &httpclient.Mock{ - DoMock: func(req *http.Request) (*http.Response, error) { - return nil, fmt.Errorf("some error") - }, + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + return nil, fmt.Errorf("some error") }, - ), - ), + }, + }, }, args: args{ ctx: context.Background(), @@ -91,20 +82,17 @@ func TestCreate(t *testing.T) { { name: "should_fail_to_unmarshaling_response", fields: fields{ - credential: cred, - config: option.ApplyClientOptions( - option.WithCustomClient( - &httpclient.Mock{ - DoMock: func(req *http.Request) (*http.Response, error) { - stringReader := strings.NewReader("invalid json") - stringReadCloser := io.NopCloser(stringReader) - return &http.Response{ - Body: stringReadCloser, - }, nil - }, + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader("invalid json") + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil }, - ), - ), + }, + }, }, args: args{ ctx: context.Background(), @@ -115,20 +103,17 @@ func TestCreate(t *testing.T) { { name: "should_return_formatted_response", fields: fields{ - credential: cred, - config: option.ApplyClientOptions( - option.WithCustomClient( - &httpclient.Mock{ - DoMock: func(req *http.Request) (*http.Response, error) { - stringReader := strings.NewReader(string(createResponse)) - stringReadCloser := io.NopCloser(stringReader) - return &http.Response{ - Body: stringReadCloser, - }, nil - }, + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(createResponse)) + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil }, - ), - ), + }, + }, }, args: args{ ctx: context.Background(), @@ -174,8 +159,7 @@ func TestCreate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := &client{ - credential: tt.fields.credential, - config: tt.fields.config, + config: tt.fields.config, } got, err := c.Create(tt.args.ctx, tt.args.dto) gotErr := "" diff --git a/pkg/paymentmethod/payment_method_test.go b/pkg/paymentmethod/payment_method_test.go index 818f5c3c..f150e9c6 100644 --- a/pkg/paymentmethod/payment_method_test.go +++ b/pkg/paymentmethod/payment_method_test.go @@ -80,7 +80,7 @@ func TestList(t *testing.T) { ctx: context.Background(), }, want: nil, - wantErr: "invalid character 'i' looking for beginning of value", + wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", }, { name: "should_return_formatted_response", From 0d77d35c32098a8f8a6d58bbc5e40b096aa9d3b2 Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 20:42:18 -0300 Subject: [PATCH 07/25] Add payment examples --- examples/apis/payment/cancel/main.go | 27 +++++++++++ examples/apis/payment/capture/main.go | 47 ++++++++++++++++++++ examples/apis/payment/capture_amount/main.go | 47 ++++++++++++++++++++ examples/apis/payment/create/main.go | 38 ++++++++++++++++ examples/apis/payment/get/main.go | 27 +++++++++++ examples/apis/payment/search/main.go | 33 ++++++++++++++ pkg/payment/search_request.go | 12 ++++- 7 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 examples/apis/payment/cancel/main.go create mode 100644 examples/apis/payment/capture/main.go create mode 100644 examples/apis/payment/capture_amount/main.go create mode 100644 examples/apis/payment/create/main.go create mode 100644 examples/apis/payment/get/main.go create mode 100644 examples/apis/payment/search/main.go diff --git a/examples/apis/payment/cancel/main.go b/examples/apis/payment/cancel/main.go new file mode 100644 index 00000000..c08dd7ea --- /dev/null +++ b/examples/apis/payment/cancel/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "context" + "fmt" + + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/payment" +) + +func main() { + at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" + c, err := config.New(at) + if err != nil { + fmt.Println(err) + return + } + + client := payment.NewClient(c) + result, err := client.Cancel(context.Background(), 123) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/examples/apis/payment/capture/main.go b/examples/apis/payment/capture/main.go new file mode 100644 index 00000000..a7149447 --- /dev/null +++ b/examples/apis/payment/capture/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "context" + "fmt" + + "github.com/google/uuid" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/payment" +) + +func main() { + at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" + c, err := config.New(at) + if err != nil { + fmt.Println(err) + return + } + + // Create payment. + dto := payment.Request{ + TransactionAmount: 105.1, + PaymentMethodID: "visa", + Payer: &payment.PayerRequest{ + Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + }, + Token: "cdec5028665c41976be212a7981437d6", + Installments: 1, + Capture: false, + } + + client := payment.NewClient(c) + result, err := client.Create(context.Background(), dto) + if err != nil { + fmt.Println(err) + return + } + + // Capture. + result, err = client.Capture(context.Background(), result.ID) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/examples/apis/payment/capture_amount/main.go b/examples/apis/payment/capture_amount/main.go new file mode 100644 index 00000000..871b7576 --- /dev/null +++ b/examples/apis/payment/capture_amount/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "context" + "fmt" + + "github.com/google/uuid" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/payment" +) + +func main() { + at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" + c, err := config.New(at) + if err != nil { + fmt.Println(err) + return + } + + // Create payment. + dto := payment.Request{ + TransactionAmount: 105.1, + PaymentMethodID: "visa", + Payer: &payment.PayerRequest{ + Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + }, + Token: "cdec5028665c41976be212a7981437d6", + Installments: 1, + Capture: false, + } + + client := payment.NewClient(c) + result, err := client.Create(context.Background(), dto) + if err != nil { + fmt.Println(err) + return + } + + // Capture amount. + result, err = client.CaptureAmount(context.Background(), result.ID, 100.1) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/examples/apis/payment/create/main.go b/examples/apis/payment/create/main.go new file mode 100644 index 00000000..fa61afff --- /dev/null +++ b/examples/apis/payment/create/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "context" + "fmt" + + "github.com/google/uuid" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/payment" +) + +func main() { + at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" + c, err := config.New(at) + if err != nil { + fmt.Println(err) + return + } + + dto := payment.Request{ + TransactionAmount: 105.1, + PaymentMethodID: "visa", + Payer: &payment.PayerRequest{ + Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + }, + Token: "cdec5028665c41976be212a7981437d6", + Installments: 1, + } + + client := payment.NewClient(c) + result, err := client.Create(context.Background(), dto) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/examples/apis/payment/get/main.go b/examples/apis/payment/get/main.go new file mode 100644 index 00000000..d53b86ed --- /dev/null +++ b/examples/apis/payment/get/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "context" + "fmt" + + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/payment" +) + +func main() { + at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" + c, err := config.New(at) + if err != nil { + fmt.Println(err) + return + } + + client := payment.NewClient(c) + result, err := client.Get(context.Background(), 123) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/examples/apis/payment/search/main.go b/examples/apis/payment/search/main.go new file mode 100644 index 00000000..71f6c1a9 --- /dev/null +++ b/examples/apis/payment/search/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "context" + "fmt" + + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/payment" +) + +func main() { + at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" + c, err := config.New(at) + if err != nil { + fmt.Println(err) + return + } + + dto := payment.SearchRequest{ + Filters: map[string]string{ + "external_reference": "abc_def_ghi_123_456123", + }, + } + + client := payment.NewClient(c) + result, err := client.Search(context.Background(), dto) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(result) +} diff --git a/pkg/payment/search_request.go b/pkg/payment/search_request.go index 95d1cf04..4a054052 100644 --- a/pkg/payment/search_request.go +++ b/pkg/payment/search_request.go @@ -33,10 +33,18 @@ func (s SearchRequest) Parameters() string { } if !limitKey { - params.Add("limit", s.Limit) + limit := "30" + if s.Limit != "" { + limit = s.Limit + } + params.Add("limit", limit) } if !offsetKey { - params.Add("offset", s.Offset) + offset := "0" + if s.Limit != "" { + offset = s.Limit + } + params.Add("offset", offset) } return params.Encode() From b1030c9fc81eade536920985b2728c64add8099d Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 21:00:07 -0300 Subject: [PATCH 08/25] Search test --- pkg/payment/payment_test.go | 165 +++++++++++++++---- resources/mocks/payment/create_response.json | 142 +--------------- resources/mocks/payment/search_response.json | 19 +++ 3 files changed, 152 insertions(+), 174 deletions(-) create mode 100644 resources/mocks/payment/search_response.json diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index 2255085e..f91f7efc 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -9,7 +9,6 @@ import ( "reflect" "strings" "testing" - "time" "github.com/mercadopago/sdk-go/pkg/config" "github.com/mercadopago/sdk-go/pkg/internal/httpclient" @@ -18,6 +17,9 @@ import ( var ( createResponseJSON, _ = os.Open("../../resources/mocks/payment/create_response.json") createResponse, _ = io.ReadAll(createResponseJSON) + + searchResponseJSON, _ = os.Open("../../resources/mocks/payment/search_response.json") + searchResponse, _ = io.ReadAll(searchResponseJSON) ) func TestCreate(t *testing.T) { @@ -119,39 +121,9 @@ func TestCreate(t *testing.T) { ctx: context.Background(), }, want: &Response{ - ID: 1316782634, - DateCreated: func() *time.Time { t := time.Date(2024, 1, 26, 10, 1, 4, 655, time.UTC); return &t }(), - DateLastUpdated: func() *time.Time { t := time.Date(2024, 1, 26, 10, 1, 4, 655, time.UTC); return &t }(), - DateOfExpiration: nil, - MoneyReleaseDate: nil, - MoneyReleaseStatus: "released", - OperationType: "regular_payment", - IssuerID: "162", - PaymentMethodID: "master", - PaymentTypeID: "credit_card", - PaymentMethod: &PaymentMethodResponse{ - ID: "master", - Type: "credit_card", - IssuerID: "162", - }, - // Status: "pending", - // Status_detail: "pending_challenge", - // CurrencyID: "MXN", - // Description: nil, - // LiveMode: false, - // SponsorID: nil, - // authorization_code nil, - // money_release_schema nil, - // taxes_amount 0, - // counter_currency nil, - // brand_id nil, - // shipping_amount 0, - // build_version "54.20.12-hotfix-9", - // pos_id nil, - // store_id nil, - // integrator_id nil, - // platform_id nil, - // corporation_id nil, + ID: 123, + Status: "pending", + StatusDetail: "pending_challenge", }, wantErr: "", }, @@ -176,3 +148,128 @@ func TestCreate(t *testing.T) { }) } } + +func TestSearch(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + dto SearchRequest + } + tests := []struct { + name string + fields fields + args args + want *SearchResponse + wantErr string + }{ + { + name: "should_fail_to_create_request", + fields: fields{ + config: nil, + }, + args: args{ + ctx: nil, + }, + want: nil, + wantErr: "error creating request: net/http: nil Context", + }, + { + name: "should_fail_to_send_request", + fields: fields{ + config: &config.Config{ + HTTPClient: &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_fail_to_unmarshaling_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader("invalid json") + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + }, + { + name: "should_return_formatted_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &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(), + }, + want: &SearchResponse{ + Paging: PagingResponse{ + Total: 2, + Limit: 30, + Offset: 0, + }, + Results: []Response{ + { + ID: 123, + Status: "approved", + StatusDetail: "accredited", + }, + { + ID: 456, + Status: "pending", + StatusDetail: "pending_waiting_transfer", + }, + }, + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + config: tt.fields.config, + } + got, err := c.Search(tt.args.ctx, tt.args.dto) + 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) + } + }) + } +} diff --git a/resources/mocks/payment/create_response.json b/resources/mocks/payment/create_response.json index 5023cffe..74a04fad 100644 --- a/resources/mocks/payment/create_response.json +++ b/resources/mocks/payment/create_response.json @@ -1,143 +1,5 @@ { - "id": 1316782634, - "date_created": "2024-01-26T10:01:04.655-04:00", - "date_approved": null, - "date_last_updated": "2024-01-26T10:01:04.655-04:00", - "date_of_expiration": null, - "money_release_date": null, - "money_release_status": "released", - "operation_type": "regular_payment", - "issuer_id": "162", - "payment_method_id": "master", - "payment_type_id": "credit_card", - "payment_method": { - "id": "master", - "type": "credit_card", - "issuer_id": "162" - }, + "id": 123, "status": "pending", - "status_detail": "pending_challenge", - "currency_id": "MXN", - "description": null, - "live_mode": false, - "sponsor_id": null, - "authorization_code": null, - "money_release_schema": null, - "taxes_amount": 0, - "counter_currency": null, - "brand_id": null, - "shipping_amount": 0, - "build_version": "54.20.12-hotfix-9", - "pos_id": null, - "store_id": null, - "integrator_id": null, - "platform_id": null, - "corporation_id": null, - "payer": { - "identification": { - "number": "32659430", - "type": "DNI" - }, - "entity_type": null, - "phone": { - "number": null, - "extension": null, - "area_code": null - }, - "last_name": null, - "id": "1655897964", - "type": null, - "first_name": null, - "email": "test_user_80507629@testuser.com" - }, - "collector_id": 1227208776, - "marketplace_owner": null, - "metadata": {}, - "additional_info": { - "available_balance": null, - "nsu_processadora": null, - "authentication_code": null - }, - "order": {}, - "external_reference": null, - "transaction_amount": 500, - "transaction_amount_refunded": 0, - "coupon_amount": 0, - "differential_pricing_id": null, - "financing_group": null, - "deduction_schema": null, - "installments": 1, - "transaction_details": { - "payment_method_reference_id": null, - "acquirer_reference": null, - "net_received_amount": 0, - "total_paid_amount": 500, - "overpaid_amount": 0, - "external_resource_url": null, - "installment_amount": 500, - "financial_institution": null, - "payable_deferral_period": null - }, - "fee_details": [], - "charges_details": [ - { - "id": "1316782634-001", - "name": "mercadopago_fee", - "type": "fee", - "accounts": { - "from": "collector", - "to": "mp" - }, - "client_id": 0, - "date_created": "2024-01-26T10:01:04.658-04:00", - "last_updated": "2024-01-26T10:01:04.658-04:00", - "amounts": { - "original": 24.89, - "refunded": 0 - }, - "metadata": {}, - "reserve_id": null, - "refund_charges": [] - } - ], - "captured": true, - "binary_mode": false, - "call_for_authorize_id": null, - "statement_descriptor": null, - "card": { - "id": null, - "first_six_digits": "548392", - "last_four_digits": "4623", - "expiration_month": 11, - "expiration_year": 2025, - "date_created": "2024-01-26T10:01:04.000-04:00", - "date_last_updated": "2024-01-26T10:01:04.000-04:00", - "cardholder": { - "name": "GABS", - "identification": { - "number": null, - "type": null - } - } - }, - "notification_url": null, - "refunds": [], - "processing_mode": "aggregator", - "merchant_account_id": null, - "merchant_number": null, - "acquirer_reconciliation": [], - "point_of_interaction": { - "type": "UNSPECIFIED", - "business_info": { - "unit": "online_payments", - "sub_unit": "default", - "branch": null - } - }, - "accounts_info": null, - "three_ds_info": { - "external_resource_url": "https://api.mercadopago.com/cardholder_authenticator/v2/prod/browser-challenges", - "creq": "" - }, - "tags": null + "status_detail": "pending_challenge" } \ No newline at end of file diff --git a/resources/mocks/payment/search_response.json b/resources/mocks/payment/search_response.json new file mode 100644 index 00000000..5b9f31fd --- /dev/null +++ b/resources/mocks/payment/search_response.json @@ -0,0 +1,19 @@ +{ + "paging": { + "total": 2, + "limit": 30, + "offset": 0 + }, + "results": [ + { + "id": 123, + "status": "approved", + "status_detail": "accredited" + }, + { + "id": 456, + "status": "pending", + "status_detail": "pending_waiting_transfer" + } + ] +} \ No newline at end of file From d15e653c365224a758671fb56c9dd4f618fc1f8a Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 21:03:41 -0300 Subject: [PATCH 09/25] Add get tests --- pkg/payment/payment_test.go | 148 ++++++++++++++++++++++ resources/mocks/payment/get_response.json | 5 + 2 files changed, 153 insertions(+) create mode 100644 resources/mocks/payment/get_response.json diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index f91f7efc..578fbd7b 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -20,6 +20,9 @@ var ( searchResponseJSON, _ = os.Open("../../resources/mocks/payment/search_response.json") searchResponse, _ = io.ReadAll(searchResponseJSON) + + getResponseJSON, _ = os.Open("../../resources/mocks/payment/get_response.json") + getResponse, _ = io.ReadAll(getResponseJSON) ) func TestCreate(t *testing.T) { @@ -273,3 +276,148 @@ func TestSearch(t *testing.T) { }) } } + +func TestGet(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + id int64 + } + tests := []struct { + name string + fields fields + args args + want *Response + wantErr string + }{ + { + name: "should_fail_to_create_request", + fields: fields{ + config: nil, + }, + args: args{ + ctx: nil, + }, + want: nil, + wantErr: "error creating request: net/http: nil Context", + }, + { + name: "should_fail_to_send_request", + fields: fields{ + config: &config.Config{ + HTTPClient: &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_fail_to_unmarshaling_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader("invalid json") + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + }, + { + name: "should_return_formatted_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &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(), + }, + want: &Response{ + ID: 789, + Status: "refunded", + StatusDetail: "refunded", + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + config: 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 Test_client_Cancel(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + id int64 + } + tests := []struct { + name string + fields fields + args args + want *Response + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + config: tt.fields.config, + } + got, err := c.Cancel(tt.args.ctx, tt.args.id) + if (err != nil) != tt.wantErr { + t.Errorf("client.Cancel() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("client.Cancel() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/resources/mocks/payment/get_response.json b/resources/mocks/payment/get_response.json new file mode 100644 index 00000000..daaf07a1 --- /dev/null +++ b/resources/mocks/payment/get_response.json @@ -0,0 +1,5 @@ +{ + "id": 789, + "status": "refunded", + "status_detail": "refunded" +} \ No newline at end of file From 42746096e09532c4b214bd505ab9c1c3143bea97 Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 21:07:04 -0300 Subject: [PATCH 10/25] Add cancel test --- pkg/payment/payment_test.go | 90 ++++++++++++++++++-- resources/mocks/payment/cancel_response.json | 5 ++ 2 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 resources/mocks/payment/cancel_response.json diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index 578fbd7b..42a9619d 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -23,6 +23,9 @@ var ( getResponseJSON, _ = os.Open("../../resources/mocks/payment/get_response.json") getResponse, _ = io.ReadAll(getResponseJSON) + + cancelResponseJSON, _ = os.Open("../../resources/mocks/payment/cancel_response.json") + cancelResponse, _ = io.ReadAll(cancelResponseJSON) ) func TestCreate(t *testing.T) { @@ -388,7 +391,7 @@ func TestGet(t *testing.T) { } } -func Test_client_Cancel(t *testing.T) { +func TestCancel(t *testing.T) { type fields struct { config *config.Config } @@ -401,9 +404,82 @@ func Test_client_Cancel(t *testing.T) { fields fields args args want *Response - wantErr bool + wantErr string }{ - // TODO: Add test cases. + { + name: "should_fail_to_create_request", + fields: fields{ + config: nil, + }, + args: args{ + ctx: nil, + }, + want: nil, + wantErr: "error creating request: net/http: nil Context", + }, + { + name: "should_fail_to_send_request", + fields: fields{ + config: &config.Config{ + HTTPClient: &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_fail_to_unmarshaling_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader("invalid json") + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + }, + { + name: "should_return_formatted_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(cancelResponse)) + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: &Response{ + ID: 123, + Status: "cancelled", + StatusDetail: "by_collector", + }, + wantErr: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -411,9 +487,13 @@ func Test_client_Cancel(t *testing.T) { config: tt.fields.config, } got, err := c.Cancel(tt.args.ctx, tt.args.id) - if (err != nil) != tt.wantErr { + gotErr := "" + if err != nil { + gotErr = err.Error() + } + + if gotErr != tt.wantErr { t.Errorf("client.Cancel() error = %v, wantErr %v", err, tt.wantErr) - return } if !reflect.DeepEqual(got, tt.want) { t.Errorf("client.Cancel() = %v, want %v", got, tt.want) diff --git a/resources/mocks/payment/cancel_response.json b/resources/mocks/payment/cancel_response.json new file mode 100644 index 00000000..937183f5 --- /dev/null +++ b/resources/mocks/payment/cancel_response.json @@ -0,0 +1,5 @@ +{ + "id": 123, + "status": "cancelled", + "status_detail": "by_collector" +} \ No newline at end of file From 5433d643171e11d5b6ca37ad8febe6548857c600 Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 21:09:58 -0300 Subject: [PATCH 11/25] Add capture test --- pkg/payment/payment_test.go | 114 ++++++++++++++++++ resources/mocks/payment/capture_response.json | 5 + 2 files changed, 119 insertions(+) create mode 100644 resources/mocks/payment/capture_response.json diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index 42a9619d..3c206d36 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -26,6 +26,9 @@ var ( cancelResponseJSON, _ = os.Open("../../resources/mocks/payment/cancel_response.json") cancelResponse, _ = io.ReadAll(cancelResponseJSON) + + captureResponseJSON, _ = os.Open("../../resources/mocks/payment/capture_response.json") + captureResponse, _ = io.ReadAll(captureResponseJSON) ) func TestCreate(t *testing.T) { @@ -501,3 +504,114 @@ func TestCancel(t *testing.T) { }) } } + +func TestCapture(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + id int64 + } + tests := []struct { + name string + fields fields + args args + want *Response + wantErr string + }{ + { + name: "should_fail_to_create_request", + fields: fields{ + config: nil, + }, + args: args{ + ctx: nil, + }, + want: nil, + wantErr: "error creating request: net/http: nil Context", + }, + { + name: "should_fail_to_send_request", + fields: fields{ + config: &config.Config{ + HTTPClient: &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_fail_to_unmarshaling_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader("invalid json") + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + }, + { + name: "should_return_formatted_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(captureResponse)) + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: &Response{ + ID: 123, + Status: "approved", + StatusDetail: "accredited", + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + config: tt.fields.config, + } + got, err := c.Capture(tt.args.ctx, tt.args.id) + gotErr := "" + if err != nil { + gotErr = err.Error() + } + + if gotErr != tt.wantErr { + t.Errorf("client.Capture() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("client.Capture() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/resources/mocks/payment/capture_response.json b/resources/mocks/payment/capture_response.json new file mode 100644 index 00000000..4e346a77 --- /dev/null +++ b/resources/mocks/payment/capture_response.json @@ -0,0 +1,5 @@ +{ + "id": 123, + "status": "approved", + "status_detail": "accredited" +} \ No newline at end of file From fb2c9ae2e57e0be8786401994a857d88bfc8fc45 Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 21:12:04 -0300 Subject: [PATCH 12/25] Add capture amount test --- pkg/payment/payment_test.go | 115 ++++++++++++++++++ .../payment/capture_amount_response.json | 5 + 2 files changed, 120 insertions(+) create mode 100644 resources/mocks/payment/capture_amount_response.json diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index 3c206d36..f2091e10 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -29,6 +29,9 @@ var ( captureResponseJSON, _ = os.Open("../../resources/mocks/payment/capture_response.json") captureResponse, _ = io.ReadAll(captureResponseJSON) + + captureAmountResponseJSON, _ = os.Open("../../resources/mocks/payment/capture_amount_response.json") + captureAmountResponse, _ = io.ReadAll(captureAmountResponseJSON) ) func TestCreate(t *testing.T) { @@ -615,3 +618,115 @@ func TestCapture(t *testing.T) { }) } } + +func TestCaptureAmount(t *testing.T) { + type fields struct { + config *config.Config + } + type args struct { + ctx context.Context + id int64 + amount float64 + } + tests := []struct { + name string + fields fields + args args + want *Response + wantErr string + }{ + { + name: "should_fail_to_create_request", + fields: fields{ + config: nil, + }, + args: args{ + ctx: nil, + }, + want: nil, + wantErr: "error creating request: net/http: nil Context", + }, + { + name: "should_fail_to_send_request", + fields: fields{ + config: &config.Config{ + HTTPClient: &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_fail_to_unmarshaling_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader("invalid json") + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: nil, + wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + }, + { + name: "should_return_formatted_response", + fields: fields{ + config: &config.Config{ + HTTPClient: &httpclient.Mock{ + DoMock: func(req *http.Request) (*http.Response, error) { + stringReader := strings.NewReader(string(captureAmountResponse)) + stringReadCloser := io.NopCloser(stringReader) + return &http.Response{ + Body: stringReadCloser, + }, nil + }, + }, + }, + }, + args: args{ + ctx: context.Background(), + }, + want: &Response{ + ID: 123, + Status: "approved", + StatusDetail: "accredited", + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &client{ + config: tt.fields.config, + } + got, err := c.CaptureAmount(tt.args.ctx, tt.args.id, tt.args.amount) + gotErr := "" + if err != nil { + gotErr = err.Error() + } + + if gotErr != tt.wantErr { + t.Errorf("client.CaptureAmount() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("client.CaptureAmount() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/resources/mocks/payment/capture_amount_response.json b/resources/mocks/payment/capture_amount_response.json new file mode 100644 index 00000000..4e346a77 --- /dev/null +++ b/resources/mocks/payment/capture_amount_response.json @@ -0,0 +1,5 @@ +{ + "id": 123, + "status": "approved", + "status_detail": "accredited" +} \ No newline at end of file From 71f6e48109efecfc50da0e5791ead49d9432fad4 Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 21:28:01 -0300 Subject: [PATCH 13/25] Add integration tests --- test/integration/payment_test.go | 184 +++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 test/integration/payment_test.go diff --git a/test/integration/payment_test.go b/test/integration/payment_test.go new file mode 100644 index 00000000..dde12ff3 --- /dev/null +++ b/test/integration/payment_test.go @@ -0,0 +1,184 @@ +package integration + +import ( + "context" + "fmt" + "os" + "testing" + + "github.com/google/uuid" + "github.com/mercadopago/sdk-go/pkg/config" + "github.com/mercadopago/sdk-go/pkg/payment" +) + +func TestPayment(t *testing.T) { + t.Run("should_create_payment", func(t *testing.T) { + c, err := config.New(os.Getenv("at")) + if err != nil { + t.Fatal(err) + } + + client := payment.NewClient(c) + + dto := payment.Request{ + TransactionAmount: 105.1, + PaymentMethodID: "pix", + Payer: &payment.PayerRequest{ + Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + }, + } + + result, err := client.Create(context.Background(), dto) + if result == nil { + t.Error("result can't be nil") + } + if result.ID == 0 { + t.Error("id can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) + + t.Run("should_search_payment", func(t *testing.T) { + c, err := config.New(os.Getenv("at")) + if err != nil { + t.Fatal(err) + } + + dto := payment.SearchRequest{ + Filters: map[string]string{ + "external_reference": "abc_def_ghi_123_456123", + }, + } + + client := payment.NewClient(c) + result, err := client.Search(context.Background(), dto) + if result == nil { + t.Error("result can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) + + t.Run("should_get_payment", func(t *testing.T) { + c, err := config.New(os.Getenv("at")) + if err != nil { + t.Fatal(err) + } + + client := payment.NewClient(c) + dto := payment.Request{ + TransactionAmount: 105.1, + PaymentMethodID: "pix", + Payer: &payment.PayerRequest{ + Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + }, + } + + result, err := client.Create(context.Background(), dto) + if result == nil { + t.Error("result can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + + result, err = client.Get(context.Background(), result.ID) + if result == nil { + t.Error("result can't be nil") + } + if result.ID == 0 { + t.Error("id can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) + + t.Run("should_cancel_payment", func(t *testing.T) { + c, err := config.New(os.Getenv("at")) + if err != nil { + t.Fatal(err) + } + + client := payment.NewClient(c) + dto := payment.Request{ + TransactionAmount: 105.1, + PaymentMethodID: "pix", + Payer: &payment.PayerRequest{ + Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + }, + } + + result, err := client.Create(context.Background(), dto) + if result == nil { + t.Error("result can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + + result, err = client.Cancel(context.Background(), result.ID) + if result == nil { + t.Error("result can't be nil") + } + if result.ID == 0 { + t.Error("id can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) + + // We should validate how to test capture and capture amount. + + // t.Run("should_capture_payment", func(t *testing.T) { + // c, err := config.New(os.Getenv("at")) + // if err != nil { + // t.Fatal(err) + // } + + // client := payment.NewClient(c) + // dto := payment.Request{ + // TransactionAmount: 105.1, + // PaymentMethodID: "pix", + // Payer: &payment.PayerRequest{ + // Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + // }, + // } + + // result, err := client.Create(context.Background(), dto) + // if result == nil { + // t.Error("result can't be nil") + // } + // if err != nil { + // t.Errorf(err.Error()) + // } + + // result, err = client.Capture(context.Background(), result.ID) + // if result == nil { + // t.Error("result can't be nil") + // } + // if err != nil { + // t.Errorf(err.Error()) + // } + // }) + + // t.Run("should_capture_amount_payment", func(t *testing.T) { + // c, err := config.New(os.Getenv("at")) + // if err != nil { + // t.Fatal(err) + // } + + // client := payment.NewClient(c) + // result, err := client.CaptureAmount(context.Background(), 123, 100.1) + // if result == nil { + // t.Error("result can't be nil") + // } + // if err != nil { + // t.Errorf(err.Error()) + // } + // }) +} From d908a89bd9e12fb7e20f8e6ecd207bde4e34a892 Mon Sep 17 00:00:00 2001 From: gabs Date: Fri, 26 Jan 2024 21:28:52 -0300 Subject: [PATCH 14/25] Update test name --- test/integration/payment_method_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/payment_method_test.go b/test/integration/payment_method_test.go index ffe0242c..47e0232b 100644 --- a/test/integration/payment_method_test.go +++ b/test/integration/payment_method_test.go @@ -9,7 +9,7 @@ import ( "github.com/mercadopago/sdk-go/pkg/paymentmethod" ) -func TestList(t *testing.T) { +func TestPaymentMethod(t *testing.T) { t.Run("should_list_payment_methods", func(t *testing.T) { c, err := config.New(os.Getenv("at")) if err != nil { From a3b482548bfd881b1b9f8b310a557f59acfbf56a Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Wed, 31 Jan 2024 16:31:52 -0300 Subject: [PATCH 15/25] merge main into feature payment implementation --- pkg/payment/payment_test.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index f2091e10..434f0f1f 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -80,7 +80,7 @@ func TestCreate(t *testing.T) { name: "should_fail_to_send_request", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { return nil, fmt.Errorf("some error") }, @@ -97,7 +97,7 @@ func TestCreate(t *testing.T) { name: "should_fail_to_unmarshaling_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader("invalid json") stringReadCloser := io.NopCloser(stringReader) @@ -118,7 +118,7 @@ func TestCreate(t *testing.T) { name: "should_return_formatted_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader(string(createResponse)) stringReadCloser := io.NopCloser(stringReader) @@ -191,7 +191,7 @@ func TestSearch(t *testing.T) { name: "should_fail_to_send_request", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { return nil, fmt.Errorf("some error") }, @@ -208,7 +208,7 @@ func TestSearch(t *testing.T) { name: "should_fail_to_unmarshaling_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader("invalid json") stringReadCloser := io.NopCloser(stringReader) @@ -229,7 +229,7 @@ func TestSearch(t *testing.T) { name: "should_return_formatted_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader(string(searchResponse)) stringReadCloser := io.NopCloser(stringReader) @@ -316,7 +316,7 @@ func TestGet(t *testing.T) { name: "should_fail_to_send_request", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { return nil, fmt.Errorf("some error") }, @@ -333,7 +333,7 @@ func TestGet(t *testing.T) { name: "should_fail_to_unmarshaling_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader("invalid json") stringReadCloser := io.NopCloser(stringReader) @@ -354,7 +354,7 @@ func TestGet(t *testing.T) { name: "should_return_formatted_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader(string(getResponse)) stringReadCloser := io.NopCloser(stringReader) @@ -427,7 +427,7 @@ func TestCancel(t *testing.T) { name: "should_fail_to_send_request", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { return nil, fmt.Errorf("some error") }, @@ -444,7 +444,7 @@ func TestCancel(t *testing.T) { name: "should_fail_to_unmarshaling_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader("invalid json") stringReadCloser := io.NopCloser(stringReader) @@ -465,7 +465,7 @@ func TestCancel(t *testing.T) { name: "should_return_formatted_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader(string(cancelResponse)) stringReadCloser := io.NopCloser(stringReader) @@ -538,7 +538,7 @@ func TestCapture(t *testing.T) { name: "should_fail_to_send_request", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { return nil, fmt.Errorf("some error") }, @@ -555,7 +555,7 @@ func TestCapture(t *testing.T) { name: "should_fail_to_unmarshaling_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader("invalid json") stringReadCloser := io.NopCloser(stringReader) @@ -576,7 +576,7 @@ func TestCapture(t *testing.T) { name: "should_return_formatted_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader(string(captureResponse)) stringReadCloser := io.NopCloser(stringReader) @@ -650,7 +650,7 @@ func TestCaptureAmount(t *testing.T) { name: "should_fail_to_send_request", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { return nil, fmt.Errorf("some error") }, @@ -667,7 +667,7 @@ func TestCaptureAmount(t *testing.T) { name: "should_fail_to_unmarshaling_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader("invalid json") stringReadCloser := io.NopCloser(stringReader) @@ -688,7 +688,7 @@ func TestCaptureAmount(t *testing.T) { name: "should_return_formatted_response", fields: fields{ config: &config.Config{ - HTTPClient: &httpclient.Mock{ + Requester: &httpclient.Mock{ DoMock: func(req *http.Request) (*http.Response, error) { stringReader := strings.NewReader(string(captureAmountResponse)) stringReadCloser := io.NopCloser(stringReader) From 1c21392ce27f643a3373964d9be642715ea2b34c Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Wed, 31 Jan 2024 16:34:31 -0300 Subject: [PATCH 16/25] adjust integration test --- test/integration/{ => payment}/payment_test.go | 0 test/integration/{ => payment_method}/payment_method_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/integration/{ => payment}/payment_test.go (100%) rename test/integration/{ => payment_method}/payment_method_test.go (100%) diff --git a/test/integration/payment_test.go b/test/integration/payment/payment_test.go similarity index 100% rename from test/integration/payment_test.go rename to test/integration/payment/payment_test.go diff --git a/test/integration/payment_method_test.go b/test/integration/payment_method/payment_method_test.go similarity index 100% rename from test/integration/payment_method_test.go rename to test/integration/payment_method/payment_method_test.go From 7728ca73c72aad232eb254994ef48e7b423d95a9 Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Wed, 31 Jan 2024 17:39:59 -0300 Subject: [PATCH 17/25] adjust examples --- examples/apis/payment/cancel/main.go | 5 +++-- examples/apis/payment/capture/main.go | 5 +++-- examples/apis/payment/capture_amount/main.go | 5 +++-- examples/apis/payment/create/main.go | 5 +++-- examples/apis/payment/get/main.go | 5 +++-- examples/apis/payment/search/main.go | 5 +++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/examples/apis/payment/cancel/main.go b/examples/apis/payment/cancel/main.go index c08dd7ea..0636701c 100644 --- a/examples/apis/payment/cancel/main.go +++ b/examples/apis/payment/cancel/main.go @@ -9,8 +9,9 @@ import ( ) func main() { - at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" - c, err := config.New(at) + accessToken := "{{ACCESS_TOKEN}}" + + c, err := config.New(accessToken) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/capture/main.go b/examples/apis/payment/capture/main.go index a7149447..ea093038 100644 --- a/examples/apis/payment/capture/main.go +++ b/examples/apis/payment/capture/main.go @@ -10,8 +10,9 @@ import ( ) func main() { - at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" - c, err := config.New(at) + accessToken := "{{ACCESS_TOKEN}}" + + c, err := config.New(accessToken) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/capture_amount/main.go b/examples/apis/payment/capture_amount/main.go index 871b7576..187c76ad 100644 --- a/examples/apis/payment/capture_amount/main.go +++ b/examples/apis/payment/capture_amount/main.go @@ -10,8 +10,9 @@ import ( ) func main() { - at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" - c, err := config.New(at) + accessToken := "{{ACCESS_TOKEN}}" + + c, err := config.New(accessToken) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/create/main.go b/examples/apis/payment/create/main.go index fa61afff..980ab21a 100644 --- a/examples/apis/payment/create/main.go +++ b/examples/apis/payment/create/main.go @@ -10,8 +10,9 @@ import ( ) func main() { - at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" - c, err := config.New(at) + accessToken := "{{ACCESS_TOKEN}}" + + c, err := config.New(accessToken) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/get/main.go b/examples/apis/payment/get/main.go index d53b86ed..40f46b11 100644 --- a/examples/apis/payment/get/main.go +++ b/examples/apis/payment/get/main.go @@ -9,8 +9,9 @@ import ( ) func main() { - at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" - c, err := config.New(at) + accessToken := "{{ACCESS_TOKEN}}" + + c, err := config.New(accessToken) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/search/main.go b/examples/apis/payment/search/main.go index 71f6c1a9..400c7137 100644 --- a/examples/apis/payment/search/main.go +++ b/examples/apis/payment/search/main.go @@ -9,8 +9,9 @@ import ( ) func main() { - at := "TEST-640110472259637-071923-a761f639c4eb1f0835ff7611f3248628-793910800" - c, err := config.New(at) + accessToken := "{{ACCESS_TOKEN}}" + + c, err := config.New(accessToken) if err != nil { fmt.Println(err) return From a22d5ff41276c62d3367a2455c251f7a96d77ed0 Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Thu, 1 Feb 2024 09:58:15 -0300 Subject: [PATCH 18/25] adjust capture payment integration tests --- test/integration/payment/payment_test.go | 93 ++++++++++++------------ 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/test/integration/payment/payment_test.go b/test/integration/payment/payment_test.go index dde12ff3..79706c9d 100644 --- a/test/integration/payment/payment_test.go +++ b/test/integration/payment/payment_test.go @@ -133,52 +133,51 @@ func TestPayment(t *testing.T) { }) // We should validate how to test capture and capture amount. + t.Run("should_capture_payment", func(t *testing.T) { + c, err := config.New(os.Getenv("at")) + if err != nil { + t.Fatal(err) + } + + client := payment.NewClient(c) + dto := payment.Request{ + TransactionAmount: 105.1, + PaymentMethodID: "pix", + Payer: &payment.PayerRequest{ + Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + }, + } + + result, err := client.Create(context.Background(), dto) + if result == nil { + t.Error("result can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } - // t.Run("should_capture_payment", func(t *testing.T) { - // c, err := config.New(os.Getenv("at")) - // if err != nil { - // t.Fatal(err) - // } - - // client := payment.NewClient(c) - // dto := payment.Request{ - // TransactionAmount: 105.1, - // PaymentMethodID: "pix", - // Payer: &payment.PayerRequest{ - // Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), - // }, - // } - - // result, err := client.Create(context.Background(), dto) - // if result == nil { - // t.Error("result can't be nil") - // } - // if err != nil { - // t.Errorf(err.Error()) - // } - - // result, err = client.Capture(context.Background(), result.ID) - // if result == nil { - // t.Error("result can't be nil") - // } - // if err != nil { - // t.Errorf(err.Error()) - // } - // }) - - // t.Run("should_capture_amount_payment", func(t *testing.T) { - // c, err := config.New(os.Getenv("at")) - // if err != nil { - // t.Fatal(err) - // } - - // client := payment.NewClient(c) - // result, err := client.CaptureAmount(context.Background(), 123, 100.1) - // if result == nil { - // t.Error("result can't be nil") - // } - // if err != nil { - // t.Errorf(err.Error()) - // } - // }) + result, err = client.Capture(context.Background(), result.ID) + if result == nil { + t.Error("result can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) + + t.Run("should_capture_amount_payment", func(t *testing.T) { + c, err := config.New(os.Getenv("at")) + if err != nil { + t.Fatal(err) + } + + client := payment.NewClient(c) + result, err := client.CaptureAmount(context.Background(), 123, 100.1) + if result == nil { + t.Error("result can't be nil") + } + if err != nil { + t.Errorf(err.Error()) + } + }) } From 01fe1428bcf5e5d8c56ea4b81ee62cde0de404fd Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Thu, 1 Feb 2024 10:52:16 -0300 Subject: [PATCH 19/25] adjust examples and integration test --- examples/apis/payment/cancel/main.go | 4 ++-- examples/apis/payment/capture/main.go | 9 ++++----- examples/apis/payment/capture_amount/main.go | 9 ++++----- examples/apis/payment/create/main.go | 9 ++++----- examples/apis/payment/get/main.go | 20 +++++++++++++++++--- examples/apis/payment/search/main.go | 4 ++-- test/integration/payment/payment_test.go | 8 +++++++- 7 files changed, 40 insertions(+), 23 deletions(-) diff --git a/examples/apis/payment/cancel/main.go b/examples/apis/payment/cancel/main.go index 0636701c..b79d8fd1 100644 --- a/examples/apis/payment/cancel/main.go +++ b/examples/apis/payment/cancel/main.go @@ -11,13 +11,13 @@ import ( func main() { accessToken := "{{ACCESS_TOKEN}}" - c, err := config.New(accessToken) + cfg, err := config.New(accessToken) if err != nil { fmt.Println(err) return } - client := payment.NewClient(c) + client := payment.NewClient(cfg) result, err := client.Cancel(context.Background(), 123) if err != nil { fmt.Println(err) diff --git a/examples/apis/payment/capture/main.go b/examples/apis/payment/capture/main.go index ea093038..39bc75e8 100644 --- a/examples/apis/payment/capture/main.go +++ b/examples/apis/payment/capture/main.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/google/uuid" "github.com/mercadopago/sdk-go/pkg/config" "github.com/mercadopago/sdk-go/pkg/payment" ) @@ -12,7 +11,7 @@ import ( func main() { accessToken := "{{ACCESS_TOKEN}}" - c, err := config.New(accessToken) + cfg, err := config.New(accessToken) if err != nil { fmt.Println(err) return @@ -23,14 +22,14 @@ func main() { TransactionAmount: 105.1, PaymentMethodID: "visa", Payer: &payment.PayerRequest{ - Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + Email: "{{EMAIL}}", }, - Token: "cdec5028665c41976be212a7981437d6", + Token: "{{CARD_TOKEN}}", Installments: 1, Capture: false, } - client := payment.NewClient(c) + client := payment.NewClient(cfg) result, err := client.Create(context.Background(), dto) if err != nil { fmt.Println(err) diff --git a/examples/apis/payment/capture_amount/main.go b/examples/apis/payment/capture_amount/main.go index 187c76ad..835f2edc 100644 --- a/examples/apis/payment/capture_amount/main.go +++ b/examples/apis/payment/capture_amount/main.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/google/uuid" "github.com/mercadopago/sdk-go/pkg/config" "github.com/mercadopago/sdk-go/pkg/payment" ) @@ -12,7 +11,7 @@ import ( func main() { accessToken := "{{ACCESS_TOKEN}}" - c, err := config.New(accessToken) + cfg, err := config.New(accessToken) if err != nil { fmt.Println(err) return @@ -23,14 +22,14 @@ func main() { TransactionAmount: 105.1, PaymentMethodID: "visa", Payer: &payment.PayerRequest{ - Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + Email: "{{EMAIL}}", }, - Token: "cdec5028665c41976be212a7981437d6", + Token: "{{CARD_TOKEN}}", Installments: 1, Capture: false, } - client := payment.NewClient(c) + client := payment.NewClient(cfg) result, err := client.Create(context.Background(), dto) if err != nil { fmt.Println(err) diff --git a/examples/apis/payment/create/main.go b/examples/apis/payment/create/main.go index 980ab21a..49561e13 100644 --- a/examples/apis/payment/create/main.go +++ b/examples/apis/payment/create/main.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/google/uuid" "github.com/mercadopago/sdk-go/pkg/config" "github.com/mercadopago/sdk-go/pkg/payment" ) @@ -12,7 +11,7 @@ import ( func main() { accessToken := "{{ACCESS_TOKEN}}" - c, err := config.New(accessToken) + cfg, err := config.New(accessToken) if err != nil { fmt.Println(err) return @@ -22,13 +21,13 @@ func main() { TransactionAmount: 105.1, PaymentMethodID: "visa", Payer: &payment.PayerRequest{ - Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), + Email: "{{EMAIL}}", }, - Token: "cdec5028665c41976be212a7981437d6", + Token: "{{CARD_TOKEN}}", Installments: 1, } - client := payment.NewClient(c) + client := payment.NewClient(cfg) result, err := client.Create(context.Background(), dto) if err != nil { fmt.Println(err) diff --git a/examples/apis/payment/get/main.go b/examples/apis/payment/get/main.go index 40f46b11..91ed5c5b 100644 --- a/examples/apis/payment/get/main.go +++ b/examples/apis/payment/get/main.go @@ -11,14 +11,28 @@ import ( func main() { accessToken := "{{ACCESS_TOKEN}}" - c, err := config.New(accessToken) + cfg, err := config.New(accessToken) + if err != nil { + fmt.Println(err) + return + } + dto := payment.Request{ + TransactionAmount: 105.1, + PaymentMethodID: "pix", + Payer: &payment.PayerRequest{ + Email: "{{EMAIL}}", + }, + } + + client := payment.NewClient(cfg) + + result, err := client.Create(context.Background(), dto) if err != nil { fmt.Println(err) return } - client := payment.NewClient(c) - result, err := client.Get(context.Background(), 123) + result, err = client.Get(context.Background(), result.ID) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/search/main.go b/examples/apis/payment/search/main.go index 400c7137..3a513d59 100644 --- a/examples/apis/payment/search/main.go +++ b/examples/apis/payment/search/main.go @@ -11,7 +11,7 @@ import ( func main() { accessToken := "{{ACCESS_TOKEN}}" - c, err := config.New(accessToken) + cfg, err := config.New(accessToken) if err != nil { fmt.Println(err) return @@ -23,7 +23,7 @@ func main() { }, } - client := payment.NewClient(c) + client := payment.NewClient(cfg) result, err := client.Search(context.Background(), dto) if err != nil { fmt.Println(err) diff --git a/test/integration/payment/payment_test.go b/test/integration/payment/payment_test.go index 79706c9d..40c37aec 100644 --- a/test/integration/payment/payment_test.go +++ b/test/integration/payment/payment_test.go @@ -140,12 +140,18 @@ func TestPayment(t *testing.T) { } client := payment.NewClient(c) + + // Create payment. dto := payment.Request{ TransactionAmount: 105.1, - PaymentMethodID: "pix", + PaymentMethodID: "visa", Payer: &payment.PayerRequest{ Email: fmt.Sprintf("gabs_%s@testuser.com", uuid.New()), }, + // Need to get a token from a card. + Token: "", + Installments: 1, + Capture: false, } result, err := client.Create(context.Background(), dto) From d44a2b1039dc2106b8f1af8870bbab4013df1921 Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Thu, 1 Feb 2024 11:43:31 -0300 Subject: [PATCH 20/25] adjust examples --- examples/apis/payment/cancel/main.go | 3 ++- examples/apis/payment/capture/main.go | 4 ++-- examples/apis/payment/capture_amount/main.go | 4 ++-- examples/apis/payment/create/main.go | 4 ++-- examples/apis/payment/search/main.go | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/apis/payment/cancel/main.go b/examples/apis/payment/cancel/main.go index b79d8fd1..522a9378 100644 --- a/examples/apis/payment/cancel/main.go +++ b/examples/apis/payment/cancel/main.go @@ -18,7 +18,8 @@ func main() { } client := payment.NewClient(cfg) - result, err := client.Cancel(context.Background(), 123) + paymentID := int64(123) + result, err := client.Cancel(context.Background(), paymentID) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/capture/main.go b/examples/apis/payment/capture/main.go index 39bc75e8..39957409 100644 --- a/examples/apis/payment/capture/main.go +++ b/examples/apis/payment/capture/main.go @@ -18,7 +18,7 @@ func main() { } // Create payment. - dto := payment.Request{ + paymentRequest := payment.Request{ TransactionAmount: 105.1, PaymentMethodID: "visa", Payer: &payment.PayerRequest{ @@ -30,7 +30,7 @@ func main() { } client := payment.NewClient(cfg) - result, err := client.Create(context.Background(), dto) + result, err := client.Create(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/capture_amount/main.go b/examples/apis/payment/capture_amount/main.go index 835f2edc..420d4357 100644 --- a/examples/apis/payment/capture_amount/main.go +++ b/examples/apis/payment/capture_amount/main.go @@ -18,7 +18,7 @@ func main() { } // Create payment. - dto := payment.Request{ + paymentRequest := payment.Request{ TransactionAmount: 105.1, PaymentMethodID: "visa", Payer: &payment.PayerRequest{ @@ -30,7 +30,7 @@ func main() { } client := payment.NewClient(cfg) - result, err := client.Create(context.Background(), dto) + result, err := client.Create(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/create/main.go b/examples/apis/payment/create/main.go index 49561e13..79679f6f 100644 --- a/examples/apis/payment/create/main.go +++ b/examples/apis/payment/create/main.go @@ -17,7 +17,7 @@ func main() { return } - dto := payment.Request{ + paymentRequest := payment.Request{ TransactionAmount: 105.1, PaymentMethodID: "visa", Payer: &payment.PayerRequest{ @@ -28,7 +28,7 @@ func main() { } client := payment.NewClient(cfg) - result, err := client.Create(context.Background(), dto) + result, err := client.Create(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/search/main.go b/examples/apis/payment/search/main.go index 3a513d59..209c1d85 100644 --- a/examples/apis/payment/search/main.go +++ b/examples/apis/payment/search/main.go @@ -17,14 +17,14 @@ func main() { return } - dto := payment.SearchRequest{ + paymentRequest := payment.SearchRequest{ Filters: map[string]string{ "external_reference": "abc_def_ghi_123_456123", }, } client := payment.NewClient(cfg) - result, err := client.Search(context.Background(), dto) + result, err := client.Search(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return From 09341bbd49594ad2e592da6da98c75e247b85f36 Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Thu, 1 Feb 2024 13:44:05 -0300 Subject: [PATCH 21/25] rename variable names --- examples/apis/payment/cancel/main.go | 3 ++- examples/apis/payment/capture/main.go | 4 ++-- examples/apis/payment/capture_amount/main.go | 4 ++-- examples/apis/payment/create/main.go | 4 ++-- examples/apis/payment/get/main.go | 8 ++++---- examples/apis/payment/search/main.go | 4 ++-- pkg/payment/payment.go | 8 ++++---- pkg/payment/search_request.go | 19 +++++-------------- test/integration/payment/payment_test.go | 12 ++++++------ 9 files changed, 29 insertions(+), 37 deletions(-) diff --git a/examples/apis/payment/cancel/main.go b/examples/apis/payment/cancel/main.go index 522a9378..b74eab66 100644 --- a/examples/apis/payment/cancel/main.go +++ b/examples/apis/payment/cancel/main.go @@ -18,7 +18,8 @@ func main() { } client := payment.NewClient(cfg) - paymentID := int64(123) + var paymentID int64 = 123 + result, err := client.Cancel(context.Background(), paymentID) if err != nil { fmt.Println(err) diff --git a/examples/apis/payment/capture/main.go b/examples/apis/payment/capture/main.go index 39957409..c617ccd9 100644 --- a/examples/apis/payment/capture/main.go +++ b/examples/apis/payment/capture/main.go @@ -30,14 +30,14 @@ func main() { } client := payment.NewClient(cfg) - result, err := client.Create(context.Background(), paymentRequest) + pay, err := client.Create(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return } // Capture. - result, err = client.Capture(context.Background(), result.ID) + result, err := client.Capture(context.Background(), pay.ID) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/capture_amount/main.go b/examples/apis/payment/capture_amount/main.go index 420d4357..972f82ac 100644 --- a/examples/apis/payment/capture_amount/main.go +++ b/examples/apis/payment/capture_amount/main.go @@ -30,14 +30,14 @@ func main() { } client := payment.NewClient(cfg) - result, err := client.Create(context.Background(), paymentRequest) + pay, err := client.Create(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return } // Capture amount. - result, err = client.CaptureAmount(context.Background(), result.ID, 100.1) + result, err := client.CaptureAmount(context.Background(), pay.ID, 100.1) if err != nil { fmt.Println(err) return diff --git a/examples/apis/payment/create/main.go b/examples/apis/payment/create/main.go index 79679f6f..57cb2695 100644 --- a/examples/apis/payment/create/main.go +++ b/examples/apis/payment/create/main.go @@ -28,11 +28,11 @@ func main() { } client := payment.NewClient(cfg) - result, err := client.Create(context.Background(), paymentRequest) + pay, err := client.Create(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return } - fmt.Println(result) + fmt.Println(pay) } diff --git a/examples/apis/payment/get/main.go b/examples/apis/payment/get/main.go index 91ed5c5b..1c6478f5 100644 --- a/examples/apis/payment/get/main.go +++ b/examples/apis/payment/get/main.go @@ -16,7 +16,7 @@ func main() { fmt.Println(err) return } - dto := payment.Request{ + paymentRequest := payment.Request{ TransactionAmount: 105.1, PaymentMethodID: "pix", Payer: &payment.PayerRequest{ @@ -26,17 +26,17 @@ func main() { client := payment.NewClient(cfg) - result, err := client.Create(context.Background(), dto) + pay, err := client.Create(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return } - result, err = client.Get(context.Background(), result.ID) + pay, err = client.Get(context.Background(), pay.ID) if err != nil { fmt.Println(err) return } - fmt.Println(result) + fmt.Println(pay) } diff --git a/examples/apis/payment/search/main.go b/examples/apis/payment/search/main.go index 209c1d85..c62549b7 100644 --- a/examples/apis/payment/search/main.go +++ b/examples/apis/payment/search/main.go @@ -24,11 +24,11 @@ func main() { } client := payment.NewClient(cfg) - result, err := client.Search(context.Background(), paymentRequest) + pay, err := client.Search(context.Background(), paymentRequest) if err != nil { fmt.Println(err) return } - fmt.Println(result) + fmt.Println(pay) } diff --git a/pkg/payment/payment.go b/pkg/payment/payment.go index 0de4e2db..f1baafa5 100644 --- a/pkg/payment/payment.go +++ b/pkg/payment/payment.go @@ -24,12 +24,12 @@ type Client interface { // Create creates a new payment. // It is a post request to the endpoint: https://api.mercadopago.com/v1/payments // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments/post/ - Create(ctx context.Context, dto Request) (*Response, error) + Create(ctx context.Context, request Request) (*Response, error) // Search searches for payments. // It is a get request to the endpoint: https://api.mercadopago.com/v1/payments/search // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments_search/get/ - Search(ctx context.Context, dto SearchRequest) (*SearchResponse, error) + Search(ctx context.Context, request SearchRequest) (*SearchResponse, error) // Get gets a payment by its ID. // It is a get request to the endpoint: https://api.mercadopago.com/v1/payments/{id} @@ -61,8 +61,8 @@ func NewClient(c *config.Config) Client { } } -func (c *client) Create(ctx context.Context, dto Request) (*Response, error) { - body, err := json.Marshal(&dto) +func (c *client) Create(ctx context.Context, request Request) (*Response, error) { + body, err := json.Marshal(&request) if err != nil { return nil, fmt.Errorf("error marshaling request body: %w", err) } diff --git a/pkg/payment/search_request.go b/pkg/payment/search_request.go index 4a054052..9d8d5801 100644 --- a/pkg/payment/search_request.go +++ b/pkg/payment/search_request.go @@ -2,7 +2,6 @@ package payment import ( "net/url" - "strings" ) // SearchRequest is the request to search services. @@ -19,30 +18,22 @@ type SearchRequest struct { func (s SearchRequest) Parameters() string { params := url.Values{} - var limitKey, offsetKey bool for k, v := range s.Filters { params.Add(k, v) - - if strings.EqualFold(k, "limit") { - limitKey = true - continue - } - if strings.EqualFold(k, "offset") { - offsetKey = true - } } - if !limitKey { + if _, ok := s.Filters["limit"]; !ok { limit := "30" if s.Limit != "" { limit = s.Limit } params.Add("limit", limit) } - if !offsetKey { + + if _, ok := s.Filters["offset"]; !ok { offset := "0" - if s.Limit != "" { - offset = s.Limit + if s.Offset != "" { + offset = s.Offset } params.Add("offset", offset) } diff --git a/test/integration/payment/payment_test.go b/test/integration/payment/payment_test.go index 40c37aec..d984bc78 100644 --- a/test/integration/payment/payment_test.go +++ b/test/integration/payment/payment_test.go @@ -13,7 +13,7 @@ import ( func TestPayment(t *testing.T) { t.Run("should_create_payment", func(t *testing.T) { - c, err := config.New(os.Getenv("at")) + c, err := config.New(os.Getenv("ACCESS_TOKEN")) if err != nil { t.Fatal(err) } @@ -41,7 +41,7 @@ func TestPayment(t *testing.T) { }) t.Run("should_search_payment", func(t *testing.T) { - c, err := config.New(os.Getenv("at")) + c, err := config.New(os.Getenv("ACCESS_TOKEN")) if err != nil { t.Fatal(err) } @@ -63,7 +63,7 @@ func TestPayment(t *testing.T) { }) t.Run("should_get_payment", func(t *testing.T) { - c, err := config.New(os.Getenv("at")) + c, err := config.New(os.Getenv("ACCESS_TOKEN")) if err != nil { t.Fatal(err) } @@ -98,7 +98,7 @@ func TestPayment(t *testing.T) { }) t.Run("should_cancel_payment", func(t *testing.T) { - c, err := config.New(os.Getenv("at")) + c, err := config.New(os.Getenv("ACCESS_TOKEN")) if err != nil { t.Fatal(err) } @@ -134,7 +134,7 @@ func TestPayment(t *testing.T) { // We should validate how to test capture and capture amount. t.Run("should_capture_payment", func(t *testing.T) { - c, err := config.New(os.Getenv("at")) + c, err := config.New(os.Getenv("ACCESS_TOKEN")) if err != nil { t.Fatal(err) } @@ -172,7 +172,7 @@ func TestPayment(t *testing.T) { }) t.Run("should_capture_amount_payment", func(t *testing.T) { - c, err := config.New(os.Getenv("at")) + c, err := config.New(os.Getenv("ACCESS_TOKEN")) if err != nil { t.Fatal(err) } From eec206b0f8f9284f1285d3eb696a9f5b08d72460 Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Fri, 2 Feb 2024 10:16:52 -0300 Subject: [PATCH 22/25] remover pointer from response --- examples/apis/payment/capture/main.go | 4 +- examples/apis/payment/capture_amount/main.go | 4 +- pkg/payment/payment.go | 78 ++-- pkg/payment/payment_test.go | 4 +- pkg/payment/response.go | 370 +++++++++---------- resources/mocks/payment/search_response.json | 4 +- 6 files changed, 245 insertions(+), 219 deletions(-) diff --git a/examples/apis/payment/capture/main.go b/examples/apis/payment/capture/main.go index c617ccd9..c5f763d2 100644 --- a/examples/apis/payment/capture/main.go +++ b/examples/apis/payment/capture/main.go @@ -37,11 +37,11 @@ func main() { } // Capture. - result, err := client.Capture(context.Background(), pay.ID) + pay, err = client.Capture(context.Background(), pay.ID) if err != nil { fmt.Println(err) return } - fmt.Println(result) + fmt.Println(pay) } diff --git a/examples/apis/payment/capture_amount/main.go b/examples/apis/payment/capture_amount/main.go index 972f82ac..bd293760 100644 --- a/examples/apis/payment/capture_amount/main.go +++ b/examples/apis/payment/capture_amount/main.go @@ -37,11 +37,11 @@ func main() { } // Capture amount. - result, err := client.CaptureAmount(context.Background(), pay.ID, 100.1) + pay, err = client.CaptureAmount(context.Background(), pay.ID, 100.1) if err != nil { fmt.Println(err) return } - fmt.Println(result) + fmt.Println(pay) } diff --git a/pkg/payment/payment.go b/pkg/payment/payment.go index f1baafa5..283fca44 100644 --- a/pkg/payment/payment.go +++ b/pkg/payment/payment.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" "strconv" "strings" @@ -13,27 +14,28 @@ import ( ) const ( - postURL = "https://api.mercadopago.com/v1/payments" - searchURL = "https://api.mercadopago.com/v1/payments/search" - getURL = "https://api.mercadopago.com/v1/payments/{id}" - putURL = "https://api.mercadopago.com/v1/payments/{id}" + baseURL = "https://api.mercadopago.com/v1/" + postURL = baseURL + "payments" + searchURL = baseURL + "payments/search" + getURL = baseURL + "payments/{id}" + putURL = baseURL + "payments/{id}" ) // Client contains the methods to interact with the Payments API. type Client interface { // Create creates a new payment. // It is a post request to the endpoint: https://api.mercadopago.com/v1/payments - // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments/post/ + // Reference: https://www.mercadopago.com/developers/en/reference/payments/_payments/post/ Create(ctx context.Context, request Request) (*Response, error) // Search searches for payments. // It is a get request to the endpoint: https://api.mercadopago.com/v1/payments/search - // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments_search/get/ + // Reference: https://www.mercadopago.com/developers/en/reference/payments/_payments_search/get/ Search(ctx context.Context, request SearchRequest) (*SearchResponse, error) // Get gets a payment by its ID. // It is a get request to the endpoint: https://api.mercadopago.com/v1/payments/{id} - // Reference: https://www.mercadopago.com.br/developers/pt/reference/payments/_payments_id/get/ + // Reference: https://www.mercadopago.com/developers/en/reference/payments/_payments_id/get/ Get(ctx context.Context, id int64) (*Response, error) // Cancel cancels a payment by its ID. @@ -77,17 +79,25 @@ func (c *client) Create(ctx context.Context, request Request) (*Response, error) return nil, err } - formatted := &Response{} - if err := json.Unmarshal(res, &formatted); err != nil { + var payment *Response + if err := json.Unmarshal(res, &payment); err != nil { return nil, fmt.Errorf("error unmarshaling response: %w", err) } - return formatted, nil + return payment, nil } func (c *client) Search(ctx context.Context, dto SearchRequest) (*SearchResponse, error) { params := dto.Parameters() - req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL+"?"+params, nil) + + url, err := url.Parse(searchURL) + if err != nil { + return nil, fmt.Errorf("error parsing url: %w", err) + } + url.RawQuery = params + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url.String(), nil) + if err != nil { return nil, fmt.Errorf("error creating request: %w", err) } @@ -97,12 +107,12 @@ func (c *client) Search(ctx context.Context, dto SearchRequest) (*SearchResponse return nil, err } - var formatted *SearchResponse - if err := json.Unmarshal(res, &formatted); err != nil { + var payment *SearchResponse + if err := json.Unmarshal(res, &payment); err != nil { return nil, fmt.Errorf("error unmarshaling response: %w", err) } - return formatted, nil + return payment, nil } func (c *client) Get(ctx context.Context, id int64) (*Response, error) { @@ -118,12 +128,12 @@ func (c *client) Get(ctx context.Context, id int64) (*Response, error) { return nil, err } - formatted := &Response{} - if err := json.Unmarshal(res, &formatted); err != nil { + var payment *Response + if err := json.Unmarshal(res, &payment); err != nil { return nil, fmt.Errorf("error unmarshaling response: %w", err) } - return formatted, nil + return payment, nil } func (c *client) Cancel(ctx context.Context, id int64) (*Response, error) { @@ -144,12 +154,12 @@ func (c *client) Cancel(ctx context.Context, id int64) (*Response, error) { return nil, err } - formatted := &Response{} - if err := json.Unmarshal(res, &formatted); err != nil { + var payment *Response + if err := json.Unmarshal(res, &payment); err != nil { return nil, fmt.Errorf("error unmarshaling response: %w", err) } - return formatted, nil + return payment, nil } func (c *client) Capture(ctx context.Context, id int64) (*Response, error) { @@ -170,12 +180,12 @@ func (c *client) Capture(ctx context.Context, id int64) (*Response, error) { return nil, err } - formatted := &Response{} - if err := json.Unmarshal(res, &formatted); err != nil { + var payment *Response + if err := json.Unmarshal(res, &payment); err != nil { return nil, fmt.Errorf("error unmarshaling response: %w", err) } - return formatted, nil + return payment, nil } func (c *client) CaptureAmount(ctx context.Context, id int64, amount float64) (*Response, error) { @@ -196,10 +206,26 @@ func (c *client) CaptureAmount(ctx context.Context, id int64, amount float64) (* return nil, err } - formatted := &Response{} - if err := json.Unmarshal(res, &formatted); err != nil { + var payment *Response + if err := json.Unmarshal(res, &payment); err != nil { return nil, fmt.Errorf("error unmarshaling response: %w", err) } - return formatted, nil + return payment, nil +} + +func buildUrl(params url.Values) (string, error) { + url, err := url.Parse(searchURL) + if err != nil { + return "", fmt.Errorf("error parsing url: %w", err) + } + + for key, value := range params { + for _, v := range value { + q := url.Query() + q.Add(key, v) + url.RawQuery = q.Encode() + } + } + return url.String(), nil } diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index 434f0f1f..4488cd0f 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -251,12 +251,12 @@ func TestSearch(t *testing.T) { }, Results: []Response{ { - ID: 123, + ID: 57592046572, Status: "approved", StatusDetail: "accredited", }, { - ID: 456, + ID: 57592038796, Status: "pending", StatusDetail: "pending_waiting_transfer", }, diff --git a/pkg/payment/response.go b/pkg/payment/response.go index 61c1dfdd..fff8eb57 100644 --- a/pkg/payment/response.go +++ b/pkg/payment/response.go @@ -6,328 +6,328 @@ import ( // Response is the response from the Payments API. type Response struct { - DifferentialPricingID string `json:"differential_pricing_id,omitempty"` - MoneyReleaseSchema string `json:"money_release_schema,omitempty"` - OperationType string `json:"operation_type,omitempty"` - IssuerID string `json:"issuer_id,omitempty"` - PaymentMethodID string `json:"payment_method_id,omitempty"` - PaymentTypeID string `json:"payment_type_id,omitempty"` - Status string `json:"status,omitempty"` - StatusDetail string `json:"status_detail,omitempty"` - CurrencyID string `json:"currency_id,omitempty"` - Description string `json:"description,omitempty"` - AuthorizationCode string `json:"authorization_code,omitempty"` - IntegratorID string `json:"integrator_id,omitempty"` - PlatformID string `json:"platform_id,omitempty"` - CorporationID string `json:"corporation_id,omitempty"` - NotificationURL string `json:"notification_url,omitempty"` - CallbackURL string `json:"callback_url,omitempty"` - ProcessingMode string `json:"processing_mode,omitempty"` - MerchantAccountID string `json:"merchant_account_id,omitempty"` - MerchantNumber string `json:"merchant_number,omitempty"` - CouponCode string `json:"coupon_code,omitempty"` - ExternalReference string `json:"external_reference,omitempty"` - PaymentMethodOptionID string `json:"payment_method_option_id,omitempty"` - PosID string `json:"pos_id,omitempty"` - StoreID string `json:"store_id,omitempty"` - DeductionSchema string `json:"deduction_schema,omitempty"` - CounterCurrency string `json:"counter_currency,omitempty"` - CallForAuthorizeID string `json:"call_for_authorize_id,omitempty"` - StatementDescriptor string `json:"statement_descriptor,omitempty"` - MoneyReleaseStatus string `json:"money_release_status,omitempty"` - Installments int `json:"installments,omitempty"` - ID int64 `json:"id,omitempty"` - SponsorID int64 `json:"sponsor_id,omitempty"` - CollectorID int64 `json:"collector_id,omitempty"` - TransactionAmount float64 `json:"transaction_amount,omitempty"` - TransactionAmountRefunded float64 `json:"transaction_amount_refunded,omitempty"` - CouponAmount float64 `json:"coupon_amount,omitempty"` - TaxesAmount float64 `json:"taxes_amount,omitempty"` - ShippingAmount float64 `json:"shipping_amount,omitempty"` - NetAmount float64 `json:"net_amount,omitempty"` - LiveMode bool `json:"live_mode,omitempty"` - Captured bool `json:"captured,omitempty"` - BinaryMode bool `json:"binary_mode,omitempty"` - Metadata map[string]any `json:"metadata,omitempty"` - InternalMetadata map[string]any `json:"internal_metadata,omitempty"` - - DateCreated *time.Time `json:"date_created,omitempty"` - DateApproved *time.Time `json:"date_approved,omitempty"` - DateLastUpdated *time.Time `json:"date_last_updated,omitempty"` - DateOfExpiration *time.Time `json:"date_of_expiration,omitempty"` - MoneyReleaseDate *time.Time `json:"money_release_date,omitempty"` - Payer *PayerResponse `json:"payer,omitempty"` - AdditionalInfo *AdditionalInfoResponse `json:"additional_info,omitempty"` - Order *OrderResponse `json:"order,omitempty"` - TransactionDetails *TransactionDetailsResponse `json:"transaction_details,omitempty"` - Card *CardResponse `json:"card,omitempty"` - PointOfInteraction *PointOfInteractionResponse `json:"point_of_interaction,omitempty"` - PaymentMethod *PaymentMethodResponse `json:"payment_method,omitempty"` - ThreeDSInfo *ThreeDSInfoResponse `json:"three_ds_info,omitempty"` - FeeDetails []FeeDetailResponse `json:"fee_details,omitempty"` - Taxes []TaxResponse `json:"taxes,omitempty"` - Refunds []RefundResponse `json:"refunds,omitempty"` + DifferentialPricingID string `json:"differential_pricing_id"` + MoneyReleaseSchema string `json:"money_release_schema"` + OperationType string `json:"operation_type"` + IssuerID string `json:"issuer_id"` + PaymentMethodID string `json:"payment_method_id"` + PaymentTypeID string `json:"payment_type_id"` + Status string `json:"status"` + StatusDetail string `json:"status_detail"` + CurrencyID string `json:"currency_id"` + Description string `json:"description"` + AuthorizationCode string `json:"authorization_code"` + IntegratorID string `json:"integrator_id"` + PlatformID string `json:"platform_id"` + CorporationID string `json:"corporation_id"` + NotificationURL string `json:"notification_url"` + CallbackURL string `json:"callback_url"` + ProcessingMode string `json:"processing_mode"` + MerchantAccountID string `json:"merchant_account_id"` + MerchantNumber string `json:"merchant_number"` + CouponCode string `json:"coupon_code"` + ExternalReference string `json:"external_reference"` + PaymentMethodOptionID string `json:"payment_method_option_id"` + PosID string `json:"pos_id"` + StoreID string `json:"store_id"` + DeductionSchema string `json:"deduction_schema"` + CounterCurrency string `json:"counter_currency"` + CallForAuthorizeID string `json:"call_for_authorize_id"` + StatementDescriptor string `json:"statement_descriptor"` + MoneyReleaseStatus string `json:"money_release_status"` + Installments int `json:"installments"` + ID int64 `json:"id"` + SponsorID int64 `json:"sponsor_id"` + CollectorID int64 `json:"collector_id"` + TransactionAmount float64 `json:"transaction_amount"` + TransactionAmountRefunded float64 `json:"transaction_amount_refunded"` + CouponAmount float64 `json:"coupon_amount"` + TaxesAmount float64 `json:"taxes_amount"` + ShippingAmount float64 `json:"shipping_amount"` + NetAmount float64 `json:"net_amount"` + LiveMode bool `json:"live_mode"` + Captured bool `json:"captured"` + BinaryMode bool `json:"binary_mode"` + Metadata map[string]any `json:"metadata"` + InternalMetadata map[string]any `json:"internal_metadata"` + + DateCreated time.Time `json:"date_created"` + DateApproved time.Time `json:"date_approved"` + DateLastUpdated time.Time `json:"date_last_updated"` + DateOfExpiration time.Time `json:"date_of_expiration"` + MoneyReleaseDate time.Time `json:"money_release_date"` + Payer PayerResponse `json:"payer"` + AdditionalInfo AdditionalInfoResponse `json:"additional_info"` + Order OrderResponse `json:"order"` + TransactionDetails TransactionDetailsResponse `json:"transaction_details"` + Card CardResponse `json:"card"` + PointOfInteraction PointOfInteractionResponse `json:"point_of_interaction"` + PaymentMethod PaymentMethodResponse `json:"payment_method"` + ThreeDSInfo ThreeDSInfoResponse `json:"three_ds_info"` + FeeDetails []FeeDetailResponse `json:"fee_details"` + Taxes []TaxResponse `json:"taxes"` + Refunds []RefundResponse `json:"refunds"` } // PayerResponse represents the payer of the payment. type PayerResponse struct { - Type string `json:"type,omitempty"` - ID string `json:"id,omitempty"` - Email string `json:"email,omitempty"` - FirstName string `json:"first_name,omitempty"` - LastName string `json:"last_name,omitempty"` - EntityType string `json:"entity_type,omitempty"` + Type string `json:"type"` + ID string `json:"id"` + Email string `json:"email"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + EntityType string `json:"entity_type"` - Identification *IdentificationResponse `json:"identification,omitempty"` + Identification IdentificationResponse `json:"identification"` } // IdentificationResponse represents payer's personal identification. type IdentificationResponse struct { - Type string `json:"type,omitempty"` - Number string `json:"number,omitempty"` + Type string `json:"type"` + Number string `json:"number"` } // AdditionalInfoResponse represents additional information about a payment. type AdditionalInfoResponse struct { - IPAddress string `json:"ip_address,omitempty"` + IPAddress string `json:"ip_address"` - Payer *AdditionalInfoPayerResponse `json:"payer,omitempty"` - Shipments *ShipmentsResponse `json:"shipments,omitempty"` - Items []ItemResponse `json:"items,omitempty"` + Payer AdditionalInfoPayerResponse `json:"payer"` + Shipments ShipmentsResponse `json:"shipments"` + Items []ItemResponse `json:"items"` } // ItemResponse represents an item. type ItemResponse struct { - ID string `json:"id,omitempty"` - Title string `json:"title,omitempty"` - Description string `json:"description,omitempty"` - PictureURL string `json:"picture_url,omitempty"` - CategoryID string `json:"category_id,omitempty"` - Quantity int `json:"quantity,omitempty"` - UnitPrice float64 `json:"unit_price,omitempty"` + ID string `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + PictureURL string `json:"picture_url"` + CategoryID string `json:"category_id"` + Quantity int `json:"quantity"` + UnitPrice float64 `json:"unit_price"` } // AdditionalInfoPayerResponse represents payer's additional information. type AdditionalInfoPayerResponse struct { - FirstName string `json:"first_name,omitempty"` - LastName string `json:"last_name,omitempty"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` - RegistrationDate *time.Time `json:"registration_date,omitempty"` - Phone *PhoneResponse `json:"phone,omitempty"` - Address *AddressResponse `json:"address,omitempty"` + RegistrationDate time.Time `json:"registration_date"` + Phone PhoneResponse `json:"phone"` + Address AddressResponse `json:"address"` } // PhoneResponse represents phone information. type PhoneResponse struct { - AreaCode string `json:"area_code,omitempty"` - Number string `json:"number,omitempty"` + AreaCode string `json:"area_code"` + Number string `json:"number"` } // AddressResponse represents address information. type AddressResponse struct { - ZipCode string `json:"zip_code,omitempty"` - StreetName string `json:"street_name,omitempty"` - StreetNumber string `json:"street_number,omitempty"` + ZipCode string `json:"zip_code"` + StreetName string `json:"street_name"` + StreetNumber string `json:"street_number"` } // ShipmentsResponse represents shipment information. type ShipmentsResponse struct { - ReceiverAddress *ReceiverAddressResponse `json:"receiver_address,omitempty"` + ReceiverAddress ReceiverAddressResponse `json:"receiver_address"` } // ReceiverAddressResponse represents the receiver's address within ShipmentsResponse. type ReceiverAddressResponse struct { - StateName string `json:"state_name,omitempty"` - CityName string `json:"city_name,omitempty"` - Floor string `json:"floor,omitempty"` - Apartment string `json:"apartment,omitempty"` + StateName string `json:"state_name"` + CityName string `json:"city_name"` + Floor string `json:"floor"` + Apartment string `json:"apartment"` - Address *AddressResponse `json:"address,omitempty"` + Address AddressResponse `json:"address"` } // OrderResponse represents order information. type OrderResponse struct { - ID int `json:"id,omitempty"` - Type string `json:"type,omitempty"` + ID int `json:"id"` + Type string `json:"type"` } // TransactionDetailsResponse represents transaction details. type TransactionDetailsResponse struct { - FinancialInstitution string `json:"financial_institution,omitempty"` - ExternalResourceURL string `json:"external_resource_url,omitempty"` - PaymentMethodReferenceID string `json:"payment_method_reference_id,omitempty"` - AcquirerReference string `json:"acquirer_reference,omitempty"` - TransactionID string `json:"transaction_id,omitempty"` - NetReceivedAmount float64 `json:"net_received_amount,omitempty"` - TotalPaidAmount float64 `json:"total_paid_amount,omitempty"` - InstallmentAmount float64 `json:"installment_amount,omitempty"` - OverpaidAmount float64 `json:"overpaid_amount,omitempty"` + FinancialInstitution string `json:"financial_institution"` + ExternalResourceURL string `json:"external_resource_url"` + PaymentMethodReferenceID string `json:"payment_method_reference_id"` + AcquirerReference string `json:"acquirer_reference"` + TransactionID string `json:"transaction_id"` + NetReceivedAmount float64 `json:"net_received_amount"` + TotalPaidAmount float64 `json:"total_paid_amount"` + InstallmentAmount float64 `json:"installment_amount"` + OverpaidAmount float64 `json:"overpaid_amount"` } // CardResponse represents card information. type CardResponse struct { - ID string `json:"id,omitempty"` - LastFourDigits string `json:"last_four_digits,omitempty"` - FirstSixDigits string `json:"first_six_digits,omitempty"` - ExpirationYear int `json:"expiration_year,omitempty"` - ExpirationMonth int `json:"expiration_month,omitempty"` + ID string `json:"id"` + LastFourDigits string `json:"last_four_digits"` + FirstSixDigits string `json:"first_six_digits"` + ExpirationYear int `json:"expiration_year"` + ExpirationMonth int `json:"expiration_month"` - DateCreated *time.Time `json:"date_created,omitempty"` - DateLastUpdated *time.Time `json:"date_last_updated,omitempty"` - Cardholder *CardholderResponse `json:"cardholder,omitempty"` + DateCreated time.Time `json:"date_created"` + DateLastUpdated time.Time `json:"date_last_updated"` + Cardholder CardholderResponse `json:"cardholder"` } // CardholderResponse represents cardholder information. type CardholderResponse struct { - Name string `json:"name,omitempty"` + Name string `json:"name"` - Identification *IdentificationResponse `json:"identification,omitempty"` + Identification IdentificationResponse `json:"identification"` } // PointOfInteractionResponse represents point of interaction information. type PointOfInteractionResponse struct { - Type string `json:"type,omitempty"` - SubType string `json:"sub_type,omitempty"` - LinkedTo string `json:"linked_to,omitempty"` + Type string `json:"type"` + SubType string `json:"sub_type"` + LinkedTo string `json:"linked_to"` - ApplicationData *ApplicationDataResponse `json:"application_data,omitempty"` - TransactionData *TransactionDataResponse `json:"transaction_data,omitempty"` + ApplicationData ApplicationDataResponse `json:"application_data"` + TransactionData TransactionDataResponse `json:"transaction_data"` } // ApplicationDataResponse represents application data within PointOfInteractionResponse. type ApplicationDataResponse struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` + Name string `json:"name"` + Version string `json:"version"` } // TransactionDataResponse represents transaction data within PointOfInteractionResponse. type TransactionDataResponse struct { - QRCode string `json:"qr_code,omitempty"` - QRCodeBase64 string `json:"qr_code_base64,omitempty"` - TransactionID string `json:"transaction_id,omitempty"` - TicketURL string `json:"ticket_url,omitempty"` - SubscriptionID string `json:"subscription_id,omitempty"` - BillingDate string `json:"billing_date,omitempty"` - BankTransferID int64 `json:"bank_transfer_id,omitempty"` - FinancialInstitution int64 `json:"financial_institution,omitempty"` - FirstTimeUse bool `json:"first_time_use,omitempty"` - - BankInfo *BankInfoResponse `json:"bank_info,omitempty"` - SubscriptionSequence *SubscriptionSequenceResponse `json:"subscription_sequence,omitempty"` - InvoicePeriod *InvoicePeriodResponse `json:"invoice_period,omitempty"` - PaymentReference *PaymentReferenceResponse `json:"payment_reference,omitempty"` + QRCode string `json:"qr_code"` + QRCodeBase64 string `json:"qr_code_base64"` + TransactionID string `json:"transaction_id"` + TicketURL string `json:"ticket_url"` + SubscriptionID string `json:"subscription_id"` + BillingDate string `json:"billing_date"` + BankTransferID int64 `json:"bank_transfer_id"` + FinancialInstitution int64 `json:"financial_institution"` + FirstTimeUse bool `json:"first_time_use"` + + BankInfo BankInfoResponse `json:"bank_info"` + SubscriptionSequence SubscriptionSequenceResponse `json:"subscription_sequence"` + InvoicePeriod InvoicePeriodResponse `json:"invoice_period"` + PaymentReference PaymentReferenceResponse `json:"payment_reference"` } // BankInfoResponse represents bank information. type BankInfoResponse struct { - IsSameBankAccountOwner string `json:"is_same_bank_account_owner,omitempty"` + IsSameBankAccountOwner string `json:"is_same_bank_account_owner"` - Payer *BankInfoPayerResponse `json:"payer,omitempty"` - Collector *BankInfoCollectorResponse `json:"collector,omitempty"` + Payer BankInfoPayerResponse `json:"payer"` + Collector BankInfoCollectorResponse `json:"collector"` } // SubscriptionSequenceResponse represents subscription sequence. type SubscriptionSequenceResponse struct { - Number int64 `json:"number,omitempty"` - Total int64 `json:"total,omitempty"` + Number int64 `json:"number"` + Total int64 `json:"total"` } // InvoicePeriodResponse represents invoice period. type InvoicePeriodResponse struct { - Type string `json:"type,omitempty"` - Period int64 `json:"period,omitempty"` + Type string `json:"type"` + Period int64 `json:"period"` } // PaymentReferenceResponse represents payment reference. type PaymentReferenceResponse struct { - ID string `json:"id,omitempty"` + ID string `json:"id"` } // BankInfoPayerResponse represents payer information within BankInfoResponse. type BankInfoPayerResponse struct { - Email string `json:"email,omitempty"` - LongName string `json:"long_name,omitempty"` - AccountID int64 `json:"account_id,omitempty"` + Email string `json:"email"` + LongName string `json:"long_name"` + AccountID int64 `json:"account_id"` } // BankInfoCollectorResponse represents collector information within BankInfoResponse. type BankInfoCollectorResponse struct { - LongName string `json:"long_name,omitempty"` - AccountID int64 `json:"account_id,omitempty"` + LongName string `json:"long_name"` + AccountID int64 `json:"account_id"` } // PaymentMethodResponse represents payment method information. type PaymentMethodResponse struct { - ID string `json:"id,omitempty"` - Type string `json:"type,omitempty"` - IssuerID string `json:"issuer_id,omitempty"` + ID string `json:"id"` + Type string `json:"type"` + IssuerID string `json:"issuer_id"` - Data *DataResponse `json:"data,omitempty"` + Data DataResponse `json:"data"` } // DataResponse represents data within PaymentMethodResponse. type DataResponse struct { - Rules *RulesResponse `json:"rules,omitempty"` + Rules RulesResponse `json:"rules"` } // RulesResponse represents payment rules. type RulesResponse struct { - Fine *FeeResponse `json:"fine,omitempty"` - Interest *FeeResponse `json:"interest,omitempty"` - Discounts []DiscountResponse `json:"discounts,omitempty"` + Fine FeeResponse `json:"fine"` + Interest FeeResponse `json:"interest"` + Discounts []DiscountResponse `json:"discounts"` } // DiscountResponse represents payment discount information. type DiscountResponse struct { - Type string `json:"type,omitempty"` - Value float64 `json:"value,omitempty"` + Type string `json:"type"` + Value float64 `json:"value"` - LimitDate *time.Time `json:"limit_date,omitempty"` + LimitDate time.Time `json:"limit_date"` } // FeeResponse represents payment fee information. type FeeResponse struct { - Type string `json:"type,omitempty"` - Value float64 `json:"value,omitempty"` + Type string `json:"type"` + Value float64 `json:"value"` } // ThreeDSInfoResponse represents 3DS (Three-Domain Secure) information. type ThreeDSInfoResponse struct { - ExternalResourceURL string `json:"external_resource_url,omitempty"` - Creq string `json:"creq,omitempty"` + ExternalResourceURL string `json:"external_resource_url"` + Creq string `json:"creq"` } // FeeDetailResponse represents payment fee detail information. type FeeDetailResponse struct { - Type string `json:"type,omitempty"` - FeePayer string `json:"fee_payer,omitempty"` - Amount float64 `json:"amount,omitempty"` + Type string `json:"type"` + FeePayer string `json:"fee_payer"` + Amount float64 `json:"amount"` } // TaxResponse represents tax information. type TaxResponse struct { - Type string `json:"type,omitempty"` - Value float64 `json:"value,omitempty"` + Type string `json:"type"` + Value float64 `json:"value"` } // RefundResponse represents refund information. type RefundResponse struct { - Status string `json:"status,omitempty"` - RefundMode string `json:"refund_mode,omitempty"` - Reason string `json:"reason,omitempty"` - UniqueSequenceNumber string `json:"unique_sequence_number,omitempty"` - ID int64 `json:"id,omitempty"` - PaymentID int64 `json:"payment_id,omitempty"` - Amount float64 `json:"amount,omitempty"` - AdjustmentAmount float64 `json:"adjustment_amount,omitempty"` + Status string `json:"status"` + RefundMode string `json:"refund_mode"` + Reason string `json:"reason"` + UniqueSequenceNumber string `json:"unique_sequence_number"` + ID int64 `json:"id"` + PaymentID int64 `json:"payment_id"` + Amount float64 `json:"amount"` + AdjustmentAmount float64 `json:"adjustment_amount"` - DateCreated *time.Time `json:"date_created,omitempty"` - Source *SourceResponse `json:"source,omitempty"` + DateCreated time.Time `json:"date_created"` + Source SourceResponse `json:"source"` } // SourceResponse represents source information. type SourceResponse struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` + ID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` } diff --git a/resources/mocks/payment/search_response.json b/resources/mocks/payment/search_response.json index 5b9f31fd..6f8d8ef2 100644 --- a/resources/mocks/payment/search_response.json +++ b/resources/mocks/payment/search_response.json @@ -6,12 +6,12 @@ }, "results": [ { - "id": 123, + "id": 57592046572, "status": "approved", "status_detail": "accredited" }, { - "id": 456, + "id": 57592038796, "status": "pending", "status_detail": "pending_waiting_transfer" } From 35c9f050cd66e8cfa4c4b47465fd7a01150bd0f3 Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Wed, 7 Feb 2024 15:01:43 -0300 Subject: [PATCH 23/25] merge with develop and adjust test --- pkg/payment/payment_test.go | 13 ++++++++----- pkg/paymentmethod/client_test.go | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg/payment/payment_test.go b/pkg/payment/payment_test.go index 77b8751b..4022660c 100644 --- a/pkg/payment/payment_test.go +++ b/pkg/payment/payment_test.go @@ -223,7 +223,7 @@ func TestSearch(t *testing.T) { ctx: context.Background(), }, want: nil, - wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + wantErr: "invalid character 'i' looking for beginning of value", }, { name: "should_return_formatted_response", @@ -242,6 +242,9 @@ func TestSearch(t *testing.T) { }, args: args{ ctx: context.Background(), + dto: SearchRequest{ + Limit: "30", + }, }, want: &SearchResponse{ Paging: PagingResponse{ @@ -348,7 +351,7 @@ func TestGet(t *testing.T) { ctx: context.Background(), }, want: nil, - wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + wantErr: "invalid character 'i' looking for beginning of value", }, { name: "should_return_formatted_response", @@ -459,7 +462,7 @@ func TestCancel(t *testing.T) { ctx: context.Background(), }, want: nil, - wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + wantErr: "invalid character 'i' looking for beginning of value", }, { name: "should_return_formatted_response", @@ -570,7 +573,7 @@ func TestCapture(t *testing.T) { ctx: context.Background(), }, want: nil, - wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + wantErr: "invalid character 'i' looking for beginning of value", }, { name: "should_return_formatted_response", @@ -682,7 +685,7 @@ func TestCaptureAmount(t *testing.T) { ctx: context.Background(), }, want: nil, - wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + wantErr: "invalid character 'i' looking for beginning of value", }, { name: "should_return_formatted_response", diff --git a/pkg/paymentmethod/client_test.go b/pkg/paymentmethod/client_test.go index cd11e2eb..359f2a21 100644 --- a/pkg/paymentmethod/client_test.go +++ b/pkg/paymentmethod/client_test.go @@ -80,7 +80,7 @@ func TestList(t *testing.T) { ctx: context.Background(), }, want: nil, - wantErr: "error unmarshaling response: invalid character 'i' looking for beginning of value", + wantErr: "invalid character 'i' looking for beginning of value", }, { name: "should_return_formatted_response", @@ -129,7 +129,7 @@ func TestList(t *testing.T) { if err != nil { gotErr = err.Error() } - + if gotErr != tt.wantErr { t.Errorf("client.List() error = %v, wantErr %v", err, tt.wantErr) } From 37b775bbe54d710a871e2a681a061b5745e7663a Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Wed, 7 Feb 2024 15:18:03 -0300 Subject: [PATCH 24/25] add lint suggestion --- test/integration/payment/payment_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/payment/payment_test.go b/test/integration/payment/payment_test.go index d984bc78..43f4c30b 100644 --- a/test/integration/payment/payment_test.go +++ b/test/integration/payment/payment_test.go @@ -32,7 +32,7 @@ func TestPayment(t *testing.T) { if result == nil { t.Error("result can't be nil") } - if result.ID == 0 { + if result != nil && result.ID == 0 { t.Error("id can't be nil") } if err != nil { @@ -89,7 +89,7 @@ func TestPayment(t *testing.T) { if result == nil { t.Error("result can't be nil") } - if result.ID == 0 { + if result != nil && result.ID == 0 { t.Error("id can't be nil") } if err != nil { @@ -124,7 +124,7 @@ func TestPayment(t *testing.T) { if result == nil { t.Error("result can't be nil") } - if result.ID == 0 { + if result != nil && result.ID == 0 { t.Error("id can't be nil") } if err != nil { From d4f617870f84dca373435fd828017437c75d175e Mon Sep 17 00:00:00 2001 From: edmarSoaress Date: Wed, 7 Feb 2024 15:24:45 -0300 Subject: [PATCH 25/25] add lint suggestion --- test/integration/payment/payment_test.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/integration/payment/payment_test.go b/test/integration/payment/payment_test.go index 43f4c30b..1921eaff 100644 --- a/test/integration/payment/payment_test.go +++ b/test/integration/payment/payment_test.go @@ -31,8 +31,9 @@ func TestPayment(t *testing.T) { result, err := client.Create(context.Background(), dto) if result == nil { t.Error("result can't be nil") + return } - if result != nil && result.ID == 0 { + if result.ID == 0 { t.Error("id can't be nil") } if err != nil { @@ -80,6 +81,7 @@ func TestPayment(t *testing.T) { result, err := client.Create(context.Background(), dto) if result == nil { t.Error("result can't be nil") + return } if err != nil { t.Errorf(err.Error()) @@ -88,8 +90,9 @@ func TestPayment(t *testing.T) { result, err = client.Get(context.Background(), result.ID) if result == nil { t.Error("result can't be nil") + return } - if result != nil && result.ID == 0 { + if result.ID == 0 { t.Error("id can't be nil") } if err != nil { @@ -115,6 +118,7 @@ func TestPayment(t *testing.T) { result, err := client.Create(context.Background(), dto) if result == nil { t.Error("result can't be nil") + return } if err != nil { t.Errorf(err.Error()) @@ -123,8 +127,9 @@ func TestPayment(t *testing.T) { result, err = client.Cancel(context.Background(), result.ID) if result == nil { t.Error("result can't be nil") + return } - if result != nil && result.ID == 0 { + if result.ID == 0 { t.Error("id can't be nil") } if err != nil { @@ -157,6 +162,7 @@ func TestPayment(t *testing.T) { result, err := client.Create(context.Background(), dto) if result == nil { t.Error("result can't be nil") + return } if err != nil { t.Errorf(err.Error())