From 137dc32f3dc11c0c4b9e2e9769ca8b5f29c818c5 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:31:51 +0100 Subject: [PATCH 01/23] check payments resources against api reference. (#326) --- docs/README.md | 423 ++++++++++++++++++++++++++++++--------- docs/v4-upgrade.md | 21 ++ mollie/captures.go | 9 + mollie/common_types.go | 10 + mollie/customers.go | 2 +- mollie/customers_test.go | 26 ++- mollie/payments.go | 262 ++++++++++++++++++------ mollie/payments_test.go | 35 ++-- 8 files changed, 609 insertions(+), 179 deletions(-) create mode 100644 docs/v4-upgrade.md diff --git a/docs/README.md b/docs/README.md index 6ae5cf9b..748164cc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,6 +20,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [Constants](<#constants>) - [func CheckResponse\(r \*Response\) error](<#CheckResponse>) +- [type AccessTokenPaymentFields](<#AccessTokenPaymentFields>) - [type Address](<#Address>) - [type Amount](<#Amount>) - [type ApplePaymentSession](<#ApplePaymentSession>) @@ -54,6 +55,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type BusinessCategory](<#BusinessCategory>) - [type Capture](<#Capture>) - [type CaptureLinks](<#CaptureLinks>) +- [type CaptureMode](<#CaptureMode>) - [type CapturesList](<#CapturesList>) - [type CapturesService](<#CapturesService>) - [func \(cs \*CapturesService\) Get\(ctx context.Context, payment, capture string\) \(res \*Response, c \*Capture, err error\)](<#CapturesService.Get>) @@ -96,6 +98,11 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(c \*Config\) ToggleTesting\(\) bool](<#Config.ToggleTesting>) - [type ContextValue](<#ContextValue>) - [type ContextValues](<#ContextValues>) +- [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) +- [type CreatePayment](<#CreatePayment>) +- [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) +- [type CreatePreAuthorizedPaymentFields](<#CreatePreAuthorizedPaymentFields>) +- [type CreateRecurrentPaymentFields](<#CreateRecurrentPaymentFields>) - [type CreateShipmentRequest](<#CreateShipmentRequest>) - [type Customer](<#Customer>) - [type CustomerLinks](<#CustomerLinks>) @@ -103,7 +110,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CustomersListOptions](<#CustomersListOptions>) - [type CustomersService](<#CustomersService>) - [func \(cs \*CustomersService\) Create\(ctx context.Context, c Customer\) \(res \*Response, cc \*Customer, err error\)](<#CustomersService.Create>) - - [func \(cs \*CustomersService\) CreatePayment\(ctx context.Context, id string, p Payment\) \(res \*Response, pp \*Payment, err error\)](<#CustomersService.CreatePayment>) + - [func \(cs \*CustomersService\) CreatePayment\(ctx context.Context, id string, p CreatePayment\) \(res \*Response, pp \*Payment, err error\)](<#CustomersService.CreatePayment>) - [func \(cs \*CustomersService\) Delete\(ctx context.Context, id string\) \(res \*Response, err error\)](<#CustomersService.Delete>) - [func \(cs \*CustomersService\) Get\(ctx context.Context, id string\) \(res \*Response, c \*Customer, err error\)](<#CustomersService.Get>) - [func \(cs \*CustomersService\) GetPayments\(ctx context.Context, id string, options \*CustomersListOptions\) \(res \*Response, pl \*PaymentList, err error\)](<#CustomersService.GetPayments>) @@ -121,6 +128,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type GiftCardIssuerStatus](<#GiftCardIssuerStatus>) - [type GiftCardLinks](<#GiftCardLinks>) - [type Image](<#Image>) +- [type IncludeValue](<#IncludeValue>) - [type Invoice](<#Invoice>) - [type InvoiceLinks](<#InvoiceLinks>) - [type InvoiceStatus](<#InvoiceStatus>) @@ -149,6 +157,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type MiscellaneousService](<#MiscellaneousService>) - [func \(ms \*MiscellaneousService\) ApplePaymentSession\(ctx context.Context, asr \*ApplePaymentSessionRequest\) \(res \*Response, aps \*ApplePaymentSession, err error\)](<#MiscellaneousService.ApplePaymentSession>) - [type Mode](<#Mode>) +- [type MollieConnectPaymentFields](<#MollieConnectPaymentFields>) - [type Onboarding](<#Onboarding>) - [type OnboardingData](<#OnboardingData>) - [type OnboardingDataOrganization](<#OnboardingDataOrganization>) @@ -206,6 +215,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ps \*PartnerService\) List\(ctx context.Context, opts \*ListPartnerClientsOptions\) \(res \*Response, pc \*PartnerClientList, err error\)](<#PartnerService.List>) - [type PartnerType](<#PartnerType>) - [type Payment](<#Payment>) +- [type PaymentDestination](<#PaymentDestination>) - [type PaymentDetails](<#PaymentDetails>) - [type PaymentDetailsAddress](<#PaymentDetailsAddress>) - [type PaymentLink](<#PaymentLink>) @@ -231,12 +241,13 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ms \*PaymentMethodsService\) Get\(ctx context.Context, id PaymentMethod, options \*PaymentMethodOptions\) \(res \*Response, pmd \*PaymentMethodDetails, err error\)](<#PaymentMethodsService.Get>) - [func \(ms \*PaymentMethodsService\) List\(ctx context.Context, options \*PaymentMethodsListOptions\) \(res \*Response, pm \*PaymentMethodsList, err error\)](<#PaymentMethodsService.List>) - [type PaymentOptions](<#PaymentOptions>) +- [type PaymentRouting](<#PaymentRouting>) - [type PaymentsService](<#PaymentsService>) - [func \(ps \*PaymentsService\) Cancel\(ctx context.Context, id string\) \(res \*Response, p \*Payment, err error\)](<#PaymentsService.Cancel>) - - [func \(ps \*PaymentsService\) Create\(ctx context.Context, p Payment, opts \*PaymentOptions\) \(res \*Response, np \*Payment, err error\)](<#PaymentsService.Create>) + - [func \(ps \*PaymentsService\) Create\(ctx context.Context, p CreatePayment, opts \*PaymentOptions\) \(res \*Response, np \*Payment, err error\)](<#PaymentsService.Create>) - [func \(ps \*PaymentsService\) Get\(ctx context.Context, id string, opts \*PaymentOptions\) \(res \*Response, p \*Payment, err error\)](<#PaymentsService.Get>) - [func \(ps \*PaymentsService\) List\(ctx context.Context, opts \*ListPaymentOptions\) \(res \*Response, pl \*PaymentList, err error\)](<#PaymentsService.List>) - - [func \(ps \*PaymentsService\) Update\(ctx context.Context, id string, up Payment\) \(res \*Response, p \*Payment, err error\)](<#PaymentsService.Update>) + - [func \(ps \*PaymentsService\) Update\(ctx context.Context, id string, up UpdatePayment\) \(res \*Response, p \*Payment, err error\)](<#PaymentsService.Update>) - [type Permission](<#Permission>) - [type PermissionGrant](<#PermissionGrant>) - [type PermissionLinks](<#PermissionLinks>) @@ -245,6 +256,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ps \*PermissionsService\) Get\(ctx context.Context, id PermissionGrant\) \(res \*Response, p \*Permission, err error\)](<#PermissionsService.Get>) - [func \(ps \*PermissionsService\) List\(ctx context.Context\) \(res \*Response, pl \*PermissionsList, err error\)](<#PermissionsService.List>) - [type PhoneNumber](<#PhoneNumber>) +- [type PreAuthorizedPaymentFields](<#PreAuthorizedPaymentFields>) - [type ProductType](<#ProductType>) - [type Profile](<#Profile>) - [type ProfileLinks](<#ProfileLinks>) @@ -266,6 +278,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ps \*ProfilesService\) Update\(ctx context.Context, id string, up \*Profile\) \(res \*Response, p \*Profile, err error\)](<#ProfilesService.Update>) - [type QRCode](<#QRCode>) - [type Rate](<#Rate>) +- [type RecurrentPaymentFields](<#RecurrentPaymentFields>) - [type Refund](<#Refund>) - [type RefundLinks](<#RefundLinks>) - [type RefundList](<#RefundList>) @@ -334,6 +347,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type TransferDestination](<#TransferDestination>) - [type TransferFrequency](<#TransferFrequency>) - [type URL](<#URL>) +- [type UpdatePayment](<#UpdatePayment>) - [type UsedGiftCard](<#UsedGiftCard>) - [type UserAgentToken](<#UserAgentToken>) @@ -365,6 +379,17 @@ func CheckResponse(r *Response) error CheckResponse checks the API response for errors, and returns them if present. A response is considered an error if it has a status code outside the 200 range. API error responses are expected to have either no response body, or a JSON response body. + +## type [AccessTokenPaymentFields]() + +AccessTokenPaymentFields describes the fields specific to payments created using an access token. + +```go +type AccessTokenPaymentFields struct { + Testmode bool `json:"testmode,omitempty"` +} +``` + ## type [Address]() @@ -961,7 +986,7 @@ const ( ``` -## type [Capture]() +## type [Capture]() Capture describes a single capture. Captures are used for payments that have the authorize\-then\-capture flow. @@ -981,7 +1006,7 @@ type Capture struct { ``` -## type [CaptureLinks]() +## type [CaptureLinks]() CaptureLinks contains relevant links for a capture object. @@ -995,8 +1020,26 @@ type CaptureLinks struct { } ``` + +## type [CaptureMode]() + +CaptureMode describes the mode of a capture. + +```go +type CaptureMode string +``` + +CaptureMode possible values. + +```go +const ( + AutomaticCapture CaptureMode = "automatic" + ManualCapture CaptureMode = "manual" +) +``` + -## type [CapturesList]() +## type [CapturesList]() CapturesList describes a list of captures. @@ -1011,7 +1054,7 @@ type CapturesList struct { ``` -## type [CapturesService]() +## type [CapturesService]() CapturesService operates over captures resource. @@ -1020,7 +1063,7 @@ type CapturesService service ``` -### func \(\*CapturesService\) [Get]() +### func \(\*CapturesService\) [Get]() ```go func (cs *CapturesService) Get(ctx context.Context, payment, capture string) (res *Response, c *Capture, err error) @@ -1031,7 +1074,7 @@ Get retrieves a single capture by its ID. Note the original payment’s ID is ne See: https://docs.mollie.com/reference/v2/captures-api/get-capture -### func \(\*CapturesService\) [List]() +### func \(\*CapturesService\) [List]() ```go func (cs *CapturesService) List(ctx context.Context, payment string) (res *Response, cl *CapturesList, err error) @@ -1667,6 +1710,111 @@ ContextValues is a map of TransactionType to ContextValue. type ContextValues map[TransactionType]ContextValue ``` + +## type [CreateMollieConnectPaymentFields]() + +CreateMollieConnectPaymentFields describes the fields to be sent to the Mollie API when creating a new payment using Mollie Connect. + +See: https://docs.mollie.com/reference/v2/payments-api/create-payment#mollie-connect-parameters + +```go +type CreateMollieConnectPaymentFields struct { + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` + Routing []*PaymentRouting `json:"routing,omitempty"` +} +``` + + +## type [CreatePayment]() + +CreatePayment describes the payload to be sent to the Mollie API when creating or updating a new payment. + +Some fields are only valid for specific payment methods, and are documented in the Mollie API reference. + +See: https://docs.mollie.com/reference/v2/payments-api/create-payment#payment-method-specific-parameters + +```go +type CreatePayment struct { + Description string `json:"description,omitempty"` + RedirectURL string `json:"redirectUrl,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + RestrictPaymentMethodsToCountry string `json:"restrictPaymentMethodsToCountry,omitempty"` + Amount *Amount `json:"amount,omitempty"` + Locale Locale `json:"locale,omitempty"` + Method []PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` + + // PaymentMethods specific fields + DigitalGoods bool `json:"digitalGoods,omitempty"` + ApplePayPaymentToken string `json:"applePayPaymentToken,omitempty"` + BillingEmail string `json:"billingEmail,omitempty"` + CardToken string `json:"cardToken,omitempty"` + VoucherNumber string `json:"voucherNumber,omitempty"` + VoucherPin string `json:"voucherPin,omitempty"` + Issuer string `json:"issuer,omitempty"` + ExtraMerchantData string `json:"extraMerchantData,omitempty"` + SessionID string `json:"sessionId,omitempty"` + CustomerReference string `json:"customerReference,omitempty"` + TerminalID string `json:"terminalId,omitempty"` + ConsumerName string `json:"consumerName,omitempty"` + ConsumerAccount string `json:"consumerAccount,omitempty"` + DueDate *ShortDate `json:"dueDate,omitempty"` + ShippingAddress *Address `json:"shippingAddress,omitempty"` + BillingAddress *Address `json:"billingAddress,omitempty"` + Company *Company `json:"company,omitempty"` + + // Other case specific fields + CreateRecurrentPaymentFields + CreatePreAuthorizedPaymentFields + CreatePaymentAccessTokenFields + CreateMollieConnectPaymentFields +} +``` + + +## type [CreatePaymentAccessTokenFields]() + +CreatePaymentAccessTokenFields describes the fields to be sent to the Mollie API when creating a new payment using an access token. + +See: https://docs.mollie.com/reference/v2/payments-api/create-payment#access-token-parameters + +```go +type CreatePaymentAccessTokenFields struct { + ProfileID string `json:"profileId,omitempty"` + Testmode bool `json:"testmode,omitempty"` +} +``` + + +## type [CreatePreAuthorizedPaymentFields]() + +CreatePreAuthorizedPaymentFields describes the fields to be sent to the Mollie API when creating a new pre\-authorized payment. + +See: https://docs.mollie.com/reference/v2/payments-api/create-payment#parameters-for-pre-authorized-payments + +```go +type CreatePreAuthorizedPaymentFields struct { + CaptureDelay string `json:"captureDelay,omitempty"` + CaptureMode CaptureMode `json:"captureMode,omitempty"` +} +``` + + +## type [CreateRecurrentPaymentFields]() + +CreateRecurrentPaymentFields describes the fields to be sent to the Mollie API when creating a new recurrent payment. + +See: https://docs.mollie.com/reference/v2/payments-api/create-payment#parameters-for-recurring-payments + +```go +type CreateRecurrentPaymentFields struct { + CustomerID string `json:"customerId,omitempty"` + MandateID string `json:"mandateId,omitempty"` + SequenceType SequenceType `json:"sequenceType,omitempty"` +} +``` + ## type [CreateShipmentRequest]() @@ -1769,7 +1917,7 @@ See: https://docs.mollie.com/reference/v2/customers-api/create-customer ### func \(\*CustomersService\) [CreatePayment]() ```go -func (cs *CustomersService) CreatePayment(ctx context.Context, id string, p Payment) (res *Response, pp *Payment, err error) +func (cs *CustomersService) CreatePayment(ctx context.Context, id string, p CreatePayment) (res *Response, pp *Payment, err error) ``` CreatePayment creates a payment for the customer. @@ -1857,7 +2005,7 @@ const ( ``` -## type [EmbedValue]() +## type [EmbedValue]() EmbedValue describes the valid value of embed query string. @@ -1873,6 +2021,7 @@ const ( EmbedRefund EmbedValue = "refunds" EmbedShipments EmbedValue = "shipments" EmbedChargebacks EmbedValue = "chargebacks" + EmbedCaptures EmbedValue = "captures" ) ``` @@ -2069,7 +2218,7 @@ type GiftCardLinks struct { ``` -## type [Image]() +## type [Image]() Image describes a generic image resource retrieved by Mollie. @@ -2081,6 +2230,24 @@ type Image struct { } ``` + +## type [IncludeValue]() + +IncludeValue is a valid value for the Include query string parameter. + +```go +type IncludeValue string +``` + +Supported Include values. + +```go +const ( + IncludeQrCode IncludeValue = "details.qrCode" + IncludeRemainderDetails IncludeValue = "details.remainderDetails" +) +``` + ## type [Invoice]() @@ -2222,17 +2389,17 @@ type ListPartnerClientsOptions struct { ``` -## type [ListPaymentOptions]() +## type [ListPaymentOptions]() ListPaymentOptions describes list payments endpoint valid query string parameters. ```go type ListPaymentOptions struct { - Limit int `url:"limit,omitempty"` - Include string `url:"include,omitempty"` - Embed string `url:"embed,omitempty"` - ProfileID string `url:"profileId,omitempty"` - From string `url:"from,omitempty"` + Limit int `url:"limit,omitempty"` + Include []IncludeValue `url:"include,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` + ProfileID string `url:"profileId,omitempty"` + From string `url:"from,omitempty"` } ``` @@ -2499,6 +2666,17 @@ const ( ) ``` + +## type [MollieConnectPaymentFields]() + +MollieConnectPaymentFields describes the fields specific to Mollie Connect payments. + +```go +type MollieConnectPaymentFields struct { + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` +} +``` + ## type [Onboarding]() @@ -3218,7 +3396,7 @@ GetPartnerStatus retrieves details about the partner status of the currently aut See: https://docs.mollie.com/reference/v2/organizations-api/get-partner -## type [Owner]() +## type [Owner]() Personal data of your customer. @@ -3340,66 +3518,63 @@ const ( ``` -## type [Payment]() +## type [Payment]() Payment describes a transaction between a customer and a merchant. ```go type Payment struct { - IsCancellable bool `json:"isCancellable,omitempty"` - TestMode bool `json:"testmode,omitempty"` - DigitalGoods bool `json:"digitalGoods,omitempty"` - ApplePayPaymentToken string `json:"applePayPaymentToken,omitempty"` - BillingEmail string `json:"billingEmail,omitempty"` - CardToken string `json:"cardToken,omitempty"` - Issuer string `json:"issuer,omitempty"` - VoucherNumber string `json:"voucherNumber,omitempty"` - VoucherPin string `json:"voucherPin,omitempty"` - ExtraMerchantData string `json:"extraMerchantData,omitempty"` - SessionID string `json:"sessionId,omitempty"` - CustomerReference string `json:"customerReference,omitempty"` - ConsumerName string `json:"consumerName,omitempty"` - ConsumerAccount string `json:"consumerAccount,omitempty"` - WebhookURL string `json:"webhookUrl,omitempty"` - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - MandateID string `json:"mandateId,omitempty"` - OrderID string `json:"orderId,omitempty"` - ProfileID string `json:"profileId,omitempty"` - SettlementID string `json:"settlementId,omitempty"` - CustomerID string `json:"customerId,omitempty"` - Status string `json:"status,omitempty"` - Description string `json:"description,omitempty"` - RedirectURL string `json:"redirectUrl,omitempty"` - CountryCode string `json:"countryCode,omitempty"` - SubscriptionID string `json:"subscriptionId,omitempty"` - CancelURL string `json:"cancelUrl,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - Amount *Amount `json:"amount,omitempty"` - AmountRefunded *Amount `json:"amountRefunded,omitempty"` - AmountRemaining *Amount `json:"amountRemaining,omitempty"` - AmountCaptured *Amount `json:"amountCaptured,omitempty"` - AmountChargedBack *Amount `json:"amountChargedBack,omitempty"` - SettlementAmount *Amount `json:"settlementAmount,omitempty"` - ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` - Details *PaymentDetails `json:"details,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - AuthorizedAt *time.Time `json:"authorizedAt,omitempty"` - PaidAt *time.Time `json:"paidAt,omitempty"` - CanceledAt *time.Time `json:"canceledAt,omitempty"` - ExpiresAt *time.Time `json:"expiresAt,omitempty"` - ExpiredAt *time.Time `json:"expiredAt,omitempty"` - FailedAt *time.Time `json:"failedAt,omitempty"` - DueDate *ShortDate `json:"dueDate,omitempty"` - BillingAddress *Address `json:"billingAddress,omitempty"` - ShippingAddress *PaymentDetailsAddress `json:"shippingAddress,omitempty"` - Mode Mode `json:"mode,omitempty"` - Locale Locale `json:"locale,omitempty"` - RestrictPaymentMethodsToCountry Locale `json:"restrictPaymentMethodsToCountry,omitempty"` - Method PaymentMethod `json:"method,omitempty"` - Links PaymentLinks `json:"_links,omitempty"` - SequenceType SequenceType `json:"sequenceType,omitempty"` - Company Company `json:"company,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` + Description string `json:"description,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + CountryCode string `json:"countryCode,omitempty"` + RestrictPaymentMethodsToCountry string `json:"restrictPaymentMethodsToCountry,omitempty"` + ProfileID string `json:"profileId,omitempty"` + SettlementID string `json:"settlementId,omitempty"` + OrderID string `json:"orderId,omitempty"` + IsCancelable bool `json:"isCancelable,omitempty"` + Mode Mode `json:"mode,omitempty"` + Locale Locale `json:"locale,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` + Links PaymentLinks `json:"_links,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + AuthorizedAt *time.Time `json:"authorizedAt,omitempty"` + PaidAt *time.Time `json:"paidAt,omitempty"` + CanceledAt *time.Time `json:"canceledAt,omitempty"` + ExpiresAt *time.Time `json:"expiresAt,omitempty"` + ExpiredAt *time.Time `json:"expiredAt,omitempty"` + FailedAt *time.Time `json:"failedAt,omitempty"` + Amount *Amount `json:"amount,omitempty"` + AmountRefunded *Amount `json:"amountRefunded,omitempty"` + AmountRemaining *Amount `json:"amountRemaining,omitempty"` + AmountCaptured *Amount `json:"amountCaptured,omitempty"` + AmountChargedBack *Amount `json:"amountChargeback,omitempty"` + SettlementAmount *Amount `json:"settlementAmount,omitempty"` + + // PaymentMethods specific fields + Details PaymentDetails `json:"details,omitempty"` + + // Other case specific fields + RecurrentPaymentFields + PreAuthorizedPaymentFields + MollieConnectPaymentFields + AccessTokenPaymentFields +} +``` + + +## type [PaymentDestination]() + +PaymentDestination describes the destination of a payment. + +```go +type PaymentDestination struct { + Kind string `json:"type,omitempty"` + OrganizationID string `json:"organizationId,omitempty"` } ``` @@ -3533,7 +3708,7 @@ type PaymentLinkOptions struct { ``` -## type [PaymentLinks]() +## type [PaymentLinks]() PaymentLinks describes all the possible links to be returned with a payment object. @@ -3552,6 +3727,8 @@ type PaymentLinks struct { Customer *URL `json:"customer,omitempty"` Order *URL `json:"order,omitempty"` Dashboard *URL `json:"dashboard,omitempty"` + MobileAppCheckout *URL `json:"mobileAppCheckout,omitempty"` + Terminal *URL `json:"terminal,omitempty"` } ``` @@ -3613,7 +3790,7 @@ List retrieves all payments links created with the current website profile, orde See: https://docs.mollie.com/reference/v2/payment-links-api/list-payment-links -## type [PaymentList]() +## type [PaymentList]() PaymentList describes how a list of payments will be retrieved by Mollie. @@ -3643,6 +3820,7 @@ const ( Bancontact PaymentMethod = "bancontact" BankTransfer PaymentMethod = "banktransfer" Belfius PaymentMethod = "belfius" + CBC PaymentMethod = "cbc" CreditCard PaymentMethod = "creditcard" DirectDebit PaymentMethod = "directdebit" EPS PaymentMethod = "eps" @@ -3822,7 +4000,7 @@ The results are not paginated. See: https://docs.mollie.com/reference/v2/methods-api/list-methods -## type [PaymentOptions]() +## type [PaymentOptions]() PaymentOptions describes payments endpoint valid query string parameters. @@ -3830,13 +4008,26 @@ See: https://docs.mollie.com/reference/v2/payments-api/get-payment ```go type PaymentOptions struct { - Include string `url:"include,omitempty"` - Embed string `url:"embed,omitempty"` + Include []IncludeValue `url:"include,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` +} +``` + + +## type [PaymentRouting]() + +PaymentRouting describes the routing of a payment. + +```go +type PaymentRouting struct { + Destination PaymentDestination `json:"destination,omitempty"` + Amount *Amount `json:"amount,omitempty"` + ReleaseDate *ShortDate `json:"releaseDate,omitempty"` } ``` -## type [PaymentsService]() +## type [PaymentsService]() PaymentsService instance operates over payment resources. @@ -3845,7 +4036,7 @@ type PaymentsService service ``` -### func \(\*PaymentsService\) [Cancel]() +### func \(\*PaymentsService\) [Cancel]() ```go func (ps *PaymentsService) Cancel(ctx context.Context, id string) (res *Response, p *Payment, err error) @@ -3856,10 +4047,10 @@ Cancel removes a payment \(if possible\) from your Mollie account. See: https://docs.mollie.com/reference/v2/payments-api/cancel-payment -### func \(\*PaymentsService\) [Create]() +### func \(\*PaymentsService\) [Create]() ```go -func (ps *PaymentsService) Create(ctx context.Context, p Payment, opts *PaymentOptions) (res *Response, np *Payment, err error) +func (ps *PaymentsService) Create(ctx context.Context, p CreatePayment, opts *PaymentOptions) (res *Response, np *Payment, err error) ``` Create stores a new payment object attached to your Mollie account. @@ -3867,7 +4058,7 @@ Create stores a new payment object attached to your Mollie account. See: https://docs.mollie.com/reference/v2/payments-api/create-payment# -### func \(\*PaymentsService\) [Get]() +### func \(\*PaymentsService\) [Get]() ```go func (ps *PaymentsService) Get(ctx context.Context, id string, opts *PaymentOptions) (res *Response, p *Payment, err error) @@ -3876,7 +4067,7 @@ func (ps *PaymentsService) Get(ctx context.Context, id string, opts *PaymentOpti Get retrieves a single payment object by its payment token. -### func \(\*PaymentsService\) [List]() +### func \(\*PaymentsService\) [List]() ```go func (ps *PaymentsService) List(ctx context.Context, opts *ListPaymentOptions) (res *Response, pl *PaymentList, err error) @@ -3887,15 +4078,15 @@ List retrieves a list of payments associated with your account/organization. See: https://docs.mollie.com/reference/v2/payments-api/list-payments -### func \(\*PaymentsService\) [Update]() +### func \(\*PaymentsService\) [Update]() ```go -func (ps *PaymentsService) Update(ctx context.Context, id string, up Payment) (res *Response, p *Payment, err error) +func (ps *PaymentsService) Update(ctx context.Context, id string, up UpdatePayment) (res *Response, p *Payment, err error) ``` Update can be used to update some details of a created payment. -See: https://docs.mollie.com/reference/v2/payments-api/update-payment# +See: https://docs.mollie.com/reference/v2/payments-api/update-payment ## type [Permission]() @@ -4016,6 +4207,19 @@ PhoneNumber represents a phone number in the E.164 format. type PhoneNumber string ``` + +## type [PreAuthorizedPaymentFields]() + +PreAuthorizedPaymentFields describes the fields specific to pre\-authorized payments. + +```go +type PreAuthorizedPaymentFields struct { + CaptureDelay string `json:"captureDelay,omitempty"` + CaptureMode CaptureMode `json:"captureMode,omitempty"` + CaptureBefore *time.Time `json:"captureBefore,omitempty"` +} +``` + ## type [ProductType]() @@ -4265,7 +4469,7 @@ type QRCode struct { ``` -## type [Rate]() +## type [Rate]() Rate describes service rates, further divided into fixed and percentage costs. @@ -4276,6 +4480,20 @@ type Rate struct { } ``` + +## type [RecurrentPaymentFields]() + +RecurrentPaymentFields describes the fields specific to recurrent payments. + +```go +type RecurrentPaymentFields struct { + SequenceType SequenceType `json:"sequenceType,omitempty"` + CustomerID string `json:"customerId,omitempty"` + MandateID string `json:"mandateId,omitempty"` + SubscriptionID string `json:"subscriptionId,omitempty"` +} +``` + ## type [Refund]() @@ -4439,7 +4657,7 @@ type Response struct { ``` -## type [SequenceType]() +## type [SequenceType]() SequenceType indicates which type of payment this is in a recurring sequence. @@ -5212,6 +5430,31 @@ type URL struct { } ``` + +## type [UpdatePayment]() + +UpdatePayment describes the payload to be sent to the Mollie API when updating a payment. + +See: https://docs.mollie.com/reference/v2/payments-api/update-payment See: https://docs.mollie.com/reference/v2/payments-api/update-payment#payment-method-specific-parameters + +```go +type UpdatePayment struct { + Description string `json:"description,omitempty"` + RedirectURL string `json:"redirectUrl,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + Metadata any `json:"metadata,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Locale Locale `json:"locale,omitempty"` + RestrictPaymentMethodsToCountry string `json:"restrictPaymentMethodsToCountry,omitempty"` + + // PaymentMethods specific fields + BillingEmail string `json:"billingEmail,omitempty"` + DueDate *ShortDate `json:"dueDate,omitempty"` + Issuer string `json:"issuer,omitempty"` +} +``` + ## type [UsedGiftCard]() diff --git a/docs/v4-upgrade.md b/docs/v4-upgrade.md new file mode 100644 index 00000000..72153fe5 --- /dev/null +++ b/docs/v4-upgrade.md @@ -0,0 +1,21 @@ +# Notable changes included in v4 + +## Breaking changes + +- `idempotency` package has moved from the `mollie` directory to the `pkg` directory. +- `pagination` package has moved from the`mollie` directory to the `pkg` directory. +- `connect` package has moved from the `mollie` directory to the `pkg` directory. +- root namespace is not `github.com/VictorAvelar/mollie-api-go/v4/`. +- Changes for payments resource + - Added `CreatePayment` type to use when creating a payment. + - Added `UpdatePayment` type to use when updating a payment. + - Ensured `Payment` object (used for read operations) contains all the available fields. + - Created types specific for fields that are conditional given the payment values, both to create new payments and to list existing payments. + +## Other changes + +- `testify.Suite` was removed from all testing. +- Improvements for devcontainer files +- Major versions of multiple github actions updated +- Base `Dockerfile` using Go 1.22.x +- Tests related to payments were update to use the new types. diff --git a/mollie/captures.go b/mollie/captures.go index d069c457..ea690e58 100644 --- a/mollie/captures.go +++ b/mollie/captures.go @@ -7,6 +7,15 @@ import ( "time" ) +// CaptureMode describes the mode of a capture. +type CaptureMode string + +// CaptureMode possible values. +const ( + AutomaticCapture CaptureMode = "automatic" + ManualCapture CaptureMode = "manual" +) + // CapturesService operates over captures resource. type CapturesService service diff --git a/mollie/common_types.go b/mollie/common_types.go index e990df68..9d797caa 100644 --- a/mollie/common_types.go +++ b/mollie/common_types.go @@ -321,6 +321,15 @@ const ( TestMode Mode = "test" ) +// IncludeValue is a valid value for the Include query string parameter. +type IncludeValue string + +// Supported Include values. +const ( + IncludeQrCode IncludeValue = "details.qrCode" + IncludeRemainderDetails IncludeValue = "details.remainderDetails" +) + // EmbedValue describes the valid value of embed query string. type EmbedValue string @@ -330,6 +339,7 @@ const ( EmbedRefund EmbedValue = "refunds" EmbedShipments EmbedValue = "shipments" EmbedChargebacks EmbedValue = "chargebacks" + EmbedCaptures EmbedValue = "captures" ) // Rate describes service rates, further divided into fixed and percentage costs. diff --git a/mollie/customers.go b/mollie/customers.go index 72fae6c3..486aa377 100644 --- a/mollie/customers.go +++ b/mollie/customers.go @@ -170,7 +170,7 @@ func (cs *CustomersService) GetPayments(ctx context.Context, id string, options // CreatePayment creates a payment for the customer. // // See: https://docs.mollie.com/reference/v2/customers-api/create-customer-payment -func (cs *CustomersService) CreatePayment(ctx context.Context, id string, p Payment) ( +func (cs *CustomersService) CreatePayment(ctx context.Context, id string, p CreatePayment) ( res *Response, pp *Payment, err error, diff --git a/mollie/customers_test.go b/mollie/customers_test.go index e97a6474..9863ab29 100644 --- a/mollie/customers_test.go +++ b/mollie/customers_test.go @@ -621,7 +621,7 @@ func TestCustomerService_CreatePayment(t *testing.T) { type args struct { ctx context.Context customer string - payment Payment + payment CreatePayment } cases := []struct { @@ -637,7 +637,11 @@ func TestCustomerService_CreatePayment(t *testing.T) { args{ context.Background(), "cst_kEn1PlbGa", - Payment{TestMode: true}, + CreatePayment{ + CreatePaymentAccessTokenFields: CreatePaymentAccessTokenFields{ + Testmode: true, + }, + }, }, false, nil, @@ -657,7 +661,11 @@ func TestCustomerService_CreatePayment(t *testing.T) { args{ context.Background(), "cst_kEn1PlbGa", - Payment{TestMode: true}, + CreatePayment{ + CreatePaymentAccessTokenFields: CreatePaymentAccessTokenFields{ + Testmode: true, + }, + }, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -669,7 +677,11 @@ func TestCustomerService_CreatePayment(t *testing.T) { args{ context.Background(), "cst_kEn1PlbGa", - Payment{TestMode: true}, + CreatePayment{ + CreatePaymentAccessTokenFields: CreatePaymentAccessTokenFields{ + Testmode: true, + }, + }, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -681,7 +693,11 @@ func TestCustomerService_CreatePayment(t *testing.T) { args{ context.Background(), "cst_kEn1PlbGa", - Payment{TestMode: true}, + CreatePayment{ + CreatePaymentAccessTokenFields: CreatePaymentAccessTokenFields{ + Testmode: true, + }, + }, }, true, errBadBaseURL, diff --git a/mollie/payments.go b/mollie/payments.go index 7ca57ff1..67af858d 100644 --- a/mollie/payments.go +++ b/mollie/payments.go @@ -15,6 +15,7 @@ const ( Bancontact PaymentMethod = "bancontact" BankTransfer PaymentMethod = "banktransfer" Belfius PaymentMethod = "belfius" + CBC PaymentMethod = "cbc" CreditCard PaymentMethod = "creditcard" DirectDebit PaymentMethod = "directdebit" EPS PaymentMethod = "eps" @@ -41,62 +42,187 @@ const ( RecurringSequence SequenceType = "recurring" ) +// PaymentRouting describes the routing of a payment. +type PaymentRouting struct { + Destination PaymentDestination `json:"destination,omitempty"` + Amount *Amount `json:"amount,omitempty"` + ReleaseDate *ShortDate `json:"releaseDate,omitempty"` +} + +// PaymentDestination describes the destination of a payment. +type PaymentDestination struct { + Kind string `json:"type,omitempty"` + OrganizationID string `json:"organizationId,omitempty"` +} + +// CreatePayment describes the payload to be sent to the Mollie API when +// creating or updating a new payment. +// +// Some fields are only valid for specific payment methods, and are +// documented in the Mollie API reference. +// +// See: https://docs.mollie.com/reference/v2/payments-api/create-payment#payment-method-specific-parameters +type CreatePayment struct { + Description string `json:"description,omitempty"` + RedirectURL string `json:"redirectUrl,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + RestrictPaymentMethodsToCountry string `json:"restrictPaymentMethodsToCountry,omitempty"` + Amount *Amount `json:"amount,omitempty"` + Locale Locale `json:"locale,omitempty"` + Method []PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` + + // PaymentMethods specific fields + DigitalGoods bool `json:"digitalGoods,omitempty"` + ApplePayPaymentToken string `json:"applePayPaymentToken,omitempty"` + BillingEmail string `json:"billingEmail,omitempty"` + CardToken string `json:"cardToken,omitempty"` + VoucherNumber string `json:"voucherNumber,omitempty"` + VoucherPin string `json:"voucherPin,omitempty"` + Issuer string `json:"issuer,omitempty"` + ExtraMerchantData string `json:"extraMerchantData,omitempty"` + SessionID string `json:"sessionId,omitempty"` + CustomerReference string `json:"customerReference,omitempty"` + TerminalID string `json:"terminalId,omitempty"` + ConsumerName string `json:"consumerName,omitempty"` + ConsumerAccount string `json:"consumerAccount,omitempty"` + DueDate *ShortDate `json:"dueDate,omitempty"` + ShippingAddress *Address `json:"shippingAddress,omitempty"` + BillingAddress *Address `json:"billingAddress,omitempty"` + Company *Company `json:"company,omitempty"` + + // Other case specific fields + CreateRecurrentPaymentFields + CreatePreAuthorizedPaymentFields + CreatePaymentAccessTokenFields + CreateMollieConnectPaymentFields +} + +// CreateRecurrentPaymentFields describes the fields to be sent to the Mollie API when +// creating a new recurrent payment. +// +// See: https://docs.mollie.com/reference/v2/payments-api/create-payment#parameters-for-recurring-payments +type CreateRecurrentPaymentFields struct { + CustomerID string `json:"customerId,omitempty"` + MandateID string `json:"mandateId,omitempty"` + SequenceType SequenceType `json:"sequenceType,omitempty"` +} + +// CreatePreAuthorizedPaymentFields describes the fields to be sent to the Mollie API when +// creating a new pre-authorized payment. +// +// See: https://docs.mollie.com/reference/v2/payments-api/create-payment#parameters-for-pre-authorized-payments +type CreatePreAuthorizedPaymentFields struct { + CaptureDelay string `json:"captureDelay,omitempty"` + CaptureMode CaptureMode `json:"captureMode,omitempty"` +} + +// CreatePaymentAccessTokenFields describes the fields to be sent to the Mollie API when +// creating a new payment using an access token. +// +// See: https://docs.mollie.com/reference/v2/payments-api/create-payment#access-token-parameters +type CreatePaymentAccessTokenFields struct { + ProfileID string `json:"profileId,omitempty"` + Testmode bool `json:"testmode,omitempty"` +} + +// CreateMollieConnectPaymentFields describes the fields to be sent to the Mollie API when +// creating a new payment using Mollie Connect. +// +// See: https://docs.mollie.com/reference/v2/payments-api/create-payment#mollie-connect-parameters +type CreateMollieConnectPaymentFields struct { + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` + Routing []*PaymentRouting `json:"routing,omitempty"` +} + +// UpdatePayment describes the payload to be sent to the Mollie API when +// updating a payment. +// +// See: https://docs.mollie.com/reference/v2/payments-api/update-payment +// See: https://docs.mollie.com/reference/v2/payments-api/update-payment#payment-method-specific-parameters +type UpdatePayment struct { + Description string `json:"description,omitempty"` + RedirectURL string `json:"redirectUrl,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + Metadata any `json:"metadata,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Locale Locale `json:"locale,omitempty"` + RestrictPaymentMethodsToCountry string `json:"restrictPaymentMethodsToCountry,omitempty"` + + // PaymentMethods specific fields + BillingEmail string `json:"billingEmail,omitempty"` + DueDate *ShortDate `json:"dueDate,omitempty"` + Issuer string `json:"issuer,omitempty"` +} + // Payment describes a transaction between a customer and a merchant. type Payment struct { - IsCancellable bool `json:"isCancellable,omitempty"` - TestMode bool `json:"testmode,omitempty"` - DigitalGoods bool `json:"digitalGoods,omitempty"` - ApplePayPaymentToken string `json:"applePayPaymentToken,omitempty"` - BillingEmail string `json:"billingEmail,omitempty"` - CardToken string `json:"cardToken,omitempty"` - Issuer string `json:"issuer,omitempty"` - VoucherNumber string `json:"voucherNumber,omitempty"` - VoucherPin string `json:"voucherPin,omitempty"` - ExtraMerchantData string `json:"extraMerchantData,omitempty"` - SessionID string `json:"sessionId,omitempty"` - CustomerReference string `json:"customerReference,omitempty"` - ConsumerName string `json:"consumerName,omitempty"` - ConsumerAccount string `json:"consumerAccount,omitempty"` - WebhookURL string `json:"webhookUrl,omitempty"` - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - MandateID string `json:"mandateId,omitempty"` - OrderID string `json:"orderId,omitempty"` - ProfileID string `json:"profileId,omitempty"` - SettlementID string `json:"settlementId,omitempty"` - CustomerID string `json:"customerId,omitempty"` - Status string `json:"status,omitempty"` - Description string `json:"description,omitempty"` - RedirectURL string `json:"redirectUrl,omitempty"` - CountryCode string `json:"countryCode,omitempty"` - SubscriptionID string `json:"subscriptionId,omitempty"` - CancelURL string `json:"cancelUrl,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - Amount *Amount `json:"amount,omitempty"` - AmountRefunded *Amount `json:"amountRefunded,omitempty"` - AmountRemaining *Amount `json:"amountRemaining,omitempty"` - AmountCaptured *Amount `json:"amountCaptured,omitempty"` - AmountChargedBack *Amount `json:"amountChargedBack,omitempty"` - SettlementAmount *Amount `json:"settlementAmount,omitempty"` - ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` - Details *PaymentDetails `json:"details,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - AuthorizedAt *time.Time `json:"authorizedAt,omitempty"` - PaidAt *time.Time `json:"paidAt,omitempty"` - CanceledAt *time.Time `json:"canceledAt,omitempty"` - ExpiresAt *time.Time `json:"expiresAt,omitempty"` - ExpiredAt *time.Time `json:"expiredAt,omitempty"` - FailedAt *time.Time `json:"failedAt,omitempty"` - DueDate *ShortDate `json:"dueDate,omitempty"` - BillingAddress *Address `json:"billingAddress,omitempty"` - ShippingAddress *PaymentDetailsAddress `json:"shippingAddress,omitempty"` - Mode Mode `json:"mode,omitempty"` - Locale Locale `json:"locale,omitempty"` - RestrictPaymentMethodsToCountry Locale `json:"restrictPaymentMethodsToCountry,omitempty"` - Method PaymentMethod `json:"method,omitempty"` - Links PaymentLinks `json:"_links,omitempty"` - SequenceType SequenceType `json:"sequenceType,omitempty"` - Company Company `json:"company,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` + Description string `json:"description,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + CountryCode string `json:"countryCode,omitempty"` + RestrictPaymentMethodsToCountry string `json:"restrictPaymentMethodsToCountry,omitempty"` + ProfileID string `json:"profileId,omitempty"` + SettlementID string `json:"settlementId,omitempty"` + OrderID string `json:"orderId,omitempty"` + IsCancelable bool `json:"isCancelable,omitempty"` + Mode Mode `json:"mode,omitempty"` + Locale Locale `json:"locale,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` + Links PaymentLinks `json:"_links,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + AuthorizedAt *time.Time `json:"authorizedAt,omitempty"` + PaidAt *time.Time `json:"paidAt,omitempty"` + CanceledAt *time.Time `json:"canceledAt,omitempty"` + ExpiresAt *time.Time `json:"expiresAt,omitempty"` + ExpiredAt *time.Time `json:"expiredAt,omitempty"` + FailedAt *time.Time `json:"failedAt,omitempty"` + Amount *Amount `json:"amount,omitempty"` + AmountRefunded *Amount `json:"amountRefunded,omitempty"` + AmountRemaining *Amount `json:"amountRemaining,omitempty"` + AmountCaptured *Amount `json:"amountCaptured,omitempty"` + AmountChargedBack *Amount `json:"amountChargeback,omitempty"` + SettlementAmount *Amount `json:"settlementAmount,omitempty"` + + // PaymentMethods specific fields + Details PaymentDetails `json:"details,omitempty"` + + // Other case specific fields + RecurrentPaymentFields + PreAuthorizedPaymentFields + MollieConnectPaymentFields + AccessTokenPaymentFields +} + +// RecurrentPaymentFields describes the fields specific to recurrent payments. +type RecurrentPaymentFields struct { + SequenceType SequenceType `json:"sequenceType,omitempty"` + CustomerID string `json:"customerId,omitempty"` + MandateID string `json:"mandateId,omitempty"` + SubscriptionID string `json:"subscriptionId,omitempty"` +} + +// PreAuthorizedPaymentFields describes the fields specific to pre-authorized payments. +type PreAuthorizedPaymentFields struct { + CaptureDelay string `json:"captureDelay,omitempty"` + CaptureMode CaptureMode `json:"captureMode,omitempty"` + CaptureBefore *time.Time `json:"captureBefore,omitempty"` +} + +// MollieConnectPaymentFields describes the fields specific to Mollie Connect payments. +type MollieConnectPaymentFields struct { + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` +} + +// AccessTokenPaymentFields describes the fields specific to payments created using an access token. +type AccessTokenPaymentFields struct { + Testmode bool `json:"testmode,omitempty"` } // PaymentLinks describes all the possible links to be returned with @@ -115,23 +241,25 @@ type PaymentLinks struct { Customer *URL `json:"customer,omitempty"` Order *URL `json:"order,omitempty"` Dashboard *URL `json:"dashboard,omitempty"` + MobileAppCheckout *URL `json:"mobileAppCheckout,omitempty"` + Terminal *URL `json:"terminal,omitempty"` } // PaymentOptions describes payments endpoint valid query string parameters. // // See: https://docs.mollie.com/reference/v2/payments-api/get-payment type PaymentOptions struct { - Include string `url:"include,omitempty"` - Embed string `url:"embed,omitempty"` + Include []IncludeValue `url:"include,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` } // ListPaymentOptions describes list payments endpoint valid query string parameters. type ListPaymentOptions struct { - Limit int `url:"limit,omitempty"` - Include string `url:"include,omitempty"` - Embed string `url:"embed,omitempty"` - ProfileID string `url:"profileId,omitempty"` - From string `url:"from,omitempty"` + Limit int `url:"limit,omitempty"` + Include []IncludeValue `url:"include,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` + ProfileID string `url:"profileId,omitempty"` + From string `url:"from,omitempty"` } // PaymentsService instance operates over payment resources. @@ -158,13 +286,13 @@ func (ps *PaymentsService) Get(ctx context.Context, id string, opts *PaymentOpti // Create stores a new payment object attached to your Mollie account. // // See: https://docs.mollie.com/reference/v2/payments-api/create-payment# -func (ps *PaymentsService) Create(ctx context.Context, p Payment, opts *PaymentOptions) ( +func (ps *PaymentsService) Create(ctx context.Context, p CreatePayment, opts *PaymentOptions) ( res *Response, np *Payment, err error, ) { if ps.client.HasAccessToken() && ps.client.config.testing { - p.TestMode = true + p.Testmode = true } res, err = ps.client.post(ctx, "v2/payments", p, opts) @@ -197,8 +325,12 @@ func (ps *PaymentsService) Cancel(ctx context.Context, id string) (res *Response // Update can be used to update some details of a created payment. // -// See: https://docs.mollie.com/reference/v2/payments-api/update-payment# -func (ps *PaymentsService) Update(ctx context.Context, id string, up Payment) (res *Response, p *Payment, err error) { +// See: https://docs.mollie.com/reference/v2/payments-api/update-payment +func (ps *PaymentsService) Update(ctx context.Context, id string, up UpdatePayment) ( + res *Response, + p *Payment, + err error, +) { res, err = ps.client.patch(ctx, fmt.Sprintf("v2/payments/%s", id), up, nil) if err != nil { return diff --git a/mollie/payments_test.go b/mollie/payments_test.go index 6c8a77c7..7e911d6a 100644 --- a/mollie/payments_test.go +++ b/mollie/payments_test.go @@ -33,7 +33,7 @@ func TestPaymentsService_Get(t *testing.T) { context.Background(), "tr_WDqYK6vllg", &PaymentOptions{ - Include: "settlements", + Include: []IncludeValue{IncludeQrCode}, }, }, false, @@ -42,7 +42,7 @@ func TestPaymentsService_Get(t *testing.T) { func(w http.ResponseWriter, r *http.Request) { testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") testMethod(t, r, "GET") - testQuery(t, r, "include=settlements") + testQuery(t, r, "include=details.qrCode") if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) @@ -209,7 +209,7 @@ func TestPaymentsService_Create(t *testing.T) { type args struct { ctx context.Context - payment Payment + payment CreatePayment options *PaymentOptions } cases := []struct { @@ -224,11 +224,11 @@ func TestPaymentsService_Create(t *testing.T) { "create payments works as expected.", args{ context.Background(), - Payment{ + CreatePayment{ BillingEmail: "test@example.com", }, &PaymentOptions{ - Include: "settlements", + Include: []IncludeValue{}, }, }, false, @@ -237,7 +237,6 @@ func TestPaymentsService_Create(t *testing.T) { func(w http.ResponseWriter, r *http.Request) { testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") testMethod(t, r, "POST") - testQuery(t, r, "include=settlements") if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) @@ -249,11 +248,11 @@ func TestPaymentsService_Create(t *testing.T) { "create payments with access token works as expected.", args{ context.Background(), - Payment{ + CreatePayment{ BillingEmail: "test@example.com", }, &PaymentOptions{ - Include: "settlements", + Include: []IncludeValue{}, }, }, false, @@ -262,7 +261,7 @@ func TestPaymentsService_Create(t *testing.T) { func(w http.ResponseWriter, r *http.Request) { testHeader(t, r, AuthHeader, "Bearer access_token_test") testMethod(t, r, "POST") - testQuery(t, r, "include=settlements&testmode=true") + testQuery(t, r, "testmode=true") if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) @@ -274,7 +273,7 @@ func TestPaymentsService_Create(t *testing.T) { "create payments, an error is returned from the server", args{ context.Background(), - Payment{}, + CreatePayment{}, nil, }, true, @@ -286,7 +285,7 @@ func TestPaymentsService_Create(t *testing.T) { "create payments, an error occurs when parsing json", args{ context.Background(), - Payment{}, + CreatePayment{}, nil, }, true, @@ -298,7 +297,7 @@ func TestPaymentsService_Create(t *testing.T) { "create payments, invalid url when building request", args{ context.Background(), - Payment{}, + CreatePayment{}, nil, }, true, @@ -336,7 +335,7 @@ func TestPaymentsService_Update(t *testing.T) { type args struct { ctx context.Context id string - payment Payment + payment UpdatePayment } cases := []struct { name string @@ -351,7 +350,7 @@ func TestPaymentsService_Update(t *testing.T) { args{ context.Background(), "tr_WDqYK6vllg", - Payment{ + UpdatePayment{ BillingEmail: "test@example.com", }, }, @@ -373,7 +372,7 @@ func TestPaymentsService_Update(t *testing.T) { args{ context.Background(), "tr_WDqYK6vllg", - Payment{ + UpdatePayment{ BillingEmail: "test@example.com", }, }, @@ -398,7 +397,7 @@ func TestPaymentsService_Update(t *testing.T) { args{ context.Background(), "tr_WDqYK6vllg", - Payment{}, + UpdatePayment{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -410,7 +409,7 @@ func TestPaymentsService_Update(t *testing.T) { args{ context.Background(), "tr_WDqYK6vllg", - Payment{}, + UpdatePayment{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -422,7 +421,7 @@ func TestPaymentsService_Update(t *testing.T) { args{ context.Background(), "tr_WDqYK6vllg", - Payment{}, + UpdatePayment{}, }, true, errBadBaseURL, From b22b15a6b972dd28e0b2ebedff9bc0a35f2fb50c Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Sun, 3 Mar 2024 14:32:43 +0100 Subject: [PATCH 02/23] balances resource api parity (#328) --- docs/README.md | 32 +++++++++++----- mollie/balances.go | 3 -- mollie/custom_types.go | 29 +++++++++++++++ mollie/custom_types_test.go | 73 +++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 13 deletions(-) create mode 100644 mollie/custom_types.go create mode 100644 mollie/custom_types_test.go diff --git a/docs/README.md b/docs/README.md index 748164cc..729dab67 100644 --- a/docs/README.md +++ b/docs/README.md @@ -98,6 +98,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(c \*Config\) ToggleTesting\(\) bool](<#Config.ToggleTesting>) - [type ContextValue](<#ContextValue>) - [type ContextValues](<#ContextValues>) + - [func \(cv \*ContextValues\) UnmarshalJSON\(data \[\]byte\) error](<#ContextValues.UnmarshalJSON>) - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) - [type CreatePayment](<#CreatePayment>) - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) @@ -676,7 +677,7 @@ type BalanceTransaction struct { ``` -## type [BalanceTransactionsList]() +## type [BalanceTransactionsList]() BalanceTransactionsList contains an array of embedded transactions. @@ -691,7 +692,7 @@ type BalanceTransactionsList struct { ``` -## type [BalanceTransactionsListOptions]() +## type [BalanceTransactionsListOptions]() BalanceTransactionsListOptions are valid query parameters for list balance transactions requests. @@ -733,7 +734,7 @@ type BalancesService service ``` -### func \(\*BalancesService\) [Get]() +### func \(\*BalancesService\) [Get]() ```go func (bs *BalancesService) Get(ctx context.Context, balance string) (res *Response, b *Balance, err error) @@ -744,7 +745,7 @@ GetBalance retrieves a balance by its id. See: https://docs.mollie.com/reference/v2/balances-api/get-balance -### func \(\*BalancesService\) [GetPrimaryReport]() +### func \(\*BalancesService\) [GetPrimaryReport]() ```go func (bs *BalancesService) GetPrimaryReport(ctx context.Context, options *BalanceReportOptions) (res *Response, br *BalanceReport, err error) @@ -755,7 +756,7 @@ GetPrimaryReport returns the report for the primary balance. See: https://docs.mollie.com/reference/v2/balances-api/get-primary-balance-report -### func \(\*BalancesService\) [GetPrimaryTransactionsList]() +### func \(\*BalancesService\) [GetPrimaryTransactionsList]() ```go func (bs *BalancesService) GetPrimaryTransactionsList(ctx context.Context, options *BalanceTransactionsListOptions) (res *Response, btl *BalanceTransactionsList, err error) @@ -766,7 +767,7 @@ GetPrimaryTransactionsList retrieves the list of movements \(transactions\) for See: https://docs.mollie.com/reference/v2/balances-api/list-primary-balance-transactions -### func \(\*BalancesService\) [GetReport]() +### func \(\*BalancesService\) [GetReport]() ```go func (bs *BalancesService) GetReport(ctx context.Context, balance string, options *BalanceReportOptions) (res *Response, br *BalanceReport, err error) @@ -777,7 +778,7 @@ GetReport returns the balance report for the specified balance id. See: https://docs.mollie.com/reference/v2/balances-api/get-balance-report -### func \(\*BalancesService\) [GetTransactionsList]() +### func \(\*BalancesService\) [GetTransactionsList]() ```go func (bs *BalancesService) GetTransactionsList(ctx context.Context, balance string, options *BalanceTransactionsListOptions) (res *Response, btl *BalanceTransactionsList, err error) @@ -788,7 +789,7 @@ GetTransactionsList retrieves a list of movements \(transactions\) for the speci See: https://docs.mollie.com/reference/v2/balances-api/list-balance-transactions -### func \(\*BalancesService\) [List]() +### func \(\*BalancesService\) [List]() ```go func (bs *BalancesService) List(ctx context.Context, options *BalanceListOptions) (res *Response, bl *BalancesList, err error) @@ -799,7 +800,7 @@ List retrieves all the organization’s balances, including the primary balance, See: https://docs.mollie.com/reference/v2/balances-api/list-balances -### func \(\*BalancesService\) [Primary]() +### func \(\*BalancesService\) [Primary]() ```go func (bs *BalancesService) Primary(ctx context.Context) (res *Response, b *Balance, err error) @@ -1702,7 +1703,7 @@ type ContextValue string ``` -## type [ContextValues]() +## type [ContextValues]() ContextValues is a map of TransactionType to ContextValue. @@ -1710,6 +1711,17 @@ ContextValues is a map of TransactionType to ContextValue. type ContextValues map[TransactionType]ContextValue ``` + +### func \(\*ContextValues\) [UnmarshalJSON]() + +```go +func (cv *ContextValues) UnmarshalJSON(data []byte) error +``` + +UnmarshalJSON implements the json.Unmarshaler interface on ContextValues. + +See: https://github.com/VictorAvelar/mollie-api-go/issues/251 + ## type [CreateMollieConnectPaymentFields]() diff --git a/mollie/balances.go b/mollie/balances.go index 631accfa..01b50498 100644 --- a/mollie/balances.go +++ b/mollie/balances.go @@ -208,9 +208,6 @@ const ( PlatformPaymentChargeback TransactionType = "platform-payment-chargeback" ) -// ContextValues is a map of TransactionType to ContextValue. -type ContextValues map[TransactionType]ContextValue - // BalanceTransactionsList contains an array of embedded transactions. type BalanceTransactionsList struct { Count int `json:"count,omitempty"` diff --git a/mollie/custom_types.go b/mollie/custom_types.go new file mode 100644 index 00000000..82abbf24 --- /dev/null +++ b/mollie/custom_types.go @@ -0,0 +1,29 @@ +package mollie + +import ( + "encoding/json" +) + +// ContextValues is a map of TransactionType to ContextValue. +type ContextValues map[TransactionType]ContextValue + +// UnmarshalJSON implements the json.Unmarshaler interface on ContextValues. +// +// See: https://github.com/VictorAvelar/mollie-api-go/issues/251 +func (cv *ContextValues) UnmarshalJSON(data []byte) error { + var d map[TransactionType]ContextValue + + if err := json.Unmarshal(data, &d); err != nil { + if _, ok := err.(*json.UnmarshalTypeError); ok { + *cv = make(ContextValues) + + return nil + } + + return err + } + + *cv = ContextValues(d) + + return nil +} diff --git a/mollie/custom_types_test.go b/mollie/custom_types_test.go new file mode 100644 index 00000000..e7f3cc7e --- /dev/null +++ b/mollie/custom_types_test.go @@ -0,0 +1,73 @@ +package mollie + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestContextValues_UnmarshalJSON(t *testing.T) { + tests := []struct { + name string + data []byte + want ContextValues + wantErr bool + }{ + // Add test cases here + { + name: "Correct decoding JSON", + data: []byte(`{"type1": "value1", "type2": "value2"}`), + want: ContextValues{ + "type1": "value1", + "type2": "value2", + }, + wantErr: false, + }, + { + name: "Handle empty JSON", + data: []byte(`{}`), + want: ContextValues{}, + wantErr: false, + }, + { + name: "Invalid JSON", + data: []byte(`{"type1": "value1", "type2": "value2"`), + want: make(ContextValues), + wantErr: true, + }, + { + name: "Incorrect type in json returns an empty map", + data: []byte(`{"type1":["value1", "value2"]}`), + want: make(ContextValues), + wantErr: false, + }, + { + name: "Test correct case described on issue #251", + data: []byte(`{"context": { + "paymentId": "tr_xxxxxxxx" + }}`), + want: make(ContextValues), + wantErr: false, + }, + { + name: "Test failing case described on issue #251", + data: []byte(`{"context": []}`), + want: make(ContextValues), + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var cv ContextValues + err := cv.UnmarshalJSON(tt.data) + + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.want, cv) + } + }) + } +} From f7975316bc7340cd173c89a61fc20f4000bc3379 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio Date: Sun, 3 Mar 2024 13:36:30 +0000 Subject: [PATCH 03/23] fix(scrutinizer): use latest go version --- .scrutinizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 9cde2516..6327ab5a 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -12,7 +12,7 @@ build: - "true" environment: go: - version: go1.17 + version: go1.22 tests: override: - go-scrutinizer-run From 8a6c0e17e1db3ddae2e04f3e59476fabe915ce52 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Sun, 3 Mar 2024 20:35:50 +0100 Subject: [PATCH 04/23] check captures resource against api reference. (#330) --- .github/workflows/golangci-lint.yml | 4 + docs/README.md | 112 ++++++++++++++--- mollie/captures.go | 105 +++++++++++++--- mollie/captures_test.go | 188 +++++++++++++++++++++++++++- testdata/captures.go | 57 +++++++++ 5 files changed, 427 insertions(+), 39 deletions(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index f6425887..a0a3d888 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -35,11 +35,15 @@ jobs: permissions: contents: read pull-requests: read + checks: write steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + with: + fetch-depth: '0' - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 with: go-version: 1.22.X - uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 with: version: latest + install-mode: binary diff --git a/docs/README.md b/docs/README.md index 729dab67..81da279a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -54,11 +54,15 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(be \*BaseError\) Error\(\) string](<#BaseError.Error>) - [type BusinessCategory](<#BusinessCategory>) - [type Capture](<#Capture>) +- [type CaptureAccessTokenFields](<#CaptureAccessTokenFields>) - [type CaptureLinks](<#CaptureLinks>) - [type CaptureMode](<#CaptureMode>) +- [type CaptureOptions](<#CaptureOptions>) +- [type CaptureStatus](<#CaptureStatus>) - [type CapturesList](<#CapturesList>) - [type CapturesService](<#CapturesService>) - - [func \(cs \*CapturesService\) Get\(ctx context.Context, payment, capture string\) \(res \*Response, c \*Capture, err error\)](<#CapturesService.Get>) + - [func \(cs \*CapturesService\) Create\(ctx context.Context, payment string, capture CreateCapture\) \(res \*Response, c \*Capture, err error\)](<#CapturesService.Create>) + - [func \(cs \*CapturesService\) Get\(ctx context.Context, payment, capture string, options \*CaptureOptions\) \(res \*Response, c \*Capture, err error\)](<#CapturesService.Get>) - [func \(cs \*CapturesService\) List\(ctx context.Context, payment string\) \(res \*Response, cl \*CapturesList, err error\)](<#CapturesService.List>) - [type CardLabel](<#CardLabel>) - [type CategoryCode](<#CategoryCode>) @@ -99,6 +103,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type ContextValue](<#ContextValue>) - [type ContextValues](<#ContextValues>) - [func \(cv \*ContextValues\) UnmarshalJSON\(data \[\]byte\) error](<#ContextValues.UnmarshalJSON>) +- [type CreateCapture](<#CreateCapture>) - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) - [type CreatePayment](<#CreatePayment>) - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) @@ -987,27 +992,41 @@ const ( ``` -## type [Capture]() +## type [Capture]() Capture describes a single capture. Captures are used for payments that have the authorize\-then\-capture flow. ```go type Capture struct { - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - Mode Mode `json:"mode,omitempty"` - Amount *Amount `json:"amount,omitempty"` - SettlementAmount *Amount `json:"settlementAmount,omitempty"` - PaymentID string `json:"paymentId,omitempty"` - ShipmentID string `json:"shipmentId,omitempty"` - SettlementID string `json:"settlementId,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - Links CaptureLinks `json:"_links,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + Mode Mode `json:"mode,omitempty"` + Amount *Amount `json:"amount,omitempty"` + Status CaptureStatus `json:"status,omitempty"` + SettlementAmount *Amount `json:"settlementAmount,omitempty"` + PaymentID string `json:"paymentId,omitempty"` + ShipmentID string `json:"shipmentId,omitempty"` + SettlementID string `json:"settlementId,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + Metadata any `json:"metadata,omitempty"` + Links CaptureLinks `json:"_links,omitempty"` + AccessTokenPaymentFields +} +``` + + +## type [CaptureAccessTokenFields]() + +CaptureAccessTokenFields describes the payload for creating a capture with an access token. + +```go +type CaptureAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` } ``` -## type [CaptureLinks]() +## type [CaptureLinks]() CaptureLinks contains relevant links for a capture object. @@ -1039,8 +1058,40 @@ const ( ) ``` + +## type [CaptureOptions]() + +CaptureOptions describes the query params available to use when retrieving captures. + +See: https://docs.mollie.com/reference/v2/captures-api/get-capture#embedding-of-related-resources + +```go +type CaptureOptions struct { + Embed []EmbedValue `url:"embed,omitempty"` +} +``` + + +## type [CaptureStatus]() + +CaptureStatus describes the status of a capture. + +```go +type CaptureStatus string +``` + +CaptureStatus possible values. + +```go +const ( + CaptureStatusPending CaptureStatus = "pending" + CaptureStatusSucceeded CaptureStatus = "succeeded" + CaptureStatusFailed CaptureStatus = "failed" +) +``` + -## type [CapturesList]() +## type [CapturesList]() CapturesList describes a list of captures. @@ -1055,7 +1106,7 @@ type CapturesList struct { ``` -## type [CapturesService]() +## type [CapturesService]() CapturesService operates over captures resource. @@ -1063,11 +1114,22 @@ CapturesService operates over captures resource. type CapturesService service ``` + +### func \(\*CapturesService\) [Create]() + +```go +func (cs *CapturesService) Create(ctx context.Context, payment string, capture CreateCapture) (res *Response, c *Capture, err error) +``` + +Create creates a new capture for a payment. + +See: https://docs.mollie.com/reference/v2/captures-api/create-capture + -### func \(\*CapturesService\) [Get]() +### func \(\*CapturesService\) [Get]() ```go -func (cs *CapturesService) Get(ctx context.Context, payment, capture string) (res *Response, c *Capture, err error) +func (cs *CapturesService) Get(ctx context.Context, payment, capture string, options *CaptureOptions) (res *Response, c *Capture, err error) ``` Get retrieves a single capture by its ID. Note the original payment’s ID is needed as well. @@ -1075,7 +1137,7 @@ Get retrieves a single capture by its ID. Note the original payment’s ID is ne See: https://docs.mollie.com/reference/v2/captures-api/get-capture -### func \(\*CapturesService\) [List]() +### func \(\*CapturesService\) [List]() ```go func (cs *CapturesService) List(ctx context.Context, payment string) (res *Response, cl *CapturesList, err error) @@ -1722,6 +1784,20 @@ UnmarshalJSON implements the json.Unmarshaler interface on ContextValues. See: https://github.com/VictorAvelar/mollie-api-go/issues/251 + +## type [CreateCapture]() + +CreateCapture describes the payload for creating a capture. + +```go +type CreateCapture struct { + Description string `json:"description,omitempty"` + Metadata any `json:"metadata,omitempty"` + Amount *Amount `json:"amount,omitempty"` + CaptureAccessTokenFields +} +``` + ## type [CreateMollieConnectPaymentFields]() diff --git a/mollie/captures.go b/mollie/captures.go index ea690e58..50936be0 100644 --- a/mollie/captures.go +++ b/mollie/captures.go @@ -16,8 +16,46 @@ const ( ManualCapture CaptureMode = "manual" ) -// CapturesService operates over captures resource. -type CapturesService service +// CaptureStatus describes the status of a capture. +type CaptureStatus string + +// CaptureStatus possible values. +const ( + CaptureStatusPending CaptureStatus = "pending" + CaptureStatusSucceeded CaptureStatus = "succeeded" + CaptureStatusFailed CaptureStatus = "failed" +) + +// CreateCapture describes the payload for creating a capture. +type CreateCapture struct { + Description string `json:"description,omitempty"` + Metadata any `json:"metadata,omitempty"` + Amount *Amount `json:"amount,omitempty"` + CaptureAccessTokenFields +} + +// CaptureAccessTokenFields describes the payload for creating a capture with an access token. +type CaptureAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` +} + +// Capture describes a single capture. +// Captures are used for payments that have the authorize-then-capture flow. +type Capture struct { + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + Mode Mode `json:"mode,omitempty"` + Amount *Amount `json:"amount,omitempty"` + Status CaptureStatus `json:"status,omitempty"` + SettlementAmount *Amount `json:"settlementAmount,omitempty"` + PaymentID string `json:"paymentId,omitempty"` + ShipmentID string `json:"shipmentId,omitempty"` + SettlementID string `json:"settlementId,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + Metadata any `json:"metadata,omitempty"` + Links CaptureLinks `json:"_links,omitempty"` + AccessTokenPaymentFields +} // CaptureLinks contains relevant links for a capture object. type CaptureLinks struct { @@ -28,19 +66,11 @@ type CaptureLinks struct { Documentation *URL `json:"documentation,omitempty"` } -// Capture describes a single capture. -// Captures are used for payments that have the authorize-then-capture flow. -type Capture struct { - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - Mode Mode `json:"mode,omitempty"` - Amount *Amount `json:"amount,omitempty"` - SettlementAmount *Amount `json:"settlementAmount,omitempty"` - PaymentID string `json:"paymentId,omitempty"` - ShipmentID string `json:"shipmentId,omitempty"` - SettlementID string `json:"settlementId,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - Links CaptureLinks `json:"_links,omitempty"` +// CaptureOptions describes the query params available to use when retrieving captures. +// +// See: https://docs.mollie.com/reference/v2/captures-api/get-capture#embedding-of-related-resources +type CaptureOptions struct { + Embed []EmbedValue `url:"embed,omitempty"` } // CapturesList describes a list of captures. @@ -52,14 +82,47 @@ type CapturesList struct { Links PaginationLinks `json:"_links,omitempty"` } +// CapturesService operates over captures resource. +type CapturesService service + // Get retrieves a single capture by its ID. // Note the original payment’s ID is needed as well. // // See: https://docs.mollie.com/reference/v2/captures-api/get-capture -func (cs *CapturesService) Get(ctx context.Context, payment, capture string) (res *Response, c *Capture, err error) { +func (cs *CapturesService) Get(ctx context.Context, payment, capture string, options *CaptureOptions) ( + res *Response, + c *Capture, + err error, +) { u := fmt.Sprintf("v2/payments/%s/captures/%s", payment, capture) - res, err = cs.client.get(ctx, u, nil) + res, err = cs.client.get(ctx, u, options) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &c); err != nil { + return + } + + return +} + +// Create creates a new capture for a payment. +// +// See: https://docs.mollie.com/reference/v2/captures-api/create-capture +func (cs *CapturesService) Create(ctx context.Context, payment string, capture CreateCapture) ( + res *Response, + c *Capture, + err error, +) { + u := fmt.Sprintf("v2/payments/%s/captures", payment) + + if cs.client.HasAccessToken() && cs.client.config.testing { + capture.Testmode = true + } + + res, err = cs.client.post(ctx, u, capture, nil) if err != nil { return } @@ -74,10 +137,14 @@ func (cs *CapturesService) Get(ctx context.Context, payment, capture string) (re // List retrieves all captures for a certain payment. // // See: https://docs.mollie.com/reference/v2/captures-api/list-captures -func (cs *CapturesService) List(ctx context.Context, payment string) (res *Response, cl *CapturesList, err error) { +func (cs *CapturesService) List(ctx context.Context, payment string, options *CaptureOptions) ( + res *Response, + cl *CapturesList, + err error, +) { u := fmt.Sprintf("v2/payments/%s/captures", payment) - res, err = cs.client.get(ctx, u, nil) + res, err = cs.client.get(ctx, u, options) if err != nil { return } diff --git a/mollie/captures_test.go b/mollie/captures_test.go index 4c0a939c..b2617e1d 100644 --- a/mollie/captures_test.go +++ b/mollie/captures_test.go @@ -18,6 +18,7 @@ func TestCapturesService_Get(t *testing.T) { ctx context.Context payment string capture string + options *CaptureOptions } cases := []struct { @@ -34,6 +35,7 @@ func TestCapturesService_Get(t *testing.T) { context.Background(), "tr_WDqYK6vllg", "cpt_4qqhO89gsT", + nil, }, false, nil, @@ -48,12 +50,37 @@ func TestCapturesService_Get(t *testing.T) { }, noPre, }, + { + "get captures works expands query params correctly", + args{ + context.Background(), + "tr_WDqYK6vllg", + "cpt_4qqhO89gsT", + &CaptureOptions{ + Embed: []EmbedValue{EmbedPayment}, + }, + }, + false, + nil, + func(w http.ResponseWriter, r *http.Request) { + testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") + testMethod(t, r, "GET") + testQuery(t, r, "embed=payments") + if _, ok := r.Header[AuthHeader]; !ok { + w.WriteHeader(http.StatusUnauthorized) + } + + _, _ = w.Write([]byte(testdata.GetCaptureResponse)) + }, + noPre, + }, { "get captures returns an http error from the server", args{ context.Background(), "tr_WDqYK6vllg", "cpt_4qqhO89gsT", + nil, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -66,6 +93,7 @@ func TestCapturesService_Get(t *testing.T) { context.Background(), "tr_WDqYK6vllg", "cpt_4qqhO89gsT", + nil, }, true, errBadBaseURL, @@ -78,6 +106,7 @@ func TestCapturesService_Get(t *testing.T) { context.Background(), "tr_WDqYK6vllg", "cpt_4qqhO89gsT", + nil, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -102,7 +131,7 @@ func TestCapturesService_Get(t *testing.T) { c.handler, ) - res, capture, err := tClient.Captures.Get(c.args.ctx, c.args.payment, c.args.capture) + res, capture, err := tClient.Captures.Get(c.args.ctx, c.args.payment, c.args.capture, c.args.options) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) @@ -116,6 +145,152 @@ func TestCapturesService_Get(t *testing.T) { } } +func TestCapturesService_Create(t *testing.T) { + setEnv() + defer unsetEnv() + + type args struct { + ctx context.Context + payment string + capture CreateCapture + options *CaptureOptions + } + + cases := []struct { + name string + args args + wantErr bool + err error + handler http.HandlerFunc + pre func() + }{ + { + "create captures works as expected", + args{ + context.Background(), + "tr_WDqYK6vllg", + CreateCapture{ + Amount: &Amount{ + Value: "20.00", + Currency: "EUR", + }, + Description: "Order #12345", + }, + nil, + }, + false, + nil, + func(w http.ResponseWriter, r *http.Request) { + testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") + testMethod(t, r, "POST") + if _, ok := r.Header[AuthHeader]; !ok { + w.WriteHeader(http.StatusUnauthorized) + } + + _, _ = w.Write([]byte(testdata.CreateCaptureResponse)) + }, + noPre, + }, + { + "create captures works as with access token expected", + args{ + context.Background(), + "tr_WDqYK6vllg", + CreateCapture{ + Amount: &Amount{ + Value: "20.00", + Currency: "EUR", + }, + Description: "Order #12345", + }, + nil, + }, + false, + nil, + func(w http.ResponseWriter, r *http.Request) { + testHeader(t, r, AuthHeader, "Bearer access_token_test") + testMethod(t, r, "POST") + if _, ok := r.Header[AuthHeader]; !ok { + w.WriteHeader(http.StatusUnauthorized) + } + + _, _ = w.Write([]byte(testdata.CreateCaptureWithAccessTokenResponse)) + }, + setAccessToken, + }, + { + "create captures returns an http error from the server", + args{ + context.Background(), + "tr_WDqYK6vllg", + CreateCapture{}, + nil, + }, + true, + fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), + errorHandler, + noPre, + }, + { + "create captures returns an error when creating the request", + args{ + context.Background(), + "tr_WDqYK6vllg", + CreateCapture{}, + nil, + }, + true, + errBadBaseURL, + errorHandler, + crashSrv, + }, + { + "create captures returns an error when trying to parse the json response", + args{ + context.Background(), + "tr_WDqYK6vllg", + CreateCapture{}, + nil, + }, + true, + fmt.Errorf("invalid character 'h' looking for beginning of object key string"), + encodingHandler, + noPre, + }, + } + + for _, c := range cases { + setup() + defer teardown() + + t.Run(c.name, func(t *testing.T) { + c.pre() + + tMux.HandleFunc( + fmt.Sprintf( + "/v2/payments/%s/captures", + c.args.payment, + ), + c.handler, + ) + + res, capture, err := tClient.Captures.Create(c.args.ctx, c.args.payment, c.args.capture) + if c.wantErr { + assert.NotNil(t, err) + assert.EqualError(t, err, c.err.Error()) + if tClient.HasAccessToken() { + assert.True(t, capture.Testmode) + } + } else { + assert.Nil(t, err) + assert.IsType(t, &Capture{}, capture) + assert.EqualValues(t, c.args.ctx, res.Request.Context()) + assert.IsType(t, &http.Response{}, res.Response) + } + }) + } +} + func TestCapturesService_List(t *testing.T) { setEnv() defer unsetEnv() @@ -124,6 +299,7 @@ func TestCapturesService_List(t *testing.T) { ctx context.Context payment string capture string + options *CaptureOptions } type key string @@ -142,12 +318,17 @@ func TestCapturesService_List(t *testing.T) { context.Background(), "tr_WDqYK6vllg", "cpt_4qqhO89gsT", + &CaptureOptions{ + Embed: []EmbedValue{EmbedPayment}, + }, }, false, nil, func(w http.ResponseWriter, r *http.Request) { testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") testMethod(t, r, "GET") + testQuery(t, r, "embed=payments") + if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) } @@ -162,6 +343,7 @@ func TestCapturesService_List(t *testing.T) { context.WithValue(context.Background(), key("test"), "test-value"), "tr_WDqYK6vllg", "cpt_4qqhO89gsT", + &CaptureOptions{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -174,6 +356,7 @@ func TestCapturesService_List(t *testing.T) { context.Background(), "tr_WDqYK6vllg", "cpt_4qqhO89gsT", + &CaptureOptions{}, }, true, errBadBaseURL, @@ -186,6 +369,7 @@ func TestCapturesService_List(t *testing.T) { context.Background(), "tr_WDqYK6vllg", "cpt_4qqhO89gsT", + &CaptureOptions{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -209,7 +393,7 @@ func TestCapturesService_List(t *testing.T) { c.handler, ) - res, list, err := tClient.Captures.List(c.args.ctx, c.args.payment) + res, list, err := tClient.Captures.List(c.args.ctx, c.args.payment, c.args.options) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) diff --git a/testdata/captures.go b/testdata/captures.go index 616a605d..d28e7892 100644 --- a/testdata/captures.go +++ b/testdata/captures.go @@ -100,3 +100,60 @@ const GetCaptureResponse = `{ } } }` + +// CreateCaptureResponse example. +const CreateCaptureResponse = `{ + "resource": "capture", + "id": "cpt_mNepDkEtco6ah3QNPUGYH", + "mode": "live", + "amount": { + "value": "35.95", + "currency": "EUR" + }, + "paymentId": "tr_WDqYK6vllg", + "createdAt": "2018-08-02T09:29:56+00:00", + "description": "Capture for cart #12345", + "_links": { + "self": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/captures/cpt_mNepDkEtco6ah3QNPUGYH", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/captures-api/create-capture", + "type": "text/html" + } + } +}` + +// CreateCaptureWithAccessTokenResponse example. +const CreateCaptureWithAccessTokenResponse = `{ + "resource": "capture", + "id": "cpt_mNepDkEtco6ah3QNPUGYH", + "mode": "live", + "amount": { + "value": "35.95", + "currency": "EUR" + }, + "paymentId": "tr_WDqYK6vllg", + "createdAt": "2018-08-02T09:29:56+00:00", + "description": "Capture for cart #12345", + "testmode": true, + "_links": { + "self": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/captures/cpt_mNepDkEtco6ah3QNPUGYH", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/captures-api/create-capture", + "type": "text/html" + } + } +}` From a0a7a36896e7a8bbd4b8243e739cb0df61ec0b6b Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Sun, 3 Mar 2024 22:56:59 +0100 Subject: [PATCH 05/23] check chargebacks resource against api reference (#331) --- Taskfile.yml | 2 + docs/README.md | 86 +++++++++++++++++++++++++------------- mollie/captures.go | 2 +- mollie/chargebacks.go | 46 +++++++++++++------- mollie/chargebacks_test.go | 8 ++-- testdata/chargebacks.go | 6 ++- 6 files changed, 99 insertions(+), 51 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 106be01f..de819ea3 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -64,6 +64,8 @@ tasks: update-docs: cmds: - gomarkdoc --output docs/README.md ./mollie + - git add --all + - "git commit --message 'chore(docs): update generated docs'" silent: false sub-pkg-docs: diff --git a/docs/README.md b/docs/README.md index 81da279a..b7bf8ebf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -63,12 +63,14 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CapturesService](<#CapturesService>) - [func \(cs \*CapturesService\) Create\(ctx context.Context, payment string, capture CreateCapture\) \(res \*Response, c \*Capture, err error\)](<#CapturesService.Create>) - [func \(cs \*CapturesService\) Get\(ctx context.Context, payment, capture string, options \*CaptureOptions\) \(res \*Response, c \*Capture, err error\)](<#CapturesService.Get>) - - [func \(cs \*CapturesService\) List\(ctx context.Context, payment string\) \(res \*Response, cl \*CapturesList, err error\)](<#CapturesService.List>) + - [func \(cs \*CapturesService\) List\(ctx context.Context, payment string, options \*CaptureOptions\) \(res \*Response, cl \*CapturesList, err error\)](<#CapturesService.List>) - [type CardLabel](<#CardLabel>) - [type CategoryCode](<#CategoryCode>) - [type Chargeback](<#Chargeback>) +- [type ChargebackAccessTokenFields](<#ChargebackAccessTokenFields>) - [type ChargebackLinks](<#ChargebackLinks>) - [type ChargebackOptions](<#ChargebackOptions>) +- [type ChargebackReason](<#ChargebackReason>) - [type ChargebacksList](<#ChargebacksList>) - [type ChargebacksListOptions](<#ChargebacksListOptions>) - [type ChargebacksService](<#ChargebacksService>) @@ -1010,7 +1012,7 @@ type Capture struct { CreatedAt *time.Time `json:"createdAt,omitempty"` Metadata any `json:"metadata,omitempty"` Links CaptureLinks `json:"_links,omitempty"` - AccessTokenPaymentFields + CaptureAccessTokenFields } ``` @@ -1137,10 +1139,10 @@ Get retrieves a single capture by its ID. Note the original payment’s ID is ne See: https://docs.mollie.com/reference/v2/captures-api/get-capture -### func \(\*CapturesService\) [List]() +### func \(\*CapturesService\) [List]() ```go -func (cs *CapturesService) List(ctx context.Context, payment string) (res *Response, cl *CapturesList, err error) +func (cs *CapturesService) List(ctx context.Context, payment string, options *CaptureOptions) (res *Response, cl *CapturesList, err error) ``` List retrieves all captures for a certain payment. @@ -1214,25 +1216,39 @@ const ( ``` -## type [Chargeback]() +## type [Chargeback]() Chargeback describes a forced transaction reversal initiated by the cardholder's bank. ```go type Chargeback struct { - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - Amount *Amount `json:"amount,omitempty"` - SettlementAmount *Amount `json:"settlementAmount,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - ReversedAt *time.Time `json:"reversedAt,omitempty"` - PaymentID string `json:"paymentId,omitempty"` - Links ChargebackLinks `json:"_links,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + PaymentID string `json:"paymentId,omitempty"` + Amount *Amount `json:"amount,omitempty"` + SettlementAmount *Amount `json:"settlementAmount,omitempty"` + Reason *ChargebackReason `json:"reason,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + ReversedAt *time.Time `json:"reversedAt,omitempty"` + Links ChargebackLinks `json:"_links,omitempty"` + ChargebackAccessTokenFields +} +``` + + +## type [ChargebackAccessTokenFields]() + +ChargebackAccessTokenFields describes the fields to be used to create a chargeback access token. + +```go +type ChargebackAccessTokenFields struct { + ProfileID string `json:"profileId,omitempty"` + Testmode bool `json:"testmode,omitempty"` } ``` -## type [ChargebackLinks]() +## type [ChargebackLinks]() ChargebackLinks describes all the possible links to be returned with a chargeback object. @@ -1246,19 +1262,31 @@ type ChargebackLinks struct { ``` -## type [ChargebackOptions]() +## type [ChargebackOptions]() ChargebackOptions describes chargeback endpoint valid query string parameters. ```go type ChargebackOptions struct { - Include string `url:"include,omitempty"` - Embed string `url:"embed,omitempty"` + Include []IncludeValue `url:"include,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` +} +``` + + +## type [ChargebackReason]() + +ChargebackReason describes the reason for the chargeback as given by the bank. + +```go +type ChargebackReason struct { + Code string `json:"code,omitempty"` + Description string `json:"description,omitempty"` } ``` -## type [ChargebacksList]() +## type [ChargebacksList]() ChargebacksList describes how a list of chargebacks will be retrieved by Mollie. @@ -1266,29 +1294,29 @@ ChargebacksList describes how a list of chargebacks will be retrieved by Mollie. type ChargebacksList struct { Count int `json:"count,omitempty"` Embedded struct { - Chargebacks []Chargeback + Chargebacks []*Chargeback } `json:"_embedded,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } ``` -## type [ChargebacksListOptions]() +## type [ChargebacksListOptions]() ChargebacksListOptions describes list chargebacks endpoint valid query string parameters. ```go type ChargebacksListOptions struct { - From string `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - Include string `url:"include,omitempty"` - Embed string `url:"embed,omitempty"` - ProfileID string `url:"profileId,omitempty"` + From string `url:"from,omitempty"` + Limit int `url:"limit,omitempty"` + Include []IncludeValue `url:"include,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` + ProfileID string `url:"profileId,omitempty"` } ``` -## type [ChargebacksService]() +## type [ChargebacksService]() ChargebacksService instance operates over chargeback resources. @@ -1297,7 +1325,7 @@ type ChargebacksService service ``` -### func \(\*ChargebacksService\) [Get]() +### func \(\*ChargebacksService\) [Get]() ```go func (cs *ChargebacksService) Get(ctx context.Context, payment, chargeback string, opts *ChargebackOptions) (res *Response, p *Chargeback, err error) @@ -1308,7 +1336,7 @@ Get retrieves a single chargeback by its ID. Note the original payment’s ID is See: https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback -### func \(\*ChargebacksService\) [List]() +### func \(\*ChargebacksService\) [List]() ```go func (cs *ChargebacksService) List(ctx context.Context, options *ChargebacksListOptions) (res *Response, cl *ChargebacksList, err error) @@ -1319,7 +1347,7 @@ List retrieves a list of chargebacks associated with your account/organization. See: https://docs.mollie.com/reference/v2/chargebacks-api/list-chargebacks -### func \(\*ChargebacksService\) [ListForPayment]() +### func \(\*ChargebacksService\) [ListForPayment]() ```go func (cs *ChargebacksService) ListForPayment(ctx context.Context, payment string, options *ChargebacksListOptions) (res *Response, cl *ChargebacksList, err error) diff --git a/mollie/captures.go b/mollie/captures.go index 50936be0..b251a600 100644 --- a/mollie/captures.go +++ b/mollie/captures.go @@ -54,7 +54,7 @@ type Capture struct { CreatedAt *time.Time `json:"createdAt,omitempty"` Metadata any `json:"metadata,omitempty"` Links CaptureLinks `json:"_links,omitempty"` - AccessTokenPaymentFields + CaptureAccessTokenFields } // CaptureLinks contains relevant links for a capture object. diff --git a/mollie/chargebacks.go b/mollie/chargebacks.go index 39c868ee..834ac279 100644 --- a/mollie/chargebacks.go +++ b/mollie/chargebacks.go @@ -9,14 +9,28 @@ import ( // Chargeback describes a forced transaction reversal initiated by the cardholder's bank. type Chargeback struct { - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - Amount *Amount `json:"amount,omitempty"` - SettlementAmount *Amount `json:"settlementAmount,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - ReversedAt *time.Time `json:"reversedAt,omitempty"` - PaymentID string `json:"paymentId,omitempty"` - Links ChargebackLinks `json:"_links,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + PaymentID string `json:"paymentId,omitempty"` + Amount *Amount `json:"amount,omitempty"` + SettlementAmount *Amount `json:"settlementAmount,omitempty"` + Reason *ChargebackReason `json:"reason,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + ReversedAt *time.Time `json:"reversedAt,omitempty"` + Links ChargebackLinks `json:"_links,omitempty"` + ChargebackAccessTokenFields +} + +// ChargebackReason describes the reason for the chargeback as given by the bank. +type ChargebackReason struct { + Code string `json:"code,omitempty"` + Description string `json:"description,omitempty"` +} + +// ChargebackAccessTokenFields describes the fields to be used to create a chargeback access token. +type ChargebackAccessTokenFields struct { + ProfileID string `json:"profileId,omitempty"` + Testmode bool `json:"testmode,omitempty"` } // ChargebackLinks describes all the possible links to be returned with @@ -30,24 +44,24 @@ type ChargebackLinks struct { // ChargebackOptions describes chargeback endpoint valid query string parameters. type ChargebackOptions struct { - Include string `url:"include,omitempty"` - Embed string `url:"embed,omitempty"` + Include []IncludeValue `url:"include,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` } // ChargebacksListOptions describes list chargebacks endpoint valid query string parameters. type ChargebacksListOptions struct { - From string `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - Include string `url:"include,omitempty"` - Embed string `url:"embed,omitempty"` - ProfileID string `url:"profileId,omitempty"` + From string `url:"from,omitempty"` + Limit int `url:"limit,omitempty"` + Include []IncludeValue `url:"include,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` + ProfileID string `url:"profileId,omitempty"` } // ChargebacksList describes how a list of chargebacks will be retrieved by Mollie. type ChargebacksList struct { Count int `json:"count,omitempty"` Embedded struct { - Chargebacks []Chargeback + Chargebacks []*Chargeback } `json:"_embedded,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } diff --git a/mollie/chargebacks_test.go b/mollie/chargebacks_test.go index 2887b099..83999875 100644 --- a/mollie/chargebacks_test.go +++ b/mollie/chargebacks_test.go @@ -37,7 +37,7 @@ func TestChargebacksService_Get(t *testing.T) { "tr_WDqYK6vllg", "chb_n9z0tp", &ChargebackOptions{ - Include: "details.qrCode", + Include: []IncludeValue{IncludeQrCode}, }, }, false, @@ -60,7 +60,7 @@ func TestChargebacksService_Get(t *testing.T) { "tr_WDqYK6vllg", "chb_n9z0tp", &ChargebackOptions{ - Include: "details.qrCode", + Include: []IncludeValue{IncludeQrCode}, }, }, true, @@ -75,7 +75,7 @@ func TestChargebacksService_Get(t *testing.T) { "tr_WDqYK6vllg", "chb_n9z0tp", &ChargebackOptions{ - Include: "details.qrCode", + Include: []IncludeValue{IncludeQrCode}, }, }, true, @@ -93,7 +93,7 @@ func TestChargebacksService_Get(t *testing.T) { "tr_WDqYK6vllg", "chb_n9z0tp", &ChargebackOptions{ - Include: "details.qrCode", + Include: []IncludeValue{IncludeQrCode}, }, }, true, diff --git a/testdata/chargebacks.go b/testdata/chargebacks.go index 38a6d06c..aac830e7 100644 --- a/testdata/chargebacks.go +++ b/testdata/chargebacks.go @@ -13,6 +13,10 @@ const ( "value": "-35.07" }, "createdAt": "2018-03-14T17:00:52.0Z", + "reason": { + "code": "AC01", + "description": "Account identifier incorrect (i.e. invalid IBAN)" + }, "reversedAt": null, "paymentId": "tr_WDqYK6vllg", "_links": { @@ -25,7 +29,7 @@ const ( "type": "application/hal+json" }, "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", + "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-payment-chargeback", "type": "text/html" } } From a74c8f610ce034f13fbebb9f02ea0e5d937ea1dd Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:28:58 +0100 Subject: [PATCH 06/23] check client_links resources against api reference (#333) --- docs/README.md | 78 ++++++++++++++++++------------------- mollie/client_links.go | 33 ++++++++-------- mollie/client_links_test.go | 47 ++++++++++++---------- mollie/permissions.go | 2 +- 4 files changed, 83 insertions(+), 77 deletions(-) diff --git a/docs/README.md b/docs/README.md index b7bf8ebf..0418b941 100644 --- a/docs/README.md +++ b/docs/README.md @@ -84,13 +84,12 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(c \*Client\) NewAPIRequest\(ctx context.Context, method string, uri string, body interface\{\}\) \(req \*http.Request, err error\)](<#Client.NewAPIRequest>) - [func \(c \*Client\) SetIdempotencyKeyGenerator\(kg idempotency.KeyGenerator\)](<#Client.SetIdempotencyKeyGenerator>) - [func \(c \*Client\) WithAuthenticationValue\(k string\) error](<#Client.WithAuthenticationValue>) -- [type ClientDetails](<#ClientDetails>) - [type ClientLink](<#ClientLink>) -- [type ClientLinkFinalizeOptions](<#ClientLinkFinalizeOptions>) +- [type ClientLinkAuthorizeOptions](<#ClientLinkAuthorizeOptions>) - [type ClientLinkLinks](<#ClientLinkLinks>) - [type ClientLinksService](<#ClientLinksService>) - - [func \(cls \*ClientLinksService\) CreateClientLink\(ctx context.Context, cd \*ClientDetails\) \(res \*Response, cl \*ClientLink, err error\)](<#ClientLinksService.CreateClientLink>) - - [func \(cls \*ClientLinksService\) CreateFinalizeClientLink\(ctx context.Context, clientLink string, options \*ClientLinkFinalizeOptions\) \(clientLinkURI string\)](<#ClientLinksService.CreateFinalizeClientLink>) + - [func \(cls \*ClientLinksService\) Create\(ctx context.Context, cd CreateClientLink\) \(res \*Response, cl \*ClientLink, err error\)](<#ClientLinksService.Create>) + - [func \(cls \*ClientLinksService\) GetFinalClientLink\(ctx context.Context, clientLink string, options \*ClientLinkAuthorizeOptions\) \(clientLinkURI string\)](<#ClientLinksService.GetFinalClientLink>) - [type Commission](<#Commission>) - [type Company](<#Company>) - [type Config](<#Config>) @@ -106,6 +105,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type ContextValues](<#ContextValues>) - [func \(cv \*ContextValues\) UnmarshalJSON\(data \[\]byte\) error](<#ContextValues.UnmarshalJSON>) - [type CreateCapture](<#CreateCapture>) +- [type CreateClientLink](<#CreateClientLink>) - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) - [type CreatePayment](<#CreatePayment>) - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) @@ -1457,23 +1457,8 @@ WithAuthenticationValue offers a convenient setter for any of the valid authenti Ideally your API key will be provided from and environment variable or a secret management engine. This should only be used when environment variables are "impossible" to be used. - -## type [ClientDetails]() - -ClientDetails contains information to link a new organization to an OAuth application. - -```go -type ClientDetails struct { - Owner Owner `json:"owner,omitempty"` - Name string `json:"name,omitempty"` - Address *Address `json:"address,omitempty"` - RegistrationNumber string `json:"registrationNumber,omitempty"` - VATNumber string `json:"vatNumber,omitempty"` -} -``` - -## type [ClientLink]() +## type [ClientLink]() ClientLink object with redirect target. @@ -1485,22 +1470,22 @@ type ClientLink struct { } ``` - -## type [ClientLinkFinalizeOptions]() + +## type [ClientLinkAuthorizeOptions]() -ClientLinkFinalizeOptions subset of the parameters allowed for the Authorize endpoint. +ClientLinkAuthorizeOptions subset of the parameters allowed for the Authorize endpoint. ```go -type ClientLinkFinalizeOptions struct { - ClientID string `url:"clientID,omitempty"` - State string `url:"state,omitempty"` - Scope string `url:"scope,omitempty"` - ApprovalPrompt string `url:"approvalPrompt,omitempty"` +type ClientLinkAuthorizeOptions struct { + ClientID string `url:"clientId,omitempty"` + State string `url:"state,omitempty"` + Scope []PermissionGrant `del:"+" url:"scope,omitempty"` + ApprovalPrompt ApprovalPromptAction `url:"approvalPrompt,omitempty"` } ``` -## type [ClientLinkLinks]() +## type [ClientLinkLinks]() ClientLinkLinks describes all the possible links to be returned with a client links response object. @@ -1512,7 +1497,7 @@ type ClientLinkLinks struct { ``` -## type [ClientLinksService]() +## type [ClientLinksService]() ClientLinksService interacts with the Client Links API to create new organizations for your customers. @@ -1520,25 +1505,25 @@ ClientLinksService interacts with the Client Links API to create new organizatio type ClientLinksService service ``` - -### func \(\*ClientLinksService\) [CreateClientLink]() + +### func \(\*ClientLinksService\) [Create]() ```go -func (cls *ClientLinksService) CreateClientLink(ctx context.Context, cd *ClientDetails) (res *Response, cl *ClientLink, err error) +func (cls *ClientLinksService) Create(ctx context.Context, cd CreateClientLink) (res *Response, cl *ClientLink, err error) ``` -CreateClientLink based on the provided ClientDetails. +Create a client link based on the provided CreateClientLink values. See: https://docs.mollie.com/reference/v2/client-links-api/create-client-link - -### func \(\*ClientLinksService\) [CreateFinalizeClientLink]() + +### func \(\*ClientLinksService\) [GetFinalClientLink]() ```go -func (cls *ClientLinksService) CreateFinalizeClientLink(ctx context.Context, clientLink string, options *ClientLinkFinalizeOptions) (clientLinkURI string) +func (cls *ClientLinksService) GetFinalClientLink(ctx context.Context, clientLink string, options *ClientLinkAuthorizeOptions) (clientLinkURI string) ``` - +GetFinalClientLink returns the final client link URI with the provided options. ## type [Commission]() @@ -1826,6 +1811,21 @@ type CreateCapture struct { } ``` + +## type [CreateClientLink]() + +CreateClientLink contains information to link a new organization to an OAuth application. + +```go +type CreateClientLink struct { + Owner Owner `json:"owner,omitempty"` + Name string `json:"name,omitempty"` + Address *Address `json:"address,omitempty"` + RegistrationNumber string `json:"registrationNumber,omitempty"` + VATNumber string `json:"vatNumber,omitempty"` +} +``` + ## type [CreateMollieConnectPaymentFields]() @@ -4251,7 +4251,7 @@ const ( ShipmentsWrite PermissionGrant = "shipments.write" OrganizationsRead PermissionGrant = "organizations.read" OrganizationsWrite PermissionGrant = "organizations.write" - OnboardingRead PermissionGrant = "onbording.read" + OnboardingRead PermissionGrant = "onboarding.read" OnboardingWrite PermissionGrant = "onbording.write" ) ``` diff --git a/mollie/client_links.go b/mollie/client_links.go index 36462936..a833132d 100644 --- a/mollie/client_links.go +++ b/mollie/client_links.go @@ -8,13 +8,9 @@ import ( "github.com/google/go-querystring/query" ) -// ClientLinksService interacts with the Client Links API to create -// new organizations for your customers. -type ClientLinksService service - -// ClientDetails contains information to link a new organization to an +// CreateClientLink contains information to link a new organization to an // OAuth application. -type ClientDetails struct { +type CreateClientLink struct { Owner Owner `json:"owner,omitempty"` Name string `json:"name,omitempty"` Address *Address `json:"address,omitempty"` @@ -36,10 +32,14 @@ type ClientLink struct { Links ClientLinkLinks `json:"_links,omitempty"` } -// CreateClientLink based on the provided ClientDetails. +// ClientLinksService interacts with the Client Links API to create +// new organizations for your customers. +type ClientLinksService service + +// Create a client link based on the provided CreateClientLink values. // // See: https://docs.mollie.com/reference/v2/client-links-api/create-client-link -func (cls *ClientLinksService) CreateClientLink(ctx context.Context, cd *ClientDetails) ( +func (cls *ClientLinksService) Create(ctx context.Context, cd CreateClientLink) ( res *Response, cl *ClientLink, err error, @@ -66,18 +66,19 @@ const ( AutoApproval ApprovalPromptAction = "auto" ) -// ClientLinkFinalizeOptions subset of the parameters allowed for the Authorize endpoint. -type ClientLinkFinalizeOptions struct { - ClientID string `url:"clientID,omitempty"` - State string `url:"state,omitempty"` - Scope string `url:"scope,omitempty"` - ApprovalPrompt string `url:"approvalPrompt,omitempty"` +// ClientLinkAuthorizeOptions subset of the parameters allowed for the Authorize endpoint. +type ClientLinkAuthorizeOptions struct { + ClientID string `url:"clientId,omitempty"` + State string `url:"state,omitempty"` + Scope []PermissionGrant `del:"+" url:"scope,omitempty"` + ApprovalPrompt ApprovalPromptAction `url:"approvalPrompt,omitempty"` } -func (cls *ClientLinksService) CreateFinalizeClientLink( +// GetFinalClientLink returns the final client link URI with the provided options. +func (cls *ClientLinksService) GetFinalClientLink( ctx context.Context, clientLink string, - options *ClientLinkFinalizeOptions, + options *ClientLinkAuthorizeOptions, ) ( clientLinkURI string, ) { diff --git a/mollie/client_links_test.go b/mollie/client_links_test.go index 624e01ae..66dd3f7f 100644 --- a/mollie/client_links_test.go +++ b/mollie/client_links_test.go @@ -10,13 +10,13 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCreateClientLink(t *testing.T) { +func TestClientLinkService_Create(t *testing.T) { setEnv() defer unsetEnv() type args struct { ctx context.Context - cd *ClientDetails + cd CreateClientLink } cases := []struct { @@ -31,7 +31,7 @@ func TestCreateClientLink(t *testing.T) { "create new client link", args{ context.Background(), - &ClientDetails{}, + CreateClientLink{}, }, false, nil, @@ -50,7 +50,7 @@ func TestCreateClientLink(t *testing.T) { "create client link, an error is returned from the server", args{ context.Background(), - &ClientDetails{}, + CreateClientLink{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -61,7 +61,7 @@ func TestCreateClientLink(t *testing.T) { "create client link, an error occurs when parsing json", args{ context.Background(), - &ClientDetails{}, + CreateClientLink{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -72,7 +72,7 @@ func TestCreateClientLink(t *testing.T) { "create client link, invalid url when building request", args{ context.Background(), - &ClientDetails{}, + CreateClientLink{}, }, true, errBadBaseURL, @@ -91,7 +91,7 @@ func TestCreateClientLink(t *testing.T) { ) c.pre() - res, cb, err := tClient.ClientLinks.CreateClientLink(c.args.ctx, c.args.cd) + res, cb, err := tClient.ClientLinks.Create(c.args.ctx, c.args.cd) if c.wantErr { assert.Error(t, err) assert.EqualError(t, err, c.err.Error()) @@ -105,11 +105,14 @@ func TestCreateClientLink(t *testing.T) { } } -func TestCreateFinalizeClientLink(t *testing.T) { +func TestClientLinkService_GetFinalClientLink(t *testing.T) { + setEnv() + defer unsetEnv() + type args struct { ctx context.Context clientLink string - options *ClientLinkFinalizeOptions + options *ClientLinkAuthorizeOptions } tests := []struct { name string @@ -121,43 +124,45 @@ func TestCreateFinalizeClientLink(t *testing.T) { args{ context.Background(), "https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH", - &ClientLinkFinalizeOptions{ + &ClientLinkAuthorizeOptions{ ClientID: "app_j9Pakf56Ajta6Y65AkdTtAv", - State: "decafbad", - Scope: "onboarding.read+organization.read+payments.write+payments.read+profiles.write", + State: "unique_string_to_compare", + Scope: []PermissionGrant{OnboardingRead, OnboardingWrite}, }, }, - "https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH?clientID=app_j9Pakf56Ajta6Y65AkdTtAv&scope=onboarding.read%2Borganization.read%2Bpayments.write%2Bpayments.read%2Bprofiles.write&state=decafbad", + "https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH?clientId=app_j9Pakf56Ajta6Y65AkdTtAv&scope=onboarding.read%2Bonbording.write&state=unique_string_to_compare", }, { "constructs client link finalize with complex values", args{ context.Background(), "https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH", - &ClientLinkFinalizeOptions{ + &ClientLinkAuthorizeOptions{ ClientID: "", State: "\ns\\s\\s\\s\n", - Scope: "", + Scope: []PermissionGrant{}, }, }, "https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH?state=%0As%5Cs%5Cs%5Cs%0A", }, { - "constructs client link finalize with complex values", + "constructs client link finalize with no query params", args{ context.Background(), "https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH", - &ClientLinkFinalizeOptions{}, + &ClientLinkAuthorizeOptions{}, }, "https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH?", }, } + + setup() + defer teardown() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotClientLinkURI := tClient.ClientLinks.CreateFinalizeClientLink(tt.args.ctx, tt.args.clientLink, tt.args.options) - if gotClientLinkURI != tt.wantClientLinkURI { - t.Errorf("ClientLinksService.CreateFinalizeClientLink() = %v, want %v", gotClientLinkURI, tt.wantClientLinkURI) - } + gotClientLinkURI := tClient.ClientLinks.GetFinalClientLink(tt.args.ctx, tt.args.clientLink, tt.args.options) + + assert.Equal(t, tt.wantClientLinkURI, gotClientLinkURI) }) } } diff --git a/mollie/permissions.go b/mollie/permissions.go index 8822d7cb..9e44e308 100644 --- a/mollie/permissions.go +++ b/mollie/permissions.go @@ -30,7 +30,7 @@ const ( ShipmentsWrite PermissionGrant = "shipments.write" OrganizationsRead PermissionGrant = "organizations.read" OrganizationsWrite PermissionGrant = "organizations.write" - OnboardingRead PermissionGrant = "onbording.read" + OnboardingRead PermissionGrant = "onboarding.read" OnboardingWrite PermissionGrant = "onbording.write" ) From ff042f4f4d0909fb7806c94d526b59d38b24cdcb Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Wed, 6 Mar 2024 20:44:29 +0100 Subject: [PATCH 07/23] check customers resource against api reference (#334) --- docs/README.md | 68 +++++++++++++++++++++++++++++----------- mollie/customers.go | 30 +++++++++++++----- mollie/customers_test.go | 20 ++++++------ mollie/payments.go | 2 +- 4 files changed, 83 insertions(+), 37 deletions(-) diff --git a/docs/README.md b/docs/README.md index 0418b941..f9cdcfcb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -106,6 +106,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(cv \*ContextValues\) UnmarshalJSON\(data \[\]byte\) error](<#ContextValues.UnmarshalJSON>) - [type CreateCapture](<#CreateCapture>) - [type CreateClientLink](<#CreateClientLink>) +- [type CreateCustomer](<#CreateCustomer>) - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) - [type CreatePayment](<#CreatePayment>) - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) @@ -117,13 +118,13 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CustomersList](<#CustomersList>) - [type CustomersListOptions](<#CustomersListOptions>) - [type CustomersService](<#CustomersService>) - - [func \(cs \*CustomersService\) Create\(ctx context.Context, c Customer\) \(res \*Response, cc \*Customer, err error\)](<#CustomersService.Create>) + - [func \(cs \*CustomersService\) Create\(ctx context.Context, c CreateCustomer\) \(res \*Response, cc \*Customer, err error\)](<#CustomersService.Create>) - [func \(cs \*CustomersService\) CreatePayment\(ctx context.Context, id string, p CreatePayment\) \(res \*Response, pp \*Payment, err error\)](<#CustomersService.CreatePayment>) - [func \(cs \*CustomersService\) Delete\(ctx context.Context, id string\) \(res \*Response, err error\)](<#CustomersService.Delete>) - [func \(cs \*CustomersService\) Get\(ctx context.Context, id string\) \(res \*Response, c \*Customer, err error\)](<#CustomersService.Get>) - [func \(cs \*CustomersService\) GetPayments\(ctx context.Context, id string, options \*CustomersListOptions\) \(res \*Response, pl \*PaymentList, err error\)](<#CustomersService.GetPayments>) - [func \(cs \*CustomersService\) List\(ctx context.Context, options \*CustomersListOptions\) \(res \*Response, cl \*CustomersList, err error\)](<#CustomersService.List>) - - [func \(cs \*CustomersService\) Update\(ctx context.Context, id string, c Customer\) \(res \*Response, cc \*Customer, err error\)](<#CustomersService.Update>) + - [func \(cs \*CustomersService\) Update\(ctx context.Context, id string, c UpdateCustomer\) \(res \*Response, cc \*Customer, err error\)](<#CustomersService.Update>) - [type EligibilityReasons](<#EligibilityReasons>) - [type EmbedValue](<#EmbedValue>) - [type EntityType](<#EntityType>) @@ -355,6 +356,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type TransferDestination](<#TransferDestination>) - [type TransferFrequency](<#TransferFrequency>) - [type URL](<#URL>) +- [type UpdateCustomer](<#UpdateCustomer>) - [type UpdatePayment](<#UpdatePayment>) - [type UsedGiftCard](<#UsedGiftCard>) - [type UserAgentToken](<#UserAgentToken>) @@ -1826,6 +1828,20 @@ type CreateClientLink struct { } ``` + +## type [CreateCustomer]() + +CreateCustomer contains the parameters to create a customer. + +```go +type CreateCustomer struct { + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Locale Locale `json:"locale,omitempty"` + Metadata any `json:"metadata,omitempty"` +} +``` + ## type [CreateMollieConnectPaymentFields]() @@ -1945,7 +1961,7 @@ type CreateShipmentRequest struct { ``` -## type [Customer]() +## type [Customer]() Customer represents buyers. @@ -1957,30 +1973,30 @@ type Customer struct { Name string `json:"name,omitempty"` Email string `json:"email,omitempty"` Locale Locale `json:"locale,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` + Metadata any `json:"metadata,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` Links CustomerLinks `json:"_links,omitempty"` } ``` -## type [CustomerLinks]() +## type [CustomerLinks]() CustomerLinks contains the HAL resources for a customer response. ```go type CustomerLinks struct { Self *URL `json:"self,omitempty"` + Dashboard *URL `json:"dashboard,omitempty"` Mandates *URL `json:"mandates,omitempty"` Subscriptions *URL `json:"subscriptions,omitempty"` Payments *URL `json:"payments,omitempty"` Documentation *URL `json:"documentation,omitempty"` - Dashboard *URL `json:"dashboard,omitempty"` } ``` -## type [CustomersList]() +## type [CustomersList]() CustomersList contains a embedded list of customers wrapped in a standard Mollie paginated response. @@ -1988,14 +2004,14 @@ CustomersList contains a embedded list of customers wrapped in a standard Mollie type CustomersList struct { Count int `json:"count,omitempty"` Embedded struct { - Customers []Customer `json:"customers,omitempty"` + Customers []*Customer `json:"customers,omitempty"` } `json:"_embedded,omitempty"` Links PaginationLinks `json:"links,omitempty"` } ``` -## type [CustomersListOptions]() +## type [CustomersListOptions]() CustomersListOptions contains valid query parameters for the list customers endpoint. @@ -2010,7 +2026,7 @@ type CustomersListOptions struct { ``` -## type [CustomersService]() +## type [CustomersService]() CustomersService operates over the customer resource. @@ -2019,10 +2035,10 @@ type CustomersService service ``` -### func \(\*CustomersService\) [Create]() +### func \(\*CustomersService\) [Create]() ```go -func (cs *CustomersService) Create(ctx context.Context, c Customer) (res *Response, cc *Customer, err error) +func (cs *CustomersService) Create(ctx context.Context, c CreateCustomer) (res *Response, cc *Customer, err error) ``` Create creates a simple minimal representation of a customer in the Mollie API to use for the Mollie Checkout and Recurring features. @@ -2030,7 +2046,7 @@ Create creates a simple minimal representation of a customer in the Mollie API t See: https://docs.mollie.com/reference/v2/customers-api/create-customer -### func \(\*CustomersService\) [CreatePayment]() +### func \(\*CustomersService\) [CreatePayment]() ```go func (cs *CustomersService) CreatePayment(ctx context.Context, id string, p CreatePayment) (res *Response, pp *Payment, err error) @@ -2041,7 +2057,7 @@ CreatePayment creates a payment for the customer. See: https://docs.mollie.com/reference/v2/customers-api/create-customer-payment -### func \(\*CustomersService\) [Delete]() +### func \(\*CustomersService\) [Delete]() ```go func (cs *CustomersService) Delete(ctx context.Context, id string) (res *Response, err error) @@ -2054,7 +2070,7 @@ All mandates and subscriptions created for this customer will be canceled as wel See: https://docs.mollie.com/reference/v2/customers-api/delete-customer -### func \(\*CustomersService\) [Get]() +### func \(\*CustomersService\) [Get]() ```go func (cs *CustomersService) Get(ctx context.Context, id string) (res *Response, c *Customer, err error) @@ -2065,7 +2081,7 @@ Get finds a customer by its ID. See: https://docs.mollie.com/reference/v2/customers-api/get-customer -### func \(\*CustomersService\) [GetPayments]() +### func \(\*CustomersService\) [GetPayments]() ```go func (cs *CustomersService) GetPayments(ctx context.Context, id string, options *CustomersListOptions) (res *Response, pl *PaymentList, err error) @@ -2076,7 +2092,7 @@ GetPayments retrieves all payments linked to the customer. See: https://docs.mollie.com/reference/v2/customers-api/list-customer-payments -### func \(\*CustomersService\) [List]() +### func \(\*CustomersService\) [List]() ```go func (cs *CustomersService) List(ctx context.Context, options *CustomersListOptions) (res *Response, cl *CustomersList, err error) @@ -2087,10 +2103,10 @@ List retrieves all customers created. See: https://docs.mollie.com/reference/v2/customers-api/list-customers -### func \(\*CustomersService\) [Update]() +### func \(\*CustomersService\) [Update]() ```go -func (cs *CustomersService) Update(ctx context.Context, id string, c Customer) (res *Response, cc *Customer, err error) +func (cs *CustomersService) Update(ctx context.Context, id string, c UpdateCustomer) (res *Response, cc *Customer, err error) ``` Update an existing customer. @@ -5546,6 +5562,20 @@ type URL struct { } ``` + +## type [UpdateCustomer]() + +UpdateCustomer contains the parameters to update a customer. + +```go +type UpdateCustomer struct { + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Locale Locale `json:"locale,omitempty"` + Metadata any `json:"metadata,omitempty"` +} +``` + ## type [UpdatePayment]() diff --git a/mollie/customers.go b/mollie/customers.go index 486aa377..a3e67397 100644 --- a/mollie/customers.go +++ b/mollie/customers.go @@ -7,17 +7,30 @@ import ( "time" ) -// CustomersService operates over the customer resource. -type CustomersService service +// CreateCustomer contains the parameters to create a customer. +type CreateCustomer struct { + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Locale Locale `json:"locale,omitempty"` + Metadata any `json:"metadata,omitempty"` +} + +// UpdateCustomer contains the parameters to update a customer. +type UpdateCustomer struct { + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Locale Locale `json:"locale,omitempty"` + Metadata any `json:"metadata,omitempty"` +} // CustomerLinks contains the HAL resources for a customer response. type CustomerLinks struct { Self *URL `json:"self,omitempty"` + Dashboard *URL `json:"dashboard,omitempty"` Mandates *URL `json:"mandates,omitempty"` Subscriptions *URL `json:"subscriptions,omitempty"` Payments *URL `json:"payments,omitempty"` Documentation *URL `json:"documentation,omitempty"` - Dashboard *URL `json:"dashboard,omitempty"` } // Customer represents buyers. @@ -28,7 +41,7 @@ type Customer struct { Name string `json:"name,omitempty"` Email string `json:"email,omitempty"` Locale Locale `json:"locale,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` + Metadata any `json:"metadata,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` Links CustomerLinks `json:"_links,omitempty"` } @@ -47,11 +60,14 @@ type CustomersListOptions struct { type CustomersList struct { Count int `json:"count,omitempty"` Embedded struct { - Customers []Customer `json:"customers,omitempty"` + Customers []*Customer `json:"customers,omitempty"` } `json:"_embedded,omitempty"` Links PaginationLinks `json:"links,omitempty"` } +// CustomersService operates over the customer resource. +type CustomersService service + // Get finds a customer by its ID. // // See: https://docs.mollie.com/reference/v2/customers-api/get-customer @@ -74,7 +90,7 @@ func (cs *CustomersService) Get(ctx context.Context, id string) (res *Response, // to use for the Mollie Checkout and Recurring features. // // See: https://docs.mollie.com/reference/v2/customers-api/create-customer -func (cs *CustomersService) Create(ctx context.Context, c Customer) (res *Response, cc *Customer, err error) { +func (cs *CustomersService) Create(ctx context.Context, c CreateCustomer) (res *Response, cc *Customer, err error) { res, err = cs.client.post(ctx, "v2/customers", c, nil) if err != nil { return @@ -90,7 +106,7 @@ func (cs *CustomersService) Create(ctx context.Context, c Customer) (res *Respon // Update an existing customer. // // See: https://docs.mollie.com/reference/v2/customers-api/update-customer -func (cs *CustomersService) Update(ctx context.Context, id string, c Customer) ( +func (cs *CustomersService) Update(ctx context.Context, id string, c UpdateCustomer) ( res *Response, cc *Customer, err error, diff --git a/mollie/customers_test.go b/mollie/customers_test.go index 9863ab29..86e6b442 100644 --- a/mollie/customers_test.go +++ b/mollie/customers_test.go @@ -106,7 +106,7 @@ func TestCustomersService_Create(t *testing.T) { defer unsetEnv() type args struct { ctx context.Context - customer Customer + customer CreateCustomer } cases := []struct { @@ -123,7 +123,7 @@ func TestCustomersService_Create(t *testing.T) { http.StatusAccepted, args{ context.Background(), - Customer{Locale: German}, + CreateCustomer{Locale: German}, }, false, nil, @@ -143,7 +143,7 @@ func TestCustomersService_Create(t *testing.T) { http.StatusInternalServerError, args{ context.Background(), - Customer{}, + CreateCustomer{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -155,7 +155,7 @@ func TestCustomersService_Create(t *testing.T) { http.StatusInternalServerError, args{ context.Background(), - Customer{}, + CreateCustomer{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -167,7 +167,7 @@ func TestCustomersService_Create(t *testing.T) { http.StatusInternalServerError, args{ context.Background(), - Customer{}, + CreateCustomer{}, }, true, errBadBaseURL, @@ -203,7 +203,7 @@ func TestCustomersService_Update(t *testing.T) { type args struct { ctx context.Context customerID string - customer Customer + customer UpdateCustomer } cases := []struct { @@ -221,7 +221,7 @@ func TestCustomersService_Update(t *testing.T) { args{ context.Background(), "cst_kEn1PlbGa", - Customer{Locale: French}, + UpdateCustomer{Locale: French}, }, false, nil, @@ -242,7 +242,7 @@ func TestCustomersService_Update(t *testing.T) { args{ context.Background(), "cst_kEn1PlbGa", - Customer{}, + UpdateCustomer{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -255,7 +255,7 @@ func TestCustomersService_Update(t *testing.T) { args{ context.Background(), "cst_kEn1PlbGa", - Customer{}, + UpdateCustomer{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -268,7 +268,7 @@ func TestCustomersService_Update(t *testing.T) { args{ context.Background(), "cst_kEn1PlbGa", - Customer{}, + UpdateCustomer{}, }, true, errBadBaseURL, diff --git a/mollie/payments.go b/mollie/payments.go index 67af858d..e18d5e73 100644 --- a/mollie/payments.go +++ b/mollie/payments.go @@ -347,7 +347,7 @@ func (ps *PaymentsService) Update(ctx context.Context, id string, up UpdatePayme type PaymentList struct { Count int `json:"count,omitempty"` Embedded struct { - Payments []Payment + Payments []*Payment } `json:"_embedded,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } From 448596af5d57a5676913b947882d26d0f2c1b614 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:42:24 +0100 Subject: [PATCH 08/23] check invoices resource against api reference (#335) --- docs/README.md | 12 ++++++------ mollie/invoices.go | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/README.md b/docs/README.md index f9cdcfcb..f20e14be 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2391,7 +2391,6 @@ type Invoice struct { ID string `json:"id,omitempty"` Reference string `json:"reference,omitempty"` VatNumber string `json:"vatNumber,omitempty"` - Status InvoiceStatus `json:"status,omitempty"` IssuedAt string `json:"issuedAt,omitempty"` PaidAt string `json:"paidAt,omitempty"` DueAt string `json:"dueAt,omitempty"` @@ -2399,6 +2398,7 @@ type Invoice struct { VatAmount *Amount `json:"vatAmount,omitempty"` GrossAmount *Amount `json:"grossAmount,omitempty"` Lines []*LineItem `json:"lines,omitempty"` + Status InvoiceStatus `json:"status,omitempty"` Links InvoiceLinks `json:"_links,omitempty"` } ``` @@ -2444,7 +2444,7 @@ InvoicesList describes how a list of invoices will be retrieved by Mollie. type InvoicesList struct { Count int `json:"count,omitempty"` Embedded struct { - Invoices []Invoice `json:"invoices"` + Invoices []*Invoice `json:"invoices"` } `json:"_embedded,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } @@ -2457,10 +2457,10 @@ InvoicesListOptions describes list invoices endpoint valid query string paramete ```go type InvoicesListOptions struct { + Limit int64 `url:"limit,omitempty"` Reference string `url:"reference,omitempty"` Year string `url:"year,omitempty"` From string `url:"from,omitempty"` - Limit int64 `url:"limit,omitempty"` } ``` @@ -2498,10 +2498,10 @@ LineItem product details. ```go type LineItem struct { - Period string `json:"period,omitempty"` - Description string `json:"description,omitempty"` Count int64 `json:"count,omitempty"` VatPercentage float64 `json:"vatPercentage,omitempty"` + Period string `json:"period,omitempty"` + Description string `json:"description,omitempty"` Amount *Amount `json:"amount,omitempty"` } ``` @@ -3930,7 +3930,7 @@ PaymentList describes how a list of payments will be retrieved by Mollie. type PaymentList struct { Count int `json:"count,omitempty"` Embedded struct { - Payments []Payment + Payments []*Payment } `json:"_embedded,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } diff --git a/mollie/invoices.go b/mollie/invoices.go index 4bd18f1f..c833d4a1 100644 --- a/mollie/invoices.go +++ b/mollie/invoices.go @@ -22,7 +22,6 @@ type Invoice struct { ID string `json:"id,omitempty"` Reference string `json:"reference,omitempty"` VatNumber string `json:"vatNumber,omitempty"` - Status InvoiceStatus `json:"status,omitempty"` IssuedAt string `json:"issuedAt,omitempty"` PaidAt string `json:"paidAt,omitempty"` DueAt string `json:"dueAt,omitempty"` @@ -30,15 +29,16 @@ type Invoice struct { VatAmount *Amount `json:"vatAmount,omitempty"` GrossAmount *Amount `json:"grossAmount,omitempty"` Lines []*LineItem `json:"lines,omitempty"` + Status InvoiceStatus `json:"status,omitempty"` Links InvoiceLinks `json:"_links,omitempty"` } // LineItem product details. type LineItem struct { - Period string `json:"period,omitempty"` - Description string `json:"description,omitempty"` Count int64 `json:"count,omitempty"` VatPercentage float64 `json:"vatPercentage,omitempty"` + Period string `json:"period,omitempty"` + Description string `json:"description,omitempty"` Amount *Amount `json:"amount,omitempty"` } @@ -52,17 +52,17 @@ type InvoiceLinks struct { // InvoicesListOptions describes list invoices endpoint valid query string parameters. type InvoicesListOptions struct { + Limit int64 `url:"limit,omitempty"` Reference string `url:"reference,omitempty"` Year string `url:"year,omitempty"` From string `url:"from,omitempty"` - Limit int64 `url:"limit,omitempty"` } // InvoicesList describes how a list of invoices will be retrieved by Mollie. type InvoicesList struct { Count int `json:"count,omitempty"` Embedded struct { - Invoices []Invoice `json:"invoices"` + Invoices []*Invoice `json:"invoices"` } `json:"_embedded,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } From 1e55ab8fdc078f1bea545f41103f3f8f4bdc0a9a Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 8 Mar 2024 16:10:45 +0100 Subject: [PATCH 09/23] check mandates resource against api reference (#336) --- docs/README.md | 72 +++++++++++++++++++++++++++++------------ mollie/mandates.go | 36 +++++++++++++++++---- mollie/mandates_test.go | 10 +++--- 3 files changed, 86 insertions(+), 32 deletions(-) diff --git a/docs/README.md b/docs/README.md index f20e14be..e7980607 100644 --- a/docs/README.md +++ b/docs/README.md @@ -107,6 +107,8 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CreateCapture](<#CreateCapture>) - [type CreateClientLink](<#CreateClientLink>) - [type CreateCustomer](<#CreateCustomer>) +- [type CreateMandate](<#CreateMandate>) +- [type CreateMandateAccessTokenFields](<#CreateMandateAccessTokenFields>) - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) - [type CreatePayment](<#CreatePayment>) - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) @@ -158,7 +160,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type MandatesList](<#MandatesList>) - [type MandatesListOptions](<#MandatesListOptions>) - [type MandatesService](<#MandatesService>) - - [func \(ms \*MandatesService\) Create\(ctx context.Context, customer string, mandate Mandate\) \(res \*Response, mr \*Mandate, err error\)](<#MandatesService.Create>) + - [func \(ms \*MandatesService\) Create\(ctx context.Context, customer string, mandate CreateMandate\) \(res \*Response, mr \*Mandate, err error\)](<#MandatesService.Create>) - [func \(ms \*MandatesService\) Get\(ctx context.Context, customer, mandate string\) \(res \*Response, mr \*Mandate, err error\)](<#MandatesService.Get>) - [func \(ms \*MandatesService\) List\(ctx context.Context, customer string, options \*MandatesListOptions\) \(res \*Response, ml \*MandatesList, err error\)](<#MandatesService.List>) - [func \(ms \*MandatesService\) Revoke\(ctx context.Context, customer, mandate string\) \(res \*Response, err error\)](<#MandatesService.Revoke>) @@ -1152,7 +1154,7 @@ List retrieves all captures for a certain payment. See: https://docs.mollie.com/reference/v2/captures-api/list-captures -## type [CardLabel]() +## type [CardLabel]() CardLabel Note that not all labels can be processed through Mollie. @@ -1842,6 +1844,36 @@ type CreateCustomer struct { } ``` + +## type [CreateMandate]() + +CreateMandate contains the parameters to create a mandate. + +```go +type CreateMandate struct { + ConsumerName string `json:"consumerName,omitempty"` + ConsumerAccount string `json:"consumerAccount,omitempty"` + ConsumerBIC string `json:"consumerBic,omitempty"` + ConsumerEmail string `json:"consumerEmail,omitempty"` + MandateReference string `json:"mandateReference,omitempty"` + PaypalBillingAgreementID string `json:"paypalBillingAgreementId,omitempty"` + SignatureDate *ShortDate `json:"signatureDate,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + CreateMandateAccessTokenFields +} +``` + + +## type [CreateMandateAccessTokenFields]() + +CreateMandateAccessTokenFields contains the parameters to create a mandate when using an access token. + +```go +type CreateMandateAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` +} +``` + ## type [CreateMollieConnectPaymentFields]() @@ -2590,7 +2622,7 @@ const ( ``` -## type [Mandate]() +## type [Mandate]() Mandate allow you to charge a customer’s credit card or bank account recurrently. @@ -2598,22 +2630,22 @@ Mandate allow you to charge a customer’s credit card or bank account recurrent type Mandate struct { ID string `json:"id,omitempty"` Resource string `json:"resource,omitempty"` - Method PaymentMethod `json:"method,omitempty"` ConsumerName string `json:"consumerName,omitempty"` ConsumerAccount string `json:"consumerAccount,omitempty"` ConsumerBic string `json:"consumerBic,omitempty"` - SignatureDate *ShortDate `json:"signatureDate,omitempty"` MandateReference string `json:"mandateReference,omitempty"` + SignatureDate *ShortDate `json:"signatureDate,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` Mode Mode `json:"mode,omitempty"` Status MandateStatus `json:"status,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` + Method PaymentMethod `json:"method,omitempty"` Details MandateDetails `json:"details,omitempty"` Links MandateLinks `json:"_links,omitempty"` } ``` -## type [MandateDetails]() +## type [MandateDetails]() MandateDetails are possible values inside the mandate.details field. @@ -2624,14 +2656,14 @@ type MandateDetails struct { ConsumerBic string `json:"consumerBic,omitempty"` CardHolder string `json:"cardHolder,omitempty"` CardNumber string `json:"cardNumber,omitempty"` - CardLabel CardLabel `json:"cardLabel,omitempty"` CardFingerprint string `json:"cardFingerprint,omitempty"` CardExpiryDate *ShortDate `json:"cardExpiryDate,omitempty"` + CardLabel CardLabel `json:"cardLabel,omitempty"` } ``` -## type [MandateLinks]() +## type [MandateLinks]() MandateLinks response objects. @@ -2644,7 +2676,7 @@ type MandateLinks struct { ``` -## type [MandateStatus]() +## type [MandateStatus]() MandateStatus for the Mandate object. @@ -2663,7 +2695,7 @@ const ( ``` -## type [MandatesList]() +## type [MandatesList]() MandatesList describes how a list of mandates will be retrieved by Mollie. @@ -2671,14 +2703,14 @@ MandatesList describes how a list of mandates will be retrieved by Mollie. type MandatesList struct { Count int `json:"count,omitempty"` Embedded struct { - Mandates []Mandate + Mandates []*Mandate } `json:"_embedded,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } ``` -## type [MandatesListOptions]() +## type [MandatesListOptions]() MandatesListOptions contains valid query parameters to filter the List mandates actions. @@ -2686,13 +2718,13 @@ From is a mandate id to offset from \(inclusive\) Limit is the max number of man ```go type MandatesListOptions struct { - From string `url:"from,omitempty"` Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` } ``` -## type [MandatesService]() +## type [MandatesService]() MandatesService operates over customer mandates endpoints. @@ -2701,10 +2733,10 @@ type MandatesService service ``` -### func \(\*MandatesService\) [Create]() +### func \(\*MandatesService\) [Create]() ```go -func (ms *MandatesService) Create(ctx context.Context, customer string, mandate Mandate) (res *Response, mr *Mandate, err error) +func (ms *MandatesService) Create(ctx context.Context, customer string, mandate CreateMandate) (res *Response, mr *Mandate, err error) ``` Create a mandate for a specific customer. @@ -2714,7 +2746,7 @@ Mandates allow you to charge a customer’s credit card or bank account recurren See: https://docs.mollie.com/reference/v2/mandates-api/create-mandate -### func \(\*MandatesService\) [Get]() +### func \(\*MandatesService\) [Get]() ```go func (ms *MandatesService) Get(ctx context.Context, customer, mandate string) (res *Response, mr *Mandate, err error) @@ -2725,7 +2757,7 @@ Get retrieves a mandate by its ID and its customer’s ID. The mandate will eith See: https://docs.mollie.com/reference/v2/mandates-api/get-mandate -### func \(\*MandatesService\) [List]() +### func \(\*MandatesService\) [List]() ```go func (ms *MandatesService) List(ctx context.Context, customer string, options *MandatesListOptions) (res *Response, ml *MandatesList, err error) @@ -2736,7 +2768,7 @@ List retrieves all mandates for the given customerId, ordered from newest to old See: https://docs.mollie.com/reference/v2/mandates-api/list-mandates -### func \(\*MandatesService\) [Revoke]() +### func \(\*MandatesService\) [Revoke]() ```go func (ms *MandatesService) Revoke(ctx context.Context, customer, mandate string) (res *Response, err error) diff --git a/mollie/mandates.go b/mollie/mandates.go index 4627ffab..b9e7624d 100644 --- a/mollie/mandates.go +++ b/mollie/mandates.go @@ -7,19 +7,37 @@ import ( "time" ) +// CreateMandate contains the parameters to create a mandate. +type CreateMandate struct { + ConsumerName string `json:"consumerName,omitempty"` + ConsumerAccount string `json:"consumerAccount,omitempty"` + ConsumerBIC string `json:"consumerBic,omitempty"` + ConsumerEmail string `json:"consumerEmail,omitempty"` + MandateReference string `json:"mandateReference,omitempty"` + PaypalBillingAgreementID string `json:"paypalBillingAgreementId,omitempty"` + SignatureDate *ShortDate `json:"signatureDate,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + CreateMandateAccessTokenFields +} + +// CreateMandateAccessTokenFields contains the parameters to create a mandate when using an access token. +type CreateMandateAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` +} + // Mandate allow you to charge a customer’s credit card or bank account recurrently. type Mandate struct { ID string `json:"id,omitempty"` Resource string `json:"resource,omitempty"` - Method PaymentMethod `json:"method,omitempty"` ConsumerName string `json:"consumerName,omitempty"` ConsumerAccount string `json:"consumerAccount,omitempty"` ConsumerBic string `json:"consumerBic,omitempty"` - SignatureDate *ShortDate `json:"signatureDate,omitempty"` MandateReference string `json:"mandateReference,omitempty"` + SignatureDate *ShortDate `json:"signatureDate,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` Mode Mode `json:"mode,omitempty"` Status MandateStatus `json:"status,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` + Method PaymentMethod `json:"method,omitempty"` Details MandateDetails `json:"details,omitempty"` Links MandateLinks `json:"_links,omitempty"` } @@ -31,9 +49,9 @@ type MandateDetails struct { ConsumerBic string `json:"consumerBic,omitempty"` CardHolder string `json:"cardHolder,omitempty"` CardNumber string `json:"cardNumber,omitempty"` - CardLabel CardLabel `json:"cardLabel,omitempty"` CardFingerprint string `json:"cardFingerprint,omitempty"` CardExpiryDate *ShortDate `json:"cardExpiryDate,omitempty"` + CardLabel CardLabel `json:"cardLabel,omitempty"` } // MandateStatus for the Mandate object. @@ -82,15 +100,15 @@ type MandateLinks struct { // From is a mandate id to offset from (inclusive) // Limit is the max number of mandates to retrieve. type MandatesListOptions struct { - From string `url:"from,omitempty"` Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` } // MandatesList describes how a list of mandates will be retrieved by Mollie. type MandatesList struct { Count int `json:"count,omitempty"` Embedded struct { - Mandates []Mandate + Mandates []*Mandate } `json:"_embedded,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } @@ -100,13 +118,17 @@ type MandatesList struct { // Mandates allow you to charge a customer’s credit card or bank account recurrently. // // See: https://docs.mollie.com/reference/v2/mandates-api/create-mandate -func (ms *MandatesService) Create(ctx context.Context, customer string, mandate Mandate) ( +func (ms *MandatesService) Create(ctx context.Context, customer string, mandate CreateMandate) ( res *Response, mr *Mandate, err error, ) { u := fmt.Sprintf("v2/customers/%s/mandates", customer) + if ms.client.HasAccessToken() && ms.client.config.testing { + mandate.Testmode = true + } + res, err = ms.client.post(ctx, u, mandate, nil) if err != nil { return diff --git a/mollie/mandates_test.go b/mollie/mandates_test.go index fe13c2bd..3a032103 100644 --- a/mollie/mandates_test.go +++ b/mollie/mandates_test.go @@ -120,7 +120,7 @@ func TestMandatesService_Create(t *testing.T) { type args struct { ctx context.Context - mandate Mandate + mandate CreateMandate customer string } @@ -136,7 +136,7 @@ func TestMandatesService_Create(t *testing.T) { "create mandates works as expected.", args{ context.Background(), - Mandate{ + CreateMandate{ Method: PayPal, }, "cst_4qqhO89gsT", @@ -158,7 +158,7 @@ func TestMandatesService_Create(t *testing.T) { "create mandate, an error is returned from the server", args{ context.Background(), - Mandate{ + CreateMandate{ Method: PayPal, }, "cst_4qqhO89gsT", @@ -172,7 +172,7 @@ func TestMandatesService_Create(t *testing.T) { "create mandate, an error occurs when parsing json", args{ context.Background(), - Mandate{ + CreateMandate{ Method: PayPal, }, "cst_4qqhO89gsT", @@ -186,7 +186,7 @@ func TestMandatesService_Create(t *testing.T) { "create mandate, invalid url when building request", args{ context.Background(), - Mandate{ + CreateMandate{ Method: PayPal, }, "cst_4qqhO89gsT", From be31f07c5bed090f53fce31953dd1534f7c28eed Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:00:04 +0100 Subject: [PATCH 10/23] check mandates resources against api reference (#337) From 33954069533d8dc5d8d46880091955b448e14622 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:04:16 +0100 Subject: [PATCH 11/23] check wallets resources against api reference (#338) --- docs/README.md | 50 +++++++++---------- mollie/mollie.go | 4 +- mollie/{miscellaneous.go => wallets.go} | 8 +-- ...{miscellaneous_test.go => wallets_test.go} | 2 +- 4 files changed, 32 insertions(+), 32 deletions(-) rename mollie/{miscellaneous.go => wallets.go} (83%) rename mollie/{miscellaneous_test.go => wallets_test.go} (95%) diff --git a/docs/README.md b/docs/README.md index e7980607..95887273 100644 --- a/docs/README.md +++ b/docs/README.md @@ -165,8 +165,6 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ms \*MandatesService\) List\(ctx context.Context, customer string, options \*MandatesListOptions\) \(res \*Response, ml \*MandatesList, err error\)](<#MandatesService.List>) - [func \(ms \*MandatesService\) Revoke\(ctx context.Context, customer, mandate string\) \(res \*Response, err error\)](<#MandatesService.Revoke>) - [type MethodsLinks](<#MethodsLinks>) -- [type MiscellaneousService](<#MiscellaneousService>) - - [func \(ms \*MiscellaneousService\) ApplePaymentSession\(ctx context.Context, asr \*ApplePaymentSessionRequest\) \(res \*Response, aps \*ApplePaymentSession, err error\)](<#MiscellaneousService.ApplePaymentSession>) - [type Mode](<#Mode>) - [type MollieConnectPaymentFields](<#MollieConnectPaymentFields>) - [type Onboarding](<#Onboarding>) @@ -362,6 +360,8 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type UpdatePayment](<#UpdatePayment>) - [type UsedGiftCard](<#UsedGiftCard>) - [type UserAgentToken](<#UserAgentToken>) +- [type WalletsService](<#WalletsService>) + - [func \(ms \*WalletsService\) ApplePaymentSession\(ctx context.Context, asr \*ApplePaymentSessionRequest\) \(res \*Response, aps \*ApplePaymentSession, err error\)](<#WalletsService.ApplePaymentSession>) ## Constants @@ -437,7 +437,7 @@ type Amount struct { ``` -## type [ApplePaymentSession]() +## type [ApplePaymentSession]() ApplePaymentSession contains information about an Apple pay session. @@ -455,7 +455,7 @@ type ApplePaymentSession struct { ``` -## type [ApplePaymentSessionRequest]() +## type [ApplePaymentSessionRequest]() ApplePaymentSessionRequest contains the body parameters for requesting a valid PaymentSession from Apple. @@ -1384,7 +1384,7 @@ type Client struct { Captures *CapturesService Subscriptions *SubscriptionsService Customers *CustomersService - Miscellaneous *MiscellaneousService + Wallets *WalletsService Mandates *MandatesService Permissions *PermissionsService Onboarding *OnboardingService @@ -2792,26 +2792,6 @@ type MethodsLinks struct { } ``` - -## type [MiscellaneousService]() - -MiscellaneousService operates over the resources described in Mollie's miscellaneous API endpoints section. - -```go -type MiscellaneousService service -``` - - -### func \(\*MiscellaneousService\) [ApplePaymentSession]() - -```go -func (ms *MiscellaneousService) ApplePaymentSession(ctx context.Context, asr *ApplePaymentSessionRequest) (res *Response, aps *ApplePaymentSession, err error) -``` - -ApplePaymentSession returns an Apple Payment Session object valid for one transaction. - -See: https://docs.mollie.com/reference/v2/wallets-api/request-apple-pay-payment-session - ## type [Mode]() @@ -5659,4 +5639,24 @@ type UserAgentToken struct { } ``` + +## type [WalletsService]() + +WalletsService operates over the resources described in Mollie's wallets API endpoints section. + +```go +type WalletsService service +``` + + +### func \(\*WalletsService\) [ApplePaymentSession]() + +```go +func (ms *WalletsService) ApplePaymentSession(ctx context.Context, asr *ApplePaymentSessionRequest) (res *Response, aps *ApplePaymentSession, err error) +``` + +ApplePaymentSession returns an Apple Payment Session object valid for one transaction. + +See: https://docs.mollie.com/reference/v2/wallets-api/request-apple-pay-payment-session + Generated by [gomarkdoc]() diff --git a/mollie/mollie.go b/mollie/mollie.go index 1a1d01c5..f3b2f446 100644 --- a/mollie/mollie.go +++ b/mollie/mollie.go @@ -63,7 +63,7 @@ type Client struct { Captures *CapturesService Subscriptions *SubscriptionsService Customers *CustomersService - Miscellaneous *MiscellaneousService + Wallets *WalletsService Mandates *MandatesService Permissions *PermissionsService Onboarding *OnboardingService @@ -299,7 +299,7 @@ func NewClient(baseClient *http.Client, conf *Config) (mollie *Client, err error mollie.Settlements = (*SettlementsService)(&mollie.common) mollie.Subscriptions = (*SubscriptionsService)(&mollie.common) mollie.Customers = (*CustomersService)(&mollie.common) - mollie.Miscellaneous = (*MiscellaneousService)(&mollie.common) + mollie.Wallets = (*WalletsService)(&mollie.common) mollie.Mandates = (*MandatesService)(&mollie.common) mollie.Permissions = (*PermissionsService)(&mollie.common) mollie.Onboarding = (*OnboardingService)(&mollie.common) diff --git a/mollie/miscellaneous.go b/mollie/wallets.go similarity index 83% rename from mollie/miscellaneous.go rename to mollie/wallets.go index f1921ba6..bc429edd 100644 --- a/mollie/miscellaneous.go +++ b/mollie/wallets.go @@ -5,9 +5,9 @@ import ( "encoding/json" ) -// MiscellaneousService operates over the resources described -// in Mollie's miscellaneous API endpoints section. -type MiscellaneousService service +// WalletsService operates over the resources described +// in Mollie's wallets API endpoints section. +type WalletsService service // ApplePaymentSession contains information about an Apple pay session. type ApplePaymentSession struct { @@ -31,7 +31,7 @@ type ApplePaymentSessionRequest struct { // ApplePaymentSession returns an Apple Payment Session object valid for one transaction. // // See: https://docs.mollie.com/reference/v2/wallets-api/request-apple-pay-payment-session -func (ms *MiscellaneousService) ApplePaymentSession(ctx context.Context, asr *ApplePaymentSessionRequest) ( +func (ms *WalletsService) ApplePaymentSession(ctx context.Context, asr *ApplePaymentSessionRequest) ( res *Response, aps *ApplePaymentSession, err error, diff --git a/mollie/miscellaneous_test.go b/mollie/wallets_test.go similarity index 95% rename from mollie/miscellaneous_test.go rename to mollie/wallets_test.go index 0bab18d3..09be8bc7 100644 --- a/mollie/miscellaneous_test.go +++ b/mollie/wallets_test.go @@ -91,7 +91,7 @@ func TestMiscellaneousService_ApplePaymentSession(t *testing.T) { c.pre() tMux.HandleFunc("/v2/wallets/applepay/sessions", c.handler) - res, m, err := tClient.Miscellaneous.ApplePaymentSession(c.args.ctx, c.args.appleSess) + res, m, err := tClient.Wallets.ApplePaymentSession(c.args.ctx, c.args.appleSess) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) From 9a25a2ad592f73699d375347939bf7961e1e6a55 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:21:01 +0100 Subject: [PATCH 12/23] check onboarding resources against api reference (#339) --- docs/README.md | 6 +++--- mollie/onboarding.go | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/README.md b/docs/README.md index 95887273..4a9d6250 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2828,12 +2828,12 @@ Onboarding data for an organization. ```go type Onboarding struct { + CanReceivePayments bool `json:"canReceivePayments,omitempty"` + CanReceiveSettlements bool `json:"canReceiveSettlements,omitempty"` Resource string `json:"reference,omitempty"` Name string `json:"name,omitempty"` SignedUpAt *time.Time `json:"signedUpAt,omitempty"` Status OnboardingStatus `json:"status,omitempty"` - CanReceivePayments bool `json:"canReceivePayments,omitempty"` - CanReveiceSettlements bool `json:"canReceiveSettlements,omitempty"` Links OnboardingLinks `json:"_links,omitempty"` } ``` @@ -2858,10 +2858,10 @@ OnboardingDataOrganization contains data of the organization you want to provide ```go type OnboardingDataOrganization struct { Name string `json:"name,omitempty"` - Address *Address `json:"address,omitempty"` RegistrationNumber string `json:"registrationNumber,omitempty"` VatNumber string `json:"vatNumber,omitempty"` VatRegulation string `json:"vatRegulation,omitempty"` + Address *Address `json:"address,omitempty"` } ``` diff --git a/mollie/onboarding.go b/mollie/onboarding.go index 45621d94..e8386974 100644 --- a/mollie/onboarding.go +++ b/mollie/onboarding.go @@ -6,7 +6,7 @@ import ( "time" ) -const onboardingTarget = "v2/onboarding/me" +const onboardingURLPath = "v2/onboarding/me" // OnboardingStatus describes status of the organization’s onboarding process. type OnboardingStatus string @@ -31,12 +31,12 @@ type OnboardingLinks struct { // Onboarding data for an organization. type Onboarding struct { + CanReceivePayments bool `json:"canReceivePayments,omitempty"` + CanReceiveSettlements bool `json:"canReceiveSettlements,omitempty"` Resource string `json:"reference,omitempty"` Name string `json:"name,omitempty"` SignedUpAt *time.Time `json:"signedUpAt,omitempty"` Status OnboardingStatus `json:"status,omitempty"` - CanReceivePayments bool `json:"canReceivePayments,omitempty"` - CanReveiceSettlements bool `json:"canReceiveSettlements,omitempty"` Links OnboardingLinks `json:"_links,omitempty"` } @@ -44,7 +44,7 @@ type Onboarding struct { // // See: https://docs.mollie.com/reference/v2/onboarding-api/get-onboarding-status func (os *OnboardingService) GetOnboardingStatus(ctx context.Context) (res *Response, o *Onboarding, err error) { - res, err = os.client.get(ctx, onboardingTarget, nil) + res, err = os.client.get(ctx, onboardingURLPath, nil) if err != nil { return } @@ -66,10 +66,10 @@ func (os *OnboardingService) GetOnboardingStatus(ctx context.Context) (res *Resp // OnboardingDataOrganization contains data of the organization you want to provide. type OnboardingDataOrganization struct { Name string `json:"name,omitempty"` - Address *Address `json:"address,omitempty"` RegistrationNumber string `json:"registrationNumber,omitempty"` VatNumber string `json:"vatNumber,omitempty"` VatRegulation string `json:"vatRegulation,omitempty"` + Address *Address `json:"address,omitempty"` } // OnboardingDataProfile contains data of the payment profile you want to provide. @@ -96,7 +96,7 @@ type OnboardingData struct { // // See: https://docs.mollie.com/reference/v2/onboarding-api/submit-onboarding-data func (os *OnboardingService) SubmitOnboardingData(ctx context.Context, d *OnboardingData) (res *Response, err error) { - res, err = os.client.post(ctx, onboardingTarget, d, nil) + res, err = os.client.post(ctx, onboardingURLPath, d, nil) if err != nil { return } From 3bd0e0e0805a97452c8142e977847bf639ad0447 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 8 Mar 2024 22:57:28 +0100 Subject: [PATCH 13/23] check orders resource against api reference (#340) --- docs/README.md | 298 ++++++++++++++++++++++++++-------------- mollie/captures_test.go | 4 +- mollie/common_types.go | 4 +- mollie/orders.go | 249 +++++++++++++++++++++------------ mollie/orders_test.go | 117 +++++++--------- testdata/orders.go | 4 +- 6 files changed, 413 insertions(+), 263 deletions(-) diff --git a/docs/README.md b/docs/README.md index 4a9d6250..0ee9b420 100644 --- a/docs/README.md +++ b/docs/README.md @@ -110,6 +110,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CreateMandate](<#CreateMandate>) - [type CreateMandateAccessTokenFields](<#CreateMandateAccessTokenFields>) - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) +- [type CreateOrder](<#CreateOrder>) - [type CreatePayment](<#CreatePayment>) - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) - [type CreatePreAuthorizedPaymentFields](<#CreatePreAuthorizedPaymentFields>) @@ -177,6 +178,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(os \*OnboardingService\) SubmitOnboardingData\(ctx context.Context, d \*OnboardingData\) \(res \*Response, err error\)](<#OnboardingService.SubmitOnboardingData>) - [type OnboardingStatus](<#OnboardingStatus>) - [type Order](<#Order>) +- [type OrderAccessTokenFields](<#OrderAccessTokenFields>) - [type OrderAddress](<#OrderAddress>) - [type OrderLine](<#OrderLine>) - [type OrderLineChangeInstruction](<#OrderLineChangeInstruction>) @@ -197,15 +199,15 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type OrdersService](<#OrdersService>) - [func \(ors \*OrdersService\) Cancel\(ctx context.Context, orderID string\) \(res \*Response, order \*Order, err error\)](<#OrdersService.Cancel>) - [func \(ors \*OrdersService\) CancelOrderLines\(ctx context.Context, orderID string, orderLines \[\]OrderLine\) \(res \*Response, err error\)](<#OrdersService.CancelOrderLines>) - - [func \(ors \*OrdersService\) Create\(ctx context.Context, ord Order, opts \*OrderOptions\) \(res \*Response, order \*Order, err error\)](<#OrdersService.Create>) + - [func \(ors \*OrdersService\) Create\(ctx context.Context, ord CreateOrder, opts \*OrderOptions\) \(res \*Response, order \*Order, err error\)](<#OrdersService.Create>) - [func \(ors \*OrdersService\) CreateOrderPayment\(ctx context.Context, orderID string, ordPay \*OrderPayment\) \(res \*Response, payment \*Payment, err error\)](<#OrdersService.CreateOrderPayment>) - [func \(ors \*OrdersService\) CreateOrderRefund\(ctx context.Context, orderID string, order \*Order\) \(res \*Response, refund \*Refund, err error\)](<#OrdersService.CreateOrderRefund>) - [func \(ors \*OrdersService\) Get\(ctx context.Context, orID string, opts \*OrderOptions\) \(res \*Response, order \*Order, err error\)](<#OrdersService.Get>) - [func \(ors \*OrdersService\) List\(ctx context.Context, opts \*OrderListOptions\) \(res \*Response, ordList \*OrderList, err error\)](<#OrdersService.List>) - [func \(ors \*OrdersService\) ListOrderRefunds\(ctx context.Context, orderID string, opts \*OrderListRefundOptions\) \(res \*Response, orderListRefund \*OrderListRefund, err error\)](<#OrdersService.ListOrderRefunds>) - [func \(ors \*OrdersService\) ManageOrderLines\(ctx context.Context, orderID string, operations \*OrderLineOperations\) \(res \*Response, order \*Order, err error\)](<#OrdersService.ManageOrderLines>) - - [func \(ors \*OrdersService\) Update\(ctx context.Context, orderID string, ord Order\) \(res \*Response, order \*Order, err error\)](<#OrdersService.Update>) - - [func \(ors \*OrdersService\) UpdateOrderLine\(ctx context.Context, orderID string, orderLineID string, orderLine OrderLine\) \(res \*Response, order \*Order, err error\)](<#OrdersService.UpdateOrderLine>) + - [func \(ors \*OrdersService\) Update\(ctx context.Context, orderID string, ord UpdateOrder\) \(res \*Response, order \*Order, err error\)](<#OrdersService.Update>) + - [func \(ors \*OrdersService\) UpdateOrderLine\(ctx context.Context, orderID string, orderLineID string, orderLine UpdateOrderLine\) \(res \*Response, order \*Order, err error\)](<#OrdersService.UpdateOrderLine>) - [type Organization](<#Organization>) - [type OrganizationLinks](<#OrganizationLinks>) - [type OrganizationPartnerLinks](<#OrganizationPartnerLinks>) @@ -266,7 +268,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ps \*PermissionsService\) List\(ctx context.Context\) \(res \*Response, pl \*PermissionsList, err error\)](<#PermissionsService.List>) - [type PhoneNumber](<#PhoneNumber>) - [type PreAuthorizedPaymentFields](<#PreAuthorizedPaymentFields>) -- [type ProductType](<#ProductType>) +- [type ProductKind](<#ProductKind>) - [type Profile](<#Profile>) - [type ProfileLinks](<#ProfileLinks>) - [type ProfileList](<#ProfileList>) @@ -357,6 +359,8 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type TransferFrequency](<#TransferFrequency>) - [type URL](<#URL>) - [type UpdateCustomer](<#UpdateCustomer>) +- [type UpdateOrder](<#UpdateOrder>) +- [type UpdateOrderLine](<#UpdateOrderLine>) - [type UpdatePayment](<#UpdatePayment>) - [type UsedGiftCard](<#UsedGiftCard>) - [type UserAgentToken](<#UserAgentToken>) @@ -1888,6 +1892,32 @@ type CreateMollieConnectPaymentFields struct { } ``` + +## type [CreateOrder]() + +CreateOrder contains the parameters to create an order. + +```go +type CreateOrder struct { + ShopperCountryMustMatchTheBillingCountry bool `json:"shopperCountryMustMatchTheBillingCountry,omitempty"` + OrderNumber string `json:"orderNumber,omitempty"` + RedirectURL string `json:"redirectUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + Amount *Amount `json:"amount,omitempty"` + BillingAddress *OrderAddress `json:"billingAddress,omitempty"` + ShippingAddress *OrderAddress `json:"shippingAddress,omitempty"` + ConsumerDateOfBirth *ShortDate `json:"consumerDateOfBirth,omitempty"` + Payment *OrderPayment `json:"payment,omitempty"` + ExpiresAt *ShortDate `json:"expiresAt,omitempty"` + Lines []OrderLine `json:"lines,omitempty"` + Method []PaymentMethod `json:"method,omitempty"` + Locale Locale `json:"locale,omitempty"` + Metadata any `json:"metadata,omitempty"` + OrderAccessTokenFields +} +``` + ## type [CreatePayment]() @@ -2177,18 +2207,26 @@ EmbedValue describes the valid value of embed query string. type EmbedValue string ``` -Valid Embed query string value. +Valid Embed query string value. ```go const ( - EmbedPayment EmbedValue = "payments" - EmbedRefund EmbedValue = "refunds" + EmbedPayments EmbedValue = "payments" + EmbedRefunds EmbedValue = "refunds" EmbedShipments EmbedValue = "shipments" EmbedChargebacks EmbedValue = "chargebacks" EmbedCaptures EmbedValue = "captures" ) ``` +Local embed value type. + +```go +const ( + EmbedNestedPaymentDetails EmbedValue = "payments.details.remainderDetails" +) +``` + ## type [EntityType]() @@ -2948,36 +2986,28 @@ const ( ``` -## type [Order]() +## type [Order]() Order explain the items that customers need to pay for. ```go type Order struct { - TestMode bool `json:"testmode,omitempty"` IsCancelable bool `json:"isCancelable,omitempty"` ShopperCountryMustMatchTheBillingCountry bool `json:"shopperCountryMustMatchTheBillingCountry,omitempty"` Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` ProfileID string `json:"profileId,omitempty"` - OrderNumber string `json:"orderNumber,omitempty"` RedirectURL string `json:"redirectUrl,omitempty"` - WebhookURL string `json:"webhookUrl,omitempty"` - Description string `json:"description,omitempty"` - Sku string `json:"sku,omitempty"` CancelURL string `json:"cancelUrl,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - Mode Mode `json:"mode,omitempty"` - Method PaymentMethod `json:"method,omitempty"` - Status OrderStatus `json:"status,omitempty"` - Locale Locale `json:"locale,omitempty"` - ShippingAddress OrderAddress `json:"shippingAddress,omitempty"` - Links OrderLinks `json:"_links,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + OrderNumber string `json:"orderNumber,omitempty"` + Lines []*OrderLine `json:"lines,omitempty"` Amount *Amount `json:"amount,omitempty"` AmountCaptured *Amount `json:"amountCaptured,omitempty"` AmountRefunded *Amount `json:"amountRefunded,omitempty"` BillingAddress *OrderAddress `json:"billingAddress,omitempty"` ConsumerDateOfBirth *ShortDate `json:"consumerDateOfBirth,omitempty"` + ShippingAddress *OrderAddress `json:"shippingAddress,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` ExpiresAt *time.Time `json:"expiresAt,omitempty"` ExpiredAt *time.Time `json:"expiredAt,omitempty"` @@ -2985,8 +3015,12 @@ type Order struct { AuthorizedAt *time.Time `json:"authorizedAt,omitempty"` CanceledAt *time.Time `json:"canceledAt,omitempty"` CompletedAt *time.Time `json:"completedAt,omitempty"` - OrderPayment *OrderPayment `json:"payment,omitempty"` - Lines []*OrderLine `json:"lines,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Mode Mode `json:"mode,omitempty"` + Locale Locale `json:"locale,omitempty"` + Status OrderStatus `json:"status,omitempty"` + Links OrderLinks `json:"_links,omitempty"` + Metadata any `json:"metadata,omitempty"` Embedded struct { Payments []*Payment `json:"payments,omitempty"` Refunds []*Refund `json:"refunds,omitempty"` @@ -2994,8 +3028,20 @@ type Order struct { } ``` + +## type [OrderAccessTokenFields]() + +OrderAccessTokenFields contains the fields available to include in an order when using an access token. + +```go +type OrderAccessTokenFields struct { + ProfileID string `json:"profileId,omitempty"` + Testmode bool `json:"testmode,omitempty"` +} +``` + -## type [OrderAddress]() +## type [OrderAddress]() OrderAddress identify both the address and the person the order is billed or shipped to. @@ -3006,57 +3052,53 @@ type OrderAddress struct { GivenName string `json:"givenName,omitempty"` FamilyName string `json:"familyName,omitempty"` Email string `json:"email,omitempty"` - Phone PhoneNumber `json:"phone,omitempty"` StreetAndNumber string `json:"streetAndNumber,omitempty"` StreetAdditional string `json:"streetAdditional,omitempty"` PostalCode string `json:"postalCode,omitempty"` City string `json:"city,omitempty"` Region string `json:"region,omitempty"` Country string `json:"country,omitempty"` + Phone PhoneNumber `json:"phone,omitempty"` } ``` -## type [OrderLine]() +## type [OrderLine]() OrderLine contain the actual things the customer bought. ```go type OrderLine struct { - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - OrderID string `json:"orderId,omitempty"` - ProductType ProductType `json:"type,omitempty"` - Name string `json:"name,omitempty"` - Amount *Amount `json:"amount,omitempty"` - Status OrderLineStatus `json:"status,omitempty"` IsCancelable bool `json:"isCancelable,omitempty"` Quantity int `json:"quantity,omitempty"` QuantityShipped int `json:"quantityShipped,omitempty"` - AmountShipped *Amount `json:"amountShipped,omitempty"` QuantityRefunded int `json:"quantityRefunded,omitempty"` - AmountRefunded *Amount `json:"amountRefunded,omitempty"` QuantityCanceled int `json:"quantityCanceled,omitempty"` - AmountCanceled *Amount `json:"amountCanceled,omitempty"` ShippableQuantity int `json:"shippableQuantity,omitempty"` RefundableQuantity int `json:"refundableQuantity,omitempty"` CancelableQuantity int `json:"cancelableQuantity,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + OrderID string `json:"orderId,omitempty"` + Name string `json:"name,omitempty"` + VatRate string `json:"vatRate,omitempty"` + SKU string `json:"sku,omitempty"` + AmountShipped *Amount `json:"amountShipped,omitempty"` + AmountRefunded *Amount `json:"amountRefunded,omitempty"` + AmountCanceled *Amount `json:"amountCanceled,omitempty"` UnitPrice *Amount `json:"unitPrice,omitempty"` DiscountAmount *Amount `json:"discountAmount,omitempty"` TotalAmount *Amount `json:"totalAmount,omitempty"` - VatRate string `json:"vatRate,omitempty"` VatAmount *Amount `json:"vatAmount,omitempty"` - SKU string `json:"sku,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` + ProductType ProductKind `json:"type,omitempty"` + Status OrderLineStatus `json:"status,omitempty"` Links OrderLineLinks `json:"_links,omitempty"` - ImageURL string `json:"imageUrl,omitempty"` - ProductURL string `json:"productUrl,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` } ``` -## type [OrderLineChangeInstruction]() +## type [OrderLineChangeInstruction]() OrderLineChangeInstruction contains details on what needs to be changed when managing order lines. @@ -3068,7 +3110,7 @@ type OrderLineChangeInstruction struct { ``` -## type [OrderLineLinks]() +## type [OrderLineLinks]() OrderLineLinks describes object with several URL objects relevant to the order line. @@ -3080,7 +3122,7 @@ type OrderLineLinks struct { ``` -## type [OrderLineOperation]() +## type [OrderLineOperation]() OrderLineOperation describes supported operations when managing order lines. @@ -3088,18 +3130,18 @@ OrderLineOperation describes supported operations when managing order lines. type OrderLineOperation string ``` -Supported order lines operation types. +Supported order lines operation types. ```go const ( - AddOrderLine OrderLineOperation = "add" - UpdateOrderLine OrderLineOperation = "update" - CancelOrderLine OrderLineOperation = "cancel" + AddOrderLineOperation OrderLineOperation = "add" + UpdateOrderLineOperation OrderLineOperation = "update" + CancelOrderLineOperation OrderLineOperation = "cancel" ) ``` -## type [OrderLineOperationData]() +## type [OrderLineOperationData]() OrderLineOperationData contains the order line’s details for an update operation. @@ -3112,19 +3154,20 @@ type OrderLineOperationData struct { ImageURL string `json:"imageUrl,omitempty"` ProductURL string `json:"productUrl,omitempty"` VATRate string `json:"vatRate,omitempty"` - Type string `json:"type,omitempty"` + Kind ProductKind `json:"type,omitempty"` Category OrderLineOperationProductCategory `json:"category,omitempty"` Amount *Amount `json:"amount,omitempty"` UnitPrice *Amount `json:"unitPrice,omitempty"` DiscountAmount *Amount `json:"discountAmount,omitempty"` VATAmount *Amount `json:"vatAmount,omitempty"` TotalAmount *Amount `json:"totalAmount,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` + Metadata any `json:"metadata,omitempty"` + OrderAccessTokenFields } ``` -## type [OrderLineOperationProductCategory]() +## type [OrderLineOperationProductCategory]() OrderLineOperationProductCategory contains the product category. @@ -3143,7 +3186,7 @@ const ( ``` -## type [OrderLineOperations]() +## type [OrderLineOperations]() OrderLineOperations contains the operations to be performed when managing order lines. @@ -3154,7 +3197,7 @@ type OrderLineOperations struct { ``` -## type [OrderLineStatus]() +## type [OrderLineStatus]() OrderLineStatus describes status of the order line. @@ -3176,7 +3219,7 @@ const ( ``` -## type [OrderLinks]() +## type [OrderLinks]() OrderLinks describes an object with several URL objects relevant to the order. Every URL object will contain an href and a type field. @@ -3190,7 +3233,7 @@ type OrderLinks struct { ``` -## type [OrderList]() +## type [OrderList]() OrderList for containing the response of list orders. @@ -3205,20 +3248,21 @@ type OrderList struct { ``` -## type [OrderListOptions]() +## type [OrderListOptions]() OrderListOptions describes order endpoint valid query string parameters. ```go type OrderListOptions struct { - ProfileID string `url:"profileId,omitempty"` - From string `url:"from,omitempty"` Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` + Sort string `url:"sort,omitempty"` + ProfileID string `url:"profileId,omitempty"` } ``` -## type [OrderListRefund]() +## type [OrderListRefund]() OrderListRefund for containing the response of list orders. @@ -3233,7 +3277,7 @@ type OrderListRefund struct { ``` -## type [OrderListRefundOptions]() +## type [OrderListRefundOptions]() OrderListRefundOptions describes order endpoint valid query string parameters. @@ -3246,40 +3290,51 @@ type OrderListRefundOptions struct { ``` -## type [OrderOptions]() +## type [OrderOptions]() OrderOptions describes order endpoint valid query string parameters. ```go type OrderOptions struct { - Embed []EmbedValue `url:"embed,omitempty"` ProfileID string `url:"profileId,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` } ``` -## type [OrderPayment]() +## type [OrderPayment]() OrderPayment describes payment specific parameters that can be passed during order creation. ```go type OrderPayment struct { - ConsumerAccount string `json:"consumerAccount,omitempty"` - CustomerID string `json:"customerId,omitempty"` - CustomerReference string `json:"customerReference,omitempty"` - Issuer string `json:"issuer,omitempty"` - MandateID string `json:"mandateId,omitempty"` - SequenceType SequenceType `json:"sequenceType,omitempty"` - VoucherNumber string `json:"voucherNumber,omitempty"` - VoucherPin string `json:"voucherPin,omitempty"` - WebhookURL string `json:"webhookUrl,omitempty"` - ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` - Method PaymentMethod `json:"method,omitempty"` + ApplePayPaymentToken string `json:"applePayPaymentToken,omitempty"` + CardToken string `json:"cardToken,omitempty"` + ConsumerAccount string `json:"consumerAccount,omitempty"` + CustomerID string `json:"customerId,omitempty"` + CustomerReference string `json:"customerReference,omitempty"` + ExtraMerchantData string `json:"extraMerchantData,omitempty"` + Issuer string `json:"issuer,omitempty"` + VoucherNumber string `json:"voucherNumber,omitempty"` + VoucherPin string `json:"voucherPin,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + BillingEmail string `json:"billingEmail,omitempty"` + SessionID string `json:"sessionId,omitempty"` + TerminalID string `json:"terminalId,omitempty"` + ConsumerName string `json:"consumerName,omitempty"` + DueDate *ShortDate `json:"dueDate,omitempty"` + ShippingAddress *Address `json:"shippingAddress,omitempty"` + BillingAddress *Address `json:"billingAddress,omitempty"` + Company *Company `json:"company,omitempty"` + // Only available when using access tokens. + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` + SequenceType SequenceType `json:"sequenceType,omitempty"` + Method []PaymentMethod `json:"method,omitempty"` } ``` -## type [OrderStatus]() +## type [OrderStatus]() OrderStatus describes the valid order status. @@ -3302,7 +3357,7 @@ const ( ``` -## type [OrdersService]() +## type [OrdersService]() OrdersService instance operates over refund resources. @@ -3311,7 +3366,7 @@ type OrdersService service ``` -### func \(\*OrdersService\) [Cancel]() +### func \(\*OrdersService\) [Cancel]() ```go func (ors *OrdersService) Cancel(ctx context.Context, orderID string) (res *Response, order *Order, err error) @@ -3322,7 +3377,7 @@ Cancel try to cancel the order that fulfill certain requirements. See https://docs.mollie.com/reference/v2/orders-api/cancel-order -### func \(\*OrdersService\) [CancelOrderLines]() +### func \(\*OrdersService\) [CancelOrderLines]() ```go func (ors *OrdersService) CancelOrderLines(ctx context.Context, orderID string, orderLines []OrderLine) (res *Response, err error) @@ -3333,10 +3388,10 @@ CancelOrderLines can be used to cancel one or more order lines that were previou See https://docs.mollie.com/reference/v2/orders-api/cancel-order-lines -### func \(\*OrdersService\) [Create]() +### func \(\*OrdersService\) [Create]() ```go -func (ors *OrdersService) Create(ctx context.Context, ord Order, opts *OrderOptions) (res *Response, order *Order, err error) +func (ors *OrdersService) Create(ctx context.Context, ord CreateOrder, opts *OrderOptions) (res *Response, order *Order, err error) ``` Create an order will automatically create the required payment to allow your customer to pay for the order. @@ -3344,7 +3399,7 @@ Create an order will automatically create the required payment to allow your cus See https://docs.mollie.com/reference/v2/orders-api/create-order -### func \(\*OrdersService\) [CreateOrderPayment]() +### func \(\*OrdersService\) [CreateOrderPayment]() ```go func (ors *OrdersService) CreateOrderPayment(ctx context.Context, orderID string, ordPay *OrderPayment) (res *Response, payment *Payment, err error) @@ -3355,7 +3410,7 @@ CreateOrderPayment can only be created while the status of the order is created, See https://docs.mollie.com/reference/v2/orders-api/create-order-payment -### func \(\*OrdersService\) [CreateOrderRefund]() +### func \(\*OrdersService\) [CreateOrderRefund]() ```go func (ors *OrdersService) CreateOrderRefund(ctx context.Context, orderID string, order *Order) (res *Response, refund *Refund, err error) @@ -3366,7 +3421,7 @@ CreateOrderRefund using the Orders API, refunds should be made against the order See https://docs.mollie.com/reference/v2/orders-api/create-order-refund -### func \(\*OrdersService\) [Get]() +### func \(\*OrdersService\) [Get]() ```go func (ors *OrdersService) Get(ctx context.Context, orID string, opts *OrderOptions) (res *Response, order *Order, err error) @@ -3377,7 +3432,7 @@ Get retrieve a single order by its ID. See https://docs.mollie.com/reference/v2/orders-api/get-order -### func \(\*OrdersService\) [List]() +### func \(\*OrdersService\) [List]() ```go func (ors *OrdersService) List(ctx context.Context, opts *OrderListOptions) (res *Response, ordList *OrderList, err error) @@ -3388,7 +3443,7 @@ List is to retrieve all orders. See https://docs.mollie.com/reference/v2/orders-api/list-orders -### func \(\*OrdersService\) [ListOrderRefunds]() +### func \(\*OrdersService\) [ListOrderRefunds]() ```go func (ors *OrdersService) ListOrderRefunds(ctx context.Context, orderID string, opts *OrderListRefundOptions) (res *Response, orderListRefund *OrderListRefund, err error) @@ -3399,7 +3454,7 @@ ListOrderRefunds retrieve all order refunds. See https://docs.mollie.com/reference/v2/orders-api/list-order-refunds -### func \(\*OrdersService\) [ManageOrderLines]() +### func \(\*OrdersService\) [ManageOrderLines]() ```go func (ors *OrdersService) ManageOrderLines(ctx context.Context, orderID string, operations *OrderLineOperations) (res *Response, order *Order, err error) @@ -3410,10 +3465,10 @@ ManageOrderLines allows to update, cancel, or add one or more order lines. See: https://docs.mollie.com/reference/v2/orders-api/manage-order-lines -### func \(\*OrdersService\) [Update]() +### func \(\*OrdersService\) [Update]() ```go -func (ors *OrdersService) Update(ctx context.Context, orderID string, ord Order) (res *Response, order *Order, err error) +func (ors *OrdersService) Update(ctx context.Context, orderID string, ord UpdateOrder) (res *Response, order *Order, err error) ``` Update is used to update the billing and/or shipping address of an order. @@ -3421,10 +3476,10 @@ Update is used to update the billing and/or shipping address of an order. See https://docs.mollie.com/reference/v2/orders-api/update-order -### func \(\*OrdersService\) [UpdateOrderLine]() +### func \(\*OrdersService\) [UpdateOrderLine]() ```go -func (ors *OrdersService) UpdateOrderLine(ctx context.Context, orderID string, orderLineID string, orderLine OrderLine) (res *Response, order *Order, err error) +func (ors *OrdersService) UpdateOrderLine(ctx context.Context, orderID string, orderLineID string, orderLine UpdateOrderLine) (res *Response, order *Order, err error) ``` UpdateOrderLine can be used to update an order line. @@ -4364,26 +4419,26 @@ type PreAuthorizedPaymentFields struct { } ``` - -## type [ProductType]() + +## type [ProductKind]() -ProductType describes the type of product bought, for example, a physical or a digital product. +ProductKind describes the type of product bought, for example, a physical or a digital product. ```go -type ProductType string +type ProductKind string ``` -Valid product type. +Valid product type. ```go const ( - Physical ProductType = "physical" - Discount ProductType = "discount" - Digital ProductType = "digital" - ShippingFee ProductType = "shipping_fee" - StoreCredit ProductType = "store_credit" - GiftCardProduct ProductType = "gift_card" - Surcharge ProductType = "surcharge" + PhysicalProduct ProductKind = "physical" + DiscountProduct ProductKind = "discount" + DigitalProduct ProductKind = "digital" + ShippingFeeProduct ProductKind = "shipping_fee" + StoreCreditProduct ProductKind = "store_credit" + GiftCardProductProduct ProductKind = "gift_card" + SurchargeProduct ProductKind = "surcharge" ) ``` @@ -5588,6 +5643,45 @@ type UpdateCustomer struct { } ``` + +## type [UpdateOrder]() + +UpdateOrder contains the parameters to update an order. + +```go +type UpdateOrder struct { + OrderNumber string `json:"orderNumber,omitempty"` + RedirectURL string `json:"redirectUrl,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + BillingAddress *OrderAddress `json:"billingAddress,omitempty"` + ShippingAddress *OrderAddress `json:"shippingAddress,omitempty"` + OrderAccessTokenFields +} +``` + + +## type [UpdateOrderLine]() + +UpdateOrderLine contains the parameters to update an order line. + +```go +type UpdateOrderLine struct { + Quantity int `json:"quantity,omitempty"` + Name string `json:"name,omitempty"` + ImageURL string `json:"imageUrl,omitempty"` + ProductURL string `json:"productUrl,omitempty"` + SKU string `json:"sku,omitempty"` + VATRate string `json:"vatRate,omitempty"` + UnitPrice *Amount `json:"unitPrice,omitempty"` + DiscountAmount *Amount `json:"discountAmount,omitempty"` + TotalAmount *Amount `json:"totalAmount,omitempty"` + VATAmount *Amount `json:"vatAmount,omitempty"` + Metadata any `json:"metadata,omitempty"` + OrderAccessTokenFields +} +``` + ## type [UpdatePayment]() diff --git a/mollie/captures_test.go b/mollie/captures_test.go index b2617e1d..72defd93 100644 --- a/mollie/captures_test.go +++ b/mollie/captures_test.go @@ -57,7 +57,7 @@ func TestCapturesService_Get(t *testing.T) { "tr_WDqYK6vllg", "cpt_4qqhO89gsT", &CaptureOptions{ - Embed: []EmbedValue{EmbedPayment}, + Embed: []EmbedValue{EmbedPayments}, }, }, false, @@ -319,7 +319,7 @@ func TestCapturesService_List(t *testing.T) { "tr_WDqYK6vllg", "cpt_4qqhO89gsT", &CaptureOptions{ - Embed: []EmbedValue{EmbedPayment}, + Embed: []EmbedValue{EmbedPayments}, }, }, false, diff --git a/mollie/common_types.go b/mollie/common_types.go index 9d797caa..5dd26c9b 100644 --- a/mollie/common_types.go +++ b/mollie/common_types.go @@ -335,8 +335,8 @@ type EmbedValue string // Valid Embed query string value. const ( - EmbedPayment EmbedValue = "payments" - EmbedRefund EmbedValue = "refunds" + EmbedPayments EmbedValue = "payments" + EmbedRefunds EmbedValue = "refunds" EmbedShipments EmbedValue = "shipments" EmbedChargebacks EmbedValue = "chargebacks" EmbedCaptures EmbedValue = "captures" diff --git a/mollie/orders.go b/mollie/orders.go index 5cc7979a..5bdc29fa 100644 --- a/mollie/orders.go +++ b/mollie/orders.go @@ -7,32 +7,55 @@ import ( "time" ) +// Local embed value type. +const ( + EmbedNestedPaymentDetails EmbedValue = "payments.details.remainderDetails" +) + +// CreateOrder contains the parameters to create an order. +type CreateOrder struct { + ShopperCountryMustMatchTheBillingCountry bool `json:"shopperCountryMustMatchTheBillingCountry,omitempty"` + OrderNumber string `json:"orderNumber,omitempty"` + RedirectURL string `json:"redirectUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + Amount *Amount `json:"amount,omitempty"` + BillingAddress *OrderAddress `json:"billingAddress,omitempty"` + ShippingAddress *OrderAddress `json:"shippingAddress,omitempty"` + ConsumerDateOfBirth *ShortDate `json:"consumerDateOfBirth,omitempty"` + Payment *OrderPayment `json:"payment,omitempty"` + ExpiresAt *ShortDate `json:"expiresAt,omitempty"` + Lines []OrderLine `json:"lines,omitempty"` + Method []PaymentMethod `json:"method,omitempty"` + Locale Locale `json:"locale,omitempty"` + Metadata any `json:"metadata,omitempty"` + OrderAccessTokenFields +} + +// OrderAccessTokenFields contains the fields available to include in an order when using an access token. +type OrderAccessTokenFields struct { + ProfileID string `json:"profileId,omitempty"` + Testmode bool `json:"testmode,omitempty"` +} + // Order explain the items that customers need to pay for. type Order struct { - TestMode bool `json:"testmode,omitempty"` IsCancelable bool `json:"isCancelable,omitempty"` ShopperCountryMustMatchTheBillingCountry bool `json:"shopperCountryMustMatchTheBillingCountry,omitempty"` Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` ProfileID string `json:"profileId,omitempty"` - OrderNumber string `json:"orderNumber,omitempty"` RedirectURL string `json:"redirectUrl,omitempty"` - WebhookURL string `json:"webhookUrl,omitempty"` - Description string `json:"description,omitempty"` - Sku string `json:"sku,omitempty"` CancelURL string `json:"cancelUrl,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - Mode Mode `json:"mode,omitempty"` - Method PaymentMethod `json:"method,omitempty"` - Status OrderStatus `json:"status,omitempty"` - Locale Locale `json:"locale,omitempty"` - ShippingAddress OrderAddress `json:"shippingAddress,omitempty"` - Links OrderLinks `json:"_links,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + OrderNumber string `json:"orderNumber,omitempty"` + Lines []*OrderLine `json:"lines,omitempty"` Amount *Amount `json:"amount,omitempty"` AmountCaptured *Amount `json:"amountCaptured,omitempty"` AmountRefunded *Amount `json:"amountRefunded,omitempty"` BillingAddress *OrderAddress `json:"billingAddress,omitempty"` ConsumerDateOfBirth *ShortDate `json:"consumerDateOfBirth,omitempty"` + ShippingAddress *OrderAddress `json:"shippingAddress,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` ExpiresAt *time.Time `json:"expiresAt,omitempty"` ExpiredAt *time.Time `json:"expiredAt,omitempty"` @@ -40,27 +63,46 @@ type Order struct { AuthorizedAt *time.Time `json:"authorizedAt,omitempty"` CanceledAt *time.Time `json:"canceledAt,omitempty"` CompletedAt *time.Time `json:"completedAt,omitempty"` - OrderPayment *OrderPayment `json:"payment,omitempty"` - Lines []*OrderLine `json:"lines,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Mode Mode `json:"mode,omitempty"` + Locale Locale `json:"locale,omitempty"` + Status OrderStatus `json:"status,omitempty"` + Links OrderLinks `json:"_links,omitempty"` + Metadata any `json:"metadata,omitempty"` Embedded struct { Payments []*Payment `json:"payments,omitempty"` Refunds []*Refund `json:"refunds,omitempty"` } `json:"_embedded,omitempty"` } -// OrderPayment describes payment specific parameters that can be passed during order creation. -type OrderPayment struct { - ConsumerAccount string `json:"consumerAccount,omitempty"` - CustomerID string `json:"customerId,omitempty"` - CustomerReference string `json:"customerReference,omitempty"` - Issuer string `json:"issuer,omitempty"` - MandateID string `json:"mandateId,omitempty"` - SequenceType SequenceType `json:"sequenceType,omitempty"` - VoucherNumber string `json:"voucherNumber,omitempty"` - VoucherPin string `json:"voucherPin,omitempty"` - WebhookURL string `json:"webhookUrl,omitempty"` - ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` - Method PaymentMethod `json:"method,omitempty"` +// UpdateOrder contains the parameters to update an order. +type UpdateOrder struct { + OrderNumber string `json:"orderNumber,omitempty"` + RedirectURL string `json:"redirectUrl,omitempty"` + CancelURL string `json:"cancelUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + BillingAddress *OrderAddress `json:"billingAddress,omitempty"` + ShippingAddress *OrderAddress `json:"shippingAddress,omitempty"` + OrderAccessTokenFields +} + +// OrderList for containing the response of list orders. +type OrderList struct { + Count int `json:"count,omitempty"` + Embedded struct { + Orders []*Order `json:"orders,omitempty"` + } `json:"_embedded,omitempty"` + Links PaginationLinks `json:"links,omitempty"` +} + +// OrderLinks describes an object with several URL objects +// relevant to the order. +// Every URL object will contain an href and a type field. +type OrderLinks struct { + Self *URL `json:"self,omitempty"` + Checkout *URL `json:"checkout,omitempty"` + Documentation *URL `json:"documentation,omitempty"` + Dashboard *URL `json:"dashboard,omitempty"` } // OrderStatus describes the valid order status. @@ -77,6 +119,32 @@ const ( Expired OrderStatus = "expired" ) +// OrderPayment describes payment specific parameters that can be passed during order creation. +type OrderPayment struct { + ApplePayPaymentToken string `json:"applePayPaymentToken,omitempty"` + CardToken string `json:"cardToken,omitempty"` + ConsumerAccount string `json:"consumerAccount,omitempty"` + CustomerID string `json:"customerId,omitempty"` + CustomerReference string `json:"customerReference,omitempty"` + ExtraMerchantData string `json:"extraMerchantData,omitempty"` + Issuer string `json:"issuer,omitempty"` + VoucherNumber string `json:"voucherNumber,omitempty"` + VoucherPin string `json:"voucherPin,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + BillingEmail string `json:"billingEmail,omitempty"` + SessionID string `json:"sessionId,omitempty"` + TerminalID string `json:"terminalId,omitempty"` + ConsumerName string `json:"consumerName,omitempty"` + DueDate *ShortDate `json:"dueDate,omitempty"` + ShippingAddress *Address `json:"shippingAddress,omitempty"` + BillingAddress *Address `json:"billingAddress,omitempty"` + Company *Company `json:"company,omitempty"` + // Only available when using access tokens. + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` + SequenceType SequenceType `json:"sequenceType,omitempty"` + Method []PaymentMethod `json:"method,omitempty"` +} + // OrderAddress identify both the address and the person the order is billed or shipped to. type OrderAddress struct { OrganizationName string `json:"organizationName,omitempty"` @@ -84,56 +152,64 @@ type OrderAddress struct { GivenName string `json:"givenName,omitempty"` FamilyName string `json:"familyName,omitempty"` Email string `json:"email,omitempty"` - Phone PhoneNumber `json:"phone,omitempty"` StreetAndNumber string `json:"streetAndNumber,omitempty"` StreetAdditional string `json:"streetAdditional,omitempty"` PostalCode string `json:"postalCode,omitempty"` City string `json:"city,omitempty"` Region string `json:"region,omitempty"` Country string `json:"country,omitempty"` -} - -// OrderLinks describes an object with several URL objects -// relevant to the order. -// Every URL object will contain an href and a type field. -type OrderLinks struct { - Self *URL `json:"self,omitempty"` - Checkout *URL `json:"checkout,omitempty"` - Documentation *URL `json:"documentation,omitempty"` - Dashboard *URL `json:"dashboard,omitempty"` + Phone PhoneNumber `json:"phone,omitempty"` } // OrderLine contain the actual things the customer bought. type OrderLine struct { - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - OrderID string `json:"orderId,omitempty"` - ProductType ProductType `json:"type,omitempty"` - Name string `json:"name,omitempty"` - Amount *Amount `json:"amount,omitempty"` - Status OrderLineStatus `json:"status,omitempty"` IsCancelable bool `json:"isCancelable,omitempty"` Quantity int `json:"quantity,omitempty"` QuantityShipped int `json:"quantityShipped,omitempty"` - AmountShipped *Amount `json:"amountShipped,omitempty"` QuantityRefunded int `json:"quantityRefunded,omitempty"` - AmountRefunded *Amount `json:"amountRefunded,omitempty"` QuantityCanceled int `json:"quantityCanceled,omitempty"` - AmountCanceled *Amount `json:"amountCanceled,omitempty"` ShippableQuantity int `json:"shippableQuantity,omitempty"` RefundableQuantity int `json:"refundableQuantity,omitempty"` CancelableQuantity int `json:"cancelableQuantity,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + OrderID string `json:"orderId,omitempty"` + Name string `json:"name,omitempty"` + VatRate string `json:"vatRate,omitempty"` + SKU string `json:"sku,omitempty"` + AmountShipped *Amount `json:"amountShipped,omitempty"` + AmountRefunded *Amount `json:"amountRefunded,omitempty"` + AmountCanceled *Amount `json:"amountCanceled,omitempty"` UnitPrice *Amount `json:"unitPrice,omitempty"` DiscountAmount *Amount `json:"discountAmount,omitempty"` TotalAmount *Amount `json:"totalAmount,omitempty"` - VatRate string `json:"vatRate,omitempty"` VatAmount *Amount `json:"vatAmount,omitempty"` - SKU string `json:"sku,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` + ProductType ProductKind `json:"type,omitempty"` + Status OrderLineStatus `json:"status,omitempty"` Links OrderLineLinks `json:"_links,omitempty"` - ImageURL string `json:"imageUrl,omitempty"` - ProductURL string `json:"productUrl,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` +} + +// OrderLineLinks describes object with several URL objects relevant to the order line. +type OrderLineLinks struct { + ProductURL *URL `json:"productUrl,omitempty"` + ImageURL *URL `json:"imageUrl,omitempty"` +} + +// UpdateOrderLine contains the parameters to update an order line. +type UpdateOrderLine struct { + Quantity int `json:"quantity,omitempty"` + Name string `json:"name,omitempty"` + ImageURL string `json:"imageUrl,omitempty"` + ProductURL string `json:"productUrl,omitempty"` + SKU string `json:"sku,omitempty"` + VATRate string `json:"vatRate,omitempty"` + UnitPrice *Amount `json:"unitPrice,omitempty"` + DiscountAmount *Amount `json:"discountAmount,omitempty"` + TotalAmount *Amount `json:"totalAmount,omitempty"` + VATAmount *Amount `json:"vatAmount,omitempty"` + Metadata any `json:"metadata,omitempty"` + OrderAccessTokenFields } // OrderLineOperation describes supported operations when managing order lines. @@ -141,9 +217,9 @@ type OrderLineOperation string // Supported order lines operation types. const ( - AddOrderLine OrderLineOperation = "add" - UpdateOrderLine OrderLineOperation = "update" - CancelOrderLine OrderLineOperation = "cancel" + AddOrderLineOperation OrderLineOperation = "add" + UpdateOrderLineOperation OrderLineOperation = "update" + CancelOrderLineOperation OrderLineOperation = "cancel" ) // OrderLineOperationProductCategory contains the product category. @@ -165,14 +241,15 @@ type OrderLineOperationData struct { ImageURL string `json:"imageUrl,omitempty"` ProductURL string `json:"productUrl,omitempty"` VATRate string `json:"vatRate,omitempty"` - Type string `json:"type,omitempty"` + Kind ProductKind `json:"type,omitempty"` Category OrderLineOperationProductCategory `json:"category,omitempty"` Amount *Amount `json:"amount,omitempty"` UnitPrice *Amount `json:"unitPrice,omitempty"` DiscountAmount *Amount `json:"discountAmount,omitempty"` VATAmount *Amount `json:"vatAmount,omitempty"` TotalAmount *Amount `json:"totalAmount,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` + Metadata any `json:"metadata,omitempty"` + OrderAccessTokenFields } // OrderLineChangeInstruction contains details on what needs to be changed when managing order lines. @@ -186,15 +263,6 @@ type OrderLineOperations struct { Operations []*OrderLineChangeInstruction `json:"operations,omitempty"` } -// OrderList for containing the response of list orders. -type OrderList struct { - Count int `json:"count,omitempty"` - Embedded struct { - Orders []*Order `json:"orders,omitempty"` - } `json:"_embedded,omitempty"` - Links PaginationLinks `json:"links,omitempty"` -} - // OrderListRefund for containing the response of list orders. type OrderListRefund struct { Count int `json:"count,omitempty"` @@ -204,18 +272,18 @@ type OrderListRefund struct { Links PaginationLinks `json:"links,omitempty"` } -// ProductType describes the type of product bought, for example, a physical or a digital product. -type ProductType string +// ProductKind describes the type of product bought, for example, a physical or a digital product. +type ProductKind string // Valid product type. const ( - Physical ProductType = "physical" - Discount ProductType = "discount" - Digital ProductType = "digital" - ShippingFee ProductType = "shipping_fee" - StoreCredit ProductType = "store_credit" - GiftCardProduct ProductType = "gift_card" - Surcharge ProductType = "surcharge" + PhysicalProduct ProductKind = "physical" + DiscountProduct ProductKind = "discount" + DigitalProduct ProductKind = "digital" + ShippingFeeProduct ProductKind = "shipping_fee" + StoreCreditProduct ProductKind = "store_credit" + GiftCardProductProduct ProductKind = "gift_card" + SurchargeProduct ProductKind = "surcharge" ) // OrderLineStatus describes status of the order line. @@ -231,23 +299,18 @@ const ( OrderLineCompleted OrderLineStatus = "completed" ) -// OrderLineLinks describes object with several URL objects relevant to the order line. -type OrderLineLinks struct { - ProductURL *URL `json:"productUrl,omitempty"` - ImageURL *URL `json:"imageUrl,omitempty"` -} - // OrderOptions describes order endpoint valid query string parameters. type OrderOptions struct { - Embed []EmbedValue `url:"embed,omitempty"` ProfileID string `url:"profileId,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` } // OrderListOptions describes order endpoint valid query string parameters. type OrderListOptions struct { - ProfileID string `url:"profileId,omitempty"` - From string `url:"from,omitempty"` Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` + Sort string `url:"sort,omitempty"` + ProfileID string `url:"profileId,omitempty"` } // OrderListRefundOptions describes order endpoint valid query string parameters. @@ -283,13 +346,13 @@ func (ors *OrdersService) Get(ctx context.Context, orID string, opts *OrderOptio // Create an order will automatically create the required payment to allow your customer to pay for the order. // // See https://docs.mollie.com/reference/v2/orders-api/create-order -func (ors *OrdersService) Create(ctx context.Context, ord Order, opts *OrderOptions) ( +func (ors *OrdersService) Create(ctx context.Context, ord CreateOrder, opts *OrderOptions) ( res *Response, order *Order, err error, ) { if ors.client.HasAccessToken() && ors.client.config.testing { - ord.TestMode = true + ord.Testmode = true } res, err = ors.client.post(ctx, "v2/orders", ord, opts) @@ -307,11 +370,15 @@ func (ors *OrdersService) Create(ctx context.Context, ord Order, opts *OrderOpti // Update is used to update the billing and/or shipping address of an order. // // See https://docs.mollie.com/reference/v2/orders-api/update-order -func (ors *OrdersService) Update(ctx context.Context, orderID string, ord Order) ( +func (ors *OrdersService) Update(ctx context.Context, orderID string, ord UpdateOrder) ( res *Response, order *Order, err error, ) { + if ors.client.HasAccessToken() && ors.client.config.testing { + ord.Testmode = true + } + res, err = ors.client.patch(ctx, fmt.Sprintf("v2/orders/%s", orderID), ord, nil) if err != nil { return @@ -367,13 +434,17 @@ func (ors *OrdersService) UpdateOrderLine( ctx context.Context, orderID string, orderLineID string, - orderLine OrderLine) ( + orderLine UpdateOrderLine) ( res *Response, order *Order, err error, ) { u := fmt.Sprintf("v2/orders/%s/lines/%s", orderID, orderLineID) + if ors.client.HasAccessToken() && ors.client.config.testing { + orderLine.Testmode = true + } + res, err = ors.client.patch(ctx, u, orderLine, nil) if err != nil { return diff --git a/mollie/orders_test.go b/mollie/orders_test.go index e623af8d..950642d4 100644 --- a/mollie/orders_test.go +++ b/mollie/orders_test.go @@ -214,7 +214,7 @@ func TestOrdersService_Create(t *testing.T) { type args struct { ctx context.Context - order Order + order CreateOrder options *OrderOptions } cases := []struct { @@ -229,8 +229,8 @@ func TestOrdersService_Create(t *testing.T) { "create orders works as expected.", args{ context.Background(), - Order{ - Method: PayPal, + CreateOrder{ + Method: []PaymentMethod{PayPal}, }, &OrderOptions{}, }, @@ -251,8 +251,8 @@ func TestOrdersService_Create(t *testing.T) { "create orders works as expected.", args{ context.Background(), - Order{ - Method: PayPal, + CreateOrder{ + Method: []PaymentMethod{PayPal}, }, &OrderOptions{}, }, @@ -275,8 +275,8 @@ func TestOrdersService_Create(t *testing.T) { "create orders, an error is returned from the server", args{ context.Background(), - Order{ - Method: PayPal, + CreateOrder{ + Method: []PaymentMethod{PayPal}, }, nil, }, @@ -289,8 +289,8 @@ func TestOrdersService_Create(t *testing.T) { "create orders, an error occurs when parsing json", args{ context.Background(), - Order{ - Method: PayPal, + CreateOrder{ + Method: []PaymentMethod{PayPal}, }, nil, }, @@ -303,8 +303,8 @@ func TestOrdersService_Create(t *testing.T) { "create orders, invalid url when building request", args{ context.Background(), - Order{ - Method: PayPal, + CreateOrder{ + Method: []PaymentMethod{PayPal}, }, nil, }, @@ -342,7 +342,7 @@ func TestOrdersService_Update(t *testing.T) { type args struct { ctx context.Context - order Order + order UpdateOrder options *OrderOptions } cases := []struct { @@ -357,9 +357,8 @@ func TestOrdersService_Update(t *testing.T) { "update orders works as expected.", args{ context.Background(), - Order{ - Method: PayPal, - ID: "ord_kEn1PlbGa", + UpdateOrder{ + OrderNumber: "ord_kEn1PlbGa", }, &OrderOptions{}, }, @@ -380,9 +379,7 @@ func TestOrdersService_Update(t *testing.T) { "update orders works as expected.", args{ context.Background(), - Order{ - Method: PayPal, - }, + UpdateOrder{}, &OrderOptions{}, }, false, @@ -404,9 +401,7 @@ func TestOrdersService_Update(t *testing.T) { "update orders, an error is returned from the server", args{ context.Background(), - Order{ - Method: PayPal, - }, + UpdateOrder{}, nil, }, true, @@ -418,9 +413,7 @@ func TestOrdersService_Update(t *testing.T) { "update orders, an error occurs when parsing json", args{ context.Background(), - Order{ - Method: PayPal, - }, + UpdateOrder{}, nil, }, true, @@ -432,9 +425,7 @@ func TestOrdersService_Update(t *testing.T) { "update orders, invalid url when building request", args{ context.Background(), - Order{ - Method: PayPal, - }, + UpdateOrder{}, nil, }, true, @@ -450,9 +441,9 @@ func TestOrdersService_Update(t *testing.T) { t.Run(c.name, func(t *testing.T) { c.pre() - tMux.HandleFunc(fmt.Sprintf("/v2/orders/%s", c.args.order.ID), c.handler) + tMux.HandleFunc(fmt.Sprintf("/v2/orders/%s", c.args.order.OrderNumber), c.handler) - res, m, err := tClient.Orders.Update(c.args.ctx, c.args.order.ID, c.args.order) + res, m, err := tClient.Orders.Update(c.args.ctx, c.args.order.OrderNumber, c.args.order) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) @@ -599,9 +590,10 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { defer unsetEnv() type args struct { - ctx context.Context - order string - line OrderLine + ctx context.Context + order string + orderLine string + line UpdateOrderLine } cases := []struct { name string @@ -616,9 +608,9 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - OrderLine{ - ID: "odl_dgtxyl", - Status: OrderLinePaid, + "odl_dgtxyl", + UpdateOrderLine{ + Name: "new order line", }, }, false, @@ -631,7 +623,7 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) } - _, _ = w.Write([]byte(testdata.UpdateOrderlineResponse)) + _, _ = w.Write([]byte(testdata.UpdateOrderLineResponse)) }, }, { @@ -639,9 +631,9 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - OrderLine{ - ID: "odl_dgtxyl", - Status: OrderLinePaid, + "odl_dgtxyl", + UpdateOrderLine{ + Name: "new order line", }, }, false, @@ -656,7 +648,7 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) } - _, _ = w.Write([]byte(testdata.UpdateOrderlineResponse)) + _, _ = w.Write([]byte(testdata.UpdateOrderLineResponse)) }, }, { @@ -664,10 +656,8 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - OrderLine{ - ID: "odl_dgtxyl", - Status: OrderLinePaid, - }, + "odl_dgtxyl", + UpdateOrderLine{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -679,10 +669,8 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - OrderLine{ - ID: "odl_dgtxyl", - Status: OrderLinePaid, - }, + "odl_dgtxyl", + UpdateOrderLine{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -694,10 +682,8 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - OrderLine{ - ID: "odl_dgtxyl", - Status: OrderLinePaid, - }, + "odl_dgtxyl", + UpdateOrderLine{}, }, true, errBadBaseURL, @@ -712,9 +698,9 @@ func TestOrdersService_UpdateOrderLine(t *testing.T) { t.Run(c.name, func(t *testing.T) { c.pre() - tMux.HandleFunc(fmt.Sprintf("/v2/orders/%s/lines/%s", c.args.order, c.args.line.ID), c.handler) + tMux.HandleFunc(fmt.Sprintf("/v2/orders/%s/lines/%s", c.args.order, c.args.orderLine), c.handler) - res, m, err := tClient.Orders.UpdateOrderLine(c.args.ctx, c.args.order, c.args.line.ID, c.args.line) + res, m, err := tClient.Orders.UpdateOrderLine(c.args.ctx, c.args.order, c.args.orderLine, c.args.line) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) @@ -764,7 +750,7 @@ func TestOrdersService_CancelOrderLine(t *testing.T) { if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) } - _, _ = w.Write([]byte(testdata.UpdateOrderlineResponse)) + _, _ = w.Write([]byte(testdata.UpdateOrderLineResponse)) }, }, { @@ -789,7 +775,7 @@ func TestOrdersService_CancelOrderLine(t *testing.T) { if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) } - _, _ = w.Write([]byte(testdata.UpdateOrderlineResponse)) + _, _ = w.Write([]byte(testdata.UpdateOrderLineResponse)) }, }, { @@ -871,8 +857,8 @@ func TestOrdersService_CreateOrderPayment(t *testing.T) { context.Background(), "ord_8wmqcHMN4U", &OrderPayment{ - Method: PayPal, - Issuer: "tr_asdajnasd", + CustomerReference: "customer_123", + Method: []PaymentMethod{BankTransfer}, }, }, false, @@ -894,8 +880,7 @@ func TestOrdersService_CreateOrderPayment(t *testing.T) { context.Background(), "ord_8wmqcHMN4U", &OrderPayment{ - Method: PayPal, - Issuer: "tr_asdajnasd", + TerminalID: "term_12312312", }, }, false, @@ -1228,7 +1213,7 @@ func TestOrdersService_ManageOrderLines(t *testing.T) { &OrderLineOperations{ Operations: []*OrderLineChangeInstruction{ { - Operation: AddOrderLine, + Operation: AddOrderLineOperation, Data: &OrderLineOperationData{ ID: "odl_1.1l9vx0", Name: "new order line", @@ -1258,7 +1243,7 @@ func TestOrdersService_ManageOrderLines(t *testing.T) { &OrderLineOperations{ Operations: []*OrderLineChangeInstruction{ { - Operation: AddOrderLine, + Operation: AddOrderLineOperation, Data: &OrderLineOperationData{ ID: "odl_1.1l9vx0", Name: "new order line", @@ -1279,7 +1264,7 @@ func TestOrdersService_ManageOrderLines(t *testing.T) { if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) } - _, _ = w.Write([]byte(testdata.UpdateOrderlineResponse)) + _, _ = w.Write([]byte(testdata.UpdateOrderLineResponse)) }, }, { @@ -1290,7 +1275,7 @@ func TestOrdersService_ManageOrderLines(t *testing.T) { &OrderLineOperations{ Operations: []*OrderLineChangeInstruction{ { - Operation: AddOrderLine, + Operation: AddOrderLineOperation, Data: &OrderLineOperationData{ ID: "odl_1.1l9vx0", Name: "new order line", @@ -1312,7 +1297,7 @@ func TestOrdersService_ManageOrderLines(t *testing.T) { &OrderLineOperations{ Operations: []*OrderLineChangeInstruction{ { - Operation: AddOrderLine, + Operation: AddOrderLineOperation, Data: &OrderLineOperationData{ ID: "odl_1.1l9vx0", Name: "new order line", @@ -1334,7 +1319,7 @@ func TestOrdersService_ManageOrderLines(t *testing.T) { &OrderLineOperations{ Operations: []*OrderLineChangeInstruction{ { - Operation: AddOrderLine, + Operation: AddOrderLineOperation, Data: &OrderLineOperationData{ ID: "odl_1.1l9vx0", Name: "new order line", diff --git a/testdata/orders.go b/testdata/orders.go index 932a67ea..c7e79759 100644 --- a/testdata/orders.go +++ b/testdata/orders.go @@ -979,8 +979,8 @@ const UpdateOrderlineRequest = `{ } }` -// UpdateOrderlineResponse example response of update orderline -const UpdateOrderlineResponse = `{ +// UpdateOrderLineResponse example response of update orderline +const UpdateOrderLineResponse = `{ "resource":"order", "id":"ord_pbjz8x", "profileId":"pfl_URR55HPMGx", From 2f37e3101cbff50006af59ebbb6882aa15a1604e Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Sun, 10 Mar 2024 13:05:07 +0100 Subject: [PATCH 14/23] check clients resource against api reference (#341) --- docs/README.md | 213 +++++++++---------- mollie/clients.go | 88 ++++++++ mollie/{partners_test.go => clients_test.go} | 26 +-- mollie/common_types.go | 12 +- mollie/mollie.go | 4 +- mollie/partners.go | 97 --------- 6 files changed, 210 insertions(+), 230 deletions(-) create mode 100644 mollie/clients.go rename mollie/{partners_test.go => clients_test.go} (89%) delete mode 100644 mollie/partners.go diff --git a/docs/README.md b/docs/README.md index 0ee9b420..869eeea0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -90,7 +90,9 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type ClientLinksService](<#ClientLinksService>) - [func \(cls \*ClientLinksService\) Create\(ctx context.Context, cd CreateClientLink\) \(res \*Response, cl \*ClientLink, err error\)](<#ClientLinksService.Create>) - [func \(cls \*ClientLinksService\) GetFinalClientLink\(ctx context.Context, clientLink string, options \*ClientLinkAuthorizeOptions\) \(clientLinkURI string\)](<#ClientLinksService.GetFinalClientLink>) -- [type Commission](<#Commission>) +- [type ClientsService](<#ClientsService>) + - [func \(ps \*ClientsService\) Get\(ctx context.Context, id string, opts \*GetLinkedClientOptions\) \(res \*Response, pc \*LinkedClient, err error\)](<#ClientsService.Get>) + - [func \(ps \*ClientsService\) List\(ctx context.Context, opts \*ListLinkedClientsOptions\) \(res \*Response, pc \*LinkedClientList, err error\)](<#ClientsService.List>) - [type Company](<#Company>) - [type Config](<#Config>) - [func NewAPIConfig\(reqIdem bool\) \*Config](<#NewAPIConfig>) @@ -134,7 +136,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type ErrorLinks](<#ErrorLinks>) - [type FailureReason](<#FailureReason>) - [type FeeRegion](<#FeeRegion>) -- [type GetPartnerClientOptions](<#GetPartnerClientOptions>) +- [type GetLinkedClientOptions](<#GetLinkedClientOptions>) - [type GiftCardEnabled](<#GiftCardEnabled>) - [type GiftCardIssuer](<#GiftCardIssuer>) - [type GiftCardIssuerStatus](<#GiftCardIssuerStatus>) @@ -150,7 +152,10 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(is \*InvoicesService\) Get\(ctx context.Context, id string\) \(res \*Response, i \*Invoice, err error\)](<#InvoicesService.Get>) - [func \(is \*InvoicesService\) List\(ctx context.Context, options \*InvoicesListOptions\) \(res \*Response, il \*InvoicesList, err error\)](<#InvoicesService.List>) - [type LineItem](<#LineItem>) -- [type ListPartnerClientsOptions](<#ListPartnerClientsOptions>) +- [type LinkedClient](<#LinkedClient>) +- [type LinkedClientLinks](<#LinkedClientLinks>) +- [type LinkedClientList](<#LinkedClientList>) +- [type ListLinkedClientsOptions](<#ListLinkedClientsOptions>) - [type ListPaymentOptions](<#ListPaymentOptions>) - [type ListRefundOptions](<#ListRefundOptions>) - [type Locale](<#Locale>) @@ -218,12 +223,6 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(os \*OrganizationsService\) GetPartnerStatus\(ctx context.Context\) \(res \*Response, ops \*OrganizationPartnerStatus, err error\)](<#OrganizationsService.GetPartnerStatus>) - [type Owner](<#Owner>) - [type PaginationLinks](<#PaginationLinks>) -- [type PartnerClient](<#PartnerClient>) -- [type PartnerClientLinks](<#PartnerClientLinks>) -- [type PartnerClientList](<#PartnerClientList>) -- [type PartnerService](<#PartnerService>) - - [func \(ps \*PartnerService\) Get\(ctx context.Context, id string, opts \*GetPartnerClientOptions\) \(res \*Response, pc \*PartnerClient, err error\)](<#PartnerService.Get>) - - [func \(ps \*PartnerService\) List\(ctx context.Context, opts \*ListPartnerClientsOptions\) \(res \*Response, pc \*PartnerClientList, err error\)](<#PartnerService.List>) - [type PartnerType](<#PartnerType>) - [type Payment](<#Payment>) - [type PaymentDestination](<#PaymentDestination>) @@ -1393,7 +1392,7 @@ type Client struct { Permissions *PermissionsService Onboarding *OnboardingService PaymentLinks *PaymentLinksService - Partners *PartnerService + Clients *ClientsService Balances *BalancesService ClientLinks *ClientLinksService Terminals *TerminalsService @@ -1533,18 +1532,37 @@ func (cls *ClientLinksService) GetFinalClientLink(ctx context.Context, clientLin GetFinalClientLink returns the final client link URI with the provided options. - -## type [Commission]() + +## type [ClientsService]() -Commission describes a partner take from any operation on Mollie's API. +ClientsService operates over the partners API. ```go -type Commission struct { - Count int `json:"count,omitempty"` - TotalAmount *Amount `json:"totalAmount,omitempty"` -} +type ClientsService service +``` + + +### func \(\*ClientsService\) [Get]() + +```go +func (ps *ClientsService) Get(ctx context.Context, id string, opts *GetLinkedClientOptions) (res *Response, pc *LinkedClient, err error) ``` +Get retrieves a single client, linked to your partner account, by its ID. + +See: https://docs.mollie.com/reference/v2/partners-api/get-client + + +### func \(\*ClientsService\) [List]() + +```go +func (ps *ClientsService) List(ctx context.Context, opts *ListLinkedClientsOptions) (res *Response, pc *LinkedClientList, err error) +``` + +List retrieves all clients. + +See: https://docs.mollie.com/reference/v2/partners-api/list-clients + ## type [Company]() @@ -2211,11 +2229,13 @@ type EmbedValue string ```go const ( - EmbedPayments EmbedValue = "payments" - EmbedRefunds EmbedValue = "refunds" - EmbedShipments EmbedValue = "shipments" - EmbedChargebacks EmbedValue = "chargebacks" - EmbedCaptures EmbedValue = "captures" + EmbedPayments EmbedValue = "payments" + EmbedRefunds EmbedValue = "refunds" + EmbedShipments EmbedValue = "shipments" + EmbedChargebacks EmbedValue = "chargebacks" + EmbedCaptures EmbedValue = "captures" + EmbedOrganization EmbedValue = "organization" + EmbedOnboarding EmbedValue = "onboarding" ) ``` @@ -2313,14 +2333,14 @@ const ( ) ``` - -## type [GetPartnerClientOptions]() + +## type [GetLinkedClientOptions]() -GetPartnerClientOptions contains valid query parameters for the get clients endpoint. +GetLinkedClientOptions contains valid query parameters for the get clients endpoint. ```go -type GetPartnerClientOptions struct { - Embed string `url:"embed,omitempty"` +type GetLinkedClientOptions struct { + Embed []EmbedValue `url:"embed,omitempty"` } ``` @@ -2420,7 +2440,7 @@ type GiftCardLinks struct { ``` -## type [Image]() +## type [Image]() Image describes a generic image resource retrieved by Mollie. @@ -2576,17 +2596,59 @@ type LineItem struct { } ``` - -## type [ListPartnerClientsOptions]() + +## type [LinkedClient]() + +LinkedClient describes a single client, linked to your partner account. + +```go +type LinkedClient struct { + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + OrganizationCreatedAt *time.Time `json:"organizationCreatedAt,omitempty"` + Links LinkedClientLinks `json:"_links,omitempty"` +} +``` + + +## type [LinkedClientLinks]() -ListPartnerClientsOptions contains valid query parameters for the list clients endpoint. +LinkedClientLinks contains URL objects relevant to the client. ```go -type ListPartnerClientsOptions struct { - From int `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - Year int `url:"year,omitempty"` - Month int `url:"month,omitempty"` +type LinkedClientLinks struct { + Self *URL `json:"self,omitempty"` + Organization *URL `json:"organization,omitempty"` + Onboarding *URL `json:"onboarding,omitempty"` + Documentation *URL `json:"documentation,omitempty"` +} +``` + + +## type [LinkedClientList]() + +LinkedClientList describes a list of partner clients. + +```go +type LinkedClientList struct { + Count int `json:"count,omitempty"` + PartnerClients struct { + Clients []*LinkedClient `json:"clients,omitempty"` + } `json:"_embedded,omitempty"` + Links PaginationLinks `json:"_links,omitempty"` +} +``` + + +## type [ListLinkedClientsOptions]() + +ListLinkedClientsOptions contains valid query parameters for the list clients endpoint. + +```go +type ListLinkedClientsOptions struct { + Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` } ``` @@ -3595,7 +3657,7 @@ GetPartnerStatus retrieves details about the partner status of the currently aut See: https://docs.mollie.com/reference/v2/organizations-api/get-partner -## type [Owner]() +## type [Owner]() Personal data of your customer. @@ -3622,81 +3684,6 @@ type PaginationLinks struct { } ``` - -## type [PartnerClient]() - -PartnerClient describes a partner client. - -```go -type PartnerClient struct { - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - OrganizationCreatedAt *time.Time `json:"organizationCreatedAt,omitempty"` - Commission Commission `json:"commission,omitempty"` - Links PartnerClientLinks `json:"_links,omitempty"` -} -``` - - -## type [PartnerClientLinks]() - -PartnerClientLinks contains URL objects relevant to the client. - -```go -type PartnerClientLinks struct { - Self *URL `json:"self,omitempty"` - Organization *URL `json:"organization,omitempty"` - Onboarding *URL `json:"onboarding,omitempty"` - Documentation *URL `json:"documentation,omitempty"` -} -``` - - -## type [PartnerClientList]() - -PartnerClientList describes a list of partner clients. - -```go -type PartnerClientList struct { - Count int `json:"count,omitempty"` - PartnerClients struct { - Clients []*PartnerClient `json:"clients,omitempty"` - } `json:"_embedded,omitempty"` - Links PaginationLinks `json:"_links,omitempty"` -} -``` - - -## type [PartnerService]() - -PartnerService operates over the partners API. - -```go -type PartnerService service -``` - - -### func \(\*PartnerService\) [Get]() - -```go -func (ps *PartnerService) Get(ctx context.Context, id string, opts *GetPartnerClientOptions) (res *Response, pc *PartnerClient, err error) -``` - -Get retrieves a single client, linked to your partner account, by its ID. - -See: https://docs.mollie.com/reference/v2/partners-api/get-client - - -### func \(\*PartnerService\) [List]() - -```go -func (ps *PartnerService) List(ctx context.Context, opts *ListPartnerClientsOptions) (res *Response, pc *PartnerClientList, err error) -``` - -List retrieves all clients. - -See: https://docs.mollie.com/reference/v2/partners-api/list-clients - ## type [PartnerType]() @@ -4668,7 +4655,7 @@ type QRCode struct { ``` -## type [Rate]() +## type [Rate]() Rate describes service rates, further divided into fixed and percentage costs. diff --git a/mollie/clients.go b/mollie/clients.go new file mode 100644 index 00000000..1ec59c2c --- /dev/null +++ b/mollie/clients.go @@ -0,0 +1,88 @@ +package mollie + +import ( + "context" + "encoding/json" + "fmt" + "time" +) + +// LinkedClient describes a single client, linked to your partner account. +type LinkedClient struct { + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + OrganizationCreatedAt *time.Time `json:"organizationCreatedAt,omitempty"` + Links LinkedClientLinks `json:"_links,omitempty"` +} + +// LinkedClientLinks contains URL objects relevant to the client. +type LinkedClientLinks struct { + Self *URL `json:"self,omitempty"` + Organization *URL `json:"organization,omitempty"` + Onboarding *URL `json:"onboarding,omitempty"` + Documentation *URL `json:"documentation,omitempty"` +} + +// GetLinkedClientOptions contains valid query parameters for the get clients endpoint. +type GetLinkedClientOptions struct { + Embed []EmbedValue `url:"embed,omitempty"` +} + +// LinkedClientList describes a list of partner clients. +type LinkedClientList struct { + Count int `json:"count,omitempty"` + PartnerClients struct { + Clients []*LinkedClient `json:"clients,omitempty"` + } `json:"_embedded,omitempty"` + Links PaginationLinks `json:"_links,omitempty"` +} + +// ListLinkedClientsOptions contains valid query parameters for the list clients endpoint. +type ListLinkedClientsOptions struct { + Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` +} + +// ClientsService operates over the partners API. +type ClientsService service + +// List retrieves all clients. +// +// See: https://docs.mollie.com/reference/v2/partners-api/list-clients +func (ps *ClientsService) List(ctx context.Context, opts *ListLinkedClientsOptions) ( + res *Response, + pc *LinkedClientList, + err error, +) { + res, err = ps.client.get(ctx, "v2/clients", opts) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &pc); err != nil { + return + } + + return +} + +// Get retrieves a single client, linked to your partner account, by its ID. +// +// See: https://docs.mollie.com/reference/v2/partners-api/get-client +func (ps *ClientsService) Get(ctx context.Context, id string, opts *GetLinkedClientOptions) ( + res *Response, + pc *LinkedClient, + err error, +) { + res, err = ps.client.get(ctx, fmt.Sprintf("v2/clients/%s", id), opts) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &pc); err != nil { + return + } + + return +} diff --git a/mollie/partners_test.go b/mollie/clients_test.go similarity index 89% rename from mollie/partners_test.go rename to mollie/clients_test.go index 1f7b2244..9736afb4 100644 --- a/mollie/partners_test.go +++ b/mollie/clients_test.go @@ -10,14 +10,14 @@ import ( "github.com/stretchr/testify/assert" ) -func TestPartnerService_Get(t *testing.T) { +func TestClientsService_Get(t *testing.T) { setEnv() defer unsetEnv() type args struct { ctx context.Context client string - opts *GetPartnerClientOptions + opts *GetLinkedClientOptions } cases := []struct { @@ -53,8 +53,8 @@ func TestPartnerService_Get(t *testing.T) { args{ context.Background(), "org_1337", - &GetPartnerClientOptions{ - Embed: "organization", + &GetLinkedClientOptions{ + Embed: []EmbedValue{EmbedOrganization}, }, }, false, @@ -117,27 +117,27 @@ func TestPartnerService_Get(t *testing.T) { c.pre() tMux.HandleFunc(fmt.Sprintf("/v2/clients/%s", c.args.client), c.handler) - res, m, err := tClient.Partners.Get(c.args.ctx, c.args.client, c.args.opts) + res, m, err := tClient.Clients.Get(c.args.ctx, c.args.client, c.args.opts) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &PartnerClient{}, m) + assert.IsType(t, &LinkedClient{}, m) assert.IsType(t, &http.Response{}, res.Response) } }) } } -func TestPartnerService_List(t *testing.T) { +func TestClientService_List(t *testing.T) { setEnv() defer unsetEnv() type args struct { ctx context.Context client string - opts *ListPartnerClientsOptions + opts *ListLinkedClientsOptions } cases := []struct { @@ -173,8 +173,8 @@ func TestPartnerService_List(t *testing.T) { args{ context.Background(), "org_1337", - &ListPartnerClientsOptions{ - Year: 2021, + &ListLinkedClientsOptions{ + Embed: []EmbedValue{EmbedOrganization}, }, }, false, @@ -183,7 +183,7 @@ func TestPartnerService_List(t *testing.T) { func(w http.ResponseWriter, r *http.Request) { testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") testMethod(t, r, "GET") - testQuery(t, r, "year=2021") + testQuery(t, r, "embed=organization") if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) @@ -237,13 +237,13 @@ func TestPartnerService_List(t *testing.T) { c.pre() tMux.HandleFunc("/v2/clients", c.handler) - res, m, err := tClient.Partners.List(c.args.ctx, c.args.opts) + res, m, err := tClient.Clients.List(c.args.ctx, c.args.opts) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &PartnerClientList{}, m) + assert.IsType(t, &LinkedClientList{}, m) assert.IsType(t, &http.Response{}, res.Response) } }) diff --git a/mollie/common_types.go b/mollie/common_types.go index 5dd26c9b..b40d7bdd 100644 --- a/mollie/common_types.go +++ b/mollie/common_types.go @@ -335,11 +335,13 @@ type EmbedValue string // Valid Embed query string value. const ( - EmbedPayments EmbedValue = "payments" - EmbedRefunds EmbedValue = "refunds" - EmbedShipments EmbedValue = "shipments" - EmbedChargebacks EmbedValue = "chargebacks" - EmbedCaptures EmbedValue = "captures" + EmbedPayments EmbedValue = "payments" + EmbedRefunds EmbedValue = "refunds" + EmbedShipments EmbedValue = "shipments" + EmbedChargebacks EmbedValue = "chargebacks" + EmbedCaptures EmbedValue = "captures" + EmbedOrganization EmbedValue = "organization" + EmbedOnboarding EmbedValue = "onboarding" ) // Rate describes service rates, further divided into fixed and percentage costs. diff --git a/mollie/mollie.go b/mollie/mollie.go index f3b2f446..b19e52c7 100644 --- a/mollie/mollie.go +++ b/mollie/mollie.go @@ -68,7 +68,7 @@ type Client struct { Permissions *PermissionsService Onboarding *OnboardingService PaymentLinks *PaymentLinksService - Partners *PartnerService + Clients *ClientsService Balances *BalancesService ClientLinks *ClientLinksService Terminals *TerminalsService @@ -304,7 +304,7 @@ func NewClient(baseClient *http.Client, conf *Config) (mollie *Client, err error mollie.Permissions = (*PermissionsService)(&mollie.common) mollie.Onboarding = (*OnboardingService)(&mollie.common) mollie.PaymentLinks = (*PaymentLinksService)(&mollie.common) - mollie.Partners = (*PartnerService)(&mollie.common) + mollie.Clients = (*ClientsService)(&mollie.common) mollie.Balances = (*BalancesService)(&mollie.common) mollie.ClientLinks = (*ClientLinksService)(&mollie.common) mollie.Terminals = (*TerminalsService)(&mollie.common) diff --git a/mollie/partners.go b/mollie/partners.go deleted file mode 100644 index 3f3ca670..00000000 --- a/mollie/partners.go +++ /dev/null @@ -1,97 +0,0 @@ -package mollie - -import ( - "context" - "encoding/json" - "fmt" - "time" -) - -// PartnerClient describes a partner client. -type PartnerClient struct { - Resource string `json:"resource,omitempty"` - ID string `json:"id,omitempty"` - OrganizationCreatedAt *time.Time `json:"organizationCreatedAt,omitempty"` - Commission Commission `json:"commission,omitempty"` - Links PartnerClientLinks `json:"_links,omitempty"` -} - -// PartnerClientList describes a list of partner clients. -type PartnerClientList struct { - Count int `json:"count,omitempty"` - PartnerClients struct { - Clients []*PartnerClient `json:"clients,omitempty"` - } `json:"_embedded,omitempty"` - Links PaginationLinks `json:"_links,omitempty"` -} - -// PartnerClientLinks contains URL objects relevant to the client. -type PartnerClientLinks struct { - Self *URL `json:"self,omitempty"` - Organization *URL `json:"organization,omitempty"` - Onboarding *URL `json:"onboarding,omitempty"` - Documentation *URL `json:"documentation,omitempty"` -} - -// Commission describes a partner take from any -// operation on Mollie's API. -type Commission struct { - Count int `json:"count,omitempty"` - TotalAmount *Amount `json:"totalAmount,omitempty"` -} - -// GetPartnerClientOptions contains valid query parameters for the get clients endpoint. -type GetPartnerClientOptions struct { - Embed string `url:"embed,omitempty"` -} - -// ListPartnerClientsOptions contains valid query parameters for the list clients endpoint. -type ListPartnerClientsOptions struct { - From int `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - Year int `url:"year,omitempty"` - Month int `url:"month,omitempty"` -} - -// PartnerService operates over the partners API. -type PartnerService service - -// List retrieves all clients. -// -// See: https://docs.mollie.com/reference/v2/partners-api/list-clients -func (ps *PartnerService) List(ctx context.Context, opts *ListPartnerClientsOptions) ( - res *Response, - pc *PartnerClientList, - err error, -) { - res, err = ps.client.get(ctx, "v2/clients", opts) - if err != nil { - return - } - - if err = json.Unmarshal(res.content, &pc); err != nil { - return - } - - return -} - -// Get retrieves a single client, linked to your partner account, by its ID. -// -// See: https://docs.mollie.com/reference/v2/partners-api/get-client -func (ps *PartnerService) Get(ctx context.Context, id string, opts *GetPartnerClientOptions) ( - res *Response, - pc *PartnerClient, - err error, -) { - res, err = ps.client.get(ctx, fmt.Sprintf("v2/clients/%s", id), opts) - if err != nil { - return - } - - if err = json.Unmarshal(res.content, &pc); err != nil { - return - } - - return -} From 654201dbf8e27ea374c36e054dbc63a3a5724902 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:07:13 +0100 Subject: [PATCH 15/23] check payment methods resource against api reference (#345) --- docs/README.md | 75 ++++++++++++++++++++++------------ mollie/common_types.go | 6 ++- mollie/custom_types_test.go | 55 +++++++++++++++++++++++++ mollie/payment_methods.go | 25 ++++++------ mollie/payment_methods_test.go | 12 ++++-- mollie/wallets.go | 8 ++++ 6 files changed, 136 insertions(+), 45 deletions(-) diff --git a/docs/README.md b/docs/README.md index 869eeea0..360c1ba5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -363,6 +363,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type UpdatePayment](<#UpdatePayment>) - [type UsedGiftCard](<#UsedGiftCard>) - [type UserAgentToken](<#UserAgentToken>) +- [type Wallet](<#Wallet>) - [type WalletsService](<#WalletsService>) - [func \(ms \*WalletsService\) ApplePaymentSession\(ctx context.Context, asr \*ApplePaymentSessionRequest\) \(res \*Response, aps \*ApplePaymentSession, err error\)](<#WalletsService.ApplePaymentSession>) @@ -434,13 +435,13 @@ Amount represents a currency and value pair. ```go type Amount struct { - Currency string `json:"currency,omitempty"` - Value string `json:"value,omitempty"` + Currency string `json:"currency,omitempty" url:"currency,omitempty"` + Value string `json:"value,omitempty" url:"value,omitempty"` } ``` -## type [ApplePaymentSession]() +## type [ApplePaymentSession]() ApplePaymentSession contains information about an Apple pay session. @@ -458,7 +459,7 @@ type ApplePaymentSession struct { ``` -## type [ApplePaymentSessionRequest]() +## type [ApplePaymentSessionRequest]() ApplePaymentSessionRequest contains the body parameters for requesting a valid PaymentSession from Apple. @@ -2217,7 +2218,7 @@ const ( ``` -## type [EmbedValue]() +## type [EmbedValue]() EmbedValue describes the valid value of embed query string. @@ -2440,7 +2441,7 @@ type GiftCardLinks struct { ``` -## type [Image]() +## type [Image]() Image describes a generic image resource retrieved by Mollie. @@ -2467,6 +2468,8 @@ type IncludeValue string const ( IncludeQrCode IncludeValue = "details.qrCode" IncludeRemainderDetails IncludeValue = "details.remainderDetails" + IncludeIssuers IncludeValue = "issuers" + IncludePricing IncludeValue = "pricing" ) ``` @@ -3657,7 +3660,7 @@ GetPartnerStatus retrieves details about the partner status of the currently aut See: https://docs.mollie.com/reference/v2/organizations-api/get-partner -## type [Owner]() +## type [Owner]() Personal data of your customer. @@ -4054,7 +4057,7 @@ type PaymentMethodIssuer struct { Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` - Image Image `json:"image,omitempty"` + Image *Image `json:"image,omitempty"` } ``` @@ -4065,10 +4068,10 @@ PaymentMethodOptions are applicable query string parameters to get methods from ```go type PaymentMethodOptions struct { - Locale Locale `url:"locale,omitempty"` - Currency string `url:"currency,omitempty"` - ProfileID string `url:"profileId,omitempty"` - Include string `url:"include,omitempty"` + Locale Locale `url:"locale,omitempty"` + Currency string `url:"currency,omitempty"` + ProfileID string `url:"profileId,omitempty"` + Include []IncludeValue `url:"include,omitempty"` } ``` @@ -4080,8 +4083,8 @@ PaymentMethodPricing contains information about commissions and fees applicable ```go type PaymentMethodPricing struct { Description string `json:"description,omitempty"` - Fixed *Amount `json:"fixed,omitempty"` Variable string `json:"variable,omitempty"` + Fixed *Amount `json:"fixed,omitempty"` FeeRegion FeeRegion `json:"feeRegion,omitempty"` } ``` @@ -4123,7 +4126,7 @@ type PaymentMethodsList struct { ``` -## type [PaymentMethodsListOptions]() +## type [PaymentMethodsListOptions]() PaymentMethodsListOptions are applicable query string parameters to list methods from mollie's API. @@ -4132,17 +4135,18 @@ It contains list specific options and embeds GetMethodOptions. ```go type PaymentMethodsListOptions struct { PaymentMethodOptions - SequenceType SequenceType `url:"sequenceType,omitempty"` - AmountCurrency string `url:"amount[currency],omitempty"` - AmountValue string `url:"amount[value],omitempty"` - Resource string `url:"resource,omitempty"` - BillingCountry string `url:"billingCountry,omitempty"` - IncludeWallets string `url:"includeWallets,omitempty"` + Resource string `url:"resource,omitempty"` + BillingCountry string `url:"billingCountry,omitempty"` + Amount *Amount `url:"amount,omitempty"` + IncludeWallets []Wallet `url:"includeWallets,omitempty"` + OrderLineCategories []OrderLineOperationProductCategory `url:"orderLineCategories,omitempty"` + Locale Locale `url:"locale,omitempty"` + SequenceType SequenceType `url:"sequenceType,omitempty"` } ``` -## type [PaymentMethodsService]() +## type [PaymentMethodsService]() PaymentMethodsService operates on methods endpoints. @@ -4151,7 +4155,7 @@ type PaymentMethodsService service ``` -### func \(\*PaymentMethodsService\) [All]() +### func \(\*PaymentMethodsService\) [All]() ```go func (ms *PaymentMethodsService) All(ctx context.Context, options *PaymentMethodsListOptions) (res *Response, pm *PaymentMethodsList, err error) @@ -4162,7 +4166,7 @@ All retrieves all the payment methods enabled for your account/organization. See: https://docs.mollie.com/reference/v2/methods-api/list-all-methods -### func \(\*PaymentMethodsService\) [Get]() +### func \(\*PaymentMethodsService\) [Get]() ```go func (ms *PaymentMethodsService) Get(ctx context.Context, id PaymentMethod, options *PaymentMethodOptions) (res *Response, pmd *PaymentMethodDetails, err error) @@ -4173,7 +4177,7 @@ Get returns information about the payment method specified by id, it also receiv See: https://docs.mollie.com/reference/v2/methods-api/get-method -### func \(\*PaymentMethodsService\) [List]() +### func \(\*PaymentMethodsService\) [List]() ```go func (ms *PaymentMethodsService) List(ctx context.Context, options *PaymentMethodsListOptions) (res *Response, pm *PaymentMethodsList, err error) @@ -4655,7 +4659,7 @@ type QRCode struct { ``` -## type [Rate]() +## type [Rate]() Rate describes service rates, further divided into fixed and percentage costs. @@ -5720,8 +5724,25 @@ type UserAgentToken struct { } ``` + +## type [Wallet]() + +Wallet describes the wallet types that Mollie supports. + +```go +type Wallet string +``` + +Available wallet types. + +```go +const ( + ApplePayWallet Wallet = "applepay" +) +``` + -## type [WalletsService]() +## type [WalletsService]() WalletsService operates over the resources described in Mollie's wallets API endpoints section. @@ -5730,7 +5751,7 @@ type WalletsService service ``` -### func \(\*WalletsService\) [ApplePaymentSession]() +### func \(\*WalletsService\) [ApplePaymentSession]() ```go func (ms *WalletsService) ApplePaymentSession(ctx context.Context, asr *ApplePaymentSessionRequest) (res *Response, aps *ApplePaymentSession, err error) diff --git a/mollie/common_types.go b/mollie/common_types.go index b40d7bdd..353df52f 100644 --- a/mollie/common_types.go +++ b/mollie/common_types.go @@ -9,8 +9,8 @@ import ( // Amount represents a currency and value pair. type Amount struct { - Currency string `json:"currency,omitempty"` - Value string `json:"value,omitempty"` + Currency string `json:"currency,omitempty" url:"currency,omitempty"` + Value string `json:"value,omitempty" url:"value,omitempty"` } // Address provides a human friendly representation of a geographical space. @@ -328,6 +328,8 @@ type IncludeValue string const ( IncludeQrCode IncludeValue = "details.qrCode" IncludeRemainderDetails IncludeValue = "details.remainderDetails" + IncludeIssuers IncludeValue = "issuers" + IncludePricing IncludeValue = "pricing" ) // EmbedValue describes the valid value of embed query string. diff --git a/mollie/custom_types_test.go b/mollie/custom_types_test.go index e7f3cc7e..b3762182 100644 --- a/mollie/custom_types_test.go +++ b/mollie/custom_types_test.go @@ -3,6 +3,7 @@ package mollie import ( "testing" + "github.com/google/go-querystring/query" "github.com/stretchr/testify/assert" ) @@ -71,3 +72,57 @@ func TestContextValues_UnmarshalJSON(t *testing.T) { }) } } + +func TestAmount_URLEncodingSimple(t *testing.T) { + tests := []struct { + name string + a Amount + want string + }{ + { + name: "Test URL encoding simple.", + a: Amount{ + Value: "10.00", + Currency: "EUR", + }, + want: "currency=EUR&value=10.00", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v, err := query.Values(tt.a) + assert.Nil(t, err) + assert.Equal(t, tt.want, v.Encode()) + }) + } +} + +func TestAmount_URLEncodingNested(t *testing.T) { + tests := []struct { + name string + a struct { + Amount Amount `url:"amount"` + } + want string + }{ + { + name: "Test URL encoding nested amount in struct.", + a: struct { + Amount Amount `url:"amount"` + }{ + Amount{ + Value: "10.00", + Currency: "EUR", + }, + }, + want: "amount%5Bcurrency%5D=EUR&amount%5Bvalue%5D=10.00", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v, err := query.Values(tt.a) + assert.Nil(t, err) + assert.Equal(t, tt.want, v.Encode()) + }) + } +} diff --git a/mollie/payment_methods.go b/mollie/payment_methods.go index 78414b1d..1c277abb 100644 --- a/mollie/payment_methods.go +++ b/mollie/payment_methods.go @@ -44,8 +44,8 @@ type MethodsLinks struct { // applicable to a payment method. type PaymentMethodPricing struct { Description string `json:"description,omitempty"` - Fixed *Amount `json:"fixed,omitempty"` Variable string `json:"variable,omitempty"` + Fixed *Amount `json:"fixed,omitempty"` FeeRegion FeeRegion `json:"feeRegion,omitempty"` } @@ -55,7 +55,7 @@ type PaymentMethodIssuer struct { Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` - Image Image `json:"image,omitempty"` + Image *Image `json:"image,omitempty"` } // PaymentMethodsList describes a list of paginated payment methods. @@ -70,10 +70,10 @@ type PaymentMethodsList struct { // PaymentMethodOptions are applicable query string parameters to get methods // from mollie's API. type PaymentMethodOptions struct { - Locale Locale `url:"locale,omitempty"` - Currency string `url:"currency,omitempty"` - ProfileID string `url:"profileId,omitempty"` - Include string `url:"include,omitempty"` + Locale Locale `url:"locale,omitempty"` + Currency string `url:"currency,omitempty"` + ProfileID string `url:"profileId,omitempty"` + Include []IncludeValue `url:"include,omitempty"` } // PaymentMethodsListOptions are applicable query string parameters to list methods @@ -82,12 +82,13 @@ type PaymentMethodOptions struct { // It contains list specific options and embeds GetMethodOptions. type PaymentMethodsListOptions struct { PaymentMethodOptions - SequenceType SequenceType `url:"sequenceType,omitempty"` - AmountCurrency string `url:"amount[currency],omitempty"` - AmountValue string `url:"amount[value],omitempty"` - Resource string `url:"resource,omitempty"` - BillingCountry string `url:"billingCountry,omitempty"` - IncludeWallets string `url:"includeWallets,omitempty"` + Resource string `url:"resource,omitempty"` + BillingCountry string `url:"billingCountry,omitempty"` + Amount *Amount `url:"amount,omitempty"` + IncludeWallets []Wallet `url:"includeWallets,omitempty"` + OrderLineCategories []OrderLineOperationProductCategory `url:"orderLineCategories,omitempty"` + Locale Locale `url:"locale,omitempty"` + SequenceType SequenceType `url:"sequenceType,omitempty"` } // PaymentMethodsService operates on methods endpoints. diff --git a/mollie/payment_methods_test.go b/mollie/payment_methods_test.go index 9fe60efe..8a0387bd 100644 --- a/mollie/payment_methods_test.go +++ b/mollie/payment_methods_test.go @@ -51,8 +51,10 @@ func TestMethodsService_List(t *testing.T) { args{ context.Background(), &PaymentMethodsListOptions{ - AmountCurrency: "EUR", - AmountValue: "100.00", + Amount: &Amount{ + Value: "100.00", + Currency: "EUR", + }, }, }, false, @@ -166,8 +168,10 @@ func TestMethodsService_All(t *testing.T) { args{ context.Background(), &PaymentMethodsListOptions{ - AmountCurrency: "EUR", - AmountValue: "100.00", + Amount: &Amount{ + Value: "100.00", + Currency: "EUR", + }, }, }, false, diff --git a/mollie/wallets.go b/mollie/wallets.go index bc429edd..e0caeec1 100644 --- a/mollie/wallets.go +++ b/mollie/wallets.go @@ -5,6 +5,14 @@ import ( "encoding/json" ) +// Wallet describes the wallet types that Mollie supports. +type Wallet string + +// Available wallet types. +const ( + ApplePayWallet Wallet = "applepay" +) + // WalletsService operates over the resources described // in Mollie's wallets API endpoints section. type WalletsService service From e2192bc59ba18e1ecddf52b1f752758ee77158bf Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:20:47 +0100 Subject: [PATCH 16/23] check permissions resource against api reference (#346) --- docs/README.md | 22 ++++++++++++++-------- mollie/permissions.go | 10 ++++++++-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/docs/README.md b/docs/README.md index 360c1ba5..de96a39e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4279,16 +4279,16 @@ Update can be used to update some details of a created payment. See: https://docs.mollie.com/reference/v2/payments-api/update-payment -## type [Permission]() +## type [Permission]() Permission represents an action that can be performed by any API actor. ```go type Permission struct { + Granted bool `json:"granted,omitempty"` Resource string `json:"resource,omitempty"` - ID PermissionGrant `json:"id,omitempty"` Description string `json:"description,omitempty"` - Granted bool `json:"granted,omitempty"` + ID PermissionGrant `json:"id,omitempty"` Links PermissionLinks `json:"_links,omitempty"` } ``` @@ -4319,6 +4319,7 @@ const ( ProfilesRead PermissionGrant = "profiles.read" ProfilesWrite PermissionGrant = "profiles.write" InvoicesRead PermissionGrant = "invoices.read" + SettlementsRead PermissionGrant = "settlements.read" OrdersRead PermissionGrant = "orders.read" OrdersWrite PermissionGrant = "orders.write" ShipmentsRead PermissionGrant = "shipments.read" @@ -4327,11 +4328,16 @@ const ( OrganizationsWrite PermissionGrant = "organizations.write" OnboardingRead PermissionGrant = "onboarding.read" OnboardingWrite PermissionGrant = "onbording.write" + PaymentLinksRead PermissionGrant = "payment-links.read" + PaymentLinksWrite PermissionGrant = "payment-links.write" + BalancesRead PermissionGrant = "balances.read" + TerminalsRead PermissionGrant = "terminals.read" + TerminalsWrite PermissionGrant = "terminals.write" ) ``` -## type [PermissionLinks]() +## type [PermissionLinks]() PermissionLinks contains URL objects that make reference to an http address related to permissions. @@ -4343,7 +4349,7 @@ type PermissionLinks struct { ``` -## type [PermissionsList]() +## type [PermissionsList]() PermissionsList lists all the permissions given to an API actor. @@ -4358,7 +4364,7 @@ type PermissionsList struct { ``` -## type [PermissionsService]() +## type [PermissionsService]() PermissionsService operates over permission resources. @@ -4367,7 +4373,7 @@ type PermissionsService service ``` -### func \(\*PermissionsService\) [Get]() +### func \(\*PermissionsService\) [Get]() ```go func (ps *PermissionsService) Get(ctx context.Context, id PermissionGrant) (res *Response, p *Permission, err error) @@ -4378,7 +4384,7 @@ Get returns a permission by its id. See: https://docs.mollie.com/reference/v2/permissions-api/get-permission -### func \(\*PermissionsService\) [List]() +### func \(\*PermissionsService\) [List]() ```go func (ps *PermissionsService) List(ctx context.Context) (res *Response, pl *PermissionsList, err error) diff --git a/mollie/permissions.go b/mollie/permissions.go index 9e44e308..ca2008ea 100644 --- a/mollie/permissions.go +++ b/mollie/permissions.go @@ -24,6 +24,7 @@ const ( ProfilesRead PermissionGrant = "profiles.read" ProfilesWrite PermissionGrant = "profiles.write" InvoicesRead PermissionGrant = "invoices.read" + SettlementsRead PermissionGrant = "settlements.read" OrdersRead PermissionGrant = "orders.read" OrdersWrite PermissionGrant = "orders.write" ShipmentsRead PermissionGrant = "shipments.read" @@ -32,15 +33,20 @@ const ( OrganizationsWrite PermissionGrant = "organizations.write" OnboardingRead PermissionGrant = "onboarding.read" OnboardingWrite PermissionGrant = "onbording.write" + PaymentLinksRead PermissionGrant = "payment-links.read" + PaymentLinksWrite PermissionGrant = "payment-links.write" + BalancesRead PermissionGrant = "balances.read" + TerminalsRead PermissionGrant = "terminals.read" + TerminalsWrite PermissionGrant = "terminals.write" ) // Permission represents an action that // can be performed by any API actor. type Permission struct { + Granted bool `json:"granted,omitempty"` Resource string `json:"resource,omitempty"` - ID PermissionGrant `json:"id,omitempty"` Description string `json:"description,omitempty"` - Granted bool `json:"granted,omitempty"` + ID PermissionGrant `json:"id,omitempty"` Links PermissionLinks `json:"_links,omitempty"` } From 04105314143822af76e50c054bee029d91546f0e Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 15 Mar 2024 12:48:02 +0100 Subject: [PATCH 17/23] check profiles resource against api reference (#348) --- docs/README.md | 359 +++++++++++++++++++++++++++--------- mollie/gift_cards.go | 18 +- mollie/payments.go | 1 + mollie/profiles.go | 184 ++++++++++++++++--- mollie/profiles_test.go | 392 +++++++++++++++++++++++++++++++++++++++- mollie/vouchers.go | 42 +++++ testdata/profiles.go | 28 +++ 7 files changed, 894 insertions(+), 130 deletions(-) create mode 100644 mollie/vouchers.go diff --git a/docs/README.md b/docs/README.md index de96a39e..18ad8671 100644 --- a/docs/README.md +++ b/docs/README.md @@ -112,6 +112,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CreateMandate](<#CreateMandate>) - [type CreateMandateAccessTokenFields](<#CreateMandateAccessTokenFields>) - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) +- [type CreateOrUpdateProfile](<#CreateOrUpdateProfile>) - [type CreateOrder](<#CreateOrder>) - [type CreatePayment](<#CreatePayment>) - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) @@ -132,6 +133,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(cs \*CustomersService\) Update\(ctx context.Context, id string, c UpdateCustomer\) \(res \*Response, cc \*Customer, err error\)](<#CustomersService.Update>) - [type EligibilityReasons](<#EligibilityReasons>) - [type EmbedValue](<#EmbedValue>) +- [type EnableVoucherIssuer](<#EnableVoucherIssuer>) - [type EntityType](<#EntityType>) - [type ErrorLinks](<#ErrorLinks>) - [type FailureReason](<#FailureReason>) @@ -139,7 +141,6 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type GetLinkedClientOptions](<#GetLinkedClientOptions>) - [type GiftCardEnabled](<#GiftCardEnabled>) - [type GiftCardIssuer](<#GiftCardIssuer>) -- [type GiftCardIssuerStatus](<#GiftCardIssuerStatus>) - [type GiftCardLinks](<#GiftCardLinks>) - [type Image](<#Image>) - [type IncludeValue](<#IncludeValue>) @@ -151,6 +152,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type InvoicesService](<#InvoicesService>) - [func \(is \*InvoicesService\) Get\(ctx context.Context, id string\) \(res \*Response, i \*Invoice, err error\)](<#InvoicesService.Get>) - [func \(is \*InvoicesService\) List\(ctx context.Context, options \*InvoicesListOptions\) \(res \*Response, il \*InvoicesList, err error\)](<#InvoicesService.List>) +- [type IssuerStatus](<#IssuerStatus>) - [type LineItem](<#LineItem>) - [type LinkedClient](<#LinkedClient>) - [type LinkedClientLinks](<#LinkedClientLinks>) @@ -272,20 +274,26 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type ProfileLinks](<#ProfileLinks>) - [type ProfileList](<#ProfileList>) - [type ProfileListOptions](<#ProfileListOptions>) +- [type ProfileReview](<#ProfileReview>) +- [type ProfileReviewStatus](<#ProfileReviewStatus>) - [type ProfileStatus](<#ProfileStatus>) - [type ProfilesService](<#ProfilesService>) - - [func \(ps \*ProfilesService\) Create\(ctx context.Context, np \*Profile\) \(res \*Response, p \*Profile, err error\)](<#ProfilesService.Create>) + - [func \(ps \*ProfilesService\) Create\(ctx context.Context, np CreateOrUpdateProfile\) \(res \*Response, p \*Profile, err error\)](<#ProfilesService.Create>) - [func \(ps \*ProfilesService\) Current\(ctx context.Context\) \(res \*Response, p \*Profile, err error\)](<#ProfilesService.Current>) - [func \(ps \*ProfilesService\) Delete\(ctx context.Context, id string\) \(res \*Response, err error\)](<#ProfilesService.Delete>) - [func \(ps \*ProfilesService\) DisableGiftCardIssuer\(ctx context.Context, profileID string, issuer GiftCardIssuer\) \(res \*Response, err error\)](<#ProfilesService.DisableGiftCardIssuer>) - [func \(ps \*ProfilesService\) DisableGiftCardIssuerForCurrent\(ctx context.Context, issuer GiftCardIssuer\) \(res \*Response, err error\)](<#ProfilesService.DisableGiftCardIssuerForCurrent>) - [func \(ps \*ProfilesService\) DisablePaymentMethod\(ctx context.Context, id string, pm PaymentMethod\) \(res \*Response, err error\)](<#ProfilesService.DisablePaymentMethod>) + - [func \(ps \*ProfilesService\) DisableVoucherIssuer\(ctx context.Context, profileID string, issuer VoucherIssuer\) \(res \*Response, err error\)](<#ProfilesService.DisableVoucherIssuer>) + - [func \(ps \*ProfilesService\) DisableVoucherIssuerForCurrent\(ctx context.Context, issuer VoucherIssuer\) \(res \*Response, err error\)](<#ProfilesService.DisableVoucherIssuerForCurrent>) - [func \(ps \*ProfilesService\) EnableGiftCardIssuer\(ctx context.Context, profileID string, issuer GiftCardIssuer\) \(res \*Response, gc \*GiftCardEnabled, err error\)](<#ProfilesService.EnableGiftCardIssuer>) - [func \(ps \*ProfilesService\) EnableGiftCardIssuerForCurrent\(ctx context.Context, issuer GiftCardIssuer\) \(res \*Response, gc \*GiftCardEnabled, err error\)](<#ProfilesService.EnableGiftCardIssuerForCurrent>) - [func \(ps \*ProfilesService\) EnablePaymentMethod\(ctx context.Context, id string, pm PaymentMethod\) \(res \*Response, pmi \*PaymentMethodDetails, err error\)](<#ProfilesService.EnablePaymentMethod>) + - [func \(ps \*ProfilesService\) EnableVoucherIssuer\(ctx context.Context, profileID string, issuer VoucherIssuer, vi \*EnableVoucherIssuer\) \(res \*Response, vc \*VoucherIssuerEnabled, err error\)](<#ProfilesService.EnableVoucherIssuer>) + - [func \(ps \*ProfilesService\) EnableVoucherIssuerForCurrent\(ctx context.Context, issuer VoucherIssuer\) \(res \*Response, vc \*VoucherIssuerEnabled, err error\)](<#ProfilesService.EnableVoucherIssuerForCurrent>) - [func \(ps \*ProfilesService\) Get\(ctx context.Context, id string\) \(res \*Response, p \*Profile, err error\)](<#ProfilesService.Get>) - [func \(ps \*ProfilesService\) List\(ctx context.Context, opts \*ProfileListOptions\) \(res \*Response, pl \*ProfileList, err error\)](<#ProfilesService.List>) - - [func \(ps \*ProfilesService\) Update\(ctx context.Context, id string, up \*Profile\) \(res \*Response, p \*Profile, err error\)](<#ProfilesService.Update>) + - [func \(ps \*ProfilesService\) Update\(ctx context.Context, id string, up CreateOrUpdateProfile\) \(res \*Response, p \*Profile, err error\)](<#ProfilesService.Update>) - [type QRCode](<#QRCode>) - [type Rate](<#Rate>) - [type RecurrentPaymentFields](<#RecurrentPaymentFields>) @@ -363,6 +371,10 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type UpdatePayment](<#UpdatePayment>) - [type UsedGiftCard](<#UsedGiftCard>) - [type UserAgentToken](<#UserAgentToken>) +- [type VoucherContractor](<#VoucherContractor>) +- [type VoucherIssuer](<#VoucherIssuer>) +- [type VoucherIssuerEnabled](<#VoucherIssuerEnabled>) +- [type VoucherLinks](<#VoucherLinks>) - [type Wallet](<#Wallet>) - [type WalletsService](<#WalletsService>) - [func \(ms \*WalletsService\) ApplePaymentSession\(ctx context.Context, asr \*ApplePaymentSessionRequest\) \(res \*Response, aps \*ApplePaymentSession, err error\)](<#WalletsService.ApplePaymentSession>) @@ -396,7 +408,7 @@ func CheckResponse(r *Response) error CheckResponse checks the API response for errors, and returns them if present. A response is considered an error if it has a status code outside the 200 range. API error responses are expected to have either no response body, or a JSON response body. -## type [AccessTokenPaymentFields]() +## type [AccessTokenPaymentFields]() AccessTokenPaymentFields describes the fields specific to payments created using an access token. @@ -1898,7 +1910,7 @@ type CreateMandateAccessTokenFields struct { ``` -## type [CreateMollieConnectPaymentFields]() +## type [CreateMollieConnectPaymentFields]() CreateMollieConnectPaymentFields describes the fields to be sent to the Mollie API when creating a new payment using Mollie Connect. @@ -1911,6 +1923,24 @@ type CreateMollieConnectPaymentFields struct { } ``` + +## type [CreateOrUpdateProfile]() + +CreateOrUpdateProfile describes the parameters to create or update a profile. + +```go +type CreateOrUpdateProfile struct { + Name string `json:"name,omitempty"` + Website string `json:"website,omitempty"` + Email string `json:"email,omitempty"` + Description string `json:"description,omitempty"` + Phone PhoneNumber `json:"phone,omitempty"` + BusinessCategory BusinessCategory `json:"businessCategory,omitempty"` + CategoryCode CategoryCode `json:"categoryCode,omitempty"` + Mode Mode `json:"mode,omitempty"` +} +``` + ## type [CreateOrder]() @@ -1938,7 +1968,7 @@ type CreateOrder struct { ``` -## type [CreatePayment]() +## type [CreatePayment]() CreatePayment describes the payload to be sent to the Mollie API when creating or updating a new payment. @@ -1986,7 +2016,7 @@ type CreatePayment struct { ``` -## type [CreatePaymentAccessTokenFields]() +## type [CreatePaymentAccessTokenFields]() CreatePaymentAccessTokenFields describes the fields to be sent to the Mollie API when creating a new payment using an access token. @@ -2000,7 +2030,7 @@ type CreatePaymentAccessTokenFields struct { ``` -## type [CreatePreAuthorizedPaymentFields]() +## type [CreatePreAuthorizedPaymentFields]() CreatePreAuthorizedPaymentFields describes the fields to be sent to the Mollie API when creating a new pre\-authorized payment. @@ -2014,7 +2044,7 @@ type CreatePreAuthorizedPaymentFields struct { ``` -## type [CreateRecurrentPaymentFields]() +## type [CreateRecurrentPaymentFields]() CreateRecurrentPaymentFields describes the fields to be sent to the Mollie API when creating a new recurrent payment. @@ -2248,6 +2278,17 @@ const ( ) ``` + +## type [EnableVoucherIssuer]() + +EnableVoucherIssuer describes the parameters to enable a voucher issuer. + +```go +type EnableVoucherIssuer struct { + ContractID string `json:"contractId,omitempty"` +} +``` + ## type [EntityType]() @@ -2352,11 +2393,11 @@ GiftCardEnabled describes the response of a gift card issuer enable operation. ```go type GiftCardEnabled struct { - Resource string `json:"resource,omitempty"` - ID GiftCardIssuer `json:"id,omitempty"` - Description string `json:"description,omitempty"` - Status GiftCardIssuerStatus `json:"status,omitempty"` - Links GiftCardLinks `json:"_links,omitempty"` + Resource string `json:"resource,omitempty"` + ID GiftCardIssuer `json:"id,omitempty"` + Description string `json:"description,omitempty"` + Status IssuerStatus `json:"status,omitempty"` + Links GiftCardLinks `json:"_links,omitempty"` } ``` @@ -2410,24 +2451,6 @@ const ( ) ``` - -## type [GiftCardIssuerStatus]() - -GiftCardIssuerStatus describes the status of a gift card issuer in your account. - -```go -type GiftCardIssuerStatus string -``` - -Valid issuer statuses. - -```go -const ( - PendingIssuer GiftCardIssuerStatus = "pending-issuer" - EnabledIssuer GiftCardIssuerStatus = "enabled" -) -``` - ## type [GiftCardLinks]() @@ -2584,6 +2607,24 @@ func (is *InvoicesService) List(ctx context.Context, options *InvoicesListOption List retrieves a list of invoices associated with your account/organization. + +## type [IssuerStatus]() + +IssuerStatus describes the status of a gift card issuer in your account. + +```go +type IssuerStatus string +``` + +Valid issuer statuses. + +```go +const ( + PendingIssuer IssuerStatus = "pending-issuer" + EnabledIssuer IssuerStatus = "enabled" +) +``` + ## type [LineItem]() @@ -2656,7 +2697,7 @@ type ListLinkedClientsOptions struct { ``` -## type [ListPaymentOptions]() +## type [ListPaymentOptions]() ListPaymentOptions describes list payments endpoint valid query string parameters. @@ -2914,7 +2955,7 @@ const ( ``` -## type [MollieConnectPaymentFields]() +## type [MollieConnectPaymentFields]() MollieConnectPaymentFields describes the fields specific to Mollie Connect payments. @@ -3707,7 +3748,7 @@ const ( ``` -## type [Payment]() +## type [Payment]() Payment describes a transaction between a customer and a merchant. @@ -3756,7 +3797,7 @@ type Payment struct { ``` -## type [PaymentDestination]() +## type [PaymentDestination]() PaymentDestination describes the destination of a payment. @@ -3897,7 +3938,7 @@ type PaymentLinkOptions struct { ``` -## type [PaymentLinks]() +## type [PaymentLinks]() PaymentLinks describes all the possible links to be returned with a payment object. @@ -3979,7 +4020,7 @@ List retrieves all payments links created with the current website profile, orde See: https://docs.mollie.com/reference/v2/payment-links-api/list-payment-links -## type [PaymentList]() +## type [PaymentList]() PaymentList describes how a list of payments will be retrieved by Mollie. @@ -4024,6 +4065,7 @@ const ( PaySafeCard PaymentMethod = "paysafecard" PRZelewy24 PaymentMethod = "przelewy24" Sofort PaymentMethod = "sofort" + Voucher PaymentMethod = "voucher" ) ``` @@ -4190,7 +4232,7 @@ The results are not paginated. See: https://docs.mollie.com/reference/v2/methods-api/list-methods -## type [PaymentOptions]() +## type [PaymentOptions]() PaymentOptions describes payments endpoint valid query string parameters. @@ -4204,7 +4246,7 @@ type PaymentOptions struct { ``` -## type [PaymentRouting]() +## type [PaymentRouting]() PaymentRouting describes the routing of a payment. @@ -4217,7 +4259,7 @@ type PaymentRouting struct { ``` -## type [PaymentsService]() +## type [PaymentsService]() PaymentsService instance operates over payment resources. @@ -4226,7 +4268,7 @@ type PaymentsService service ``` -### func \(\*PaymentsService\) [Cancel]() +### func \(\*PaymentsService\) [Cancel]() ```go func (ps *PaymentsService) Cancel(ctx context.Context, id string) (res *Response, p *Payment, err error) @@ -4237,7 +4279,7 @@ Cancel removes a payment \(if possible\) from your Mollie account. See: https://docs.mollie.com/reference/v2/payments-api/cancel-payment -### func \(\*PaymentsService\) [Create]() +### func \(\*PaymentsService\) [Create]() ```go func (ps *PaymentsService) Create(ctx context.Context, p CreatePayment, opts *PaymentOptions) (res *Response, np *Payment, err error) @@ -4248,7 +4290,7 @@ Create stores a new payment object attached to your Mollie account. See: https://docs.mollie.com/reference/v2/payments-api/create-payment# -### func \(\*PaymentsService\) [Get]() +### func \(\*PaymentsService\) [Get]() ```go func (ps *PaymentsService) Get(ctx context.Context, id string, opts *PaymentOptions) (res *Response, p *Payment, err error) @@ -4257,7 +4299,7 @@ func (ps *PaymentsService) Get(ctx context.Context, id string, opts *PaymentOpti Get retrieves a single payment object by its payment token. -### func \(\*PaymentsService\) [List]() +### func \(\*PaymentsService\) [List]() ```go func (ps *PaymentsService) List(ctx context.Context, opts *ListPaymentOptions) (res *Response, pl *PaymentList, err error) @@ -4268,7 +4310,7 @@ List retrieves a list of payments associated with your account/organization. See: https://docs.mollie.com/reference/v2/payments-api/list-payments -### func \(\*PaymentsService\) [Update]() +### func \(\*PaymentsService\) [Update]() ```go func (ps *PaymentsService) Update(ctx context.Context, id string, up UpdatePayment) (res *Response, p *Payment, err error) @@ -4404,7 +4446,7 @@ type PhoneNumber string ``` -## type [PreAuthorizedPaymentFields]() +## type [PreAuthorizedPaymentFields]() PreAuthorizedPaymentFields describes the fields specific to pre\-authorized payments. @@ -4440,48 +4482,50 @@ const ( ``` -## type [Profile]() +## type [Profile]() Profile will usually reflect the trademark or brand name of the profile’s website or application. ```go type Profile struct { - ID string `json:"id,omitempty"` - BusinessCategory BusinessCategory `json:"businessCategory,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - Email string `json:"email,omitempty"` - Mode Mode `json:"mode,omitempty"` - Name string `json:"name,omitempty"` - Phone PhoneNumber `json:"phone,omitempty"` - Resource string `json:"resource,omitempty"` - Review struct { - Status string `json:"status,omitempty"` - } `json:"review,omitempty"` - Status ProfileStatus `json:"status,omitempty"` - Website string `json:"website,omitempty"` - Links ProfileLinks `json:"_links,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Website string `json:"website,omitempty"` + Description string `json:"description,omitempty"` + CountriesOfActivity []string `json:"countriesOfActivity,omitempty"` + Email string `json:"email,omitempty"` + Phone PhoneNumber `json:"phone,omitempty"` + Mode Mode `json:"mode,omitempty"` + BusinessCategory BusinessCategory `json:"businessCategory,omitempty"` + CategoryCode CategoryCode `json:"categoryCode,omitempty"` + Status ProfileStatus `json:"status,omitempty"` + Review ProfileReview `json:"review,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + Links ProfileLinks `json:"_links,omitempty"` } ``` -## type [ProfileLinks]() +## type [ProfileLinks]() ProfileLinks contains URL's to relevant information related to a profile. ```go type ProfileLinks struct { Self *URL `json:"self,omitempty"` + Dashboard *URL `json:"dashboard,omitempty"` Chargebacks *URL `json:"chargebacks,omitempty"` Methods *URL `json:"methods,omitempty"` + Payments *URL `json:"payments,omitempty"` Refunds *URL `json:"refunds,omitempty"` CheckoutPreviewURL *URL `json:"checkoutPreviewUrl,omitempty"` Documentation *URL `json:"documentation,omitempty"` - Dashboard *URL `json:"dashboard,omitempty"` } ``` -## type [ProfileList]() +## type [ProfileList]() ProfileList contains a list of profiles for your account. @@ -4496,17 +4540,46 @@ type ProfileList struct { ``` -## type [ProfileListOptions]() +## type [ProfileListOptions]() ProfileListOptions are optional query string parameters for the list profiles request. ```go type ProfileListOptions struct { + Limit int `url:"limit,omitempty"` From string `url:"from,omitempty"` - Limit uint `url:"limit,omitempty"` } ``` + +## type [ProfileReview]() + +ProfileReview contains the status of the profile review. + +```go +type ProfileReview struct { + Status ProfileReviewStatus `json:"status,omitempty"` +} +``` + + +## type [ProfileReviewStatus]() + +ProfileReviewStatus determines whether the profile is able to receive live payments. + +```go +type ProfileReviewStatus string +``` + +Possible profile review statuses. + +```go +const ( + ReviewStatusPending ProfileReviewStatus = "pending" + ReviewStatusRejected ProfileReviewStatus = "rejected" +) +``` + ## type [ProfileStatus]() @@ -4527,7 +4600,7 @@ const ( ``` -## type [ProfilesService]() +## type [ProfilesService]() ProfilesService operates over profile resource. @@ -4536,16 +4609,16 @@ type ProfilesService service ``` -### func \(\*ProfilesService\) [Create]() +### func \(\*ProfilesService\) [Create]() ```go -func (ps *ProfilesService) Create(ctx context.Context, np *Profile) (res *Response, p *Profile, err error) +func (ps *ProfilesService) Create(ctx context.Context, np CreateOrUpdateProfile) (res *Response, p *Profile, err error) ``` Create stores a new profile in your Mollie account. -### func \(\*ProfilesService\) [Current]() +### func \(\*ProfilesService\) [Current]() ```go func (ps *ProfilesService) Current(ctx context.Context) (res *Response, p *Profile, err error) @@ -4554,7 +4627,7 @@ func (ps *ProfilesService) Current(ctx context.Context) (res *Response, p *Profi Current returns the profile belonging to the API key. This method only works when using API keys. -### func \(\*ProfilesService\) [Delete]() +### func \(\*ProfilesService\) [Delete]() ```go func (ps *ProfilesService) Delete(ctx context.Context, id string) (res *Response, err error) @@ -4563,29 +4636,29 @@ func (ps *ProfilesService) Delete(ctx context.Context, id string) (res *Response Delete enables profile deletions, rendering the profile unavailable for further API calls and transactions. -### func \(\*ProfilesService\) [DisableGiftCardIssuer]() +### func \(\*ProfilesService\) [DisableGiftCardIssuer]() ```go func (ps *ProfilesService) DisableGiftCardIssuer(ctx context.Context, profileID string, issuer GiftCardIssuer) (res *Response, err error) ``` -DisableGiftCardIssuer deactivates the requested gift card issuer for the provided profile id. +DisableGiftCardIssuer deactivates the requested gift card issuer for the provided profile id when using Organization tokens or App Access tokens. See: https://docs.mollie.com/reference/v2/profiles-api/disable-gift-card-issuer -### func \(\*ProfilesService\) [DisableGiftCardIssuerForCurrent]() +### func \(\*ProfilesService\) [DisableGiftCardIssuerForCurrent]() ```go func (ps *ProfilesService) DisableGiftCardIssuerForCurrent(ctx context.Context, issuer GiftCardIssuer) (res *Response, err error) ``` -DisableGiftCardIssuerForCurrent deactivates the specified issuer for the current profile \(token owner\). +DisableGiftCardIssuerForCurrent deactivates the specified issuer for the current profile when using API tokens. See: https://docs.mollie.com/reference/v2/profiles-api/disable-gift-card-issuer -### func \(\*ProfilesService\) [DisablePaymentMethod]() +### func \(\*ProfilesService\) [DisablePaymentMethod]() ```go func (ps *ProfilesService) DisablePaymentMethod(ctx context.Context, id string, pm PaymentMethod) (res *Response, err error) @@ -4593,30 +4666,50 @@ func (ps *ProfilesService) DisablePaymentMethod(ctx context.Context, id string, DisablePaymentMethod disables a payment method on a specific or authenticated profile. If you're using API tokens for authentication, pass "me" as id. + +### func \(\*ProfilesService\) [DisableVoucherIssuer]() + +```go +func (ps *ProfilesService) DisableVoucherIssuer(ctx context.Context, profileID string, issuer VoucherIssuer) (res *Response, err error) +``` + +DisableVoucherIssuer deactivates the requested voucher issuer for the provided profile id when using Organization tokens or App Access tokens. + +See: https://docs.mollie.com/reference/v2/profiles-api/disable-voucher-issuer + + +### func \(\*ProfilesService\) [DisableVoucherIssuerForCurrent]() + +```go +func (ps *ProfilesService) DisableVoucherIssuerForCurrent(ctx context.Context, issuer VoucherIssuer) (res *Response, err error) +``` + +DisableVoucherIssuerForCurrent deactivates the specified issuer for the current profile when using API tokens. + -### func \(\*ProfilesService\) [EnableGiftCardIssuer]() +### func \(\*ProfilesService\) [EnableGiftCardIssuer]() ```go func (ps *ProfilesService) EnableGiftCardIssuer(ctx context.Context, profileID string, issuer GiftCardIssuer) (res *Response, gc *GiftCardEnabled, err error) ``` -EnableGiftCardIssuer activates the requested gift card issuer for the provided profile id. +EnableGiftCardIssuer activates the requested gift card issuer for the provided profile id when using Organization tokens or App Access tokens. See: https://docs.mollie.com/reference/v2/profiles-api/enable-gift-card-issuer -### func \(\*ProfilesService\) [EnableGiftCardIssuerForCurrent]() +### func \(\*ProfilesService\) [EnableGiftCardIssuerForCurrent]() ```go func (ps *ProfilesService) EnableGiftCardIssuerForCurrent(ctx context.Context, issuer GiftCardIssuer) (res *Response, gc *GiftCardEnabled, err error) ``` -EnableGiftCardIssuerForCurrent activates the specified issuer for the current profile \(token owner\). +EnableGiftCardIssuerForCurrent activates the specified issuer for the current profile when using API tokens. See: https://docs.mollie.com/reference/v2/profiles-api/enable-gift-card-issuer -### func \(\*ProfilesService\) [EnablePaymentMethod]() +### func \(\*ProfilesService\) [EnablePaymentMethod]() ```go func (ps *ProfilesService) EnablePaymentMethod(ctx context.Context, id string, pm PaymentMethod) (res *Response, pmi *PaymentMethodDetails, err error) @@ -4624,8 +4717,28 @@ func (ps *ProfilesService) EnablePaymentMethod(ctx context.Context, id string, p EnablePaymentMethod enables a payment method on a specific or authenticated profile. If you're using API tokens for authentication, pass "me" as id. + +### func \(\*ProfilesService\) [EnableVoucherIssuer]() + +```go +func (ps *ProfilesService) EnableVoucherIssuer(ctx context.Context, profileID string, issuer VoucherIssuer, vi *EnableVoucherIssuer) (res *Response, vc *VoucherIssuerEnabled, err error) +``` + +EnableVoucherIssuer activates the requested voucher issuer for the provided profile id when using Organization tokens or App Access tokens. + +See: https://docs.mollie.com/reference/v2/profiles-api/enable-voucher-issuer + + +### func \(\*ProfilesService\) [EnableVoucherIssuerForCurrent]() + +```go +func (ps *ProfilesService) EnableVoucherIssuerForCurrent(ctx context.Context, issuer VoucherIssuer) (res *Response, vc *VoucherIssuerEnabled, err error) +``` + +EnableVoucherIssuerForCurrent activates the specified issuer for the current profile when using API tokens. + -### func \(\*ProfilesService\) [Get]() +### func \(\*ProfilesService\) [Get]() ```go func (ps *ProfilesService) Get(ctx context.Context, id string) (res *Response, p *Profile, err error) @@ -4634,7 +4747,7 @@ func (ps *ProfilesService) Get(ctx context.Context, id string) (res *Response, p Get retrieves the a profile by ID. -### func \(\*ProfilesService\) [List]() +### func \(\*ProfilesService\) [List]() ```go func (ps *ProfilesService) List(ctx context.Context, opts *ProfileListOptions) (res *Response, pl *ProfileList, err error) @@ -4643,10 +4756,10 @@ func (ps *ProfilesService) List(ctx context.Context, opts *ProfileListOptions) ( List returns all the profiles for the authenticated account. -### func \(\*ProfilesService\) [Update]() +### func \(\*ProfilesService\) [Update]() ```go -func (ps *ProfilesService) Update(ctx context.Context, id string, up *Profile) (res *Response, p *Profile, err error) +func (ps *ProfilesService) Update(ctx context.Context, id string, up CreateOrUpdateProfile) (res *Response, p *Profile, err error) ``` Update allows you to perform mutations on a profile. @@ -4677,7 +4790,7 @@ type Rate struct { ``` -## type [RecurrentPaymentFields]() +## type [RecurrentPaymentFields]() RecurrentPaymentFields describes the fields specific to recurrent payments. @@ -4853,7 +4966,7 @@ type Response struct { ``` -## type [SequenceType]() +## type [SequenceType]() SequenceType indicates which type of payment this is in a recurring sequence. @@ -5680,7 +5793,7 @@ type UpdateOrderLine struct { ``` -## type [UpdatePayment]() +## type [UpdatePayment]() UpdatePayment describes the payload to be sent to the Mollie API when updating a payment. @@ -5730,6 +5843,74 @@ type UserAgentToken struct { } ``` + +## type [VoucherContractor]() + +VoucherContractor represents a contractor for a voucher. + +```go +type VoucherContractor struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ContractorID string `json:"contractorId,omitempty"` +} +``` + + +## type [VoucherIssuer]() + +VoucherIssuer represents the issuer of a voucher. + +```go +type VoucherIssuer string +``` + +List of known voucher issuers. + +```go +const ( + EdenredBelgiumCadeauVoucher VoucherIssuer = "edenred-belgium-cadeau" + EdenredBelgiumEcoVoucher VoucherIssuer = "edenred-belgium-eco" + EdenredBelgiumMealVoucher VoucherIssuer = "edenred-belgium-meal" + EdenredBelgiumSportsVoucher VoucherIssuer = "edenred-belgium-sports" + EdenredBelgiumAdditionalVoucher VoucherIssuer = "edenred-belgium-additional" + EdenredBelgiumConsumeVoucher VoucherIssuer = "edenred-belgium-consume" + MonizzeCadeauVoucher VoucherIssuer = "monizze-cadeau" + MonizzeEcoVoucher VoucherIssuer = "monizze-eco" + MonizzeMealVoucher VoucherIssuer = "monizze-meal" + PluxeeCadeauVoucher VoucherIssuer = "sodexo-cadeau" + PluxeeEcoVoucher VoucherIssuer = "sodexo-ecopass" + PluxeeLunchVoucher VoucherIssuer = "sodexo-lunchpass" +) +``` + + +## type [VoucherIssuerEnabled]() + +VoucherIssuerEnabled describes the response of a voucher enable operation. + +```go +type VoucherIssuerEnabled struct { + ID string `json:"id,omitempty"` + Description string `json:"description,omitempty"` + Status IssuerStatus `json:"status,omitempty"` + Contractor VoucherContractor `json:"contractor,omitempty"` + Links VoucherLinks `json:"_links,omitempty"` +} +``` + + +## type [VoucherLinks]() + +VoucherLinks are links embedded when a voucher is enabled. + +```go +type VoucherLinks struct { + Self *URL `json:"self,omitempty"` + Documentation *URL `json:"documentation,omitempty"` +} +``` + ## type [Wallet]() diff --git a/mollie/gift_cards.go b/mollie/gift_cards.go index 89ca6b46..de0e38bc 100644 --- a/mollie/gift_cards.go +++ b/mollie/gift_cards.go @@ -43,24 +43,24 @@ const ( Yourgift GiftCardIssuer = "yourgift" ) -// GiftCardIssuerStatus describes the status of a gift +// IssuerStatus describes the status of a gift // card issuer in your account. -type GiftCardIssuerStatus string +type IssuerStatus string // Valid issuer statuses. const ( - PendingIssuer GiftCardIssuerStatus = "pending-issuer" - EnabledIssuer GiftCardIssuerStatus = "enabled" + PendingIssuer IssuerStatus = "pending-issuer" + EnabledIssuer IssuerStatus = "enabled" ) // GiftCardEnabled describes the response of a gift card // issuer enable operation. type GiftCardEnabled struct { - Resource string `json:"resource,omitempty"` - ID GiftCardIssuer `json:"id,omitempty"` - Description string `json:"description,omitempty"` - Status GiftCardIssuerStatus `json:"status,omitempty"` - Links GiftCardLinks `json:"_links,omitempty"` + Resource string `json:"resource,omitempty"` + ID GiftCardIssuer `json:"id,omitempty"` + Description string `json:"description,omitempty"` + Status IssuerStatus `json:"status,omitempty"` + Links GiftCardLinks `json:"_links,omitempty"` } // GiftCardLinks are links embedded when a gift card is enabled. diff --git a/mollie/payments.go b/mollie/payments.go index e18d5e73..f0471a61 100644 --- a/mollie/payments.go +++ b/mollie/payments.go @@ -30,6 +30,7 @@ const ( PaySafeCard PaymentMethod = "paysafecard" PRZelewy24 PaymentMethod = "przelewy24" Sofort PaymentMethod = "sofort" + Voucher PaymentMethod = "voucher" ) // SequenceType indicates which type of payment this is in a recurring sequence. diff --git a/mollie/profiles.go b/mollie/profiles.go index 587d4f41..4d624f91 100644 --- a/mollie/profiles.go +++ b/mollie/profiles.go @@ -18,41 +18,69 @@ const ( StatusBlocked ProfileStatus = "blocked" ) +// CreateOrUpdateProfile describes the parameters to create or update a profile. +type CreateOrUpdateProfile struct { + Name string `json:"name,omitempty"` + Website string `json:"website,omitempty"` + Email string `json:"email,omitempty"` + Description string `json:"description,omitempty"` + Phone PhoneNumber `json:"phone,omitempty"` + BusinessCategory BusinessCategory `json:"businessCategory,omitempty"` + CategoryCode CategoryCode `json:"categoryCode,omitempty"` + Mode Mode `json:"mode,omitempty"` +} + // Profile will usually reflect the trademark or brand name // of the profile’s website or application. type Profile struct { - ID string `json:"id,omitempty"` - BusinessCategory BusinessCategory `json:"businessCategory,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - Email string `json:"email,omitempty"` - Mode Mode `json:"mode,omitempty"` - Name string `json:"name,omitempty"` - Phone PhoneNumber `json:"phone,omitempty"` - Resource string `json:"resource,omitempty"` - Review struct { - Status string `json:"status,omitempty"` - } `json:"review,omitempty"` - Status ProfileStatus `json:"status,omitempty"` - Website string `json:"website,omitempty"` - Links ProfileLinks `json:"_links,omitempty"` + Resource string `json:"resource,omitempty"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Website string `json:"website,omitempty"` + Description string `json:"description,omitempty"` + CountriesOfActivity []string `json:"countriesOfActivity,omitempty"` + Email string `json:"email,omitempty"` + Phone PhoneNumber `json:"phone,omitempty"` + Mode Mode `json:"mode,omitempty"` + BusinessCategory BusinessCategory `json:"businessCategory,omitempty"` + CategoryCode CategoryCode `json:"categoryCode,omitempty"` + Status ProfileStatus `json:"status,omitempty"` + Review ProfileReview `json:"review,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + Links ProfileLinks `json:"_links,omitempty"` } +// ProfileReview contains the status of the profile review. +type ProfileReview struct { + Status ProfileReviewStatus `json:"status,omitempty"` +} + +// ProfileReviewStatus determines whether the profile is able to receive live payments. +type ProfileReviewStatus string + +// Possible profile review statuses. +const ( + ReviewStatusPending ProfileReviewStatus = "pending" + ReviewStatusRejected ProfileReviewStatus = "rejected" +) + // ProfileLinks contains URL's to relevant information related to // a profile. type ProfileLinks struct { Self *URL `json:"self,omitempty"` + Dashboard *URL `json:"dashboard,omitempty"` Chargebacks *URL `json:"chargebacks,omitempty"` Methods *URL `json:"methods,omitempty"` + Payments *URL `json:"payments,omitempty"` Refunds *URL `json:"refunds,omitempty"` CheckoutPreviewURL *URL `json:"checkoutPreviewUrl,omitempty"` Documentation *URL `json:"documentation,omitempty"` - Dashboard *URL `json:"dashboard,omitempty"` } // ProfileListOptions are optional query string parameters for the list profiles request. type ProfileListOptions struct { + Limit int `url:"limit,omitempty"` From string `url:"from,omitempty"` - Limit uint `url:"limit,omitempty"` } // ProfileList contains a list of profiles for your account. @@ -64,6 +92,11 @@ type ProfileList struct { Links PaginationLinks `json:"_links,omitempty"` } +// EnableVoucherIssuer describes the parameters to enable a voucher issuer. +type EnableVoucherIssuer struct { + ContractID string `json:"contractId,omitempty"` +} + // ProfilesService operates over profile resource. type ProfilesService service @@ -110,7 +143,11 @@ func (ps *ProfilesService) get(ctx context.Context, id string) (res *Response, p } // Create stores a new profile in your Mollie account. -func (ps *ProfilesService) Create(ctx context.Context, np *Profile) (res *Response, p *Profile, err error) { +func (ps *ProfilesService) Create(ctx context.Context, np CreateOrUpdateProfile) ( + res *Response, + p *Profile, + err error, +) { res, err = ps.client.post(ctx, "v2/profiles", np, nil) if err != nil { return @@ -124,7 +161,11 @@ func (ps *ProfilesService) Create(ctx context.Context, np *Profile) (res *Respon } // Update allows you to perform mutations on a profile. -func (ps *ProfilesService) Update(ctx context.Context, id string, up *Profile) (res *Response, p *Profile, err error) { +func (ps *ProfilesService) Update(ctx context.Context, id string, up CreateOrUpdateProfile) ( + res *Response, + p *Profile, + err error, +) { res, err = ps.client.patch(ctx, fmt.Sprintf("v2/profiles/%s", id), up, nil) if err != nil { return @@ -182,7 +223,7 @@ func (ps *ProfilesService) DisablePaymentMethod(ctx context.Context, id string, } // EnableGiftCardIssuer activates the requested gift card issuer for the provided -// profile id. +// profile id when using Organization tokens or App Access tokens. // // See: https://docs.mollie.com/reference/v2/profiles-api/enable-gift-card-issuer func (ps *ProfilesService) EnableGiftCardIssuer(ctx context.Context, profileID string, issuer GiftCardIssuer) ( @@ -203,7 +244,7 @@ func (ps *ProfilesService) EnableGiftCardIssuer(ctx context.Context, profileID s } // DisableGiftCardIssuer deactivates the requested gift card issuer for the provided -// profile id. +// profile id when using Organization tokens or App Access tokens. // // See: https://docs.mollie.com/reference/v2/profiles-api/disable-gift-card-issuer func (ps *ProfilesService) DisableGiftCardIssuer(ctx context.Context, profileID string, issuer GiftCardIssuer) ( @@ -219,7 +260,7 @@ func (ps *ProfilesService) DisableGiftCardIssuer(ctx context.Context, profileID } // EnableGiftCardIssuerForCurrent activates the specified issuer for the -// current profile (token owner). +// current profile when using API tokens. // // See: https://docs.mollie.com/reference/v2/profiles-api/enable-gift-card-issuer func (ps *ProfilesService) EnableGiftCardIssuerForCurrent(ctx context.Context, issuer GiftCardIssuer) ( @@ -240,7 +281,7 @@ func (ps *ProfilesService) EnableGiftCardIssuerForCurrent(ctx context.Context, i } // DisableGiftCardIssuerForCurrent deactivates the specified issuer for the -// current profile (token owner). +// current profile when using API tokens. // // See: https://docs.mollie.com/reference/v2/profiles-api/disable-gift-card-issuer func (ps *ProfilesService) DisableGiftCardIssuerForCurrent(ctx context.Context, issuer GiftCardIssuer) ( @@ -255,6 +296,81 @@ func (ps *ProfilesService) DisableGiftCardIssuerForCurrent(ctx context.Context, return } +// EnableVoucherIssuer activates the requested voucher issuer for the provided +// profile id when using Organization tokens or App Access tokens. +// +// See: https://docs.mollie.com/reference/v2/profiles-api/enable-voucher-issuer +func (ps *ProfilesService) EnableVoucherIssuer( + ctx context.Context, + profileID string, + issuer VoucherIssuer, + vi *EnableVoucherIssuer, +) ( + res *Response, + vc *VoucherIssuerEnabled, + err error, +) { + res, err = ps.toggleVoucherIssuerStatus(ctx, profileID, http.MethodPost, issuer) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &vc); err != nil { + return + } + + return +} + +// DisableVoucherIssuer deactivates the requested voucher issuer for the provided +// profile id when using Organization tokens or App Access tokens. +// +// See: https://docs.mollie.com/reference/v2/profiles-api/disable-voucher-issuer +func (ps *ProfilesService) DisableVoucherIssuer(ctx context.Context, profileID string, issuer VoucherIssuer) ( + res *Response, + err error, +) { + res, err = ps.toggleVoucherIssuerStatus(ctx, profileID, http.MethodDelete, issuer) + if err != nil { + return + } + + return +} + +// EnableVoucherIssuerForCurrent activates the specified issuer for the +// current profile when using API tokens. +func (ps *ProfilesService) EnableVoucherIssuerForCurrent(ctx context.Context, issuer VoucherIssuer) ( + res *Response, + vc *VoucherIssuerEnabled, + err error, +) { + res, err = ps.toggleVoucherIssuerStatus(ctx, "me", http.MethodPost, issuer) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &vc); err != nil { + return + } + + return +} + +// DisableVoucherIssuerForCurrent deactivates the specified issuer for the +// current profile when using API tokens. +func (ps *ProfilesService) DisableVoucherIssuerForCurrent(ctx context.Context, issuer VoucherIssuer) ( + res *Response, + err error, +) { + res, err = ps.toggleVoucherIssuerStatus(ctx, "me", http.MethodDelete, issuer) + if err != nil { + return + } + + return +} + func (ps *ProfilesService) toggleGiftCardIssuerStatus( ctx context.Context, profile string, @@ -278,3 +394,27 @@ func (ps *ProfilesService) toggleGiftCardIssuerStatus( return } + +func (ps *ProfilesService) toggleVoucherIssuerStatus( + ctx context.Context, + profile string, + method string, + issuer VoucherIssuer) ( + r *Response, + err error, +) { + u := fmt.Sprintf("v2/profiles/%s/methods/voucher/issuers/%s", profile, issuer) + + switch method { + case http.MethodDelete: + r, err = ps.client.delete(ctx, u, nil) + case http.MethodPost: + r, err = ps.client.post(ctx, u, nil, nil) + } + + if err != nil { + return + } + + return +} diff --git a/mollie/profiles_test.go b/mollie/profiles_test.go index 005b81ba..5abeec09 100644 --- a/mollie/profiles_test.go +++ b/mollie/profiles_test.go @@ -301,7 +301,7 @@ func TestProfilesService_Create(t *testing.T) { type args struct { ctx context.Context - profile *Profile + profile CreateOrUpdateProfile } cases := []struct { name string @@ -315,7 +315,7 @@ func TestProfilesService_Create(t *testing.T) { "create profile works as expected.", args{ context.Background(), - &Profile{ + CreateOrUpdateProfile{ Name: "testing name", }, }, @@ -339,7 +339,7 @@ func TestProfilesService_Create(t *testing.T) { "create profile, an error is returned from the server", args{ context.Background(), - &Profile{}, + CreateOrUpdateProfile{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -350,7 +350,7 @@ func TestProfilesService_Create(t *testing.T) { "create profile, an error occurs when parsing json", args{ context.Background(), - &Profile{}, + CreateOrUpdateProfile{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -361,7 +361,7 @@ func TestProfilesService_Create(t *testing.T) { "create profile, invalid url when building request", args{ context.Background(), - &Profile{}, + CreateOrUpdateProfile{}, }, true, errBadBaseURL, @@ -398,7 +398,7 @@ func TestProfilesService_Update(t *testing.T) { type args struct { ctx context.Context profileID string - profile *Profile + profile CreateOrUpdateProfile } cases := []struct { name string @@ -413,7 +413,7 @@ func TestProfilesService_Update(t *testing.T) { args{ context.Background(), "pfl_v9hTwCvYqw", - &Profile{ + CreateOrUpdateProfile{ Name: "testing name", }, }, @@ -438,7 +438,7 @@ func TestProfilesService_Update(t *testing.T) { args{ context.Background(), "pfl_v9hTwCvYqw", - &Profile{}, + CreateOrUpdateProfile{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -450,7 +450,7 @@ func TestProfilesService_Update(t *testing.T) { args{ context.Background(), "pfl_v9hTwCvYqw", - &Profile{}, + CreateOrUpdateProfile{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -462,7 +462,7 @@ func TestProfilesService_Update(t *testing.T) { args{ context.Background(), "pfl_v9hTwCvYqw", - &Profile{}, + CreateOrUpdateProfile{}, }, true, errBadBaseURL, @@ -1122,3 +1122,375 @@ func TestProfilesService_DisableGiftCardIssuerForCurrent(t *testing.T) { }) } } + +func TestProfilesService_EnableVoucherIssuer(t *testing.T) { + setEnv() + defer unsetEnv() + + type args struct { + ctx context.Context + profile string + issuer VoucherIssuer + vi *EnableVoucherIssuer + } + cases := []struct { + name string + args args + wantErr bool + err error + pre func() + handler http.HandlerFunc + }{ + { + "enable voucher issuer for profile works as expected using an access key.", + args{ + context.Background(), + "pfl_v9hTwCvYqw", + PluxeeEcoVoucher, + nil, + }, + false, + nil, + setAccessToken, + func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + _, _ = w.Write([]byte(testdata.EnableVoucherIssuerResponse)) + }, + }, + { + "enable voucher issuer for profile an error is returned from the server.", + args{ + context.Background(), + "pfl_v9hTwCvYqw", + PluxeeEcoVoucher, + nil, + }, + true, + fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), + setAccessToken, + errorHandler, + }, + { + "enable voucher issuer for profile an error occurs when parsing json.", + args{ + context.Background(), + "pfl_v9hTwCvYqw", + PluxeeEcoVoucher, + nil, + }, + true, + fmt.Errorf("invalid character 'h' looking for beginning of object key string"), + setAccessToken, + encodingHandler, + }, + { + "enable voucher issuer for profile invalid url when building request.", + args{ + context.Background(), + "pfl_v9hTwCvYqw", + PluxeeEcoVoucher, + nil, + }, + true, + errBadBaseURL, + crashSrv, + errorHandler, + }, + } + + for _, c := range cases { + setup() + defer teardown() + + t.Run(c.name, func(t *testing.T) { + c.pre() + + if tClient.HasAccessToken() { + tMux.HandleFunc( + fmt.Sprintf("/v2/profiles/%s/methods/voucher/issuers/%s", + c.args.profile, + c.args.issuer, + ), + c.handler, + ) + } else { + tMux.HandleFunc( + fmt.Sprintf("/v2/profiles/me/methods/voucher/issuers/%s", + c.args.issuer, + ), + c.handler, + ) + } + + res, m, err := tClient.Profiles.EnableVoucherIssuer(c.args.ctx, c.args.profile, c.args.issuer, c.args.vi) + if c.wantErr { + assert.NotNil(t, err) + assert.EqualError(t, err, c.err.Error()) + } else { + assert.Nil(t, err) + assert.IsType(t, &VoucherIssuerEnabled{}, m) + assert.IsType(t, &http.Response{}, res.Response) + } + }) + } +} + +func TestProfileService_DisableVoucherIssuer(t *testing.T) { + setEnv() + defer unsetEnv() + + type args struct { + ctx context.Context + profile string + issuer VoucherIssuer + } + cases := []struct { + name string + args args + wantErr bool + err error + pre func() + handler http.HandlerFunc + }{ + { + "disable voucher issuer for profile works as expected.", + args{ + context.Background(), + "pfl_v9hTwCvYqw", + PluxeeEcoVoucher, + }, + false, + nil, + func() { + tClient.WithAuthenticationValue("access_X12b31ggg23") + }, + func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + w.WriteHeader(http.StatusNoContent) + }, + }, + { + "disable voucher issuer for profile an error is returned from the server.", + args{ + context.Background(), + "pfl_v9hTwCvYqw", + PluxeeEcoVoucher, + }, + true, + fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), + noPre, + errorHandler, + }, + { + "disable voucher issuer for profile invalid url when building request.", + args{ + context.Background(), + "pfl_v9hTwCvYqw", + PluxeeEcoVoucher, + }, + true, + errBadBaseURL, + crashSrv, + errorHandler, + }, + } + + for _, c := range cases { + setup() + defer teardown() + + t.Run(c.name, func(t *testing.T) { + c.pre() + tMux.HandleFunc( + fmt.Sprintf("/v2/profiles/%s/methods/voucher/issuers/%s", + c.args.profile, + c.args.issuer, + ), + c.handler, + ) + + res, err := tClient.Profiles.DisableVoucherIssuer(c.args.ctx, c.args.profile, c.args.issuer) + if c.wantErr { + assert.NotNil(t, err) + assert.EqualError(t, err, c.err.Error()) + } else { + assert.Nil(t, err) + assert.IsType(t, &http.Response{}, res.Response) + assert.Equal(t, http.StatusNoContent, res.StatusCode) + } + }) + } +} + +func TestProfileService_EnableVoucherIssuerForCurrent(t *testing.T) { + setEnv() + defer unsetEnv() + + type args struct { + ctx context.Context + issuer VoucherIssuer + } + cases := []struct { + name string + args args + wantErr bool + err error + pre func() + handler http.HandlerFunc + }{ + { + "enable voucher issuer for current profile works as expected.", + args{ + context.Background(), + PluxeeEcoVoucher, + }, + false, + nil, + noPre, + func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + w.WriteHeader(http.StatusCreated) + _, _ = w.Write([]byte(testdata.EnableVoucherIssuerResponse)) + }, + }, + { + "enable voucher issuer for current profile an error is returned from the server.", + args{ + context.Background(), + PluxeeEcoVoucher, + }, + true, + fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), + noPre, + errorHandler, + }, + { + "enable voucher issuer for current profile an error occurs when parsing json.", + args{ + context.Background(), + PluxeeEcoVoucher, + }, + true, + fmt.Errorf("invalid character 'h' looking for beginning of object key string"), + noPre, + encodingHandler, + }, + { + "enable voucher issuer for current profile invalid url when building request.", + args{ + context.Background(), + PluxeeEcoVoucher, + }, + true, + errBadBaseURL, + crashSrv, + errorHandler, + }, + } + + for _, c := range cases { + setup() + defer teardown() + + t.Run(c.name, func(t *testing.T) { + c.pre() + tMux.HandleFunc( + fmt.Sprintf("/v2/profiles/me/methods/voucher/issuers/%s", + c.args.issuer, + ), + c.handler, + ) + + res, vi, err := tClient.Profiles.EnableVoucherIssuerForCurrent(c.args.ctx, c.args.issuer) + if c.wantErr { + assert.NotNil(t, err) + assert.EqualError(t, err, c.err.Error()) + } else { + assert.Nil(t, err) + assert.IsType(t, &http.Response{}, res.Response) + assert.IsType(t, &VoucherIssuerEnabled{}, vi) + assert.Equal(t, http.StatusCreated, res.StatusCode) + } + }) + } +} + +func TestProfileService_DisableVoucherIssuerForCurrent(t *testing.T) { + setEnv() + defer unsetEnv() + + type args struct { + ctx context.Context + issuer VoucherIssuer + } + cases := []struct { + name string + args args + wantErr bool + err error + pre func() + handler http.HandlerFunc + }{ + { + "disable voucher issuer for current profile works as expected.", + args{ + context.Background(), + PluxeeEcoVoucher, + }, + false, + nil, + noPre, + func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + w.WriteHeader(http.StatusNoContent) + }, + }, + { + "disable voucher issuer for current profile an error is returned from the server.", + args{ + context.Background(), + PluxeeEcoVoucher, + }, + true, + fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), + noPre, + errorHandler, + }, + { + "disable voucher issuer for current profile invalid url when building request.", + args{ + context.Background(), + PluxeeEcoVoucher, + }, + true, + errBadBaseURL, + crashSrv, + errorHandler, + }, + } + + for _, c := range cases { + setup() + defer teardown() + + t.Run(c.name, func(t *testing.T) { + c.pre() + tMux.HandleFunc( + fmt.Sprintf("/v2/profiles/me/methods/voucher/issuers/%s", + c.args.issuer, + ), + c.handler, + ) + + res, err := tClient.Profiles.DisableVoucherIssuerForCurrent(c.args.ctx, c.args.issuer) + if c.wantErr { + assert.NotNil(t, err) + assert.EqualError(t, err, c.err.Error()) + } else { + assert.Nil(t, err) + assert.IsType(t, &http.Response{}, res.Response) + assert.Equal(t, http.StatusNoContent, res.StatusCode) + } + }) + } +} diff --git a/mollie/vouchers.go b/mollie/vouchers.go new file mode 100644 index 00000000..69c1c907 --- /dev/null +++ b/mollie/vouchers.go @@ -0,0 +1,42 @@ +package mollie + +// VoucherIssuer represents the issuer of a voucher. +type VoucherIssuer string + +// List of known voucher issuers. +const ( + EdenredBelgiumCadeauVoucher VoucherIssuer = "edenred-belgium-cadeau" + EdenredBelgiumEcoVoucher VoucherIssuer = "edenred-belgium-eco" + EdenredBelgiumMealVoucher VoucherIssuer = "edenred-belgium-meal" + EdenredBelgiumSportsVoucher VoucherIssuer = "edenred-belgium-sports" + EdenredBelgiumAdditionalVoucher VoucherIssuer = "edenred-belgium-additional" + EdenredBelgiumConsumeVoucher VoucherIssuer = "edenred-belgium-consume" + MonizzeCadeauVoucher VoucherIssuer = "monizze-cadeau" + MonizzeEcoVoucher VoucherIssuer = "monizze-eco" + MonizzeMealVoucher VoucherIssuer = "monizze-meal" + PluxeeCadeauVoucher VoucherIssuer = "sodexo-cadeau" + PluxeeEcoVoucher VoucherIssuer = "sodexo-ecopass" + PluxeeLunchVoucher VoucherIssuer = "sodexo-lunchpass" +) + +// VoucherIssuerEnabled describes the response of a voucher enable operation. +type VoucherIssuerEnabled struct { + ID string `json:"id,omitempty"` + Description string `json:"description,omitempty"` + Status IssuerStatus `json:"status,omitempty"` + Contractor VoucherContractor `json:"contractor,omitempty"` + Links VoucherLinks `json:"_links,omitempty"` +} + +// VoucherLinks are links embedded when a voucher is enabled. +type VoucherLinks struct { + Self *URL `json:"self,omitempty"` + Documentation *URL `json:"documentation,omitempty"` +} + +// VoucherContractor represents a contractor for a voucher. +type VoucherContractor struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ContractorID string `json:"contractorId,omitempty"` +} diff --git a/testdata/profiles.go b/testdata/profiles.go index 9d7e82ca..2c174e2d 100644 --- a/testdata/profiles.go +++ b/testdata/profiles.go @@ -252,3 +252,31 @@ const EnableGiftCardIssuerResponse = `{ } } ` + +// EnableVoucherIssuerResponse example. +const EnableVoucherIssuerResponse = `{ + "resource": "issuer", + "id": "appetiz", + "description": "Appetiz", + "status": "pending-issuer", + "contractor": { + "id": "Conecs", + "name": "Conecs", + "contractId": "abc123" + }, + "image": { + "size1x": "https://www.mollie.com/external/icons/voucher-issuers/apetiz.png", + "size2x": "https://www.mollie.com/external/icons/voucher-issuers/apetiz%402x.png", + "svg": "https://www.mollie.com/external/icons/voucher-issuers/apetiz.svg" + }, + "_links": { + "self": { + "href": "https://api.mollie.com/v2/issuers/appetiz", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/profiles-api/enable-voucher-issuer", + "type": "text/html" + } + } + }` From ee630247b7b20d39885c3e9971a14eed0e93e53d Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 15 Mar 2024 20:04:57 +0100 Subject: [PATCH 18/23] check refunds resource against api reference (#349) --- docs/README.md | 289 ++++++++++++----- mollie/refunds.go | 227 +++++++++---- mollie/refunds_test.go | 634 +++++++++++++++++++++++++------------ mollie/settlements.go | 2 +- mollie/settlements_test.go | 4 +- testdata/refunds.go | 202 +++++++++++- 6 files changed, 998 insertions(+), 360 deletions(-) diff --git a/docs/README.md b/docs/README.md index 18ad8671..493647b9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -114,8 +114,10 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>) - [type CreateOrUpdateProfile](<#CreateOrUpdateProfile>) - [type CreateOrder](<#CreateOrder>) +- [type CreateOrderRefund](<#CreateOrderRefund>) - [type CreatePayment](<#CreatePayment>) - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>) +- [type CreatePaymentRefund](<#CreatePaymentRefund>) - [type CreatePreAuthorizedPaymentFields](<#CreatePreAuthorizedPaymentFields>) - [type CreateRecurrentPaymentFields](<#CreateRecurrentPaymentFields>) - [type CreateShipmentRequest](<#CreateShipmentRequest>) @@ -159,7 +161,6 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type LinkedClientList](<#LinkedClientList>) - [type ListLinkedClientsOptions](<#ListLinkedClientsOptions>) - [type ListPaymentOptions](<#ListPaymentOptions>) -- [type ListRefundOptions](<#ListRefundOptions>) - [type Locale](<#Locale>) - [type Mandate](<#Mandate>) - [type MandateDetails](<#MandateDetails>) @@ -202,6 +203,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type OrderListRefundOptions](<#OrderListRefundOptions>) - [type OrderOptions](<#OrderOptions>) - [type OrderPayment](<#OrderPayment>) +- [type OrderRefundLine](<#OrderRefundLine>) - [type OrderStatus](<#OrderStatus>) - [type OrdersService](<#OrdersService>) - [func \(ors \*OrdersService\) Cancel\(ctx context.Context, orderID string\) \(res \*Response, order \*Order, err error\)](<#OrdersService.Cancel>) @@ -253,6 +255,9 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ms \*PaymentMethodsService\) Get\(ctx context.Context, id PaymentMethod, options \*PaymentMethodOptions\) \(res \*Response, pmd \*PaymentMethodDetails, err error\)](<#PaymentMethodsService.Get>) - [func \(ms \*PaymentMethodsService\) List\(ctx context.Context, options \*PaymentMethodsListOptions\) \(res \*Response, pm \*PaymentMethodsList, err error\)](<#PaymentMethodsService.List>) - [type PaymentOptions](<#PaymentOptions>) +- [type PaymentRefundAccessTokenFields](<#PaymentRefundAccessTokenFields>) +- [type PaymentRefundMollieConnectFields](<#PaymentRefundMollieConnectFields>) +- [type PaymentRefundOptions](<#PaymentRefundOptions>) - [type PaymentRouting](<#PaymentRouting>) - [type PaymentsService](<#PaymentsService>) - [func \(ps \*PaymentsService\) Cancel\(ctx context.Context, id string\) \(res \*Response, p \*Payment, err error\)](<#PaymentsService.Cancel>) @@ -299,16 +304,20 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type RecurrentPaymentFields](<#RecurrentPaymentFields>) - [type Refund](<#Refund>) - [type RefundLinks](<#RefundLinks>) -- [type RefundList](<#RefundList>) -- [type RefundOptions](<#RefundOptions>) - [type RefundStatus](<#RefundStatus>) +- [type RefundsList](<#RefundsList>) +- [type RefundsListOptions](<#RefundsListOptions>) - [type RefundsService](<#RefundsService>) - - [func \(rs \*RefundsService\) Cancel\(ctx context.Context, paymentID, refundID string\) \(res \*Response, err error\)](<#RefundsService.Cancel>) - - [func \(rs \*RefundsService\) Create\(ctx context.Context, paymentID string, re Refund, options \*RefundOptions\) \(res \*Response, rf \*Refund, err error\)](<#RefundsService.Create>) - - [func \(rs \*RefundsService\) Get\(ctx context.Context, paymentID, refundID string, opts \*RefundOptions\) \(res \*Response, refund \*Refund, err error\)](<#RefundsService.Get>) - - [func \(rs \*RefundsService\) ListRefund\(ctx context.Context, opts \*ListRefundOptions\) \(res \*Response, rl \*RefundList, err error\)](<#RefundsService.ListRefund>) - - [func \(rs \*RefundsService\) ListRefundPayment\(ctx context.Context, paymentID string, opts \*ListRefundOptions\) \(res \*Response, rl \*RefundList, err error\)](<#RefundsService.ListRefundPayment>) + - [func \(rs \*RefundsService\) CancelPaymentRefund\(ctx context.Context, paymentID, refundID string\) \(res \*Response, err error\)](<#RefundsService.CancelPaymentRefund>) + - [func \(rs \*RefundsService\) CreateOrderRefund\(ctx context.Context, orderID string, r CreateOrderRefund\) \(res \*Response, rf \*Refund, err error\)](<#RefundsService.CreateOrderRefund>) + - [func \(rs \*RefundsService\) CreatePaymentRefund\(ctx context.Context, paymentID string, re CreatePaymentRefund, options \*PaymentRefundOptions\) \(res \*Response, rf \*Refund, err error\)](<#RefundsService.CreatePaymentRefund>) + - [func \(rs \*RefundsService\) GetPaymentRefund\(ctx context.Context, paymentID, refundID string, opts \*PaymentRefundOptions\) \(res \*Response, refund \*Refund, err error\)](<#RefundsService.GetPaymentRefund>) + - [func \(rs \*RefundsService\) List\(ctx context.Context, opts \*RefundsListOptions\) \(res \*Response, rl \*RefundsList, err error\)](<#RefundsService.List>) + - [func \(rs \*RefundsService\) ListOrderRefunds\(ctx context.Context, orderID string, opts \*RefundsListOptions\) \(res \*Response, rl \*RefundsList, err error\)](<#RefundsService.ListOrderRefunds>) + - [func \(rs \*RefundsService\) ListPaymentRefunds\(ctx context.Context, paymentID string, opts \*RefundsListOptions\) \(res \*Response, rl \*RefundsList, err error\)](<#RefundsService.ListPaymentRefunds>) - [type Response](<#Response>) +- [type RoutingReversal](<#RoutingReversal>) +- [type RoutingSource](<#RoutingSource>) - [type SequenceType](<#SequenceType>) - [type Settlement](<#Settlement>) - [type SettlementCosts](<#SettlementCosts>) @@ -324,7 +333,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ss \*SettlementsService\) GetCaptures\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, cl \*CapturesList, err error\)](<#SettlementsService.GetCaptures>) - [func \(ss \*SettlementsService\) GetChargebacks\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, cl \*ChargebacksList, err error\)](<#SettlementsService.GetChargebacks>) - [func \(ss \*SettlementsService\) GetPayments\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, pl \*PaymentList, err error\)](<#SettlementsService.GetPayments>) - - [func \(ss \*SettlementsService\) GetRefunds\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, rl \*RefundList, err error\)](<#SettlementsService.GetRefunds>) + - [func \(ss \*SettlementsService\) GetRefunds\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, rl \*RefundsList, err error\)](<#SettlementsService.GetRefunds>) - [func \(ss \*SettlementsService\) List\(ctx context.Context, slo \*SettlementsListOptions\) \(res \*Response, sl \*SettlementsList, err error\)](<#SettlementsService.List>) - [func \(ss \*SettlementsService\) Next\(ctx context.Context\) \(res \*Response, s \*Settlement, err error\)](<#SettlementsService.Next>) - [func \(ss \*SettlementsService\) Open\(ctx context.Context\) \(res \*Response, s \*Settlement, err error\)](<#SettlementsService.Open>) @@ -1967,6 +1976,20 @@ type CreateOrder struct { } ``` + +## type [CreateOrderRefund]() + +CreateOrderRefund describes the payload to create a refund associated to an order. + +```go +type CreateOrderRefund struct { + Description string `json:"description,omitempty"` + Metadata any `json:"metadata,omitempty"` + Lines []*OrderRefundLine `json:"lines,omitempty"` + PaymentRefundAccessTokenFields +} +``` + ## type [CreatePayment]() @@ -2029,6 +2052,21 @@ type CreatePaymentAccessTokenFields struct { } ``` + +## type [CreatePaymentRefund]() + +CreatePaymentRefund describes the payload to create a refund associated to a payment. + +```go +type CreatePaymentRefund struct { + Description string `json:"description,omitempty"` + Metadata any `json:"metadata,omitempty"` + Amount *Amount `json:"amount,omitempty"` + PaymentRefundAccessTokenFields + PaymentRefundMollieConnectFields +} +``` + ## type [CreatePreAuthorizedPaymentFields]() @@ -2711,22 +2749,6 @@ type ListPaymentOptions struct { } ``` - -## type [ListRefundOptions]() - -ListRefundOptions describes list refund endpoint valid query string parameters. - -See: https://docs.mollie.com/reference/v2/refunds-api/list-refunds. - -```go -type ListRefundOptions struct { - From string `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - ProfileID string `url:"profileId,omitempty"` - Embed EmbedValue `url:"embed,omitempty"` -} -``` - ## type [Locale]() @@ -3439,6 +3461,19 @@ type OrderPayment struct { } ``` + +## type [OrderRefundLine]() + +OrderRefundLine describes the payload to create a refund associated to an order line. + +```go +type OrderRefundLine struct { + Quantity int `json:"quantity,omitempty"` + ID string `json:"id,omitempty"` + Amount *Amount `json:"amount,omitempty"` +} +``` + ## type [OrderStatus]() @@ -4245,6 +4280,40 @@ type PaymentOptions struct { } ``` + +## type [PaymentRefundAccessTokenFields]() + +PaymentRefundAccessTokenFields describes the access token available fields for a refund. + +```go +type PaymentRefundAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` +} +``` + + +## type [PaymentRefundMollieConnectFields]() + +PaymentRefundMollieConnectFields describes the Mollie Connect available fields for a refund. + +```go +type PaymentRefundMollieConnectFields struct { + ReverseRouting bool `json:"reverseRouting,omitempty"` + RoutingReversals []*RoutingReversal `json:"routingReversals,omitempty"` +} +``` + + +## type [PaymentRefundOptions]() + +PaymentRefundOptions describes payment refund endpoint valid query string parameters. + +```go +type PaymentRefundOptions struct { + Embed []EmbedValue `url:"embed,omitempty"` +} +``` + ## type [PaymentRouting]() @@ -4804,7 +4873,7 @@ type RecurrentPaymentFields struct { ``` -## type [Refund]() +## type [Refund]() Refund describe a refund for a certain payment. @@ -4812,23 +4881,24 @@ Refund describe a refund for a certain payment. type Refund struct { Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` - Amount *Amount `json:"amount,omitempty"` SettlementID string `json:"settlementId,omitempty"` - SettlementAmount *Amount `json:"settlementAmount,omitempty"` Description string `json:"description,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - Status RefundStatus `json:"status,omitempty"` - Lines []*OrderLine `json:"lines,omitempty"` PaymentID string `json:"paymentId,omitempty"` OrderID string `json:"orderId,omitempty"` + Amount *Amount `json:"amount,omitempty"` + SettlementAmount *Amount `json:"settlementAmount,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` - TestMode bool `json:"testmode,omitempty"` + Lines []*OrderLine `json:"lines,omitempty"` + Metadata any `json:"metadata,omitempty"` + Status RefundStatus `json:"status,omitempty"` Links RefundLinks `json:"_links,omitempty"` + PaymentRefundAccessTokenFields + PaymentRefundMollieConnectFields } ``` -## type [RefundLinks]() +## type [RefundLinks]() RefundLinks describes all the possible links to be returned with a Refund object. @@ -4842,13 +4912,34 @@ type RefundLinks struct { } ``` - -## type [RefundList]() + +## type [RefundStatus]() -RefundList describes how a list of refunds will be retrieved by Mollie. +RefundStatus describes the status of the refund. ```go -type RefundList struct { +type RefundStatus string +``` + +Valid refund status. + +```go +const ( + Queued RefundStatus = "queued" + Pending RefundStatus = "pending" + Processing RefundStatus = "processing" + Refunded RefundStatus = "refunded" + Failed RefundStatus = "failed" +) +``` + + +## type [RefundsList]() + +RefundsList describes how a list of refunds will be retrieved by Mollie. + +```go +type RefundsList struct { Count int `json:"count,omitempty"` Embedded struct { Refunds []*Refund @@ -4857,101 +4948,105 @@ type RefundList struct { } ``` - -## type [RefundOptions]() - -RefundOptions describes refund endpoint valid query string parameters. + +## type [RefundsListOptions]() -See: https://docs.mollie.com/reference/v2/refunds-api/get-refund. +RefundsListOptions describes payment and order refunds list endpoint valid query string parameters. ```go -type RefundOptions struct { - Embed EmbedValue `url:"embed,omitempty"` +type RefundsListOptions struct { + Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` + ProfileID string `url:"profileId,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` } ``` - -## type [RefundStatus]() + +## type [RefundsService]() -RefundStatus describes the status of the refund. +RefundsService instance operates over refund resources. ```go -type RefundStatus string +type RefundsService service ``` -Valid refund status. + +### func \(\*RefundsService\) [CancelPaymentRefund]() ```go -const ( - Queued RefundStatus = "queued" - Pending RefundStatus = "pending" - Processing RefundStatus = "processing" - Refunded RefundStatus = "refunded" - Failed RefundStatus = "failed" -) +func (rs *RefundsService) CancelPaymentRefund(ctx context.Context, paymentID, refundID string) (res *Response, err error) ``` - -## type [RefundsService]() +CancelPaymentRefund cancels a refund for a specific payment. -RefundsService instance operates over refund resources. +See https://docs.mollie.com/reference/v2/refunds-api/cancel-payment-refund + + +### func \(\*RefundsService\) [CreateOrderRefund]() ```go -type RefundsService service +func (rs *RefundsService) CreateOrderRefund(ctx context.Context, orderID string, r CreateOrderRefund) (res *Response, rf *Refund, err error) ``` - -### func \(\*RefundsService\) [Cancel]() +CreateOrderRefund creates a refund for a specific order. + +See https://docs.mollie.com/reference/v2/refunds-api/create-order-refund + + +### func \(\*RefundsService\) [CreatePaymentRefund]() ```go -func (rs *RefundsService) Cancel(ctx context.Context, paymentID, refundID string) (res *Response, err error) +func (rs *RefundsService) CreatePaymentRefund(ctx context.Context, paymentID string, re CreatePaymentRefund, options *PaymentRefundOptions) (res *Response, rf *Refund, err error) ``` -Cancel try to cancel the refund request. The refund can only be canceled while the refund’s status is either queued or pending. See https://docs.mollie.com/reference/v2/refunds-api/cancel-refund +Create a refund payment request. + +See https://docs.mollie.com/reference/v2/refunds-api/create-payment-refund - -### func \(\*RefundsService\) [Create]() + +### func \(\*RefundsService\) [GetPaymentRefund]() ```go -func (rs *RefundsService) Create(ctx context.Context, paymentID string, re Refund, options *RefundOptions) (res *Response, rf *Refund, err error) +func (rs *RefundsService) GetPaymentRefund(ctx context.Context, paymentID, refundID string, opts *PaymentRefundOptions) (res *Response, refund *Refund, err error) ``` -Create a refund payment request. +GetPaymentRefund retrieves a specific refund for a specific payment. -See https://docs.mollie.com/reference/v2/refunds-api/create-refund. +See: https://docs.mollie.com/reference/v2/refunds-api/get-payment-refund - -### func \(\*RefundsService\) [Get]() + +### func \(\*RefundsService\) [List]() ```go -func (rs *RefundsService) Get(ctx context.Context, paymentID, refundID string, opts *RefundOptions) (res *Response, refund *Refund, err error) +func (rs *RefundsService) List(ctx context.Context, opts *RefundsListOptions) (res *Response, rl *RefundsList, err error) ``` -Get retrieve a single refund by its ID. +List retrieves all refunds. -If you do not know the original payment’s ID, you can use the List payment refunds endpoint. +See https://docs.mollie.com/reference/v2/refunds-api/list-refunds. - -### func \(\*RefundsService\) [ListRefund]() + +### func \(\*RefundsService\) [ListOrderRefunds]() ```go -func (rs *RefundsService) ListRefund(ctx context.Context, opts *ListRefundOptions) (res *Response, rl *RefundList, err error) +func (rs *RefundsService) ListOrderRefunds(ctx context.Context, orderID string, opts *RefundsListOptions) (res *Response, rl *RefundsList, err error) ``` -ListRefund calls the top level https://api.mollie.com/v2/refunds. +ListOrderRefunds retrieves all refunds for a specific order. -See https://docs.mollie.com/reference/v2/refunds-api/list-refunds. +See https://docs.mollie.com/reference/v2/refunds-api/list-order-refunds - -### func \(\*RefundsService\) [ListRefundPayment]() + +### func \(\*RefundsService\) [ListPaymentRefunds]() ```go -func (rs *RefundsService) ListRefundPayment(ctx context.Context, paymentID string, opts *ListRefundOptions) (res *Response, rl *RefundList, err error) +func (rs *RefundsService) ListPaymentRefunds(ctx context.Context, paymentID string, opts *RefundsListOptions) (res *Response, rl *RefundsList, err error) ``` -ListRefundPayment calls the payment\-specific https://api.mollie.com/v2/payments/*paymentId*/refunds. +ListPaymentRefunds retrieves all refunds for a specific payment. -Only refunds for that specific payment are returned. See: https://docs.mollie.com/reference/v2/refunds-api/list-refunds +See: https://docs.mollie.com/reference/v2/refunds-api/list-payment-refunds ## type [Response]() @@ -4965,6 +5060,30 @@ type Response struct { } ``` + +## type [RoutingReversal]() + +RoutingReversal describes the payload to be sent to the reverse routing endpoint. + +```go +type RoutingReversal struct { + Amount *Amount `json:"amount,omitempty"` + Source string `json:"source,omitempty"` +} +``` + + +## type [RoutingSource]() + +RoutingSource describes the source of the routing. + +```go +type RoutingSource struct { + Type string `json:"type,omitempty"` + OrganizationID string `json:"organizationId,omitempty"` +} +``` + ## type [SequenceType]() @@ -5182,7 +5301,7 @@ See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-paymen ### func \(\*SettlementsService\) [GetRefunds]() ```go -func (ss *SettlementsService) GetRefunds(ctx context.Context, id string, slo *SettlementsListOptions) (res *Response, rl *RefundList, err error) +func (ss *SettlementsService) GetRefunds(ctx context.Context, id string, slo *SettlementsListOptions) (res *Response, rl *RefundsList, err error) ``` GetRefunds retrieves all refunds included in a settlement. diff --git a/mollie/refunds.go b/mollie/refunds.go index bbbec5c5..0c6beea9 100644 --- a/mollie/refunds.go +++ b/mollie/refunds.go @@ -7,26 +7,74 @@ import ( "time" ) +// CreatePaymentRefund describes the payload to create a refund associated to a payment. +type CreatePaymentRefund struct { + Description string `json:"description,omitempty"` + Metadata any `json:"metadata,omitempty"` + Amount *Amount `json:"amount,omitempty"` + PaymentRefundAccessTokenFields + PaymentRefundMollieConnectFields +} + +// CreateOrderRefund describes the payload to create a refund associated to an order. +type CreateOrderRefund struct { + Description string `json:"description,omitempty"` + Metadata any `json:"metadata,omitempty"` + Lines []*OrderRefundLine `json:"lines,omitempty"` + PaymentRefundAccessTokenFields +} + +// OrderRefundLine describes the payload to create a refund associated to an order line. +type OrderRefundLine struct { + Quantity int `json:"quantity,omitempty"` + ID string `json:"id,omitempty"` + Amount *Amount `json:"amount,omitempty"` +} + +// PaymentRefundAccessTokenFields describes the access token available fields for a refund. +type PaymentRefundAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` +} + +// PaymentRefundMollieConnectFields describes the Mollie Connect available fields for a refund. +type PaymentRefundMollieConnectFields struct { + ReverseRouting bool `json:"reverseRouting,omitempty"` + RoutingReversals []*RoutingReversal `json:"routingReversals,omitempty"` +} + +// RoutingReversal describes the payload to be sent to the reverse routing endpoint. +type RoutingReversal struct { + Amount *Amount `json:"amount,omitempty"` + Source string `json:"source,omitempty"` +} + +// RoutingSource describes the source of the routing. +type RoutingSource struct { + Type string `json:"type,omitempty"` + OrganizationID string `json:"organizationId,omitempty"` +} + // Refund describe a refund for a certain payment. type Refund struct { Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` - Amount *Amount `json:"amount,omitempty"` SettlementID string `json:"settlementId,omitempty"` - SettlementAmount *Amount `json:"settlementAmount,omitempty"` Description string `json:"description,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - Status RefundStatus `json:"status,omitempty"` - Lines []*OrderLine `json:"lines,omitempty"` PaymentID string `json:"paymentId,omitempty"` OrderID string `json:"orderId,omitempty"` + Amount *Amount `json:"amount,omitempty"` + SettlementAmount *Amount `json:"settlementAmount,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` - TestMode bool `json:"testmode,omitempty"` + Lines []*OrderLine `json:"lines,omitempty"` + Metadata any `json:"metadata,omitempty"` + Status RefundStatus `json:"status,omitempty"` Links RefundLinks `json:"_links,omitempty"` + PaymentRefundAccessTokenFields + PaymentRefundMollieConnectFields } -// RefundList describes how a list of refunds will be retrieved by Mollie. -type RefundList struct { +// RefundsList describes how a list of refunds will be retrieved by Mollie. +type RefundsList struct { Count int `json:"count,omitempty"` Embedded struct { Refunds []*Refund @@ -56,30 +104,50 @@ type RefundLinks struct { Documentation *URL `json:"documentation,omitempty"` } -// RefundOptions describes refund endpoint valid query string parameters. -// -// See: https://docs.mollie.com/reference/v2/refunds-api/get-refund. -type RefundOptions struct { - Embed EmbedValue `url:"embed,omitempty"` +// PaymentRefundOptions describes payment refund endpoint valid query string parameters. +type PaymentRefundOptions struct { + Embed []EmbedValue `url:"embed,omitempty"` } -// ListRefundOptions describes list refund endpoint valid query string parameters. -// -// See: https://docs.mollie.com/reference/v2/refunds-api/list-refunds. -type ListRefundOptions struct { - From string `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - ProfileID string `url:"profileId,omitempty"` - Embed EmbedValue `url:"embed,omitempty"` +// RefundsListOptions describes payment and order refunds list endpoint valid query string parameters. +type RefundsListOptions struct { + Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` + ProfileID string `url:"profileId,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` } // RefundsService instance operates over refund resources. type RefundsService service -// Get retrieve a single refund by its ID. +// List retrieves all refunds. +// +// See https://docs.mollie.com/reference/v2/refunds-api/list-refunds. +func (rs *RefundsService) List(ctx context.Context, opts *RefundsListOptions) ( + res *Response, + rl *RefundsList, + err error, +) { + res, err = rs.client.get(ctx, "v2/refunds", opts) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &rl); err != nil { + return + } + + return +} + +// GetPaymentRefund retrieves a specific refund for a specific payment. // -// If you do not know the original payment’s ID, you can use the List payment refunds endpoint. -func (rs *RefundsService) Get(ctx context.Context, paymentID, refundID string, opts *RefundOptions) ( +// See: https://docs.mollie.com/reference/v2/refunds-api/get-payment-refund +func (rs *RefundsService) GetPaymentRefund( + ctx context.Context, + paymentID, refundID string, + opts *PaymentRefundOptions, +) ( res *Response, refund *Refund, err error, @@ -98,10 +166,41 @@ func (rs *RefundsService) Get(ctx context.Context, paymentID, refundID string, o return } +// ListPaymentRefunds retrieves all refunds for a specific payment. +// +// See: https://docs.mollie.com/reference/v2/refunds-api/list-payment-refunds +func (rs *RefundsService) ListPaymentRefunds( + ctx context.Context, + paymentID string, + opts *RefundsListOptions, +) ( + res *Response, + rl *RefundsList, + err error, +) { + u := fmt.Sprintf("v2/payments/%s/refunds", paymentID) + + res, err = rs.client.get(ctx, u, opts) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &rl); err != nil { + return + } + + return +} + // Create a refund payment request. // -// See https://docs.mollie.com/reference/v2/refunds-api/create-refund. -func (rs *RefundsService) Create(ctx context.Context, paymentID string, re Refund, options *RefundOptions) ( +// See https://docs.mollie.com/reference/v2/refunds-api/create-payment-refund +func (rs *RefundsService) CreatePaymentRefund( + ctx context.Context, + paymentID string, + re CreatePaymentRefund, + options *PaymentRefundOptions, +) ( res *Response, rf *Refund, err error, @@ -109,7 +208,7 @@ func (rs *RefundsService) Create(ctx context.Context, paymentID string, re Refun uri := fmt.Sprintf("v2/payments/%s/refunds", paymentID) if rs.client.HasAccessToken() && rs.client.config.testing { - re.TestMode = true + re.Testmode = true } res, err = rs.client.post(ctx, uri, re, options) @@ -124,54 +223,60 @@ func (rs *RefundsService) Create(ctx context.Context, paymentID string, re Refun return } -// Cancel try to cancel the refund request. -// The refund can only be canceled while the refund’s status is either queued or pending. -// See https://docs.mollie.com/reference/v2/refunds-api/cancel-refund -func (rs *RefundsService) Cancel(ctx context.Context, paymentID, refundID string) (res *Response, err error) { - u := fmt.Sprintf("v2/payments/%s/refunds/%s", paymentID, refundID) - - res, err = rs.client.delete(ctx, u, nil) - if err != nil { - return - } - - return +// CancelPaymentRefund cancels a refund for a specific payment. +// +// See https://docs.mollie.com/reference/v2/refunds-api/cancel-payment-refund +func (rs *RefundsService) CancelPaymentRefund( + ctx context.Context, paymentID, refundID string, +) (res *Response, err error) { + return rs.client.delete(ctx, fmt.Sprintf("v2/payments/%s/refunds/%s", paymentID, refundID), nil) } -// ListRefund calls the top level https://api.mollie.com/v2/refunds. +// CreateOrderRefund creates a refund for a specific order. // -// See https://docs.mollie.com/reference/v2/refunds-api/list-refunds. -func (rs *RefundsService) ListRefund(ctx context.Context, opts *ListRefundOptions) ( +// See https://docs.mollie.com/reference/v2/refunds-api/create-order-refund +func (rs *RefundsService) CreateOrderRefund( + ctx context.Context, + orderID string, + r CreateOrderRefund, +) ( res *Response, - rl *RefundList, + rf *Refund, err error, ) { - u := "v2/refunds" + uri := fmt.Sprintf("v2/orders/%s/refunds", orderID) - return rs.list(ctx, u, opts) -} + if rs.client.HasAccessToken() && rs.client.config.testing { + r.Testmode = true + } -// ListRefundPayment calls the payment-specific -// https://api.mollie.com/v2/payments/*paymentId*/refunds. -// -// Only refunds for that specific payment are returned. -// See: https://docs.mollie.com/reference/v2/refunds-api/list-refunds -func (rs *RefundsService) ListRefundPayment(ctx context.Context, paymentID string, opts *ListRefundOptions) ( - res *Response, - rl *RefundList, - err error, -) { - u := fmt.Sprintf("v2/payments/%s/refunds", paymentID) + res, err = rs.client.post(ctx, uri, r, nil) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &rf); err != nil { + return + } - return rs.list(ctx, u, opts) + return } -func (rs *RefundsService) list(ctx context.Context, uri string, opts interface{}) ( +// ListOrderRefunds retrieves all refunds for a specific order. +// +// See https://docs.mollie.com/reference/v2/refunds-api/list-order-refunds +func (rs *RefundsService) ListOrderRefunds( + ctx context.Context, + orderID string, + opts *RefundsListOptions, +) ( res *Response, - rl *RefundList, + rl *RefundsList, err error, ) { - res, err = rs.client.get(ctx, uri, opts) + u := fmt.Sprintf("v2/orders/%s/refunds", orderID) + + res, err = rs.client.get(ctx, u, opts) if err != nil { return } diff --git a/mollie/refunds_test.go b/mollie/refunds_test.go index 504115aa..0e963554 100644 --- a/mollie/refunds_test.go +++ b/mollie/refunds_test.go @@ -10,16 +10,14 @@ import ( "github.com/stretchr/testify/assert" ) -func TestRefundsService_Get(t *testing.T) { - setEnv() - defer unsetEnv() - +func TestRefundsService_CreatePaymentRefund(t *testing.T) { type args struct { - ctx context.Context - payment string - refund string - options *RefundOptions + ctx context.Context + paymentID string + re CreatePaymentRefund + options *PaymentRefundOptions } + cases := []struct { name string args args @@ -29,36 +27,168 @@ func TestRefundsService_Get(t *testing.T) { handler http.HandlerFunc }{ { - "get refund works as expected.", + "create payment refund works as expected", args{ context.Background(), - "tr_WDqYK6vllg", - "re_4qqhO89gsT", - &RefundOptions{ - Embed: "profile", + "tr_7UhSN1zuXS", + CreatePaymentRefund{ + Amount: &Amount{ + Value: "5.00", + Currency: "EUR", + }, }, + &PaymentRefundOptions{}, }, false, nil, noPre, func(w http.ResponseWriter, r *http.Request) { - testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") - testMethod(t, r, "GET") - testQuery(t, r, "embed=profile") + w.WriteHeader(http.StatusCreated) + w.Write([]byte(testdata.CreatePaymentRefundResponse)) + }, + }, + { + "create payment refund works as expected with access tokens", + args{ + context.Background(), + "tr_7UhSN1zuXS", + CreatePaymentRefund{ + Amount: &Amount{ + Value: "5.00", + Currency: "EUR", + }, + }, + &PaymentRefundOptions{}, + }, + false, + nil, + setAccessToken, + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusCreated) + w.Write([]byte(testdata.CreatePaymentRefundResponse)) + }, + }, + { + "create payment refund, an error is returned from the server", + args{ + context.Background(), + "tr_7UhSN1zuXS", + CreatePaymentRefund{}, + &PaymentRefundOptions{}, + }, + true, + fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), + noPre, + errorHandler, + }, + { + "create payment refund, an error occurs when parsing json", + args{ + context.Background(), + "tr_7UhSN1zuXS", + CreatePaymentRefund{}, + &PaymentRefundOptions{}, + }, + true, + fmt.Errorf("invalid character 'h' looking for beginning of object key string"), + noPre, + encodingHandler, + }, + { + "get settlement refunds, invalid url when building request", + args{ + context.Background(), + "tr_7UhSN1zuXS", + CreatePaymentRefund{}, + &PaymentRefundOptions{}, + }, + true, + errBadBaseURL, + crashSrv, + errorHandler, + }, + } - if _, ok := r.Header[AuthHeader]; !ok { - w.WriteHeader(http.StatusUnauthorized) - } - _, _ = w.Write([]byte(testdata.GetRefundResponse)) + for _, c := range cases { + setup() + defer teardown() + t.Run(c.name, func(t *testing.T) { + c.pre() + tMux.HandleFunc(fmt.Sprintf("/v2/payments/%s/refunds", c.args.paymentID), c.handler) + + res, ref, err := tClient.Refunds.CreatePaymentRefund( + c.args.ctx, + c.args.paymentID, + c.args.re, + c.args.options, + ) + if c.wantErr { + assert.NotNil(t, err) + assert.EqualError(t, err, c.err.Error()) + } else { + assert.Nil(t, err) + assert.IsType(t, &Refund{}, ref) + assert.IsType(t, &http.Response{}, res.Response) + } + }) + } +} + +func TestRefundsService_GetPaymentRefund(t *testing.T) { + type args struct { + ctx context.Context + paymentID string + refundID string + opts *PaymentRefundOptions + } + + cases := []struct { + name string + args args + wantErr bool + err error + pre func() + handler http.HandlerFunc + }{ + { + "get payment refund works as expected", + args{ + context.Background(), + "tr_7UhSN1zuXS", + "re_4qqhO89gsT", + &PaymentRefundOptions{}, + }, + false, + nil, + noPre, + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(testdata.GetPaymentRefundResponse)) + }, + }, + { + "get payment refund works as expected with access tokens", + args{ + context.Background(), + "tr_7UhSN1zuXS", + "re_4qqhO89gsT", + &PaymentRefundOptions{}, + }, + false, + nil, + setAccessToken, + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(testdata.GetPaymentRefundResponse)) }, }, { - "get refund, an error is returned from the server", + "get payment refund, an error is returned from the server", args{ context.Background(), - "tr_WDqYK6vllg", + "tr_7UhSN1zuXS", "re_4qqhO89gsT", - nil, + &PaymentRefundOptions{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -66,12 +196,12 @@ func TestRefundsService_Get(t *testing.T) { errorHandler, }, { - "get refund, an error occurs when parsing json", + "get payment refund, an error occurs when parsing json", args{ context.Background(), - "tr_WDqYK6vllg", + "tr_7UhSN1zuXS", "re_4qqhO89gsT", - nil, + &PaymentRefundOptions{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -79,12 +209,12 @@ func TestRefundsService_Get(t *testing.T) { encodingHandler, }, { - "get refund, invalid url when building request", + "get payment refund, invalid url when building request", args{ context.Background(), - "tr_WDqYK6vllg", + "tr_7UhSN1zuXS", "re_4qqhO89gsT", - nil, + &PaymentRefundOptions{}, }, true, errBadBaseURL, @@ -96,34 +226,38 @@ func TestRefundsService_Get(t *testing.T) { for _, c := range cases { setup() defer teardown() - t.Run(c.name, func(t *testing.T) { c.pre() - tMux.HandleFunc(fmt.Sprintf("/v2/payments/%s/refunds/%s", c.args.payment, c.args.refund), c.handler) - - res, m, err := tClient.Refunds.Get(c.args.ctx, c.args.payment, c.args.refund, c.args.options) + tMux.HandleFunc( + fmt.Sprintf("/v2/payments/%s/refunds/%s", c.args.paymentID, c.args.refundID), + c.handler, + ) + + res, ref, err := tClient.Refunds.GetPaymentRefund( + c.args.ctx, + c.args.paymentID, + c.args.refundID, + c.args.opts, + ) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &Refund{}, m) + assert.IsType(t, &Refund{}, ref) assert.IsType(t, &http.Response{}, res.Response) } }) } } -func TestRefundsService_Create(t *testing.T) { - setEnv() - defer unsetEnv() - +func TestRefundsService_ListPaymentRefunds(t *testing.T) { type args struct { - ctx context.Context - payment string - refund Refund - options *RefundOptions + ctx context.Context + paymentID string + opts *RefundsListOptions } + cases := []struct { name string args args @@ -133,73 +267,41 @@ func TestRefundsService_Create(t *testing.T) { handler http.HandlerFunc }{ { - "create refund works as expected.", + "list payment refunds works as expected", args{ context.Background(), - "tr_WDqYK6vllg", - Refund{ - Amount: &Amount{ - Currency: "USD", - Value: "100.00", - }, - }, - &RefundOptions{ - Embed: "profile", - }, + "tr_7UhSN1zuXS", + &RefundsListOptions{}, }, false, nil, noPre, func(w http.ResponseWriter, r *http.Request) { - testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") - testMethod(t, r, "POST") - testQuery(t, r, "embed=profile") - - if _, ok := r.Header[AuthHeader]; !ok { - w.WriteHeader(http.StatusUnauthorized) - } - _, _ = w.Write([]byte(testdata.GetRefundResponse)) + w.WriteHeader(http.StatusOK) + w.Write([]byte(testdata.ListPaymentRefundsResponse)) }, }, { - "create refund with access token works as expected.", + "list payment refunds works as expected with access tokens", args{ context.Background(), - "tr_WDqYK6vllg", - Refund{ - Amount: &Amount{ - Currency: "USD", - Value: "100.00", - }, - }, - nil, + "tr_7UhSN1zuXS", + &RefundsListOptions{}, }, false, nil, setAccessToken, func(w http.ResponseWriter, r *http.Request) { - testHeader(t, r, AuthHeader, "Bearer access_token_test") - testMethod(t, r, "POST") - testQuery(t, r, "testmode=true") - - if _, ok := r.Header[AuthHeader]; !ok { - w.WriteHeader(http.StatusUnauthorized) - } - _, _ = w.Write([]byte(testdata.GetRefundResponse)) + w.WriteHeader(http.StatusOK) + w.Write([]byte(testdata.ListPaymentRefundsResponse)) }, }, { - "create refund, an error is returned from the server", + "list payment refunds, an error is returned from the server", args{ context.Background(), - "tr_WDqYK6vllg", - Refund{ - Amount: &Amount{ - Currency: "USD", - Value: "100.00", - }, - }, - nil, + "tr_7UhSN1zuXS", + &RefundsListOptions{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -207,17 +309,11 @@ func TestRefundsService_Create(t *testing.T) { errorHandler, }, { - "create refund, an error occurs when parsing json", + "list payment refunds, an error occurs when parsing json", args{ context.Background(), - "tr_WDqYK6vllg", - Refund{ - Amount: &Amount{ - Currency: "USD", - Value: "100.00", - }, - }, - nil, + "tr_7UhSN1zuXS", + &RefundsListOptions{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -225,17 +321,11 @@ func TestRefundsService_Create(t *testing.T) { encodingHandler, }, { - "create refund, invalid url when building request", + "list payment refunds, invalid url when building request", args{ context.Background(), - "tr_WDqYK6vllg", - Refund{ - Amount: &Amount{ - Currency: "USD", - Value: "100.00", - }, - }, - nil, + "tr_7UhSN1zuXS", + &RefundsListOptions{}, }, true, errBadBaseURL, @@ -247,33 +337,34 @@ func TestRefundsService_Create(t *testing.T) { for _, c := range cases { setup() defer teardown() - t.Run(c.name, func(t *testing.T) { c.pre() - tMux.HandleFunc(fmt.Sprintf("/v2/payments/%s/refunds", c.args.payment), c.handler) + tMux.HandleFunc(fmt.Sprintf("/v2/payments/%s/refunds", c.args.paymentID), c.handler) - res, m, err := tClient.Refunds.Create(c.args.ctx, c.args.payment, c.args.refund, c.args.options) + res, rl, err := tClient.Refunds.ListPaymentRefunds( + c.args.ctx, + c.args.paymentID, + c.args.opts, + ) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &Refund{}, m) + assert.IsType(t, &RefundsList{}, rl) assert.IsType(t, &http.Response{}, res.Response) } }) } } -func TestRefundsService_Cancel(t *testing.T) { - setEnv() - defer unsetEnv() - +func TestRefundsService_CancelPaymentRefund(t *testing.T) { type args struct { - ctx context.Context - payment string - refund string + ctx context.Context + paymentID string + refundID string } + cases := []struct { name string args args @@ -283,30 +374,38 @@ func TestRefundsService_Cancel(t *testing.T) { handler http.HandlerFunc }{ { - "get settlement works as expected.", + "cancel payment refund works as expected", args{ context.Background(), - "tr_WDqYK6vllg", + "tr_7UhSN1zuXS", "re_4qqhO89gsT", }, false, nil, noPre, func(w http.ResponseWriter, r *http.Request) { - testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") - testMethod(t, r, "DELETE") - - if _, ok := r.Header[AuthHeader]; !ok { - w.WriteHeader(http.StatusUnauthorized) - } - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusNoContent) + }, + }, + { + "cancel payment refund works as expected with access tokens", + args{ + context.Background(), + "tr_7UhSN1zuXS", + "re_4qqhO89gsT", + }, + false, + nil, + setAccessToken, + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNoContent) }, }, { - "get settlement, an error is returned from the server", + "cancel payment refund, an error is returned from the server", args{ context.Background(), - "tr_WDqYK6vllg", + "tr_7UhSN1zuXS", "re_4qqhO89gsT", }, true, @@ -315,10 +414,10 @@ func TestRefundsService_Cancel(t *testing.T) { errorHandler, }, { - "get settlement, invalid url when building request", + "cancel payment refund, invalid url when building request", args{ context.Background(), - "tr_WDqYK6vllg", + "tr_7UhSN1zuXS", "re_4qqhO89gsT", }, true, @@ -331,12 +430,18 @@ func TestRefundsService_Cancel(t *testing.T) { for _, c := range cases { setup() defer teardown() - t.Run(c.name, func(t *testing.T) { c.pre() - tMux.HandleFunc(fmt.Sprintf("/v2/payments/%s/refunds/%s", c.args.payment, c.args.refund), c.handler) - - res, err := tClient.Refunds.Cancel(c.args.ctx, c.args.payment, c.args.refund) + tMux.HandleFunc( + fmt.Sprintf("/v2/payments/%s/refunds/%s", c.args.paymentID, c.args.refundID), + c.handler, + ) + + res, err := tClient.Refunds.CancelPaymentRefund( + c.args.ctx, + c.args.paymentID, + c.args.refundID, + ) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) @@ -348,15 +453,13 @@ func TestRefundsService_Cancel(t *testing.T) { } } -func TestRefundsService_List(t *testing.T) { - setEnv() - defer unsetEnv() - +func TestRefundsService_CreateOrderRefund(t *testing.T) { type args struct { ctx context.Context - payment string - options *ListRefundOptions + orderID string + r CreateOrderRefund } + cases := []struct { name string args args @@ -366,34 +469,57 @@ func TestRefundsService_List(t *testing.T) { handler http.HandlerFunc }{ { - "list refund works as expected.", + "create order refund works as expected", args{ context.Background(), - "tr_WDqYK6vllg", - &ListRefundOptions{ - Limit: 10, + "ord_8wmqcHMN4U", + CreateOrderRefund{ + Lines: []*OrderRefundLine{ + { + ID: "odl_dgtxyl", + Quantity: 1, + Amount: &Amount{Value: "5.00", Currency: "EUR"}, + }, + }, }, }, false, nil, noPre, func(w http.ResponseWriter, r *http.Request) { - testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") - testMethod(t, r, "GET") - testQuery(t, r, "limit=10") - - if _, ok := r.Header[AuthHeader]; !ok { - w.WriteHeader(http.StatusUnauthorized) - } - _, _ = w.Write([]byte(testdata.GetRefundListResponse)) + w.WriteHeader(http.StatusCreated) + w.Write([]byte(testdata.CreateOrderRefundResponse)) }, }, { - "list refund, an error is returned from the server", + "create order refund works as expected with access tokens", args{ context.Background(), - "tr_WDqYK6vllg", - nil, + "ord_8wmqcHMN4U", + CreateOrderRefund{ + Lines: []*OrderRefundLine{ + { + ID: "odl_dgtxyl", + Quantity: 1, + Amount: &Amount{Value: "5.00", Currency: "EUR"}, + }, + }, + }, + }, + false, + nil, + setAccessToken, + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusCreated) + w.Write([]byte(testdata.CreateOrderRefundResponse)) + }, + }, + { + "create order refund, an error is returned from the server", + args{ + context.Background(), + "ord_8wmqcHMN4U", + CreateOrderRefund{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -401,11 +527,11 @@ func TestRefundsService_List(t *testing.T) { errorHandler, }, { - "list refund, an error occurs when parsing json", + "create order refund, an error occurs when parsing json", args{ context.Background(), - "tr_WDqYK6vllg", - nil, + "ord_8wmqcHMN4U", + CreateOrderRefund{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -413,11 +539,11 @@ func TestRefundsService_List(t *testing.T) { encodingHandler, }, { - "list refund, invalid url when building request", + "create order refund, invalid url when building request", args{ context.Background(), - "tr_WDqYK6vllg", - nil, + "ord_8wmqcHMN4U", + CreateOrderRefund{}, }, true, errBadBaseURL, @@ -429,34 +555,34 @@ func TestRefundsService_List(t *testing.T) { for _, c := range cases { setup() defer teardown() - t.Run(c.name, func(t *testing.T) { c.pre() - tMux.HandleFunc("/v2/refunds", c.handler) + tMux.HandleFunc(fmt.Sprintf("/v2/orders/%s/refunds", c.args.orderID), c.handler) - res, m, err := tClient.Refunds.ListRefund(c.args.ctx, c.args.options) + res, ref, err := tClient.Refunds.CreateOrderRefund( + c.args.ctx, + c.args.orderID, + c.args.r, + ) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &RefundList{}, m) + assert.IsType(t, &Refund{}, ref) assert.IsType(t, &http.Response{}, res.Response) } }) } } -func TestRefundsService_ListPaynents(t *testing.T) { - setEnv() - defer unsetEnv() - +func TestRefundsService_ListOrderRefunds(t *testing.T) { type args struct { ctx context.Context - payment string - refund string - options *ListRefundOptions + orderID string + opts *RefundsListOptions } + cases := []struct { name string args args @@ -466,36 +592,41 @@ func TestRefundsService_ListPaynents(t *testing.T) { handler http.HandlerFunc }{ { - "get refund works as expected.", + "list order refunds works as expected", args{ context.Background(), - "tr_WDqYK6vllg", - "re_4qqhO89gsT", - &ListRefundOptions{ - Limit: 10, - }, + "ord_8wmqcHMN4U", + &RefundsListOptions{}, }, false, nil, noPre, func(w http.ResponseWriter, r *http.Request) { - testHeader(t, r, AuthHeader, "Bearer token_X12b31ggg23") - testMethod(t, r, "GET") - testQuery(t, r, "limit=10") - - if _, ok := r.Header[AuthHeader]; !ok { - w.WriteHeader(http.StatusUnauthorized) - } - _, _ = w.Write([]byte(testdata.GetRefundListResponse)) + w.WriteHeader(http.StatusOK) + w.Write([]byte(testdata.ListOrderRefundsResponse)) }, }, { - "get refund, an error is returned from the server", + "list order refunds works as expected with access tokens", args{ context.Background(), - "tr_WDqYK6vllg", - "re_4qqhO89gsT", - nil, + "ord_8wmqcHMN4U", + &RefundsListOptions{}, + }, + false, + nil, + setAccessToken, + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(testdata.ListOrderRefundsResponse)) + }, + }, + { + "list order refunds, an error is returned from the server", + args{ + context.Background(), + "ord_8wmqcHMN4U", + &RefundsListOptions{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -503,12 +634,11 @@ func TestRefundsService_ListPaynents(t *testing.T) { errorHandler, }, { - "get refund, an error occurs when parsing json", + "list order refunds, an error occurs when parsing json", args{ context.Background(), - "tr_WDqYK6vllg", - "re_4qqhO89gsT", - nil, + "ord_8wmqcHMN4U", + &RefundsListOptions{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -516,12 +646,11 @@ func TestRefundsService_ListPaynents(t *testing.T) { encodingHandler, }, { - "get refund, invalid url when building request", + "list order refunds, invalid url when building request", args{ context.Background(), - "tr_WDqYK6vllg", - "re_4qqhO89gsT", - nil, + "ord_8wmqcHMN4U", + &RefundsListOptions{}, }, true, errBadBaseURL, @@ -533,18 +662,121 @@ func TestRefundsService_ListPaynents(t *testing.T) { for _, c := range cases { setup() defer teardown() - t.Run(c.name, func(t *testing.T) { c.pre() - tMux.HandleFunc(fmt.Sprintf("/v2/payments/%s/refunds", c.args.payment), c.handler) + tMux.HandleFunc(fmt.Sprintf("/v2/orders/%s/refunds", c.args.orderID), c.handler) - res, m, err := tClient.Refunds.ListRefundPayment(c.args.ctx, c.args.payment, c.args.options) + res, rl, err := tClient.Refunds.ListOrderRefunds( + c.args.ctx, + c.args.orderID, + c.args.opts, + ) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &RefundList{}, m) + assert.IsType(t, &RefundsList{}, rl) + assert.IsType(t, &http.Response{}, res.Response) + } + }) + } +} + +func TestRefundsService_List(t *testing.T) { + type args struct { + ctx context.Context + opts *RefundsListOptions + } + + cases := []struct { + name string + args args + wantErr bool + err error + pre func() + handler http.HandlerFunc + }{ + { + "list refunds works as expected", + args{ + context.Background(), + &RefundsListOptions{}, + }, + false, + nil, + noPre, + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(testdata.ListRefundsResponse)) + }, + }, + { + "list refunds works as expected with access tokens", + args{ + context.Background(), + &RefundsListOptions{}, + }, + false, + nil, + setAccessToken, + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(testdata.ListRefundsResponse)) + }, + }, + { + "list refunds, an error is returned from the server", + args{ + context.Background(), + &RefundsListOptions{}, + }, + true, + fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), + noPre, + errorHandler, + }, + { + "list refunds, an error occurs when parsing json", + args{ + context.Background(), + &RefundsListOptions{}, + }, + true, + fmt.Errorf("invalid character 'h' looking for beginning of object key string"), + noPre, + encodingHandler, + }, + { + "list refunds, invalid url when building request", + args{ + context.Background(), + &RefundsListOptions{}, + }, + true, + errBadBaseURL, + crashSrv, + errorHandler, + }, + } + + for _, c := range cases { + setup() + defer teardown() + t.Run(c.name, func(t *testing.T) { + c.pre() + tMux.HandleFunc("/v2/refunds", c.handler) + + res, rl, err := tClient.Refunds.List( + c.args.ctx, + c.args.opts, + ) + if c.wantErr { + assert.NotNil(t, err) + assert.EqualError(t, err, c.err.Error(), "error message does not match") + } else { + assert.Nil(t, err) + assert.IsType(t, &RefundsList{}, rl) assert.IsType(t, &http.Response{}, res.Response) } }) diff --git a/mollie/settlements.go b/mollie/settlements.go index 40df0feb..d2efda62 100644 --- a/mollie/settlements.go +++ b/mollie/settlements.go @@ -162,7 +162,7 @@ func (ss *SettlementsService) GetPayments(ctx context.Context, id string, slo *S // See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-refunds func (ss *SettlementsService) GetRefunds(ctx context.Context, id string, slo *SettlementsListOptions) ( res *Response, - rl *RefundList, + rl *RefundsList, err error, ) { res, err = ss.list(ctx, id, "refunds", slo) diff --git a/mollie/settlements_test.go b/mollie/settlements_test.go index 8166cd34..21dbb43f 100644 --- a/mollie/settlements_test.go +++ b/mollie/settlements_test.go @@ -735,7 +735,7 @@ func TestSettlementsService_GetRefunds(t *testing.T) { if _, ok := r.Header[AuthHeader]; !ok { w.WriteHeader(http.StatusUnauthorized) } - _, _ = w.Write([]byte(testdata.GetRefundListResponse)) + _, _ = w.Write([]byte(testdata.ListRefundsResponse)) }, }, { @@ -796,7 +796,7 @@ func TestSettlementsService_GetRefunds(t *testing.T) { assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &RefundList{}, m) + assert.IsType(t, &RefundsList{}, m) assert.IsType(t, &http.Response{}, res.Response) } }) diff --git a/testdata/refunds.go b/testdata/refunds.go index c89ae200..4ba72358 100644 --- a/testdata/refunds.go +++ b/testdata/refunds.go @@ -1,7 +1,7 @@ package testdata -// GetRefundResponse example -const GetRefundResponse = `{ +// CreatePaymentRefundResponse example. +const CreatePaymentRefundResponse = `{ "resource": "refund", "id": "re_4qqhO89gsT", "amount": { @@ -25,15 +25,46 @@ const GetRefundResponse = `{ "type": "application/hal+json" }, "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/get-refund", + "href": "https://docs.mollie.com/reference/v2/refunds-api/create-payment-refund", "type": "text/html" } } }` -// GetRefundListResponse example -const GetRefundListResponse = `{ - "count": 5, +// GetPaymentRefundResponse example. +const GetPaymentRefundResponse = `{ + "resource": "refund", + "id": "re_4qqhO89gsT", + "amount": { + "currency": "EUR", + "value": "5.95" + }, + "status": "pending", + "createdAt": "2018-03-14T17:09:02.0Z", + "description": "Order #33", + "metadata": { + "bookkeeping_id": 12345 + }, + "paymentId": "tr_WDqYK6vllg", + "_links": { + "self": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/refunds/re_4qqhO89gsT", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/refunds-api/get-payment-refund", + "type": "text/html" + } + } +}` + +// ListPaymentRefundsResponse example. +const ListPaymentRefundsResponse = `{ + "count": 1, "_embedded": { "refunds": [ { @@ -60,13 +91,111 @@ const GetRefundListResponse = `{ "type": "application/hal+json" }, "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/get-refund", + "href": "https://docs.mollie.com/reference/v2/refunds-api/get-payment-refund", + "type": "text/html" + } + } + } + ] + }, + "_links": { + "self": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/refunds?limit=5", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/refunds?from=re_APBiGPH2vV&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/refunds-api/list-payment-refunds", + "type": "text/html" + } + } +}` + +// ListOrderRefundsResponse example. +const ListOrderRefundsResponse = ` +{ + "count": 1, + "_embedded": { + "refunds": [ + { + "resource": "refund", + "id": "re_4qqhO89gsT", + "amount": { + "currency": "EUR", + "value": "698.00" + }, + "status": "processing", + "createdAt": "2018-03-14T17:09:02.0Z", + "description": "Required quantity not in stock, refunding one photo book.", + "metadata": { + "bookkeeping_id": 12345 + }, + "paymentId": "tr_WDqYK6vllg", + "orderId": "ord_stTC2WHAuS", + "lines": [ + { + "resource": "orderline", + "id": "odl_dgtxyl", + "orderId": "ord_stTC2WHAuS", + "name": "LEGO 42083 Bugatti Chiron", + "sku": "5702016116977", + "type": "physical", + "status": "paid", + "metadata": null, + "quantity": 1, + "unitPrice": { + "value": "399.00", + "currency": "EUR" + }, + "vatRate": "21.00", + "vatAmount": { + "value": "51.89", + "currency": "EUR" + }, + "discountAmount": { + "value": "100.00", + "currency": "EUR" + }, + "totalAmount": { + "value": "299.00", + "currency": "EUR" + }, + "createdAt": "2018-08-02T09:29:56+00:00", + "_links": { + "productUrl": { + "href": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", + "type": "text/html" + }, + "imageUrl": { + "href": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", + "type": "text/html" + } + } + } + ], + "_links": { + "self": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/refunds/re_4qqhO89gsT", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", + "type": "application/hal+json" + }, + "order": { + "href": "https://api.mollie.com/v2/orders/ord_stTC2WHAuS", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/refunds-api/get-order-refund", "type": "text/html" } } - }, - { }, - { } + } ] }, "_links": { @@ -79,6 +208,59 @@ const GetRefundListResponse = `{ "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/refunds?from=re_APBiGPH2vV&limit=5", "type": "application/hal+json" }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/refunds-api/list-order-refunds", + "type": "text/html" + } + } +}` + +// ListRefundsResponse example. +const ListRefundsResponse = `{ + "count": 1, + "_embedded": { + "refunds": [ + { + "resource": "refund", + "id": "re_4qqhO89gsT", + "amount": { + "currency": "EUR", + "value": "5.95" + }, + "status": "pending", + "createdAt": "2018-03-14T17:09:02.0Z", + "description": "Order", + "metadata": { + "bookkeeping_id": 12345 + }, + "paymentId": "tr_WDqYK6vllg", + "_links": { + "self": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/refunds/re_4qqhO89gsT", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/refunds-api/get-payment-refund", + "type": "text/html" + } + } + } + ] + }, + "_links": { + "self": { + "href": "https://api.mollie.com/v2/refunds?limit=5", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/refunds?from=re_APBiGPH2vV&limit=5", + "type": "application/hal+json" + }, "documentation": { "href": "https://docs.mollie.com/reference/v2/refunds-api/list-refunds", "type": "text/html" From 9bdaf68642d1340e4fb74a42fdacb8114038bcac Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Fri, 15 Mar 2024 20:32:23 +0100 Subject: [PATCH 19/23] check settlements resource against api reference (#350) --- docs/README.md | 135 +++++++++++++++++++------------------ mollie/common_types.go | 2 +- mollie/settlements.go | 76 +++++++++++---------- mollie/settlements_test.go | 52 +++++++------- 4 files changed, 134 insertions(+), 131 deletions(-) diff --git a/docs/README.md b/docs/README.md index 493647b9..fcc685de 100644 --- a/docs/README.md +++ b/docs/README.md @@ -161,6 +161,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type LinkedClientList](<#LinkedClientList>) - [type ListLinkedClientsOptions](<#ListLinkedClientsOptions>) - [type ListPaymentOptions](<#ListPaymentOptions>) +- [type ListSettlementsOptions](<#ListSettlementsOptions>) - [type Locale](<#Locale>) - [type Mandate](<#Mandate>) - [type MandateDetails](<#MandateDetails>) @@ -327,14 +328,13 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type SettlementRevenue](<#SettlementRevenue>) - [type SettlementStatus](<#SettlementStatus>) - [type SettlementsList](<#SettlementsList>) -- [type SettlementsListOptions](<#SettlementsListOptions>) - [type SettlementsService](<#SettlementsService>) - - [func \(ss \*SettlementsService\) Get\(ctx context.Context, id string\) \(res \*Response, s \*Settlement, err error\)](<#SettlementsService.Get>) - - [func \(ss \*SettlementsService\) GetCaptures\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, cl \*CapturesList, err error\)](<#SettlementsService.GetCaptures>) - - [func \(ss \*SettlementsService\) GetChargebacks\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, cl \*ChargebacksList, err error\)](<#SettlementsService.GetChargebacks>) - - [func \(ss \*SettlementsService\) GetPayments\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, pl \*PaymentList, err error\)](<#SettlementsService.GetPayments>) - - [func \(ss \*SettlementsService\) GetRefunds\(ctx context.Context, id string, slo \*SettlementsListOptions\) \(res \*Response, rl \*RefundsList, err error\)](<#SettlementsService.GetRefunds>) - - [func \(ss \*SettlementsService\) List\(ctx context.Context, slo \*SettlementsListOptions\) \(res \*Response, sl \*SettlementsList, err error\)](<#SettlementsService.List>) + - [func \(ss \*SettlementsService\) Get\(ctx context.Context, settlement string\) \(res \*Response, s \*Settlement, err error\)](<#SettlementsService.Get>) + - [func \(ss \*SettlementsService\) GetCaptures\(ctx context.Context, settlement string, slo \*ListSettlementsOptions\) \(res \*Response, cl \*CapturesList, err error\)](<#SettlementsService.GetCaptures>) + - [func \(ss \*SettlementsService\) GetChargebacks\(ctx context.Context, settlement string, slo \*ChargebacksListOptions\) \(res \*Response, cl \*ChargebacksList, err error\)](<#SettlementsService.GetChargebacks>) + - [func \(ss \*SettlementsService\) GetRefunds\(ctx context.Context, settlement string, slo \*ListSettlementsOptions\) \(res \*Response, rl \*RefundsList, err error\)](<#SettlementsService.GetRefunds>) + - [func \(ss \*SettlementsService\) List\(ctx context.Context, slo \*ListSettlementsOptions\) \(res \*Response, sl \*SettlementsList, err error\)](<#SettlementsService.List>) + - [func \(ss \*SettlementsService\) ListPayments\(ctx context.Context, settlement string, options \*ListPaymentOptions\) \(res \*Response, pl \*PaymentList, err error\)](<#SettlementsService.ListPayments>) - [func \(ss \*SettlementsService\) Next\(ctx context.Context\) \(res \*Response, s \*Settlement, err error\)](<#SettlementsService.Next>) - [func \(ss \*SettlementsService\) Open\(ctx context.Context\) \(res \*Response, s \*Settlement, err error\)](<#SettlementsService.Open>) - [type Shipment](<#Shipment>) @@ -2749,6 +2749,19 @@ type ListPaymentOptions struct { } ``` + +## type [ListSettlementsOptions]() + +ListSettlementsOptions contains query parameters for settlement lists. + +```go +type ListSettlementsOptions struct { + From string `url:"from,omitempty"` + Limit int `url:"limit,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` +} +``` + ## type [Locale]() @@ -4853,8 +4866,8 @@ Rate describes service rates, further divided into fixed and percentage costs. ```go type Rate struct { - Fixed *Amount `json:"fixed,omitempty"` Variable string `json:"variable,omitempty"` + Fixed *Amount `json:"fixed,omitempty"` } ``` @@ -5104,44 +5117,45 @@ const ( ``` -## type [Settlement]() +## type [Settlement]() Settlement contains successful payments, together with refunds, captures and chargebacks into settlements. ```go type Settlement struct { - ID string `json:"id,omitempty"` - Resource string `json:"resource,omitempty"` - Reference string `json:"reference,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - SettledAt *time.Time `json:"settledAt,omitempty"` - Status SettlementStatus `json:"status,omitempty"` - Amount *Amount `json:"amount,omitempty"` - Periods SettlementObject `json:"periods,omitempty"` - InvoiceID string `json:"invoiceId,omitempty"` - Links SettlementLinks `json:"_links,omitempty"` + ID string `json:"id,omitempty"` + Resource string `json:"resource,omitempty"` + Reference string `json:"reference,omitempty"` + InvoiceID string `json:"invoiceId,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + SettledAt *time.Time `json:"settledAt,omitempty"` + Amount *Amount `json:"amount,omitempty"` + Periods *SettlementObject `json:"periods,omitempty"` + Status SettlementStatus `json:"status,omitempty"` + Links SettlementLinks `json:"_links,omitempty"` } ``` -## type [SettlementCosts]() +## type [SettlementCosts]() SettlementCosts contains information about costs related to a settlement. ```go type SettlementCosts struct { + Count int `json:"count,omitempty"` Description string `json:"description,omitempty"` + InvoiceID string `json:"invoiceId,omitempty"` AmountNet *Amount `json:"amountNet,omitempty"` AmountVAT *Amount `json:"amountVat,omitempty"` AmountGross *Amount `json:"amountGross,omitempty"` - Count int `json:"count,omitempty"` Rate *Rate `json:"rate,omitempty"` Method PaymentMethod `json:"method,omitempty"` } ``` -## type [SettlementLinks]() +## type [SettlementLinks]() SettlementLinks is an object with several URL objects relevant to the settlement. @@ -5158,7 +5172,7 @@ type SettlementLinks struct { ``` -## type [SettlementObject]() +## type [SettlementObject]() SettlementObject nests as describes for settlement periods. @@ -5167,37 +5181,37 @@ type SettlementObject map[string]map[string]SettlementPeriod ``` -## type [SettlementPeriod]() +## type [SettlementPeriod]() SettlementPeriod describe the settlement by month in full detail. ```go type SettlementPeriod struct { - Revenue []*SettlementRevenue `json:"revenue,omitempty"` - Costs []*SettlementCosts `json:"costs,omitempty"` InvoiceID string `json:"invoiceId,omitempty"` InvoiceReference string `json:"invoiceReference,omitempty"` + Revenue []*SettlementRevenue `json:"revenue,omitempty"` + Costs []*SettlementCosts `json:"costs,omitempty"` } ``` -## type [SettlementRevenue]() +## type [SettlementRevenue]() SettlementRevenue objects contain the total revenue for each payment method during this period. ```go type SettlementRevenue struct { + Count int `json:"count,omitempty"` Description string `json:"description,omitempty"` AmountNet *Amount `json:"amountNet,omitempty"` AmountVAT *Amount `json:"amountVat,omitempty"` AmountGross *Amount `json:"amountGross,omitempty"` - Count int `json:"count,omitempty"` Method PaymentMethod `json:"method,omitempty"` } ``` -## type [SettlementStatus]() +## type [SettlementStatus]() SettlementStatus describes the status of the settlement. @@ -5217,7 +5231,7 @@ const ( ``` -## type [SettlementsList]() +## type [SettlementsList]() SettlementsList describes a list of settlements. @@ -5231,21 +5245,8 @@ type SettlementsList struct { } ``` - -## type [SettlementsListOptions]() - -SettlementsListOptions contains query parameters for settlement lists. - -```go -type SettlementsListOptions struct { - From string `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - Embed EmbedValue `url:"embed,omitempty"` -} -``` - -## type [SettlementsService]() +## type [SettlementsService]() SettlementsService operates over settlements resource. @@ -5254,10 +5255,10 @@ type SettlementsService service ``` -### func \(\*SettlementsService\) [Get]() +### func \(\*SettlementsService\) [Get]() ```go -func (ss *SettlementsService) Get(ctx context.Context, id string) (res *Response, s *Settlement, err error) +func (ss *SettlementsService) Get(ctx context.Context, settlement string) (res *Response, s *Settlement, err error) ``` Get returns a settlement by its id or the bank reference id @@ -5265,10 +5266,10 @@ Get returns a settlement by its id or the bank reference id See: https://docs.mollie.com/reference/v2/settlements-api/get-settlement -### func \(\*SettlementsService\) [GetCaptures]() +### func \(\*SettlementsService\) [GetCaptures]() ```go -func (ss *SettlementsService) GetCaptures(ctx context.Context, id string, slo *SettlementsListOptions) (res *Response, cl *CapturesList, err error) +func (ss *SettlementsService) GetCaptures(ctx context.Context, settlement string, slo *ListSettlementsOptions) (res *Response, cl *CapturesList, err error) ``` GetCaptures retrieves all captures included in a settlement. @@ -5276,32 +5277,21 @@ GetCaptures retrieves all captures included in a settlement. See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-captures -### func \(\*SettlementsService\) [GetChargebacks]() +### func \(\*SettlementsService\) [GetChargebacks]() ```go -func (ss *SettlementsService) GetChargebacks(ctx context.Context, id string, slo *SettlementsListOptions) (res *Response, cl *ChargebacksList, err error) +func (ss *SettlementsService) GetChargebacks(ctx context.Context, settlement string, slo *ChargebacksListOptions) (res *Response, cl *ChargebacksList, err error) ``` GetChargebacks retrieves all chargebacks included in a settlement. See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-chargebacks - -### func \(\*SettlementsService\) [GetPayments]() - -```go -func (ss *SettlementsService) GetPayments(ctx context.Context, id string, slo *SettlementsListOptions) (res *Response, pl *PaymentList, err error) -``` - -GetPayments retrieves all payments included in a settlement. - -See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-payments - -### func \(\*SettlementsService\) [GetRefunds]() +### func \(\*SettlementsService\) [GetRefunds]() ```go -func (ss *SettlementsService) GetRefunds(ctx context.Context, id string, slo *SettlementsListOptions) (res *Response, rl *RefundsList, err error) +func (ss *SettlementsService) GetRefunds(ctx context.Context, settlement string, slo *ListSettlementsOptions) (res *Response, rl *RefundsList, err error) ``` GetRefunds retrieves all refunds included in a settlement. @@ -5309,18 +5299,29 @@ GetRefunds retrieves all refunds included in a settlement. See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-refunds -### func \(\*SettlementsService\) [List]() +### func \(\*SettlementsService\) [List]() ```go -func (ss *SettlementsService) List(ctx context.Context, slo *SettlementsListOptions) (res *Response, sl *SettlementsList, err error) +func (ss *SettlementsService) List(ctx context.Context, slo *ListSettlementsOptions) (res *Response, sl *SettlementsList, err error) ``` List retrieves all settlements, ordered from new to old See: https://docs.mollie.com/reference/v2/settlements-api/list-settlements + +### func \(\*SettlementsService\) [ListPayments]() + +```go +func (ss *SettlementsService) ListPayments(ctx context.Context, settlement string, options *ListPaymentOptions) (res *Response, pl *PaymentList, err error) +``` + +ListPayments retrieves all payments included in a settlement. This API is an alias of the List payments. + +See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-payments + -### func \(\*SettlementsService\) [Next]() +### func \(\*SettlementsService\) [Next]() ```go func (ss *SettlementsService) Next(ctx context.Context) (res *Response, s *Settlement, err error) @@ -5331,7 +5332,7 @@ Next retrieves the details of the current settlement that has not yet been paid See: https://docs.mollie.com/reference/v2/settlements-api/get-next-settlement -### func \(\*SettlementsService\) [Open]() +### func \(\*SettlementsService\) [Open]() ```go func (ss *SettlementsService) Open(ctx context.Context) (res *Response, s *Settlement, err error) diff --git a/mollie/common_types.go b/mollie/common_types.go index 353df52f..77e9956b 100644 --- a/mollie/common_types.go +++ b/mollie/common_types.go @@ -348,8 +348,8 @@ const ( // Rate describes service rates, further divided into fixed and percentage costs. type Rate struct { - Fixed *Amount `json:"fixed,omitempty"` Variable string `json:"variable,omitempty"` + Fixed *Amount `json:"fixed,omitempty"` } // Image describes a generic image resource retrieved by Mollie. diff --git a/mollie/settlements.go b/mollie/settlements.go index d2efda62..07fe1847 100644 --- a/mollie/settlements.go +++ b/mollie/settlements.go @@ -7,9 +7,6 @@ import ( "time" ) -// SettlementsService operates over settlements resource. -type SettlementsService service - // SettlementStatus describes the status of the settlement. type SettlementStatus string @@ -23,31 +20,32 @@ const ( // SettlementRevenue objects contain the total revenue for each payment method during this period. type SettlementRevenue struct { + Count int `json:"count,omitempty"` Description string `json:"description,omitempty"` AmountNet *Amount `json:"amountNet,omitempty"` AmountVAT *Amount `json:"amountVat,omitempty"` AmountGross *Amount `json:"amountGross,omitempty"` - Count int `json:"count,omitempty"` Method PaymentMethod `json:"method,omitempty"` } // SettlementCosts contains information about costs related to a settlement. type SettlementCosts struct { + Count int `json:"count,omitempty"` Description string `json:"description,omitempty"` + InvoiceID string `json:"invoiceId,omitempty"` AmountNet *Amount `json:"amountNet,omitempty"` AmountVAT *Amount `json:"amountVat,omitempty"` AmountGross *Amount `json:"amountGross,omitempty"` - Count int `json:"count,omitempty"` Rate *Rate `json:"rate,omitempty"` Method PaymentMethod `json:"method,omitempty"` } // SettlementPeriod describe the settlement by month in full detail. type SettlementPeriod struct { - Revenue []*SettlementRevenue `json:"revenue,omitempty"` - Costs []*SettlementCosts `json:"costs,omitempty"` InvoiceID string `json:"invoiceId,omitempty"` InvoiceReference string `json:"invoiceReference,omitempty"` + Revenue []*SettlementRevenue `json:"revenue,omitempty"` + Costs []*SettlementCosts `json:"costs,omitempty"` } // SettlementObject nests as describes for settlement periods. @@ -67,23 +65,23 @@ type SettlementLinks struct { // Settlement contains successful payments, together with refunds, // captures and chargebacks into settlements. type Settlement struct { - ID string `json:"id,omitempty"` - Resource string `json:"resource,omitempty"` - Reference string `json:"reference,omitempty"` - CreatedAt *time.Time `json:"createdAt,omitempty"` - SettledAt *time.Time `json:"settledAt,omitempty"` - Status SettlementStatus `json:"status,omitempty"` - Amount *Amount `json:"amount,omitempty"` - Periods SettlementObject `json:"periods,omitempty"` - InvoiceID string `json:"invoiceId,omitempty"` - Links SettlementLinks `json:"_links,omitempty"` + ID string `json:"id,omitempty"` + Resource string `json:"resource,omitempty"` + Reference string `json:"reference,omitempty"` + InvoiceID string `json:"invoiceId,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + SettledAt *time.Time `json:"settledAt,omitempty"` + Amount *Amount `json:"amount,omitempty"` + Periods *SettlementObject `json:"periods,omitempty"` + Status SettlementStatus `json:"status,omitempty"` + Links SettlementLinks `json:"_links,omitempty"` } -// SettlementsListOptions contains query parameters for settlement lists. -type SettlementsListOptions struct { - From string `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - Embed EmbedValue `url:"embed,omitempty"` +// ListSettlementsOptions contains query parameters for settlement lists. +type ListSettlementsOptions struct { + From string `url:"from,omitempty"` + Limit int `url:"limit,omitempty"` + Embed []EmbedValue `url:"embed,omitempty"` } // SettlementsList describes a list of settlements. @@ -95,11 +93,14 @@ type SettlementsList struct { Links PaginationLinks `json:"_links,omitempty"` } +// SettlementsService operates over settlements resource. +type SettlementsService service + // Get returns a settlement by its id or the bank reference id // // See: https://docs.mollie.com/reference/v2/settlements-api/get-settlement -func (ss *SettlementsService) Get(ctx context.Context, id string) (res *Response, s *Settlement, err error) { - return ss.get(ctx, id) +func (ss *SettlementsService) Get(ctx context.Context, settlement string) (res *Response, s *Settlement, err error) { + return ss.get(ctx, settlement) } // Next retrieves the details of the current settlement that has not yet been paid out. @@ -120,7 +121,7 @@ func (ss *SettlementsService) Open(ctx context.Context) (res *Response, s *Settl // List retrieves all settlements, ordered from new to old // // See: https://docs.mollie.com/reference/v2/settlements-api/list-settlements -func (ss *SettlementsService) List(ctx context.Context, slo *SettlementsListOptions) ( +func (ss *SettlementsService) List(ctx context.Context, slo *ListSettlementsOptions) ( res *Response, sl *SettlementsList, err error, @@ -137,15 +138,16 @@ func (ss *SettlementsService) List(ctx context.Context, slo *SettlementsListOpti return } -// GetPayments retrieves all payments included in a settlement. +// ListPayments retrieves all payments included in a settlement. +// This API is an alias of the List payments. // // See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-payments -func (ss *SettlementsService) GetPayments(ctx context.Context, id string, slo *SettlementsListOptions) ( +func (ss *SettlementsService) ListPayments(ctx context.Context, settlement string, options *ListPaymentOptions) ( res *Response, pl *PaymentList, err error, ) { - res, err = ss.list(ctx, id, "payments", slo) + res, err = ss.list(ctx, settlement, "payments", options) if err != nil { return } @@ -160,12 +162,12 @@ func (ss *SettlementsService) GetPayments(ctx context.Context, id string, slo *S // GetRefunds retrieves all refunds included in a settlement. // // See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-refunds -func (ss *SettlementsService) GetRefunds(ctx context.Context, id string, slo *SettlementsListOptions) ( +func (ss *SettlementsService) GetRefunds(ctx context.Context, settlement string, slo *ListSettlementsOptions) ( res *Response, rl *RefundsList, err error, ) { - res, err = ss.list(ctx, id, "refunds", slo) + res, err = ss.list(ctx, settlement, "refunds", slo) if err != nil { return } @@ -180,12 +182,12 @@ func (ss *SettlementsService) GetRefunds(ctx context.Context, id string, slo *Se // GetChargebacks retrieves all chargebacks included in a settlement. // // See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-chargebacks -func (ss *SettlementsService) GetChargebacks(ctx context.Context, id string, slo *SettlementsListOptions) ( +func (ss *SettlementsService) GetChargebacks(ctx context.Context, settlement string, slo *ChargebacksListOptions) ( res *Response, cl *ChargebacksList, err error, ) { - res, err = ss.list(ctx, id, "chargebacks", slo) + res, err = ss.list(ctx, settlement, "chargebacks", slo) if err != nil { return } @@ -200,12 +202,12 @@ func (ss *SettlementsService) GetChargebacks(ctx context.Context, id string, slo // GetCaptures retrieves all captures included in a settlement. // // See: https://docs.mollie.com/reference/v2/settlements-api/list-settlement-captures -func (ss *SettlementsService) GetCaptures(ctx context.Context, id string, slo *SettlementsListOptions) ( +func (ss *SettlementsService) GetCaptures(ctx context.Context, settlement string, slo *ListSettlementsOptions) ( res *Response, cl *CapturesList, err error, ) { - res, err = ss.list(ctx, id, "captures", slo) + res, err = ss.list(ctx, settlement, "captures", slo) if err != nil { return } @@ -230,14 +232,14 @@ func (ss *SettlementsService) get(ctx context.Context, element string) (res *Res return } -func (ss *SettlementsService) list(ctx context.Context, id string, category string, opts *SettlementsListOptions) ( +func (ss *SettlementsService) list(ctx context.Context, settlement string, category string, opts any) ( res *Response, err error, ) { uri := "v2/settlements" - if id != "" { - uri = fmt.Sprintf("%s/%s", uri, id) + if settlement != "" { + uri = fmt.Sprintf("%s/%s", uri, settlement) if category != "" { uri = fmt.Sprintf("%s/%s", uri, category) diff --git a/mollie/settlements_test.go b/mollie/settlements_test.go index 21dbb43f..5f4fada4 100644 --- a/mollie/settlements_test.go +++ b/mollie/settlements_test.go @@ -289,7 +289,7 @@ func TestSettlementsService_List(t *testing.T) { type args struct { ctx context.Context - options *SettlementsListOptions + options *ListSettlementsOptions } cases := []struct { name string @@ -303,7 +303,7 @@ func TestSettlementsService_List(t *testing.T) { "list shipment works as expected.", args{ context.Background(), - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 40, }, }, @@ -325,7 +325,7 @@ func TestSettlementsService_List(t *testing.T) { "list shipment, an error is returned from the server", args{ context.Background(), - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 40, }, }, @@ -338,7 +338,7 @@ func TestSettlementsService_List(t *testing.T) { "list shipment, an error occurs when parsing json", args{ context.Background(), - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 40, }, }, @@ -351,7 +351,7 @@ func TestSettlementsService_List(t *testing.T) { "list shipment, invalid url when building request", args{ context.Background(), - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 40, }, }, @@ -390,7 +390,7 @@ func TestSettlementsService_GetPayments(t *testing.T) { type args struct { ctx context.Context settlement string - options *SettlementsListOptions + options *ListPaymentOptions } cases := []struct { name string @@ -405,7 +405,7 @@ func TestSettlementsService_GetPayments(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListPaymentOptions{ Limit: 10, }, }, @@ -428,7 +428,7 @@ func TestSettlementsService_GetPayments(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListPaymentOptions{ Limit: 10, }, }, @@ -442,7 +442,7 @@ func TestSettlementsService_GetPayments(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListPaymentOptions{ Limit: 10, }, }, @@ -456,7 +456,7 @@ func TestSettlementsService_GetPayments(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListPaymentOptions{ Limit: 10, }, }, @@ -475,7 +475,7 @@ func TestSettlementsService_GetPayments(t *testing.T) { c.pre() tMux.HandleFunc(fmt.Sprintf("/v2/settlements/%s/payments", c.args.settlement), c.handler) - res, m, err := tClient.Settlements.GetPayments(c.args.ctx, c.args.settlement, c.args.options) + res, m, err := tClient.Settlements.ListPayments(c.args.ctx, c.args.settlement, c.args.options) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) @@ -495,7 +495,7 @@ func TestSettlementsService_GetCaptures(t *testing.T) { type args struct { ctx context.Context settlement string - options *SettlementsListOptions + options *ListSettlementsOptions } cases := []struct { name string @@ -510,7 +510,7 @@ func TestSettlementsService_GetCaptures(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 10, }, }, @@ -533,7 +533,7 @@ func TestSettlementsService_GetCaptures(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 10, }, }, @@ -547,7 +547,7 @@ func TestSettlementsService_GetCaptures(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 10, }, }, @@ -561,7 +561,7 @@ func TestSettlementsService_GetCaptures(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 10, }, }, @@ -600,7 +600,7 @@ func TestSettlementsService_GetChargebacks(t *testing.T) { type args struct { ctx context.Context settlement string - options *SettlementsListOptions + options *ChargebacksListOptions } cases := []struct { name string @@ -615,7 +615,7 @@ func TestSettlementsService_GetChargebacks(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ChargebacksListOptions{ Limit: 10, }, }, @@ -638,7 +638,7 @@ func TestSettlementsService_GetChargebacks(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ChargebacksListOptions{ Limit: 10, }, }, @@ -652,7 +652,7 @@ func TestSettlementsService_GetChargebacks(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ChargebacksListOptions{ Limit: 10, }, }, @@ -666,7 +666,7 @@ func TestSettlementsService_GetChargebacks(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ChargebacksListOptions{ Limit: 10, }, }, @@ -705,7 +705,7 @@ func TestSettlementsService_GetRefunds(t *testing.T) { type args struct { ctx context.Context settlement string - options *SettlementsListOptions + options *ListSettlementsOptions } cases := []struct { name string @@ -720,7 +720,7 @@ func TestSettlementsService_GetRefunds(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 10, }, }, @@ -743,7 +743,7 @@ func TestSettlementsService_GetRefunds(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 10, }, }, @@ -757,7 +757,7 @@ func TestSettlementsService_GetRefunds(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 10, }, }, @@ -771,7 +771,7 @@ func TestSettlementsService_GetRefunds(t *testing.T) { args{ context.Background(), "stl_jDk30akdN", - &SettlementsListOptions{ + &ListSettlementsOptions{ Limit: 10, }, }, From ea1f38c8420573d5894985555438d5497dd91397 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Sat, 16 Mar 2024 00:01:41 +0100 Subject: [PATCH 20/23] check subscriptions resource against api reference (#351) --- docs/README.md | 215 ++++++++++++++++++++++------------- mollie/subscriptions.go | 120 ++++++++++++------- mollie/subscriptions_test.go | 46 ++++---- 3 files changed, 241 insertions(+), 140 deletions(-) diff --git a/docs/README.md b/docs/README.md index fcc685de..3f2f07d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -121,6 +121,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CreatePreAuthorizedPaymentFields](<#CreatePreAuthorizedPaymentFields>) - [type CreateRecurrentPaymentFields](<#CreateRecurrentPaymentFields>) - [type CreateShipmentRequest](<#CreateShipmentRequest>) +- [type CreateSubscription](<#CreateSubscription>) - [type Customer](<#Customer>) - [type CustomerLinks](<#CustomerLinks>) - [type CustomersList](<#CustomersList>) @@ -162,6 +163,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type ListLinkedClientsOptions](<#ListLinkedClientsOptions>) - [type ListPaymentOptions](<#ListPaymentOptions>) - [type ListSettlementsOptions](<#ListSettlementsOptions>) +- [type ListSubscriptionsOptions](<#ListSubscriptionsOptions>) - [type Locale](<#Locale>) - [type Mandate](<#Mandate>) - [type MandateDetails](<#MandateDetails>) @@ -350,18 +352,18 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(d \*ShortDate\) MarshalJSON\(\) \(\[\]byte, error\)](<#ShortDate.MarshalJSON>) - [func \(d \*ShortDate\) UnmarshalJSON\(b \[\]byte\) error](<#ShortDate.UnmarshalJSON>) - [type Subscription](<#Subscription>) +- [type SubscriptionAccessTokenFields](<#SubscriptionAccessTokenFields>) - [type SubscriptionLinks](<#SubscriptionLinks>) -- [type SubscriptionList](<#SubscriptionList>) -- [type SubscriptionListOptions](<#SubscriptionListOptions>) - [type SubscriptionStatus](<#SubscriptionStatus>) +- [type SubscriptionsList](<#SubscriptionsList>) - [type SubscriptionsService](<#SubscriptionsService>) - - [func \(ss \*SubscriptionsService\) All\(ctx context.Context, opts \*SubscriptionListOptions\) \(res \*Response, sl \*SubscriptionList, err error\)](<#SubscriptionsService.All>) - - [func \(ss \*SubscriptionsService\) Create\(ctx context.Context, cID string, sc \*Subscription\) \(res \*Response, s \*Subscription, err error\)](<#SubscriptionsService.Create>) - - [func \(ss \*SubscriptionsService\) Delete\(ctx context.Context, cID, sID string\) \(res \*Response, s \*Subscription, err error\)](<#SubscriptionsService.Delete>) - - [func \(ss \*SubscriptionsService\) Get\(ctx context.Context, cID, sID string\) \(res \*Response, s \*Subscription, err error\)](<#SubscriptionsService.Get>) - - [func \(ss \*SubscriptionsService\) GetPayments\(ctx context.Context, cID, sID string, opts \*SubscriptionListOptions\) \(res \*Response, sl \*PaymentList, err error\)](<#SubscriptionsService.GetPayments>) - - [func \(ss \*SubscriptionsService\) List\(ctx context.Context, cID string, opts \*SubscriptionListOptions\) \(res \*Response, sl \*SubscriptionList, err error\)](<#SubscriptionsService.List>) - - [func \(ss \*SubscriptionsService\) Update\(ctx context.Context, cID, sID string, sc \*Subscription\) \(res \*Response, s \*Subscription, err error\)](<#SubscriptionsService.Update>) + - [func \(ss \*SubscriptionsService\) All\(ctx context.Context, opts \*ListSubscriptionsOptions\) \(res \*Response, sl \*SubscriptionsList, err error\)](<#SubscriptionsService.All>) + - [func \(ss \*SubscriptionsService\) Cancel\(ctx context.Context, customer, subscription string\) \(res \*Response, s \*Subscription, err error\)](<#SubscriptionsService.Cancel>) + - [func \(ss \*SubscriptionsService\) Create\(ctx context.Context, customer string, sc CreateSubscription\) \(res \*Response, s \*Subscription, err error\)](<#SubscriptionsService.Create>) + - [func \(ss \*SubscriptionsService\) Get\(ctx context.Context, customer, subscription string\) \(res \*Response, s \*Subscription, err error\)](<#SubscriptionsService.Get>) + - [func \(ss \*SubscriptionsService\) List\(ctx context.Context, customer string, opts \*ListSubscriptionsOptions\) \(res \*Response, sl \*SubscriptionsList, err error\)](<#SubscriptionsService.List>) + - [func \(ss \*SubscriptionsService\) ListPayments\(ctx context.Context, customer, subscription string, opts \*ListSubscriptionsOptions\) \(res \*Response, sl \*PaymentList, err error\)](<#SubscriptionsService.ListPayments>) + - [func \(ss \*SubscriptionsService\) Update\(ctx context.Context, customer, subscription string, sc UpdateSubscription\) \(res \*Response, s \*Subscription, err error\)](<#SubscriptionsService.Update>) - [type Subtotal](<#Subtotal>) - [type Terminal](<#Terminal>) - [type TerminalList](<#TerminalList>) @@ -378,6 +380,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type UpdateOrder](<#UpdateOrder>) - [type UpdateOrderLine](<#UpdateOrderLine>) - [type UpdatePayment](<#UpdatePayment>) +- [type UpdateSubscription](<#UpdateSubscription>) - [type UsedGiftCard](<#UsedGiftCard>) - [type UserAgentToken](<#UserAgentToken>) - [type VoucherContractor](<#VoucherContractor>) @@ -2109,6 +2112,26 @@ type CreateShipmentRequest struct { } ``` + +## type [CreateSubscription]() + +CreateSubscription contains the fields that are required to create a subscription. + +```go +type CreateSubscription struct { + Times int `json:"times,omitempty"` + Interval string `json:"interval,omitempty"` + Description string `json:"description,omitempty"` + MandateID string `json:"mandateId,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + Amount *Amount `json:"amount,omitempty"` + StartDate *ShortDate `json:"startDate,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` + SubscriptionAccessTokenFields +} +``` + ## type [Customer]() @@ -2762,6 +2785,20 @@ type ListSettlementsOptions struct { } ``` + +## type [ListSubscriptionsOptions]() + +ListSubscriptionsOptions holds query string parameters valid for subscription lists. + +```go +type ListSubscriptionsOptions struct { + Testmode bool `url:"testmode,omitempty"` + Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` + ProfileID string `url:"profileId,omitempty"` +} +``` + ## type [Locale]() @@ -5484,37 +5521,49 @@ func (d *ShortDate) UnmarshalJSON(b []byte) error UnmarshalJSON overrides the default unmarshal action for the Date struct, as we need links to be pointers to the time.Time struct. -## type [Subscription]() +## type [Subscription]() Subscription contains information about a customer subscription. ```go type Subscription struct { + Times int `json:"times,omitempty"` + TimesRemaining int `json:"timesRemaining,omitempty"` Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` + Interval string `json:"interval,omitempty"` + Description string `json:"description,omitempty"` MandateID string `json:"mandateId,omitempty"` - Mode Mode `json:"mode,omitempty"` - CreatedAT *time.Time `json:"createdAt,omitempty"` - Status SubscriptionStatus `json:"status,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` Amount *Amount `json:"amount,omitempty"` - Times int `json:"times,omitempty"` - TimesRemaining int `json:"timesRemaining,omitempty"` - Interval string `json:"interval,omitempty"` + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` StartDate *ShortDate `json:"startDate,omitempty"` NextPaymentDate *ShortDate `json:"nextPaymentDate,omitempty"` - Description string `json:"description,omitempty"` - Method PaymentMethod `json:"method,omitempty"` + CreatedAT *time.Time `json:"createdAt,omitempty"` CanceledAt *time.Time `json:"canceledAt,omitempty"` - WebhookURL string `json:"webhookUrl,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` - TestMode bool `json:"testmode,omitempty"` + Mode Mode `json:"mode,omitempty"` + Status SubscriptionStatus `json:"status,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` Links SubscriptionLinks `json:"_links,omitempty"` } ``` + +## type [SubscriptionAccessTokenFields]() + +SubscriptionAccessTokenFields contains the fields that are available when using an access token. + +```go +type SubscriptionAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` + ProfileID string `json:"profileId,omitempty"` + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` +} +``` + -## type [SubscriptionLinks]() +## type [SubscriptionLinks]() SubscriptionLinks contains several URL objects relevant to the subscription. @@ -5522,41 +5571,14 @@ SubscriptionLinks contains several URL objects relevant to the subscription. type SubscriptionLinks struct { Self *URL `json:"self,omitempty"` Customer *URL `json:"customer,omitempty"` + Profile *URL `json:"profile,omitempty"` Payments *URL `json:"payments,omitempty"` Documentation *URL `json:"documentation,omitempty"` } ``` - -## type [SubscriptionList]() - -SubscriptionList describes the response for subscription list endpoints. - -```go -type SubscriptionList struct { - Count int `json:"count,omitempty"` - Embedded struct { - Subscriptions []*Subscription - } `json:"_embedded,omitempty"` - Links PaginationLinks `json:"_links,omitempty"` -} -``` - - -## type [SubscriptionListOptions]() - -SubscriptionListOptions holds query string parameters valid for subscription lists. - -```go -type SubscriptionListOptions struct { - From string `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - ProfileID string `url:"profileId,omitempty"` -} -``` - -## type [SubscriptionStatus]() +## type [SubscriptionStatus]() SubscriptionStatus contains references to valid subscription statuses. @@ -5576,8 +5598,23 @@ const ( ) ``` + +## type [SubscriptionsList]() + +SubscriptionsList describes the response for subscription list endpoints. + +```go +type SubscriptionsList struct { + Count int `json:"count,omitempty"` + Embedded struct { + Subscriptions []*Subscription + } `json:"_embedded,omitempty"` + Links PaginationLinks `json:"_links,omitempty"` +} +``` + -## type [SubscriptionsService]() +## type [SubscriptionsService]() SubscriptionsService operates over subscriptions resource. @@ -5586,76 +5623,76 @@ type SubscriptionsService service ``` -### func \(\*SubscriptionsService\) [All]() +### func \(\*SubscriptionsService\) [All]() ```go -func (ss *SubscriptionsService) All(ctx context.Context, opts *SubscriptionListOptions) (res *Response, sl *SubscriptionList, err error) +func (ss *SubscriptionsService) All(ctx context.Context, opts *ListSubscriptionsOptions) (res *Response, sl *SubscriptionsList, err error) ``` All retrieves all subscriptions, ordered from newest to oldest. By using an API key all the subscriptions created with the current website profile will be returned. In the case of an OAuth Access Token relies the website profile on the profileId field See: https://docs.mollie.com/reference/v2/subscriptions-api/list-all-subscriptions - -### func \(\*SubscriptionsService\) [Create]() + +### func \(\*SubscriptionsService\) [Cancel]() ```go -func (ss *SubscriptionsService) Create(ctx context.Context, cID string, sc *Subscription) (res *Response, s *Subscription, err error) +func (ss *SubscriptionsService) Cancel(ctx context.Context, customer, subscription string) (res *Response, s *Subscription, err error) ``` -Create stores a new subscription for a given customer +Cancel cancels a subscription. -See: https://docs.mollie.com/reference/v2/subscriptions-api/create-subscription +See: https://docs.mollie.com/reference/v2/subscriptions-api/cancel-subscription - -### func \(\*SubscriptionsService\) [Delete]() + +### func \(\*SubscriptionsService\) [Create]() ```go -func (ss *SubscriptionsService) Delete(ctx context.Context, cID, sID string) (res *Response, s *Subscription, err error) +func (ss *SubscriptionsService) Create(ctx context.Context, customer string, sc CreateSubscription) (res *Response, s *Subscription, err error) ``` -Delete cancels a subscription +Create stores a new subscription for a given customer -See: https://docs.mollie.com/reference/v2/subscriptions-api/cancel-subscription +See: https://docs.mollie.com/reference/v2/subscriptions-api/create-subscription -### func \(\*SubscriptionsService\) [Get]() +### func \(\*SubscriptionsService\) [Get]() ```go -func (ss *SubscriptionsService) Get(ctx context.Context, cID, sID string) (res *Response, s *Subscription, err error) +func (ss *SubscriptionsService) Get(ctx context.Context, customer, subscription string) (res *Response, s *Subscription, err error) ``` Get retrieves a customer's subscription See: https://docs.mollie.com/reference/v2/subscriptions-api/get-subscription - -### func \(\*SubscriptionsService\) [GetPayments]() + +### func \(\*SubscriptionsService\) [List]() ```go -func (ss *SubscriptionsService) GetPayments(ctx context.Context, cID, sID string, opts *SubscriptionListOptions) (res *Response, sl *PaymentList, err error) +func (ss *SubscriptionsService) List(ctx context.Context, customer string, opts *ListSubscriptionsOptions) (res *Response, sl *SubscriptionsList, err error) ``` -GetPayments retrieves all payments of a specific subscriptions of a customer +List retrieves all subscriptions of a customer -See: https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions-payments +See: https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions - -### func \(\*SubscriptionsService\) [List]() + +### func \(\*SubscriptionsService\) [ListPayments]() ```go -func (ss *SubscriptionsService) List(ctx context.Context, cID string, opts *SubscriptionListOptions) (res *Response, sl *SubscriptionList, err error) +func (ss *SubscriptionsService) ListPayments(ctx context.Context, customer, subscription string, opts *ListSubscriptionsOptions) (res *Response, sl *PaymentList, err error) ``` -List retrieves all subscriptions of a customer +ListPayments retrieves all payments of a specific subscriptions of a customer -See: https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions +See: https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions-payments -### func \(\*SubscriptionsService\) [Update]() +### func \(\*SubscriptionsService\) [Update]() ```go -func (ss *SubscriptionsService) Update(ctx context.Context, cID, sID string, sc *Subscription) (res *Response, s *Subscription, err error) +func (ss *SubscriptionsService) Update(ctx context.Context, customer, subscription string, sc UpdateSubscription) (res *Response, s *Subscription, err error) ``` Update changes fields on a subscription object @@ -5937,6 +5974,26 @@ type UpdatePayment struct { } ``` + +## type [UpdateSubscription]() + +UpdateSubscription contains the fields that are required to create a subscription. + +```go +type UpdateSubscription struct { + Times int `json:"times,omitempty"` + Interval string `json:"interval,omitempty"` + Description string `json:"description,omitempty"` + MandateID string `json:"mandateId,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + Amount *Amount `json:"amount,omitempty"` + StartDate *ShortDate `json:"startDate,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` + SubscriptionAccessTokenFields +} +``` + ## type [UsedGiftCard]() diff --git a/mollie/subscriptions.go b/mollie/subscriptions.go index bf7e0c8b..afe92028 100644 --- a/mollie/subscriptions.go +++ b/mollie/subscriptions.go @@ -7,9 +7,6 @@ import ( "time" ) -// SubscriptionsService operates over subscriptions resource. -type SubscriptionsService service - // SubscriptionStatus contains references to valid subscription statuses. type SubscriptionStatus string @@ -22,40 +19,75 @@ const ( SubscriptionStatusCompleted SubscriptionStatus = "completed" ) +// CreateSubscription contains the fields that are required to create a subscription. +type CreateSubscription struct { + Times int `json:"times,omitempty"` + Interval string `json:"interval,omitempty"` + Description string `json:"description,omitempty"` + MandateID string `json:"mandateId,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + Amount *Amount `json:"amount,omitempty"` + StartDate *ShortDate `json:"startDate,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` + SubscriptionAccessTokenFields +} + +// SubscriptionAccessTokenFields contains the fields that are available when using an access token. +type SubscriptionAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` + ProfileID string `json:"profileId,omitempty"` + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` +} + +// UpdateSubscription contains the fields that are required to create a subscription. +type UpdateSubscription struct { + Times int `json:"times,omitempty"` + Interval string `json:"interval,omitempty"` + Description string `json:"description,omitempty"` + MandateID string `json:"mandateId,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + Amount *Amount `json:"amount,omitempty"` + StartDate *ShortDate `json:"startDate,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` + SubscriptionAccessTokenFields +} + // SubscriptionLinks contains several URL objects relevant to the subscription. type SubscriptionLinks struct { Self *URL `json:"self,omitempty"` Customer *URL `json:"customer,omitempty"` + Profile *URL `json:"profile,omitempty"` Payments *URL `json:"payments,omitempty"` Documentation *URL `json:"documentation,omitempty"` } // Subscription contains information about a customer subscription. type Subscription struct { + Times int `json:"times,omitempty"` + TimesRemaining int `json:"timesRemaining,omitempty"` Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` + Interval string `json:"interval,omitempty"` + Description string `json:"description,omitempty"` MandateID string `json:"mandateId,omitempty"` - Mode Mode `json:"mode,omitempty"` - CreatedAT *time.Time `json:"createdAt,omitempty"` - Status SubscriptionStatus `json:"status,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` Amount *Amount `json:"amount,omitempty"` - Times int `json:"times,omitempty"` - TimesRemaining int `json:"timesRemaining,omitempty"` - Interval string `json:"interval,omitempty"` + ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` StartDate *ShortDate `json:"startDate,omitempty"` NextPaymentDate *ShortDate `json:"nextPaymentDate,omitempty"` - Description string `json:"description,omitempty"` - Method PaymentMethod `json:"method,omitempty"` + CreatedAT *time.Time `json:"createdAt,omitempty"` CanceledAt *time.Time `json:"canceledAt,omitempty"` - WebhookURL string `json:"webhookUrl,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - ApplicationFee *ApplicationFee `json:"applicationFee,omitempty"` - TestMode bool `json:"testmode,omitempty"` + Mode Mode `json:"mode,omitempty"` + Status SubscriptionStatus `json:"status,omitempty"` + Method PaymentMethod `json:"method,omitempty"` + Metadata any `json:"metadata,omitempty"` Links SubscriptionLinks `json:"_links,omitempty"` } -// SubscriptionList describes the response for subscription list endpoints. -type SubscriptionList struct { +// SubscriptionsList describes the response for subscription list endpoints. +type SubscriptionsList struct { Count int `json:"count,omitempty"` Embedded struct { Subscriptions []*Subscription @@ -63,18 +95,26 @@ type SubscriptionList struct { Links PaginationLinks `json:"_links,omitempty"` } -// SubscriptionListOptions holds query string parameters valid for subscription lists. -type SubscriptionListOptions struct { - From string `url:"from,omitempty"` +// ListSubscriptionsOptions holds query string parameters valid for subscription lists. +type ListSubscriptionsOptions struct { + Testmode bool `url:"testmode,omitempty"` Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` ProfileID string `url:"profileId,omitempty"` } +// SubscriptionsService operates over subscriptions resource. +type SubscriptionsService service + // Get retrieves a customer's subscription // // See: https://docs.mollie.com/reference/v2/subscriptions-api/get-subscription -func (ss *SubscriptionsService) Get(ctx context.Context, cID, sID string) (res *Response, s *Subscription, err error) { - u := fmt.Sprintf("v2/customers/%s/subscriptions/%s", cID, sID) +func (ss *SubscriptionsService) Get(ctx context.Context, customer, subscription string) ( + res *Response, + s *Subscription, + err error, +) { + u := fmt.Sprintf("v2/customers/%s/subscriptions/%s", customer, subscription) res, err = ss.client.get(ctx, u, nil) if err != nil { @@ -91,15 +131,15 @@ func (ss *SubscriptionsService) Get(ctx context.Context, cID, sID string) (res * // Create stores a new subscription for a given customer // // See: https://docs.mollie.com/reference/v2/subscriptions-api/create-subscription -func (ss *SubscriptionsService) Create(ctx context.Context, cID string, sc *Subscription) ( +func (ss *SubscriptionsService) Create(ctx context.Context, customer string, sc CreateSubscription) ( res *Response, s *Subscription, err error, ) { - uri := fmt.Sprintf("v2/customers/%s/subscriptions", cID) + uri := fmt.Sprintf("v2/customers/%s/subscriptions", customer) if ss.client.HasAccessToken() && ss.client.config.testing { - sc.TestMode = true + sc.Testmode = true } res, err = ss.client.post(ctx, uri, sc, nil) @@ -117,12 +157,12 @@ func (ss *SubscriptionsService) Create(ctx context.Context, cID string, sc *Subs // Update changes fields on a subscription object // // See: https://docs.mollie.com/reference/v2/subscriptions-api/update-subscription -func (ss *SubscriptionsService) Update(ctx context.Context, cID, sID string, sc *Subscription) ( +func (ss *SubscriptionsService) Update(ctx context.Context, customer, subscription string, sc UpdateSubscription) ( res *Response, s *Subscription, err error, ) { - u := fmt.Sprintf("v2/customers/%s/subscriptions/%s", cID, sID) + u := fmt.Sprintf("v2/customers/%s/subscriptions/%s", customer, subscription) res, err = ss.client.patch(ctx, u, sc, nil) if err != nil { @@ -136,15 +176,15 @@ func (ss *SubscriptionsService) Update(ctx context.Context, cID, sID string, sc return } -// Delete cancels a subscription +// Cancel cancels a subscription. // // See: https://docs.mollie.com/reference/v2/subscriptions-api/cancel-subscription -func (ss *SubscriptionsService) Delete(ctx context.Context, cID, sID string) ( +func (ss *SubscriptionsService) Cancel(ctx context.Context, customer, subscription string) ( res *Response, s *Subscription, err error, ) { - u := fmt.Sprintf("v2/customers/%s/subscriptions/%s", cID, sID) + u := fmt.Sprintf("v2/customers/%s/subscriptions/%s", customer, subscription) res, err = ss.client.delete(ctx, u, nil) if err != nil { @@ -163,9 +203,9 @@ func (ss *SubscriptionsService) Delete(ctx context.Context, cID, sID string) ( // In the case of an OAuth Access Token relies the website profile on the profileId field // // See: https://docs.mollie.com/reference/v2/subscriptions-api/list-all-subscriptions -func (ss *SubscriptionsService) All(ctx context.Context, opts *SubscriptionListOptions) ( +func (ss *SubscriptionsService) All(ctx context.Context, opts *ListSubscriptionsOptions) ( res *Response, - sl *SubscriptionList, + sl *SubscriptionsList, err error, ) { u := "v2/subscriptions" @@ -185,12 +225,12 @@ func (ss *SubscriptionsService) All(ctx context.Context, opts *SubscriptionListO // List retrieves all subscriptions of a customer // // See: https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions -func (ss *SubscriptionsService) List(ctx context.Context, cID string, opts *SubscriptionListOptions) ( +func (ss *SubscriptionsService) List(ctx context.Context, customer string, opts *ListSubscriptionsOptions) ( res *Response, - sl *SubscriptionList, + sl *SubscriptionsList, err error, ) { - u := fmt.Sprintf("v2/customers/%s/subscriptions", cID) + u := fmt.Sprintf("v2/customers/%s/subscriptions", customer) res, err = ss.list(ctx, u, opts) if err != nil { @@ -204,15 +244,19 @@ func (ss *SubscriptionsService) List(ctx context.Context, cID string, opts *Subs return } -// GetPayments retrieves all payments of a specific subscriptions of a customer +// ListPayments retrieves all payments of a specific subscriptions of a customer // // See: https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions-payments -func (ss *SubscriptionsService) GetPayments(ctx context.Context, cID, sID string, opts *SubscriptionListOptions) ( +func (ss *SubscriptionsService) ListPayments( + ctx context.Context, + customer, subscription string, + opts *ListSubscriptionsOptions, +) ( res *Response, sl *PaymentList, err error, ) { - u := fmt.Sprintf("v2/customers/%s/subscriptions/%s/payments", cID, sID) + u := fmt.Sprintf("v2/customers/%s/subscriptions/%s/payments", customer, subscription) res, err = ss.list(ctx, u, opts) if err != nil { diff --git a/mollie/subscriptions_test.go b/mollie/subscriptions_test.go index a44bfd66..9c5491ce 100644 --- a/mollie/subscriptions_test.go +++ b/mollie/subscriptions_test.go @@ -113,7 +113,7 @@ func TestSubscriptionsService_Create(t *testing.T) { type args struct { ctx context.Context customer string - subscription *Subscription + subscription CreateSubscription } cases := []struct { name string @@ -128,7 +128,7 @@ func TestSubscriptionsService_Create(t *testing.T) { args{ context.Background(), "cst_stTC2WHAuS", - &Subscription{ + CreateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -154,7 +154,7 @@ func TestSubscriptionsService_Create(t *testing.T) { args{ context.Background(), "cst_stTC2WHAuS", - &Subscription{ + CreateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -181,7 +181,7 @@ func TestSubscriptionsService_Create(t *testing.T) { args{ context.Background(), "cst_stTC2WHAuS", - &Subscription{ + CreateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -199,7 +199,7 @@ func TestSubscriptionsService_Create(t *testing.T) { args{ context.Background(), "cst_stTC2WHAuS", - &Subscription{ + CreateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -217,7 +217,7 @@ func TestSubscriptionsService_Create(t *testing.T) { args{ context.Background(), "cst_stTC2WHAuS", - &Subscription{ + CreateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -261,7 +261,7 @@ func TestSubscriptionsService_Update(t *testing.T) { ctx context.Context customer string sid string - subscription *Subscription + subscription UpdateSubscription } cases := []struct { name string @@ -277,7 +277,7 @@ func TestSubscriptionsService_Update(t *testing.T) { context.Background(), "cst_stTC2WHAuS", "sub_rVKGtNd6s3", - &Subscription{ + UpdateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -304,7 +304,7 @@ func TestSubscriptionsService_Update(t *testing.T) { context.Background(), "cst_stTC2WHAuS", "sub_rVKGtNd6s3", - &Subscription{ + UpdateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -332,7 +332,7 @@ func TestSubscriptionsService_Update(t *testing.T) { context.Background(), "cst_stTC2WHAuS", "sub_rVKGtNd6s3", - &Subscription{ + UpdateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -351,7 +351,7 @@ func TestSubscriptionsService_Update(t *testing.T) { context.Background(), "cst_stTC2WHAuS", "sub_rVKGtNd6s3", - &Subscription{ + UpdateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -370,7 +370,7 @@ func TestSubscriptionsService_Update(t *testing.T) { context.Background(), "cst_stTC2WHAuS", "sub_rVKGtNd6s3", - &Subscription{ + UpdateSubscription{ Amount: &Amount{ Currency: "EUR", Value: "100.00", @@ -406,7 +406,7 @@ func TestSubscriptionsService_Update(t *testing.T) { } } -func TestSubscriptionsService_Delete(t *testing.T) { +func TestSubscriptionsService_Cancel(t *testing.T) { setEnv() defer unsetEnv() @@ -510,7 +510,7 @@ func TestSubscriptionsService_Delete(t *testing.T) { c.pre() tMux.HandleFunc(fmt.Sprintf("/v2/customers/%s/subscriptions/%s", c.args.customer, c.args.sid), c.handler) - res, m, err := tClient.Subscriptions.Delete(c.args.ctx, c.args.customer, c.args.sid) + res, m, err := tClient.Subscriptions.Cancel(c.args.ctx, c.args.customer, c.args.sid) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) @@ -530,7 +530,7 @@ func TestSubscriptionsService_List(t *testing.T) { type args struct { ctx context.Context customer string - options *SubscriptionListOptions + options *ListSubscriptionsOptions } cases := []struct { name string @@ -565,7 +565,7 @@ func TestSubscriptionsService_List(t *testing.T) { args{ context.Background(), "cst_stTC2WHAuS", - &SubscriptionListOptions{ + &ListSubscriptionsOptions{ Limit: 10, }, }, @@ -635,7 +635,7 @@ func TestSubscriptionsService_List(t *testing.T) { assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &SubscriptionList{}, m) + assert.IsType(t, &SubscriptionsList{}, m) assert.IsType(t, &http.Response{}, res.Response) } }) @@ -648,7 +648,7 @@ func TestSubscriptionsService_All(t *testing.T) { type args struct { ctx context.Context - options *SubscriptionListOptions + options *ListSubscriptionsOptions } cases := []struct { name string @@ -681,7 +681,7 @@ func TestSubscriptionsService_All(t *testing.T) { "list subscriptions with options works as expected.", args{ context.Background(), - &SubscriptionListOptions{ + &ListSubscriptionsOptions{ Limit: 10, }, }, @@ -748,7 +748,7 @@ func TestSubscriptionsService_All(t *testing.T) { assert.EqualError(t, err, c.err.Error()) } else { assert.Nil(t, err) - assert.IsType(t, &SubscriptionList{}, m) + assert.IsType(t, &SubscriptionsList{}, m) assert.IsType(t, &http.Response{}, res.Response) } }) @@ -763,7 +763,7 @@ func TestSubscriptionsService_GetPayments(t *testing.T) { ctx context.Context customer string subscription string - options *SubscriptionListOptions + options *ListSubscriptionsOptions } cases := []struct { name string @@ -800,7 +800,7 @@ func TestSubscriptionsService_GetPayments(t *testing.T) { context.Background(), "cst_stTC2WHAuS", "sub_rVKGtNd6s3", - &SubscriptionListOptions{ + &ListSubscriptionsOptions{ Limit: 10, }, }, @@ -867,7 +867,7 @@ func TestSubscriptionsService_GetPayments(t *testing.T) { c.pre() tMux.HandleFunc(fmt.Sprintf("/v2/customers/%s/subscriptions/%s/payments", c.args.customer, c.args.subscription), c.handler) - res, m, err := tClient.Subscriptions.GetPayments(c.args.ctx, c.args.customer, c.args.subscription, c.args.options) + res, m, err := tClient.Subscriptions.ListPayments(c.args.ctx, c.args.customer, c.args.subscription, c.args.options) if c.wantErr { assert.NotNil(t, err) assert.EqualError(t, err, c.err.Error()) From 5c00b3ed4672741dd4aaa92ba8937df514870df4 Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Sat, 16 Mar 2024 08:23:48 +0100 Subject: [PATCH 21/23] check terminals resource against api reference (#352) --- .github/workflows/main.yml | 2 +- docs/README.md | 50 +++++++++++++++++++------------------- mollie/terminals.go | 48 ++++++++++++++++++------------------ mollie/terminals_test.go | 24 ++++++++++++++++-- 4 files changed, 72 insertions(+), 52 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4f9f1571..1a7c6de6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,4 +40,4 @@ jobs: - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 with: go-version: ${{ matrix.go }} - - run: go test -v -failfast ./... + - run: go test -failfast ./... diff --git a/docs/README.md b/docs/README.md index 3f2f07d7..e59246d6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -164,6 +164,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type ListPaymentOptions](<#ListPaymentOptions>) - [type ListSettlementsOptions](<#ListSettlementsOptions>) - [type ListSubscriptionsOptions](<#ListSubscriptionsOptions>) +- [type ListTerminalsOptions](<#ListTerminalsOptions>) - [type Locale](<#Locale>) - [type Mandate](<#Mandate>) - [type MandateDetails](<#MandateDetails>) @@ -367,11 +368,10 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type Subtotal](<#Subtotal>) - [type Terminal](<#Terminal>) - [type TerminalList](<#TerminalList>) -- [type TerminalListOptions](<#TerminalListOptions>) - [type TerminalStatus](<#TerminalStatus>) - [type TerminalsService](<#TerminalsService>) - [func \(ts \*TerminalsService\) Get\(ctx context.Context, id string\) \(res \*Response, t \*Terminal, err error\)](<#TerminalsService.Get>) - - [func \(ts \*TerminalsService\) List\(ctx context.Context, options \*TerminalListOptions\) \(res \*Response, tl \*TerminalList, err error\)](<#TerminalsService.List>) + - [func \(ts \*TerminalsService\) List\(ctx context.Context, options \*ListTerminalsOptions\) \(res \*Response, tl \*TerminalList, err error\)](<#TerminalsService.List>) - [type TransactionType](<#TransactionType>) - [type TransferDestination](<#TransferDestination>) - [type TransferFrequency](<#TransferFrequency>) @@ -2799,6 +2799,22 @@ type ListSubscriptionsOptions struct { } ``` + +## type [ListTerminalsOptions]() + +ListTerminalsOptions holds query string parameters valid for terminals lists. + +ProfileID and TestMode are valid only when using access tokens. + +```go +type ListTerminalsOptions struct { + Testmode bool `url:"testMode,omitempty"` + Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` + ProfileID string `url:"profileID,omitempty"` +} +``` + ## type [Locale]() @@ -5714,7 +5730,7 @@ type Subtotal struct { ``` -## type [Terminal]() +## type [Terminal]() Terminal symbolizes a physical device to receive payments. @@ -5723,7 +5739,6 @@ type Terminal struct { ID string `json:"id,omitempty"` Resource string `json:"resource,omitempty"` ProfileID string `json:"profileID,omitempty"` - Status TerminalStatus `json:"status,omitempty"` Brand string `json:"brand,omitempty"` Model string `json:"model,omitempty"` SerialNumber string `json:"serialNumber,omitempty"` @@ -5731,12 +5746,13 @@ type Terminal struct { Description string `json:"description,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` UpdatedAt *time.Time `json:"updatedAt,omitempty"` + Status TerminalStatus `json:"status,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } ``` -## type [TerminalList]() +## type [TerminalList]() TerminalList describes the response for terminals list endpoints. @@ -5750,24 +5766,8 @@ type TerminalList struct { } ``` - -## type [TerminalListOptions]() - -TerminalListOptions holds query string parameters valid for terminals lists. - -ProfileID and TestMode are valid only when using access tokens. - -```go -type TerminalListOptions struct { - From string `url:"from,omitempty"` - Limit int `url:"limit,omitempty"` - ProfileID string `url:"profileID,omitempty"` - TestMode bool `url:"testMode,omitempty"` -} -``` - -## type [TerminalStatus]() +## type [TerminalStatus]() TerminalStatus is the status of the terminal, which is a read\-only value determined by Mollie. @@ -5786,7 +5786,7 @@ const ( ``` -## type [TerminalsService]() +## type [TerminalsService]() TerminalsService operates over terminals resource. @@ -5795,7 +5795,7 @@ type TerminalsService service ``` -### func \(\*TerminalsService\) [Get]() +### func \(\*TerminalsService\) [Get]() ```go func (ts *TerminalsService) Get(ctx context.Context, id string) (res *Response, t *Terminal, err error) @@ -5807,7 +5807,7 @@ Get terminal retrieves a single terminal object by its terminal ID. ### func \(\*TerminalsService\) [List]() ```go -func (ts *TerminalsService) List(ctx context.Context, options *TerminalListOptions) (res *Response, tl *TerminalList, err error) +func (ts *TerminalsService) List(ctx context.Context, options *ListTerminalsOptions) (res *Response, tl *TerminalList, err error) ``` List retrieves a list of terminals symbolizing the physical devices to receive payments. diff --git a/mollie/terminals.go b/mollie/terminals.go index 27e89d17..41f06377 100644 --- a/mollie/terminals.go +++ b/mollie/terminals.go @@ -7,9 +7,6 @@ import ( "time" ) -// TerminalsService operates over terminals resource. -type TerminalsService service - // TerminalStatus is the status of the terminal, which is a read-only value determined by Mollie. type TerminalStatus string @@ -25,7 +22,6 @@ type Terminal struct { ID string `json:"id,omitempty"` Resource string `json:"resource,omitempty"` ProfileID string `json:"profileID,omitempty"` - Status TerminalStatus `json:"status,omitempty"` Brand string `json:"brand,omitempty"` Model string `json:"model,omitempty"` SerialNumber string `json:"serialNumber,omitempty"` @@ -33,31 +29,18 @@ type Terminal struct { Description string `json:"description,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` UpdatedAt *time.Time `json:"updatedAt,omitempty"` + Status TerminalStatus `json:"status,omitempty"` Links PaginationLinks `json:"_links,omitempty"` } -// Get terminal retrieves a single terminal object by its terminal ID. -func (ts *TerminalsService) Get(ctx context.Context, id string) (res *Response, t *Terminal, err error) { - res, err = ts.client.get(ctx, fmt.Sprintf("v2/terminals/%s", id), nil) - if err != nil { - return - } - - if err = json.Unmarshal(res.content, &t); err != nil { - return - } - - return -} - -// TerminalListOptions holds query string parameters valid for terminals lists. +// ListTerminalsOptions holds query string parameters valid for terminals lists. // // ProfileID and TestMode are valid only when using access tokens. -type TerminalListOptions struct { - From string `url:"from,omitempty"` +type ListTerminalsOptions struct { + Testmode bool `url:"testMode,omitempty"` Limit int `url:"limit,omitempty"` + From string `url:"from,omitempty"` ProfileID string `url:"profileID,omitempty"` - TestMode bool `url:"testMode,omitempty"` } // TerminalList describes the response for terminals list endpoints. @@ -69,14 +52,31 @@ type TerminalList struct { Links PaginationLinks `json:"_links,omitempty"` } +// TerminalsService operates over terminals resource. +type TerminalsService service + +// Get terminal retrieves a single terminal object by its terminal ID. +func (ts *TerminalsService) Get(ctx context.Context, id string) (res *Response, t *Terminal, err error) { + res, err = ts.client.get(ctx, fmt.Sprintf("v2/terminals/%s", id), nil) + if err != nil { + return + } + + if err = json.Unmarshal(res.content, &t); err != nil { + return + } + + return +} + // List retrieves a list of terminals symbolizing the physical devices to receive payments. -func (ts *TerminalsService) List(ctx context.Context, options *TerminalListOptions) ( +func (ts *TerminalsService) List(ctx context.Context, options *ListTerminalsOptions) ( res *Response, tl *TerminalList, err error, ) { if ts.client.HasAccessToken() && ts.client.config.testing { - options.TestMode = true + options.Testmode = true } res, err = ts.client.get(ctx, "v2/terminals", options) diff --git a/mollie/terminals_test.go b/mollie/terminals_test.go index 3503f7de..8958805f 100644 --- a/mollie/terminals_test.go +++ b/mollie/terminals_test.go @@ -113,7 +113,7 @@ func TestTerminalsService_List(t *testing.T) { type args struct { ctx context.Context - options *TerminalListOptions + options *ListTerminalsOptions } cases := []struct { @@ -129,7 +129,7 @@ func TestTerminalsService_List(t *testing.T) { "list terminals correctly", args{ context.Background(), - &TerminalListOptions{}, + &ListTerminalsOptions{}, }, false, nil, @@ -145,6 +145,26 @@ func TestTerminalsService_List(t *testing.T) { _, _ = w.Write([]byte(testdata.ListTerminalsResponse)) }, }, + { + "list terminals correctly with an access token", + args{ + context.Background(), + &ListTerminalsOptions{}, + }, + false, + nil, + testdata.GetTerminalResponse, + setAccessToken, + func(w http.ResponseWriter, r *http.Request) { + testHeader(t, r, AuthHeader, "Bearer access_token_test") + testMethod(t, r, "GET") + + if _, ok := r.Header[AuthHeader]; !ok { + w.WriteHeader(http.StatusUnauthorized) + } + _, _ = w.Write([]byte(testdata.ListTerminalsResponse)) + }, + }, { "get terminals list, an error is returned from the server", args{ From 86b999af76ef2041a9b62e74317a29ad306da5cb Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio <7926849+VictorAvelar@users.noreply.github.com> Date: Sat, 16 Mar 2024 08:50:49 +0100 Subject: [PATCH 22/23] check shipments resource against api reference (#353) --- docs/README.md | 77 ++++++++++++++++++++++++++-------------- mollie/shipments.go | 73 ++++++++++++++++++++++--------------- mollie/shipments_test.go | 60 ++++++++++++++++--------------- 3 files changed, 127 insertions(+), 83 deletions(-) diff --git a/docs/README.md b/docs/README.md index e59246d6..61e9d491 100644 --- a/docs/README.md +++ b/docs/README.md @@ -120,7 +120,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type CreatePaymentRefund](<#CreatePaymentRefund>) - [type CreatePreAuthorizedPaymentFields](<#CreatePreAuthorizedPaymentFields>) - [type CreateRecurrentPaymentFields](<#CreateRecurrentPaymentFields>) -- [type CreateShipmentRequest](<#CreateShipmentRequest>) +- [type CreateShipment](<#CreateShipment>) - [type CreateSubscription](<#CreateSubscription>) - [type Customer](<#Customer>) - [type CustomerLinks](<#CustomerLinks>) @@ -341,14 +341,15 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [func \(ss \*SettlementsService\) Next\(ctx context.Context\) \(res \*Response, s \*Settlement, err error\)](<#SettlementsService.Next>) - [func \(ss \*SettlementsService\) Open\(ctx context.Context\) \(res \*Response, s \*Settlement, err error\)](<#SettlementsService.Open>) - [type Shipment](<#Shipment>) +- [type ShipmentAccessTokenFields](<#ShipmentAccessTokenFields>) - [type ShipmentLinks](<#ShipmentLinks>) - [type ShipmentTracking](<#ShipmentTracking>) - [type ShipmentsList](<#ShipmentsList>) - [type ShipmentsService](<#ShipmentsService>) - - [func \(ss \*ShipmentsService\) Create\(ctx context.Context, oID string, cs CreateShipmentRequest\) \(res \*Response, s \*Shipment, err error\)](<#ShipmentsService.Create>) - - [func \(ss \*ShipmentsService\) Get\(ctx context.Context, oID string, sID string\) \(res \*Response, s \*Shipment, err error\)](<#ShipmentsService.Get>) - - [func \(ss \*ShipmentsService\) List\(ctx context.Context, oID string\) \(res \*Response, sl \*ShipmentsList, err error\)](<#ShipmentsService.List>) - - [func \(ss \*ShipmentsService\) Update\(ctx context.Context, oID string, sID string, st ShipmentTracking\) \(res \*Response, s \*Shipment, err error\)](<#ShipmentsService.Update>) + - [func \(ss \*ShipmentsService\) Create\(ctx context.Context, order string, cs CreateShipment\) \(res \*Response, s \*Shipment, err error\)](<#ShipmentsService.Create>) + - [func \(ss \*ShipmentsService\) Get\(ctx context.Context, order string, shipment string\) \(res \*Response, s \*Shipment, err error\)](<#ShipmentsService.Get>) + - [func \(ss \*ShipmentsService\) List\(ctx context.Context, order string\) \(res \*Response, sl \*ShipmentsList, err error\)](<#ShipmentsService.List>) + - [func \(ss \*ShipmentsService\) Update\(ctx context.Context, order string, shipment string, us UpdateShipment\) \(res \*Response, s \*Shipment, err error\)](<#ShipmentsService.Update>) - [type ShortDate](<#ShortDate>) - [func \(d \*ShortDate\) MarshalJSON\(\) \(\[\]byte, error\)](<#ShortDate.MarshalJSON>) - [func \(d \*ShortDate\) UnmarshalJSON\(b \[\]byte\) error](<#ShortDate.UnmarshalJSON>) @@ -380,6 +381,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y - [type UpdateOrder](<#UpdateOrder>) - [type UpdateOrderLine](<#UpdateOrderLine>) - [type UpdatePayment](<#UpdatePayment>) +- [type UpdateShipment](<#UpdateShipment>) - [type UpdateSubscription](<#UpdateSubscription>) - [type UsedGiftCard](<#UsedGiftCard>) - [type UserAgentToken](<#UserAgentToken>) @@ -2099,16 +2101,16 @@ type CreateRecurrentPaymentFields struct { } ``` - -## type [CreateShipmentRequest]() + +## type [CreateShipment]() -CreateShipmentRequest defines information required to create a new shipment. +CreateShipment contains information required to create a new shipment. ```go -type CreateShipmentRequest struct { - Lines []OrderLine `json:"lines,omitempty"` - Tracking ShipmentTracking `json:"tracking,omitempty"` - TestMode bool `json:"testmode,omitempty"` +type CreateShipment struct { + Lines []*OrderLine `json:"lines,omitempty"` + Tracking *ShipmentTracking `json:"tracking,omitempty"` + ShipmentAccessTokenFields } ``` @@ -5396,7 +5398,7 @@ Open retrieves the details of the open balance of the organization. This will re See: https://docs.mollie.com/reference/v2/settlements-api/get-open-settlement -## type [Shipment]() +## type [Shipment]() Shipment contains information about a user service/product delivery and is used in the figurative sense here. It can also mean that a service was provided or digital content was delivered. @@ -5405,16 +5407,27 @@ type Shipment struct { Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` OrderID string `json:"orderId,omitempty"` - TestMode bool `json:"testmode,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` Tracking *ShipmentTracking `json:"tracking,omitempty"` Lines []*OrderLine `json:"lines,omitempty"` Links ShipmentLinks `json:"_links,omitempty"` + ShipmentAccessTokenFields +} +``` + + +## type [ShipmentAccessTokenFields]() + +ShipmentAccessTokenFields describes the fields available when using an access token. + +```go +type ShipmentAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` } ``` -## type [ShipmentLinks]() +## type [ShipmentLinks]() ShipmentLinks contains URL objects with shipment relevant information for the user. @@ -5427,7 +5440,7 @@ type ShipmentLinks struct { ``` -## type [ShipmentTracking]() +## type [ShipmentTracking]() ShipmentTracking contains shipment tracking details. @@ -5440,7 +5453,7 @@ type ShipmentTracking struct { ``` -## type [ShipmentsList]() +## type [ShipmentsList]() ShipmentsList describes how a list of payments will be retrieved by Mollie. @@ -5455,7 +5468,7 @@ type ShipmentsList struct { ``` -## type [ShipmentsService]() +## type [ShipmentsService]() ShipmentsService operates on shipments endpoints. @@ -5464,10 +5477,10 @@ type ShipmentsService service ``` -### func \(\*ShipmentsService\) [Create]() +### func \(\*ShipmentsService\) [Create]() ```go -func (ss *ShipmentsService) Create(ctx context.Context, oID string, cs CreateShipmentRequest) (res *Response, s *Shipment, err error) +func (ss *ShipmentsService) Create(ctx context.Context, order string, cs CreateShipment) (res *Response, s *Shipment, err error) ``` Create can be used to ship order lines. @@ -5475,10 +5488,10 @@ Create can be used to ship order lines. See: https://docs.mollie.com/reference/v2/shipments-api/create-shipment -### func \(\*ShipmentsService\) [Get]() +### func \(\*ShipmentsService\) [Get]() ```go -func (ss *ShipmentsService) Get(ctx context.Context, oID string, sID string) (res *Response, s *Shipment, err error) +func (ss *ShipmentsService) Get(ctx context.Context, order string, shipment string) (res *Response, s *Shipment, err error) ``` Get retrieves a single shipment and the order lines shipped by a shipment’s ID. @@ -5486,10 +5499,10 @@ Get retrieves a single shipment and the order lines shipped by a shipment’s ID See: https://docs.mollie.com/reference/v2/shipments-api/get-shipment# -### func \(\*ShipmentsService\) [List]() +### func \(\*ShipmentsService\) [List]() ```go -func (ss *ShipmentsService) List(ctx context.Context, oID string) (res *Response, sl *ShipmentsList, err error) +func (ss *ShipmentsService) List(ctx context.Context, order string) (res *Response, sl *ShipmentsList, err error) ``` List retrieves all shipments for an order. @@ -5497,10 +5510,10 @@ List retrieves all shipments for an order. See: https://docs.mollie.com/reference/v2/shipments-api/list-shipments -### func \(\*ShipmentsService\) [Update]() +### func \(\*ShipmentsService\) [Update]() ```go -func (ss *ShipmentsService) Update(ctx context.Context, oID string, sID string, st ShipmentTracking) (res *Response, s *Shipment, err error) +func (ss *ShipmentsService) Update(ctx context.Context, order string, shipment string, us UpdateShipment) (res *Response, s *Shipment, err error) ``` Update can be used to update the tracking information of a shipment @@ -5974,6 +5987,18 @@ type UpdatePayment struct { } ``` + +## type [UpdateShipment]() + +UpdateShipment contains information required to update a shipment. + +```go +type UpdateShipment struct { + Tracking *ShipmentTracking `json:"tracking,omitempty"` + ShipmentAccessTokenFields +} +``` + ## type [UpdateSubscription]() diff --git a/mollie/shipments.go b/mollie/shipments.go index eaee09fc..3ef8df8b 100644 --- a/mollie/shipments.go +++ b/mollie/shipments.go @@ -7,8 +7,17 @@ import ( "time" ) -// ShipmentsService operates on shipments endpoints. -type ShipmentsService service +// CreateShipment contains information required to create a new shipment. +type CreateShipment struct { + Lines []*OrderLine `json:"lines,omitempty"` + Tracking *ShipmentTracking `json:"tracking,omitempty"` + ShipmentAccessTokenFields +} + +// ShipmentAccessTokenFields describes the fields available when using an access token. +type ShipmentAccessTokenFields struct { + Testmode bool `json:"testmode,omitempty"` +} // Shipment contains information about a user service/product delivery and // is used in the figurative sense here. @@ -17,11 +26,17 @@ type Shipment struct { Resource string `json:"resource,omitempty"` ID string `json:"id,omitempty"` OrderID string `json:"orderId,omitempty"` - TestMode bool `json:"testmode,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` Tracking *ShipmentTracking `json:"tracking,omitempty"` Lines []*OrderLine `json:"lines,omitempty"` Links ShipmentLinks `json:"_links,omitempty"` + ShipmentAccessTokenFields +} + +// UpdateShipment contains information required to update a shipment. +type UpdateShipment struct { + Tracking *ShipmentTracking `json:"tracking,omitempty"` + ShipmentAccessTokenFields } // ShipmentTracking contains shipment tracking details. @@ -39,11 +54,27 @@ type ShipmentLinks struct { Documentation *URL `json:"documentation,omitempty"` } +// ShipmentsList describes how a list of payments will be retrieved by Mollie. +type ShipmentsList struct { + Count int `json:"count,omitempty"` + Embedded struct { + Shipments []Shipment + } `json:"_embedded,omitempty"` + Links PaginationLinks `json:"_links,omitempty"` +} + +// ShipmentsService operates on shipments endpoints. +type ShipmentsService service + // Get retrieves a single shipment and the order lines shipped by a shipment’s ID. // // See: https://docs.mollie.com/reference/v2/shipments-api/get-shipment# -func (ss *ShipmentsService) Get(ctx context.Context, oID string, sID string) (res *Response, s *Shipment, err error) { - u := fmt.Sprintf("v2/orders/%s/shipments/%s", oID, sID) +func (ss *ShipmentsService) Get(ctx context.Context, order string, shipment string) ( + res *Response, + s *Shipment, + err error, +) { + u := fmt.Sprintf("v2/orders/%s/shipments/%s", order, shipment) res, err = ss.client.get(ctx, u, nil) if err != nil { @@ -57,25 +88,18 @@ func (ss *ShipmentsService) Get(ctx context.Context, oID string, sID string) (re return } -// CreateShipmentRequest defines information required to create a new shipment. -type CreateShipmentRequest struct { - Lines []OrderLine `json:"lines,omitempty"` - Tracking ShipmentTracking `json:"tracking,omitempty"` - TestMode bool `json:"testmode,omitempty"` -} - // Create can be used to ship order lines. // // See: https://docs.mollie.com/reference/v2/shipments-api/create-shipment -func (ss *ShipmentsService) Create(ctx context.Context, oID string, cs CreateShipmentRequest) ( +func (ss *ShipmentsService) Create(ctx context.Context, order string, cs CreateShipment) ( res *Response, s *Shipment, err error, ) { - uri := fmt.Sprintf("v2/orders/%s/shipments", oID) + uri := fmt.Sprintf("v2/orders/%s/shipments", order) if ss.client.HasAccessToken() && ss.client.config.testing { - cs.TestMode = true + cs.Testmode = true } res, err = ss.client.post(ctx, uri, cs, nil) @@ -90,20 +114,11 @@ func (ss *ShipmentsService) Create(ctx context.Context, oID string, cs CreateShi return } -// ShipmentsList describes how a list of payments will be retrieved by Mollie. -type ShipmentsList struct { - Count int `json:"count,omitempty"` - Embedded struct { - Shipments []Shipment - } `json:"_embedded,omitempty"` - Links PaginationLinks `json:"_links,omitempty"` -} - // List retrieves all shipments for an order. // // See: https://docs.mollie.com/reference/v2/shipments-api/list-shipments -func (ss *ShipmentsService) List(ctx context.Context, oID string) (res *Response, sl *ShipmentsList, err error) { - u := fmt.Sprintf("v2/orders/%s/shipments", oID) +func (ss *ShipmentsService) List(ctx context.Context, order string) (res *Response, sl *ShipmentsList, err error) { + u := fmt.Sprintf("v2/orders/%s/shipments", order) res, err = ss.client.get(ctx, u, nil) if err != nil { @@ -120,14 +135,14 @@ func (ss *ShipmentsService) List(ctx context.Context, oID string) (res *Response // Update can be used to update the tracking information of a shipment // // See: https://docs.mollie.com/reference/v2/shipments-api/update-shipment -func (ss *ShipmentsService) Update(ctx context.Context, oID string, sID string, st ShipmentTracking) ( +func (ss *ShipmentsService) Update(ctx context.Context, order string, shipment string, us UpdateShipment) ( res *Response, s *Shipment, err error, ) { - u := fmt.Sprintf("v2/orders/%s/shipments/%s", oID, sID) + u := fmt.Sprintf("v2/orders/%s/shipments/%s", order, shipment) - res, err = ss.client.patch(ctx, u, st, nil) + res, err = ss.client.patch(ctx, u, us, nil) if err != nil { return } diff --git a/mollie/shipments_test.go b/mollie/shipments_test.go index f14003c3..3cf6a222 100644 --- a/mollie/shipments_test.go +++ b/mollie/shipments_test.go @@ -209,7 +209,7 @@ func TestShipmentsService_Create(t *testing.T) { type args struct { ctx context.Context order string - shipment CreateShipmentRequest + shipment CreateShipment } cases := []struct { name string @@ -224,8 +224,12 @@ func TestShipmentsService_Create(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - CreateShipmentRequest{ - TestMode: true, + CreateShipment{ + Tracking: &ShipmentTracking{ + Carrier: "fedex", + Code: "3wmsgCJN4U", + URL: "https://www.example.fedex.com/apps/fedextrack/?tracknumbers=3wmsgCJN4U", + }, }, }, false, @@ -246,8 +250,12 @@ func TestShipmentsService_Create(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - CreateShipmentRequest{ - TestMode: true, + CreateShipment{ + Tracking: &ShipmentTracking{ + Carrier: "fedex", + Code: "3wmsgCJN4U", + URL: "https://www.example.fedex.com/apps/fedextrack/?tracknumbers=3wmsgCJN4U", + }, }, }, false, @@ -269,9 +277,7 @@ func TestShipmentsService_Create(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - CreateShipmentRequest{ - TestMode: true, - }, + CreateShipment{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -283,9 +289,7 @@ func TestShipmentsService_Create(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - CreateShipmentRequest{ - TestMode: true, - }, + CreateShipment{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -297,9 +301,7 @@ func TestShipmentsService_Create(t *testing.T) { args{ context.Background(), "ord_kEn1PlbGa", - CreateShipmentRequest{ - TestMode: true, - }, + CreateShipment{}, }, true, errBadBaseURL, @@ -337,7 +339,7 @@ func TestShipmentsService_Update(t *testing.T) { ctx context.Context order string shipment string - st ShipmentTracking + st UpdateShipment } cases := []struct { name string @@ -353,8 +355,12 @@ func TestShipmentsService_Update(t *testing.T) { context.Background(), "ord_kEn1PlbGa", "shp_3wmsgCJN4U", - ShipmentTracking{ - Carrier: "fedex", + UpdateShipment{ + Tracking: &ShipmentTracking{ + Carrier: "dhl", + Code: "3wmsgCJN4U", + URL: "https://www.example.dhl.com/apps/dhltrack/?tracknumbers=3wmsgCJN4U", + }, }, }, false, @@ -376,8 +382,12 @@ func TestShipmentsService_Update(t *testing.T) { context.Background(), "ord_kEn1PlbGa", "shp_3wmsgCJN4U", - ShipmentTracking{ - Carrier: "fedex", + UpdateShipment{ + Tracking: &ShipmentTracking{ + Carrier: "dhl", + Code: "3wmsgCJN4U", + URL: "https://www.example.dhl.com/apps/dhltrack/?tracknumbers=3wmsgCJN4U", + }, }, }, false, @@ -400,9 +410,7 @@ func TestShipmentsService_Update(t *testing.T) { context.Background(), "ord_kEn1PlbGa", "shp_3wmsgCJN4U", - ShipmentTracking{ - Carrier: "fedex", - }, + UpdateShipment{}, }, true, fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."), @@ -415,9 +423,7 @@ func TestShipmentsService_Update(t *testing.T) { context.Background(), "ord_kEn1PlbGa", "shp_3wmsgCJN4U", - ShipmentTracking{ - Carrier: "fedex", - }, + UpdateShipment{}, }, true, fmt.Errorf("invalid character 'h' looking for beginning of object key string"), @@ -430,9 +436,7 @@ func TestShipmentsService_Update(t *testing.T) { context.Background(), "ord_kEn1PlbGa", "shp_3wmsgCJN4U", - ShipmentTracking{ - Carrier: "fedex", - }, + UpdateShipment{}, }, true, errBadBaseURL, From 57c18b62c60d3abfdee196453da769b356bf44fe Mon Sep 17 00:00:00 2001 From: Victor Hugo Avelar Ossorio Date: Sat, 16 Mar 2024 07:52:02 +0000 Subject: [PATCH 23/23] chore(docs): update notes to upgrade to v4 --- docs/v4-upgrade.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/v4-upgrade.md b/docs/v4-upgrade.md index 72153fe5..6d24774b 100644 --- a/docs/v4-upgrade.md +++ b/docs/v4-upgrade.md @@ -6,11 +6,13 @@ - `pagination` package has moved from the`mollie` directory to the `pkg` directory. - `connect` package has moved from the `mollie` directory to the `pkg` directory. - root namespace is not `github.com/VictorAvelar/mollie-api-go/v4/`. -- Changes for payments resource - - Added `CreatePayment` type to use when creating a payment. - - Added `UpdatePayment` type to use when updating a payment. - - Ensured `Payment` object (used for read operations) contains all the available fields. - - Created types specific for fields that are conditional given the payment values, both to create new payments and to list existing payments. +- Changes in all resources: + - Data structures to describe request content in create, update and get operations are no longer the same, e.g. for `payments` there is a `CreatePayment` struct, a `UpdatePayment` struct and a `Payment` struct. This enables future extensions and modifications without having to check for cross request compatibility. + - Data structures that describe available url parameters are consistently names `List{ResourceName}Options`. + - Data structures that describe lists responses are consistently named as follows: e.g. for payments: `PaymentsList` +- API aliases now use the parent objects, e.g. for settlements when listing payments the options passed to the request are using the `ListPaymentsOptions` object and not a local object. +- All resources were checked for API consistency and parity, optional resources with custom types are now pointers to ensure proper json encoding and decoding to avoid issues as the one mentioned un #271 +- All resources embed a struct containing all the fields specific to access tokens, following this pattern the same happens for fields specific to Mollie connect ## Other changes @@ -18,4 +20,5 @@ - Improvements for devcontainer files - Major versions of multiple github actions updated - Base `Dockerfile` using Go 1.22.x -- Tests related to payments were update to use the new types. +- Tests were update to use the new types. +- Test coverage was slightly improved.