Skip to content

Commit

Permalink
adds support for other HTTP methods (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
KadoBOT authored Nov 26, 2020
1 parent 9463ba1 commit 3cefa60
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 47 deletions.
12 changes: 6 additions & 6 deletions src/checkout/api_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,29 @@ import (
type Checkout common.Service

/*
GetPaymentLinksLinkId Retrieve a payment link.
GetPaymentLink Retrieve a payment link.
Retrieves the payment link details using the payment link `id`.
* @param linkId Unique identifier of the payment link.
* @param ctxs ..._context.Context - optional, for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
@return PaymentLinkResource
*/
func (a Checkout) PaymentLinksLinkId(req *string, ctxs ..._context.Context) (PaymentLinkResource, *_nethttp.Response, error) {
func (a Checkout) GetPaymentLink(linkId string, ctxs ..._context.Context) (PaymentLinkResource, *_nethttp.Response, error) {
res := &PaymentLinkResource{}
httpRes, err := a.Client.MakeHTTPPostRequest(req, res, a.BasePath()+"/paymentLinks/{linkId}", ctxs...)
httpRes, err := a.Client.MakeHTTPGetRequest(res, a.BasePath()+"/paymentLinks/"+linkId, ctxs...)
return *res, httpRes, err
}

/*
PatchPaymentLinksLinkId Update the status of a payment link
UpdatePaymentLink Update the status of a payment link
Updates the status of a payment link. Use this endpoint to [force the expiry of a payment link](https://docs.adyen.com/checkout/pay-by-link#update-payment-link-status).
* @param linkId Unique identifier of the payment link.
* @param request UpdatePaymentLinkRequest - reference of UpdatePaymentLinkRequest).
* @param ctxs ..._context.Context - optional, for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
@return PaymentLinkResource
*/
func (a Checkout) PatchPaymentLinksLinkId(req *UpdatePaymentLinkRequest, ctxs ..._context.Context) (PaymentLinkResource, *_nethttp.Response, error) {
func (a Checkout) UpdatePaymentLink(linkId string, req *UpdatePaymentLinkRequest, ctxs ..._context.Context) (PaymentLinkResource, *_nethttp.Response, error) {
res := &PaymentLinkResource{}
httpRes, err := a.Client.MakeHTTPPostRequest(req, res, a.BasePath()+"/paymentLinks/{linkId}", ctxs...)
httpRes, err := a.Client.MakeHTTPPatchRequest(req, res, a.BasePath()+"/paymentLinks/"+linkId, ctxs...)
return *res, httpRes, err
}

Expand Down
38 changes: 19 additions & 19 deletions src/checkout/model_checkout_balance_check_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,45 @@ import (

// CheckoutBalanceCheckRequest struct for CheckoutBalanceCheckRequest
type CheckoutBalanceCheckRequest struct {
AccountInfo *AccountInfo `json:"accountInfo,omitempty"`
AdditionalAmount *Amount `json:"additionalAmount,omitempty"`
AccountInfo *AccountInfo `json:"accountInfo,omitempty"`
AdditionalAmount *Amount `json:"additionalAmount,omitempty"`
// This field contains additional data, which may be required for a particular payment request. The `additionalData` object consists of entries, each of which includes the key and value.
AdditionalData *map[string]interface{} `json:"additionalData,omitempty"`
Amount Amount `json:"amount"`
ApplicationInfo *ApplicationInfo `json:"applicationInfo,omitempty"`
BillingAddress *Address `json:"billingAddress,omitempty"`
BrowserInfo *BrowserInfo `json:"browserInfo,omitempty"`
AdditionalData *map[string]interface{} `json:"additionalData,omitempty"`
Amount *Amount `json:"amount,omitempty"`
ApplicationInfo *ApplicationInfo `json:"applicationInfo,omitempty"`
BillingAddress *Address `json:"billingAddress,omitempty"`
BrowserInfo *BrowserInfo `json:"browserInfo,omitempty"`
// The delay between the authorisation and scheduled auto-capture, specified in hours.
CaptureDelayHours int32 `json:"captureDelayHours,omitempty"`
// The shopper's date of birth. Format [ISO-8601](https://www.w3.org/TR/NOTE-datetime): YYYY-MM-DD
DateOfBirth *time.Time `json:"dateOfBirth,omitempty"`
DccQuote *ForexQuote `json:"dccQuote,omitempty"`
DeliveryAddress *Address `json:"deliveryAddress,omitempty"`
DateOfBirth *time.Time `json:"dateOfBirth,omitempty"`
DccQuote *ForexQuote `json:"dccQuote,omitempty"`
DeliveryAddress *Address `json:"deliveryAddress,omitempty"`
// The date and time the purchased goods should be delivered. Format [ISO 8601](https://www.w3.org/TR/NOTE-datetime): YYYY-MM-DDThh:mm:ss.sssTZD Example: 2017-07-17T13:42:40.428+01:00
DeliveryDate *time.Time `json:"deliveryDate,omitempty"`
// A string containing the shopper's device fingerprint. For more information, refer to [Device fingerprinting](https://docs.adyen.com/risk-management/device-fingerprinting).
DeviceFingerprint string `json:"deviceFingerprint,omitempty"`
// An integer value that is added to the normal fraud score. The value can be either positive or negative.
FraudOffset int32 `json:"fraudOffset,omitempty"`
FraudOffset int32 `json:"fraudOffset,omitempty"`
Installments *Installments `json:"installments,omitempty"`
// The [merchant category code](https://en.wikipedia.org/wiki/Merchant_category_code) (MCC) is a four-digit number, which relates to a particular market segment. This code reflects the predominant activity that is conducted by the merchant.
Mcc string `json:"mcc,omitempty"`
// The merchant account identifier, with which you want to process the transaction.
MerchantAccount string `json:"merchantAccount"`
// This reference allows linking multiple transactions to each other for reporting purposes (i.e. order auth-rate). The reference should be unique per billing cycle. The same merchant order reference should never be reused after the first authorised attempt. If used, this field should be supplied for all incoming authorisations. > We strongly recommend you send the `merchantOrderReference` value to benefit from linking payment requests when authorisation retries take place. In addition, we recommend you provide `retry.orderAttemptNumber`, `retry.chainAttemptNumber`, and `retry.skipRetry` values in `PaymentRequest.additionalData`.
MerchantOrderReference string `json:"merchantOrderReference,omitempty"`
MerchantRiskIndicator *MerchantRiskIndicator `json:"merchantRiskIndicator,omitempty"`
MerchantOrderReference string `json:"merchantOrderReference,omitempty"`
MerchantRiskIndicator *MerchantRiskIndicator `json:"merchantRiskIndicator,omitempty"`
// Metadata consists of entries, each of which includes a key and a value. Limitations: Maximum 20 key-value pairs per request. When exceeding, the \"177\" error occurs: \"Metadata size exceeds limit\".
Metadata map[string]string `json:"metadata,omitempty"`
// When you are doing multiple partial (gift card) payments, this is the `pspReference` of the first payment. We use this to link the multiple payments to each other. As your own reference for linking multiple payments, use the `merchantOrderReference`instead.
OrderReference string `json:"orderReference,omitempty"`
// The collection that contains the type of the payment method and its specific information.
PaymentMethod map[string]string `json:"paymentMethod"`
Recurring *Recurring `json:"recurring,omitempty"`
// Defines a recurring payment type. Allowed values: * `Subscription` – A transaction for a fixed or variable amount, which follows a fixed schedule. * `CardOnFile` – With a card-on-file (CoF) transaction, card details are stored to enable one-click or omnichannel journeys, or simply to streamline the checkout process. Any subscription not following a fixed schedule is also considered a card-on-file transaction. * `UnscheduledCardOnFile` – An unscheduled card-on-file (UCoF) transaction is a transaction that occurs on a non-fixed schedule and/or have variable amounts. For example, automatic top-ups when a cardholder's balance drops below a certain amount.
PaymentMethod map[string]interface{} `json:"paymentMethod"`
Recurring *Recurring `json:"recurring,omitempty"`
// Defines a recurring payment type. Allowed values: * `Subscription` – A transaction for a fixed or variable amount, which follows a fixed schedule. * `CardOnFile` – With a card-on-file (CoF) transaction, card details are stored to enable one-click or omnichannel journeys, or simply to streamline the checkout process. Any subscription not following a fixed schedule is also considered a card-on-file transaction. * `UnscheduledCardOnFile` – An unscheduled card-on-file (UCoF) transaction is a transaction that occurs on a non-fixed schedule and/or have variable amounts. For example, automatic top-ups when a cardholder's balance drops below a certain amount.
RecurringProcessingModel string `json:"recurringProcessingModel,omitempty"`
// The reference to uniquely identify a payment. This reference is used in all communication with you about the payment status. We recommend using a unique value per payment; however, it is not a requirement. If you need to provide multiple references for a transaction, separate them with hyphens (\"-\"). Maximum length: 80 characters.
Reference string `json:"reference"`
Reference string `json:"reference,omitempty"`
// Some payment methods require defining a value for this field to specify how to process the transaction. For the Bancontact payment method, it can be set to: * `maestro` (default), to be processed like a Maestro card, or * `bcmc`, to be processed like a Bancontact card.
SelectedBrand string `json:"selectedBrand,omitempty"`
// The `recurringDetailReference` you want to use for this payment. The value `LATEST` can be used to select the most recently stored recurring detail.
Expand All @@ -69,7 +69,7 @@ type CheckoutBalanceCheckRequest struct {
ShopperInteraction string `json:"shopperInteraction,omitempty"`
// The combination of a language code and a country code to specify the language to be used in the payment.
ShopperLocale string `json:"shopperLocale,omitempty"`
ShopperName *Name `json:"shopperName,omitempty"`
ShopperName *Name `json:"shopperName,omitempty"`
// Your reference to uniquely identify this shopper (for example, user ID or account ID). Minimum length: 3 characters. > This field is required for recurring payments.
ShopperReference string `json:"shopperReference,omitempty"`
// The text to be shown on the shopper's bank statement. To enable this field, contact our [Support Team](https://support.adyen.com/hc/en-us/requests/new). We recommend sending a maximum of 25 characters, otherwise banks might truncate the string.
Expand All @@ -81,7 +81,7 @@ type CheckoutBalanceCheckRequest struct {
// The physical store, for which this payment is processed.
Store string `json:"store,omitempty"`
// The shopper's telephone number.
TelephoneNumber string `json:"telephoneNumber,omitempty"`
TelephoneNumber string `json:"telephoneNumber,omitempty"`
ThreeDS2RequestData *ThreeDS2RequestData `json:"threeDS2RequestData,omitempty"`
// If set to true, you will only perform the [3D Secure 2 authentication](https://docs.adyen.com/checkout/3d-secure/other-3ds-flows/authentication-only), and not the payment authorisation.
ThreeDSAuthenticationOnly bool `json:"threeDSAuthenticationOnly,omitempty"`
Expand Down
22 changes: 18 additions & 4 deletions src/common/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ type Client struct {
Cfg *Config
}

// MakeHTTPPostRequest is a generic method used to make HTTP POST requests
func (c *Client) MakeHTTPPostRequest(req interface{}, res interface{}, path string, ctxs ...context.Context) (*http.Response, error) {
httpMethod := http.MethodPost

// CreateHTTPRequest is used as base to create HTTP request for all methods (GET, POST, PATCH...)
func CreateHTTPRequest(c *Client, httpMethod string, req interface{}, res interface{}, path string, ctxs []context.Context) (*http.Response, error) {
// create path and map variables
headerParams := make(map[string]string)
queryParams := url.Values{}
Expand Down Expand Up @@ -112,6 +110,22 @@ func (c *Client) MakeHTTPPostRequest(req interface{}, res interface{}, path stri
return httpResponse, nil
}

// MakeHTTPPostRequest is a generic method used to make HTTP POST requests
func (c *Client) MakeHTTPPostRequest(req interface{}, res interface{}, path string, ctxs ...context.Context) (*http.Response, error) {
return CreateHTTPRequest(c, http.MethodPost, req, res, path, ctxs)
}

// MakeHTTPGetRequest is a generic method used to make HTTP GET requests
func (c *Client) MakeHTTPGetRequest(res interface{}, path string, ctxs ...context.Context) (*http.Response, error) {
var req interface{}
return CreateHTTPRequest(c, http.MethodGet, req, res, path, ctxs)
}

// MakeHTTPPatchRequest is a generic method used to make HTTP PATCH requests
func (c *Client) MakeHTTPPatchRequest(req interface{}, res interface{}, path string, ctxs ...context.Context) (*http.Response, error) {
return CreateHTTPRequest(c, http.MethodPatch, req, res, path, ctxs)
}

// CallAPI do the Request.
func (c *Client) CallAPI(request *http.Request) (*http.Response, error) {
if c.Cfg.Debug {
Expand Down
133 changes: 115 additions & 18 deletions tests/checkout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package tests

import (
"context"
_nethttp "net/http"
"os"
"strings"
"testing"
Expand Down Expand Up @@ -39,24 +40,8 @@ func Test_Checkout(t *testing.T) {
// client.GetConfig().Debug = true

t.Run("PaymentLinks", func(t *testing.T) {
t.Run("Create an API request that should fail", func(t *testing.T) {

res, httpRes, err := client.Checkout.PaymentLinks(&checkout.CreatePaymentLinkRequest{
Amount: checkout.Amount{
Value: 1250,
Currency: "EUR",
},
MerchantAccount: MerchantAccount,
})

require.NotNil(t, err)
assert.Equal(t, true, strings.Contains(err.Error(), "Reference Missing"))
require.NotNil(t, httpRes)
require.NotNil(t, res)
})
t.Run("Create an API request that should pass", func(t *testing.T) {

res, httpRes, err := client.Checkout.PaymentLinks(&checkout.CreatePaymentLinkRequest{
createPaymentLink := func() (checkout.PaymentLinkResource, *_nethttp.Response, error) {
return client.Checkout.PaymentLinks(&checkout.CreatePaymentLinkRequest{
Reference: "123456781235",
Amount: checkout.Amount{
Value: 1250,
Expand All @@ -76,6 +61,24 @@ func Test_Checkout(t *testing.T) {
},
MerchantAccount: MerchantAccount,
})
}
t.Run("Create an API request that should fail", func(t *testing.T) {

res, httpRes, err := client.Checkout.PaymentLinks(&checkout.CreatePaymentLinkRequest{
Amount: checkout.Amount{
Value: 1250,
Currency: "EUR",
},
MerchantAccount: MerchantAccount,
})

require.NotNil(t, err)
assert.Equal(t, true, strings.Contains(err.Error(), "Reference Missing"))
require.NotNil(t, httpRes)
require.NotNil(t, res)
})
t.Run("Create an API request that should pass", func(t *testing.T) {
res, httpRes, err := createPaymentLink()

require.Nil(t, err)
require.NotNil(t, httpRes)
Expand All @@ -84,6 +87,34 @@ func Test_Checkout(t *testing.T) {
assert.Equal(t, checkout.Amount{Currency: "EUR", Value: 1250}, res.Amount)
assert.NotNil(t, res.Url)
})

t.Run("Get payment link", func(t *testing.T) {
paymentLink, _, _ := createPaymentLink()
res, httpRes, err := client.Checkout.GetPaymentLink(paymentLink.Id)

require.Nil(t, err)
require.NotNil(t, httpRes)
assert.Equal(t, 200, httpRes.StatusCode)
require.NotNil(t, res)
assert.Equal(t, paymentLink.Reference, res.Reference)
assert.Equal(t, paymentLink.Status, res.Status)
assert.NotNil(t, res.Url)
})

t.Run("Update payment link", func(t *testing.T) {
paymentLink, _, _ := createPaymentLink()
res, httpRes, err := client.Checkout.UpdatePaymentLink(paymentLink.Id, &checkout.UpdatePaymentLinkRequest{
Status: "expired",
})

require.Nil(t, err)
require.NotNil(t, httpRes)
assert.Equal(t, 200, httpRes.StatusCode)
require.NotNil(t, res)
assert.Equal(t, paymentLink.Reference, res.Reference)
assert.NotEqual(t, paymentLink.Status, res.Status)
assert.NotNil(t, res.Url)
})
})

t.Run("PaymentMethods", func(t *testing.T) {
Expand Down Expand Up @@ -337,4 +368,70 @@ func Test_Checkout(t *testing.T) {
assert.NotEmpty(t, originKeys[domain])
})
})

t.Run("Orders", func(t *testing.T) {
t.Run("Get balance", func(t *testing.T) {
t.Skip("Payment method not correctly configured in the backoffice")
res, httpRes, err := client.Checkout.PaymentMethodsBalance(&checkout.CheckoutBalanceCheckRequest{
MerchantAccount: MerchantAccount,
PaymentMethod: map[string]interface{}{
"type": "giftcard",
"brand": "givex",
"number": "603628672882001915092",
"holderName": "balance EUR 100",
"cvc": "5754",
"additionalAmount": map[string]interface{}{
"currency": "EUR",
"value": 0,
},
},
})

require.Nil(t, err)
require.NotNil(t, httpRes)
assert.Equal(t, 200, httpRes.StatusCode)
require.NotNil(t, res)
assert.Equal(t, int64(100), res.Balance.Value)
})
t.Run("Create order", func(t *testing.T) {
res, httpRes, err := client.Checkout.Orders(&checkout.CheckoutCreateOrderRequest{
Amount: checkout.Amount{
Currency: "EUR",
Value: 1000,
},
MerchantAccount: MerchantAccount,
Reference: "CREATE_ORDER_REF",
})

require.Nil(t, err)
require.NotNil(t, httpRes)
assert.Equal(t, 200, httpRes.StatusCode)
require.NotNil(t, res)
assert.Equal(t, int64(1000), res.RemainingAmount.Value)
})
t.Run("Cancel order", func(t *testing.T) {
order, _, _ := client.Checkout.Orders(&checkout.CheckoutCreateOrderRequest{
Amount: checkout.Amount{
Currency: "EUR",
Value: 1000,
},
MerchantAccount: MerchantAccount,
Reference: "CREATE_ORDER_REF",
})

res, httpRes, err := client.Checkout.OrdersCancel(&checkout.CheckoutCancelOrderRequest{
MerchantAccount: MerchantAccount,
Order: checkout.CheckoutOrder{
OrderData: order.OrderData,
PspReference: order.PspReference,
},
})

require.Nil(t, err)
require.NotNil(t, httpRes)
assert.Equal(t, 200, httpRes.StatusCode)
require.NotNil(t, res)
assert.Equal(t, "Received", res.ResultCode)
})
})
}

0 comments on commit 3cefa60

Please sign in to comment.