-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements UK payment initiation client library (#89)
- Loading branch information
skansal-plaid
committed
Jan 17, 2020
1 parent
a540b19
commit d03fb88
Showing
3 changed files
with
342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
package plaid | ||
|
||
import ( | ||
"encoding/json" | ||
"time" | ||
) | ||
|
||
type PaymentRecipientAddress struct { | ||
// Street is an array with length in range [1, 4]. | ||
Street []string `json:"street"` | ||
City string `json:"city"` | ||
PostalCode string `json:"postal_code"` | ||
// Country is an uppercase ISO 3166-1 alpha-2 country code. | ||
Country string `json:"country"` | ||
} | ||
|
||
type createPaymentRecipientRequest struct { | ||
ClientID string `json:"client_id"` | ||
Secret string `json:"secret"` | ||
Name string `json:"name"` | ||
IBAN string `json:"iban"` | ||
Address PaymentRecipientAddress `json:"address"` | ||
} | ||
|
||
type CreatePaymentRecipientResponse struct { | ||
APIResponse | ||
RecipientID string `json:"recipient_id"` | ||
} | ||
|
||
func (c *Client) CreatePaymentRecipient( | ||
name string, | ||
iban string, | ||
address PaymentRecipientAddress, | ||
) (resp CreatePaymentRecipientResponse, err error) { | ||
jsonBody, err := json.Marshal(createPaymentRecipientRequest{ | ||
ClientID: c.clientID, | ||
Secret: c.secret, | ||
Name: name, | ||
IBAN: iban, | ||
Address: address, | ||
}) | ||
|
||
if err != nil { | ||
return resp, err | ||
} | ||
|
||
err = c.Call("/payment_initiation/recipient/create", jsonBody, &resp) | ||
return resp, err | ||
} | ||
|
||
type getPaymentRecipientRequest struct { | ||
ClientID string `json:"client_id"` | ||
Secret string `json:"secret"` | ||
RecipientID string `json:"recipient_id"` | ||
} | ||
|
||
type Recipient struct { | ||
RecipientID string `json:"recipient_id"` | ||
Name string `json:"name"` | ||
IBAN string `json:"iban"` | ||
Address PaymentRecipientAddress `json:"address"` | ||
} | ||
|
||
type GetPaymentRecipientResponse struct { | ||
APIResponse | ||
Recipient | ||
} | ||
|
||
func (c *Client) GetPaymentRecipient(recipientID string) (resp GetPaymentRecipientResponse, err error) { | ||
jsonBody, err := json.Marshal(getPaymentRecipientRequest{ | ||
ClientID: c.clientID, | ||
Secret: c.secret, | ||
RecipientID: recipientID, | ||
}) | ||
|
||
if err != nil { | ||
return resp, err | ||
} | ||
|
||
err = c.Call("/payment_initiation/recipient/get", jsonBody, &resp) | ||
return resp, err | ||
} | ||
|
||
type listPaymentRecipientsRequest struct { | ||
ClientID string `json:"client_id"` | ||
Secret string `json:"secret"` | ||
} | ||
|
||
type ListPaymentRecipientsResponse struct { | ||
APIResponse | ||
Recipients []Recipient `json:"recipients"` | ||
} | ||
|
||
func (c *Client) ListPaymentRecipients() (resp ListPaymentRecipientsResponse, err error) { | ||
jsonBody, err := json.Marshal(listPaymentRecipientsRequest{ | ||
ClientID: c.clientID, | ||
Secret: c.secret, | ||
}) | ||
|
||
if err != nil { | ||
return resp, err | ||
} | ||
|
||
err = c.Call("/payment_initiation/recipient/list", jsonBody, &resp) | ||
return resp, err | ||
} | ||
|
||
type PaymentAmount struct { | ||
Currency string `json:"currency"` | ||
Value float64 `json:"value"` | ||
} | ||
|
||
type createPaymentRequest struct { | ||
ClientID string `json:"client_id"` | ||
Secret string `json:"secret"` | ||
RecipientID string `json:"recipient_id"` | ||
Reference string `json:"reference"` | ||
Amount PaymentAmount `json:"amount"` | ||
} | ||
|
||
type CreatePaymentResponse struct { | ||
APIResponse | ||
PaymentID string `json:"payment_id"` | ||
Status string `json:"status"` | ||
} | ||
|
||
func (c *Client) CreatePayment( | ||
recipientID string, | ||
reference string, | ||
amount PaymentAmount, | ||
) (resp CreatePaymentResponse, err error) { | ||
jsonBody, err := json.Marshal(createPaymentRequest{ | ||
ClientID: c.clientID, | ||
Secret: c.secret, | ||
RecipientID: recipientID, | ||
Reference: reference, | ||
Amount: amount, | ||
}) | ||
if err != nil { | ||
return resp, err | ||
} | ||
|
||
err = c.Call("/payment_initiation/payment/create", jsonBody, &resp) | ||
return resp, err | ||
} | ||
|
||
type createPaymentTokenRequest struct { | ||
ClientID string `json:"client_id"` | ||
Secret string `json:"secret"` | ||
PaymentID string `json:"payment_id"` | ||
} | ||
|
||
type CreatePaymentTokenResponse struct { | ||
APIResponse | ||
PaymentToken string `json:"payment_token"` | ||
PaymentTokenExpirationTime time.Time `json:"payment_token_expiration_time"` | ||
} | ||
|
||
func (c *Client) CreatePaymentToken( | ||
paymentID string, | ||
) (resp CreatePaymentTokenResponse, err error) { | ||
jsonBody, err := json.Marshal(createPaymentTokenRequest{ | ||
ClientID: c.clientID, | ||
Secret: c.secret, | ||
PaymentID: paymentID, | ||
}) | ||
if err != nil { | ||
return resp, err | ||
} | ||
|
||
err = c.Call("/payment_initiation/payment/token/create", jsonBody, &resp) | ||
return resp, err | ||
} | ||
|
||
type getPaymentRequest struct { | ||
ClientID string `json:"client_id"` | ||
Secret string `json:"secret"` | ||
PaymentID string `json:"payment_id"` | ||
} | ||
|
||
type Payment struct { | ||
PaymentID string `json:"payment_id"` | ||
PaymentToken *string `json:"payment_token"` | ||
Reference string `json:"reference"` | ||
Amount PaymentAmount `json:"amount"` | ||
Status string `json:"status"` | ||
LastStatusUpdate time.Time `json:"last_status_update"` | ||
PaymentTokenExpirationTime *time.Time `json:"payment_token_expiration_time"` | ||
RecipientID string `json:"recipient_id"` | ||
} | ||
|
||
type GetPaymentResponse struct { | ||
APIResponse | ||
Payment | ||
} | ||
|
||
func (c *Client) GetPayment(paymentID string) (resp GetPaymentResponse, err error) { | ||
jsonBody, err := json.Marshal(getPaymentRequest{ | ||
ClientID: c.clientID, | ||
Secret: c.secret, | ||
PaymentID: paymentID, | ||
}) | ||
if err != nil { | ||
return resp, err | ||
} | ||
|
||
err = c.Call("/payment_initiation/payment/get", jsonBody, &resp) | ||
return resp, err | ||
} | ||
|
||
type listPaymentsRequest struct { | ||
ClientID string `json:"client_id"` | ||
Secret string `json:"secret"` | ||
Count *int `json:"count"` | ||
Cursor *string `json:"cursor"` | ||
} | ||
|
||
type ListPaymentsResponse struct { | ||
APIResponse | ||
Payments []Payment `json:"payments"` | ||
NextCursor string `json:"next_cursor"` | ||
} | ||
|
||
type ListPaymentsOptions struct { | ||
Count *int | ||
Cursor *string | ||
} | ||
|
||
func (c *Client) ListPayments(options ListPaymentsOptions) (resp ListPaymentsResponse, err error) { | ||
jsonBody, err := json.Marshal(listPaymentsRequest{ | ||
ClientID: c.clientID, | ||
Secret: c.secret, | ||
Count: options.Count, | ||
Cursor: options.Cursor, | ||
}) | ||
|
||
if err != nil { | ||
return resp, err | ||
} | ||
|
||
err = c.Call("/payment_initiation/payment/list", jsonBody, &resp) | ||
return resp, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package plaid | ||
|
||
import ( | ||
"testing" | ||
|
||
assert "github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestPayment(t *testing.T) { | ||
paymentRecipientCreateResp, err := testClient.CreatePaymentRecipient("John Doe", "GB33BUKB20201555555555", PaymentRecipientAddress{ | ||
Street: []string{"Street Name 999"}, | ||
City: "City", | ||
PostalCode: "99999", | ||
Country: "GB", | ||
}) | ||
assert.Nil(t, err) | ||
assert.NotNil(t, paymentRecipientCreateResp.RecipientID) | ||
recipientID := paymentRecipientCreateResp.RecipientID | ||
|
||
paymentRecipientGetResp, err := testClient.GetPaymentRecipient(paymentRecipientCreateResp.RecipientID) | ||
assert.Nil(t, err) | ||
assert.NotNil(t, paymentRecipientGetResp.RecipientID) | ||
assert.NotNil(t, paymentRecipientGetResp.Name) | ||
assert.NotNil(t, paymentRecipientGetResp.IBAN) | ||
assert.NotNil(t, paymentRecipientGetResp.Address) | ||
|
||
paymentRecipientListResp, err := testClient.ListPaymentRecipients() | ||
assert.Nil(t, err) | ||
assert.True(t, len(paymentRecipientListResp.Recipients) > 0) | ||
|
||
paymentCreateResp, err := testClient.CreatePayment(recipientID, "TestPayment", PaymentAmount{ | ||
Currency: "GBP", | ||
Value: 100.0, | ||
}) | ||
assert.Nil(t, err) | ||
assert.NotNil(t, paymentCreateResp.PaymentID) | ||
assert.NotNil(t, paymentCreateResp.Status) | ||
paymentID := paymentCreateResp.PaymentID | ||
|
||
paymentTokenCreateResp, err := testClient.CreatePaymentToken(paymentID) | ||
assert.Nil(t, err) | ||
assert.NotNil(t, paymentTokenCreateResp.PaymentToken) | ||
assert.NotNil(t, paymentTokenCreateResp.PaymentTokenExpirationTime) | ||
|
||
paymentGetResp, err := testClient.GetPayment(paymentCreateResp.PaymentID) | ||
assert.Nil(t, err) | ||
assert.NotNil(t, paymentGetResp.PaymentID) | ||
assert.NotNil(t, paymentGetResp.PaymentToken) | ||
assert.NotNil(t, paymentGetResp.Reference) | ||
assert.NotNil(t, paymentGetResp.Amount) | ||
assert.NotNil(t, paymentGetResp.Status) | ||
assert.NotNil(t, paymentGetResp.LastStatusUpdate) | ||
assert.NotNil(t, paymentGetResp.PaymentTokenExpirationTime) | ||
assert.NotNil(t, paymentGetResp.RecipientID) | ||
|
||
count := 10 | ||
paymentListResp, err := testClient.ListPayments(ListPaymentsOptions{Count: &count}) | ||
assert.Nil(t, err) | ||
assert.True(t, len(paymentListResp.Payments) > 0) | ||
|
||
cursor := paymentListResp.NextCursor | ||
if cursor != "" { | ||
_, err = testClient.ListPayments(ListPaymentsOptions{Cursor: &cursor}) | ||
assert.Nil(t, err) | ||
} | ||
} |