Skip to content

Commit 439e110

Browse files
Added payment sessions support
1 parent 6592b2c commit 439e110

File tree

7 files changed

+307
-53
lines changed

7 files changed

+307
-53
lines changed

nas/checkout_api.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/checkout/checkout-sdk-go/payments/hosted"
2020
"github.com/checkout/checkout-sdk-go/payments/links"
2121
payments "github.com/checkout/checkout-sdk-go/payments/nas"
22+
"github.com/checkout/checkout-sdk-go/payments/sessions"
2223
"github.com/checkout/checkout-sdk-go/reports"
2324
"github.com/checkout/checkout-sdk-go/sessions"
2425
"github.com/checkout/checkout-sdk-go/tokens"
@@ -27,24 +28,25 @@ import (
2728
)
2829

2930
type Api struct {
30-
Accounts *accounts.Client
31-
Balances *balances.Client
32-
Customers *customers.Client
33-
Disputes *disputes.Client
34-
Financial *financial.Client
35-
Forex *forex.Client
36-
Hosted *hosted.Client
37-
Instruments *instruments.Client
38-
Links *links.Client
39-
Metadata *metadata.Client
40-
Payments *payments.Client
41-
Sessions *sessions.Client
42-
Tokens *tokens.Client
43-
Transfers *transfers.Client
44-
WorkFlows *workflows.Client
45-
Reports *reports.Client
46-
Issuing *issuing.Client
47-
Contexts *contexts.Client
31+
Accounts *accounts.Client
32+
Balances *balances.Client
33+
Customers *customers.Client
34+
Disputes *disputes.Client
35+
Financial *financial.Client
36+
Forex *forex.Client
37+
Hosted *hosted.Client
38+
Instruments *instruments.Client
39+
Links *links.Client
40+
Metadata *metadata.Client
41+
Payments *payments.Client
42+
Sessions *sessions.Client
43+
Tokens *tokens.Client
44+
Transfers *transfers.Client
45+
WorkFlows *workflows.Client
46+
Reports *reports.Client
47+
Issuing *issuing.Client
48+
Contexts *contexts.Client
49+
PaymentSessions *payment_sessions.Client
4850

4951
Ideal *ideal.Client
5052
Klarna *klarna.Client
@@ -73,6 +75,7 @@ func CheckoutApi(configuration *configuration.Configuration) *Api {
7375
api.Reports = reports.NewClient(configuration, apiClient)
7476
api.Issuing = issuing.NewClient(configuration, apiClient)
7577
api.Contexts = contexts.NewClient(configuration, apiClient)
78+
api.PaymentSessions = payment_sessions.NewClient(configuration, apiClient)
7679

7780
api.Ideal = ideal.NewClient(configuration, apiClient)
7881
api.Klarna = klarna.NewClient(configuration, apiClient)

payments/sessions/client.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package payment_sessions
2+
3+
import (
4+
"github.com/checkout/checkout-sdk-go/client"
5+
"github.com/checkout/checkout-sdk-go/common"
6+
"github.com/checkout/checkout-sdk-go/configuration"
7+
)
8+
9+
type Client struct {
10+
configuration *configuration.Configuration
11+
apiClient client.HttpClient
12+
}
13+
14+
func NewClient(configuration *configuration.Configuration, apiClient client.HttpClient) *Client {
15+
return &Client{
16+
configuration: configuration,
17+
apiClient: apiClient,
18+
}
19+
}
20+
21+
func (c *Client) RequestPaymentSessions(request PaymentSessionsRequest) (*PaymentSessionsResponse, error) {
22+
auth, err := c.configuration.Credentials.GetAuthorization(configuration.SecretKey)
23+
if err != nil {
24+
return nil, err
25+
}
26+
27+
var response PaymentSessionsResponse
28+
err = c.apiClient.Post(common.BuildPath(PaymentSessionsPath), auth, request, &response, nil)
29+
if err != nil {
30+
return nil, err
31+
}
32+
33+
return &response, nil
34+
}

payments/sessions/client_test.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package payment_sessions
2+
3+
import (
4+
"net/http"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/mock"
9+
10+
"github.com/checkout/checkout-sdk-go/common"
11+
"github.com/checkout/checkout-sdk-go/configuration"
12+
"github.com/checkout/checkout-sdk-go/errors"
13+
"github.com/checkout/checkout-sdk-go/mocks"
14+
)
15+
16+
func TestCreateAPaymentSessions(t *testing.T) {
17+
var (
18+
paymentMethods = PaymentMethods{
19+
Type: "card",
20+
CardSchemes: []string{
21+
"Visa",
22+
},
23+
}
24+
paymentSessionsResponse = PaymentSessionsResponse{
25+
HttpMetadata: mocks.HttpMetadataStatusCreated,
26+
Id: "pct_y3oqhf46pyzuxjbcn2giaqnb44",
27+
Amount: 2000,
28+
Locale: "en-GB",
29+
Currency: common.GBP,
30+
Customer: &common.CustomerRequest{
31+
32+
Name: "John Smith",
33+
},
34+
PaymentMethods: []PaymentMethods{
35+
paymentMethods,
36+
},
37+
Links: map[string]common.Link{
38+
"self": {
39+
HRef: &[]string{"https://api.checkout.com/payment-contexts/pct_y3oqhf46pyzuxjbcn2giaqnb44"}[0],
40+
},
41+
},
42+
}
43+
)
44+
45+
cases := []struct {
46+
name string
47+
request PaymentSessionsRequest
48+
getAuthorization func(*mock.Mock) mock.Call
49+
apiPost func(*mock.Mock) mock.Call
50+
checker func(*PaymentSessionsResponse, error)
51+
}{
52+
{
53+
name: "when request is correct then create a payment sessions",
54+
request: PaymentSessionsRequest{
55+
Amount: 2000,
56+
Currency: common.GBP,
57+
Reference: "ORD-123A",
58+
Billing: &Billing{Address: &common.Address{
59+
Country: common.GB,
60+
}},
61+
Customer: &common.CustomerRequest{
62+
63+
Name: "Bruce Wayne",
64+
},
65+
SuccessUrl: "https://example.com/payments/success",
66+
FailureUrl: "https://example.com/payments/failure",
67+
},
68+
getAuthorization: func(m *mock.Mock) mock.Call {
69+
return *m.On("GetAuthorization", mock.Anything).
70+
Return(&configuration.SdkAuthorization{}, nil)
71+
},
72+
apiPost: func(m *mock.Mock) mock.Call {
73+
return *m.On("Post", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
74+
Return(nil).
75+
Run(func(args mock.Arguments) {
76+
respMapping := args.Get(3).(*PaymentSessionsResponse)
77+
*respMapping = paymentSessionsResponse
78+
})
79+
},
80+
checker: func(response *PaymentSessionsResponse, err error) {
81+
assert.Nil(t, err)
82+
assert.NotNil(t, response)
83+
assert.Equal(t, http.StatusCreated, response.HttpMetadata.StatusCode)
84+
},
85+
},
86+
{
87+
name: "when credentials invalid then return error",
88+
getAuthorization: func(m *mock.Mock) mock.Call {
89+
return *m.On("GetAuthorization", mock.Anything).
90+
Return(nil, errors.CheckoutAuthorizationError("Invalid authorization type"))
91+
},
92+
apiPost: func(m *mock.Mock) mock.Call {
93+
return *m.On("Post", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
94+
Return(nil)
95+
},
96+
checker: func(response *PaymentSessionsResponse, err error) {
97+
assert.Nil(t, response)
98+
assert.NotNil(t, err)
99+
chkErr := err.(errors.CheckoutAuthorizationError)
100+
assert.Equal(t, "Invalid authorization type", chkErr.Error())
101+
},
102+
},
103+
{
104+
name: "when request invalid then return error",
105+
request: PaymentSessionsRequest{},
106+
getAuthorization: func(m *mock.Mock) mock.Call {
107+
return *m.On("GetAuthorization", mock.Anything).
108+
Return(&configuration.SdkAuthorization{}, nil)
109+
},
110+
apiPost: func(m *mock.Mock) mock.Call {
111+
return *m.On("Post", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
112+
Return(
113+
errors.CheckoutAPIError{
114+
StatusCode: http.StatusUnprocessableEntity,
115+
Status: "422 Invalid Request",
116+
Data: &errors.ErrorDetails{ErrorType: "request_invalid"},
117+
})
118+
},
119+
checker: func(response *PaymentSessionsResponse, err error) {
120+
assert.Nil(t, response)
121+
assert.NotNil(t, err)
122+
chkErr := err.(errors.CheckoutAPIError)
123+
assert.Equal(t, http.StatusUnprocessableEntity, chkErr.StatusCode)
124+
assert.Equal(t, "request_invalid", chkErr.Data.ErrorType)
125+
},
126+
},
127+
}
128+
129+
for _, tc := range cases {
130+
t.Run(tc.name, func(t *testing.T) {
131+
apiClient := new(mocks.ApiClientMock)
132+
credentials := new(mocks.CredentialsMock)
133+
environment := new(mocks.EnvironmentMock)
134+
135+
tc.getAuthorization(&credentials.Mock)
136+
tc.apiPost(&apiClient.Mock)
137+
138+
configuration := configuration.NewConfiguration(credentials, environment, &http.Client{}, nil)
139+
client := NewClient(configuration, apiClient)
140+
141+
tc.checker(client.RequestPaymentSessions(tc.request))
142+
})
143+
}
144+
}

payments/sessions/sessions.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package payment_sessions
2+
3+
import "github.com/checkout/checkout-sdk-go/common"
4+
5+
const PaymentSessionsPath = "payment-sessions"
6+
7+
type (
8+
Billing struct {
9+
Address *common.Address `json:"address,omitempty"`
10+
}
11+
12+
PaymentSessionsRequest struct {
13+
Amount int64 `json:"amount,omitempty"`
14+
Currency common.Currency `json:"currency,omitempty"`
15+
Reference string `json:"reference,omitempty"`
16+
Billing *Billing `json:"billing,omitempty"`
17+
Customer *common.CustomerRequest `json:"customer,omitempty"`
18+
SuccessUrl string `json:"success_url,omitempty"`
19+
FailureUrl string `json:"failure_url,omitempty"`
20+
}
21+
)
22+
23+
type (
24+
PaymentMethods struct {
25+
Type string `json:"type,omitempty"`
26+
CardSchemes []string `json:"card_schemes,omitempty"`
27+
}
28+
29+
PaymentSessionsResponse struct {
30+
HttpMetadata common.HttpMetadata
31+
Id string `json:"id,omitempty"`
32+
Amount int64 `json:"amount,omitempty"`
33+
Locale string `json:"locale,omitempty"`
34+
Currency common.Currency `json:"currency,omitempty"`
35+
Customer *common.CustomerRequest `json:"customer,omitempty"`
36+
PaymentMethods []PaymentMethods `json:"payment_methods,omitempty"`
37+
Links map[string]common.Link `json:"links,omitempty"`
38+
}
39+
)

test/forex_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
)
1313

1414
func TestRequestQuote(t *testing.T) {
15+
t.Skip("unavailable")
1516
cases := []struct {
1617
name string
1718
request forex.QuoteRequest

test/payment_sessions_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package test
2+
3+
import (
4+
"github.com/checkout/checkout-sdk-go/payments/sessions"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
9+
"github.com/checkout/checkout-sdk-go/common"
10+
)
11+
12+
var (
13+
paymentSessionsRequest = payment_sessions.PaymentSessionsRequest{
14+
Amount: int64(2000),
15+
Currency: common.GBP,
16+
Reference: "ORD-123A",
17+
Billing: &payment_sessions.Billing{Address: Address()},
18+
Customer: &common.CustomerRequest{
19+
20+
Name: "John Smith",
21+
},
22+
SuccessUrl: "https://example.com/payments/success",
23+
FailureUrl: "https://example.com/payments/fail",
24+
}
25+
)
26+
27+
func TestRequestPaymentSessions(t *testing.T) {
28+
cases := []struct {
29+
name string
30+
request payment_sessions.PaymentSessionsRequest
31+
checker func(response *payment_sessions.PaymentSessionsResponse, err error)
32+
}{
33+
{
34+
name: "when payment context is valid the return a response",
35+
request: paymentSessionsRequest,
36+
checker: func(response *payment_sessions.PaymentSessionsResponse, err error) {
37+
assert.Nil(t, err)
38+
assert.NotNil(t, response)
39+
assert.Equal(t, 201, response.HttpMetadata.StatusCode)
40+
assert.NotNil(t, response.Id)
41+
assert.Equal(t, int64(2000), response.Amount)
42+
assert.Equal(t, "en-GB", response.Locale)
43+
assert.Equal(t, common.GBP, response.Currency)
44+
assert.NotNil(t, response.PaymentMethods)
45+
if response.Links != nil {
46+
assert.NotNil(t, response.Links)
47+
}
48+
},
49+
},
50+
}
51+
52+
client := DefaultApi().PaymentSessions
53+
54+
for _, tc := range cases {
55+
t.Run(tc.name, func(t *testing.T) {
56+
tc.checker(client.RequestPaymentSessions(tc.request))
57+
})
58+
}
59+
60+
}

0 commit comments

Comments
 (0)