Skip to content

Commit

Permalink
Implements UK payment initiation client library (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
skansal-plaid committed Jan 17, 2020
1 parent a540b19 commit d03fb88
Show file tree
Hide file tree
Showing 3 changed files with 342 additions and 0 deletions.
33 changes: 33 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,37 @@ func main() {
handleError(err)
}
fmt.Println("Number of transactions:", len(transactionsResp.Transactions))

// POST /payment_initiation/recipient/create
paymentRecipientCreateResp, err := client.CreatePaymentRecipient("John Doe", "GB33BUKB20201555555555", plaid.PaymentRecipientAddress{
Street: []string{"Street Name 999"},
City: "City",
PostalCode: "99999",
Country: "GB",
})
handleError(err)
fmt.Println("Recipient ID:", paymentRecipientCreateResp.RecipientID)

// POST /payment_initiation/recipient/get
paymentRecipientGetResp, err := client.GetPaymentRecipient(paymentRecipientCreateResp.RecipientID)
handleError(err)
fmt.Println("Recipient get response:", paymentRecipientGetResp)

// POST /payment_initiation/payment/create
paymentCreateResp, err := client.CreatePayment(paymentRecipientCreateResp.RecipientID, "TestPayment", plaid.PaymentAmount{
Currency: "GBP",
Value: 100.0,
})
handleError(err)
fmt.Println("Payment ID:", paymentCreateResp.PaymentID)

// POST /payment_initiation/payment/token/create
paymentTokenCreateResp, err := client.CreatePaymentToken(paymentCreateResp.PaymentID)
handleError(err)
fmt.Println("Payment Token:", paymentTokenCreateResp.PaymentToken)

// POST /payment_initiation/payment/get
paymentGetResp, err := client.GetPayment(paymentCreateResp.PaymentID)
handleError(err)
fmt.Println("Payment get response:", paymentGetResp)
}
243 changes: 243 additions & 0 deletions plaid/payment.go
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
}
66 changes: 66 additions & 0 deletions plaid/payment_test.go
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)
}
}

0 comments on commit d03fb88

Please sign in to comment.