Skip to content

Commit 892ecea

Browse files
committed
Merge pull request plaid#5 from plaid/cl-updateandbalance
add auth and connect update, /balance, and /upgrade
2 parents 7837a50 + 85bd1df commit 892ecea

6 files changed

Lines changed: 335 additions & 43 deletions

File tree

main.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,18 @@ func main() {
7575
} else {
7676
fmt.Println(postRes.Accounts)
7777
fmt.Println("Auth Get")
78-
fmt.Println(client.AuthGet("test"))
78+
fmt.Println(client.AuthGet("test_citi"))
7979

8080
fmt.Println("Auth DELETE")
81-
fmt.Println(client.AuthDelete("test"))
81+
fmt.Println(client.AuthDelete("test_citi"))
8282
}
8383

8484
// POST /connect
8585
postRes, mfaRes, err =
86-
client.ConnectAddUser("plaid_test", "plaid_good", "", "citi", nil)
86+
// client.ConnectAddUser("plaid_test", "plaid_good", "", "citi", nil)
87+
// client.ConnectUpdate("plaid_selections", "plaid_good", "", "test")
88+
client.AuthUpdate("plaid_test", "plaid_good", "", "test_chase")
89+
// client.ConnectUpdateStep("plaid_test", "plaid_good", "", "tomato", "test")
8790
if err != nil {
8891
fmt.Println(err)
8992
} else if mfaRes != nil {
@@ -109,7 +112,7 @@ func main() {
109112
}
110113
fmt.Println(mfaRes2, postRes2)
111114

112-
postRes2, mfaRes2, err = client.ConnectStep(mfaRes.AccessToken, "tomato")
115+
postRes2, mfaRes2, err = client.ConnectStep(mfaRes.AccessToken, "1234")
113116
if err != nil {
114117
fmt.Println("Error submitting mfa", err)
115118
}
@@ -126,4 +129,21 @@ func main() {
126129
fmt.Println(client.ConnectDelete("test"))
127130
}
128131

132+
// POST /balance
133+
fmt.Println("Balance")
134+
postRes, err = client.Balance("test_citi")
135+
if err != nil {
136+
fmt.Println(err)
137+
}
138+
fmt.Println(postRes)
139+
140+
// POST /upgrade
141+
fmt.Println("Upgrade")
142+
postRes, mfaRes, err = client.Upgrade("test_bofa", "connect", nil)
143+
if err != nil {
144+
fmt.Println(err)
145+
}
146+
fmt.Println(mfaRes)
147+
fmt.Println(postRes)
148+
129149
}

plaid/auth.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,47 @@ func (c client) AuthGet(accessToken string) (postRes *postResponse, err error) {
8080
return postRes, err
8181
}
8282

83+
// PATCH /auth
84+
// Update a users credentials
85+
func (c client) AuthUpdate(username, password, pin, accessToken string) (postRes *postResponse,
86+
mfaRes *mfaResponse, err error) {
87+
88+
jsonText, err := json.Marshal(authUpdateJson{
89+
c.clientID,
90+
c.secret,
91+
username,
92+
password,
93+
pin,
94+
accessToken,
95+
})
96+
if err != nil {
97+
return nil, nil, err
98+
}
99+
return patchAndUnmarshal(c.environment, "/auth",
100+
bytes.NewReader(jsonText))
101+
}
102+
103+
// PATCH /auth/step
104+
// Send MFA for updating a user
105+
func (c client) AuthUpdateStep(username, password, pin, mfa, accessToken string) (postRes *postResponse,
106+
mfaRes *mfaResponse, err error) {
107+
108+
jsonText, err := json.Marshal(authUpdateStepJson{
109+
c.clientID,
110+
c.secret,
111+
username,
112+
password,
113+
pin,
114+
mfa,
115+
accessToken,
116+
})
117+
if err != nil {
118+
return nil, nil, err
119+
}
120+
return patchAndUnmarshal(c.environment, "/auth/step",
121+
bytes.NewReader(jsonText))
122+
}
123+
83124
// DELETE /auth
84125
// Deletes data associated with an access token
85126
func (c client) AuthDelete(accessToken string) (deleteRes *deleteResponse, err error) {
@@ -134,6 +175,27 @@ type authGetJson struct {
134175
AccessToken string `json:"access_token"`
135176
}
136177

178+
type authUpdateJson struct {
179+
ClientID string `json:"client_id"`
180+
Secret string `json:"secret"`
181+
182+
Username string `json:"username"`
183+
Password string `json:"password"`
184+
PIN string `json:"pin,omitempty"`
185+
AccessToken string `json:"access_token"`
186+
}
187+
188+
type authUpdateStepJson struct {
189+
ClientID string `json:"client_id"`
190+
Secret string `json:"secret"`
191+
192+
Username string `json:"username"`
193+
Password string `json:"password"`
194+
PIN string `json:"pin,omitempty"`
195+
MFA string `json:"mfa"`
196+
AccessToken string `json:"access_token"`
197+
}
198+
137199
type authDeleteJson struct {
138200
ClientID string `json:"client_id"`
139201
Secret string `json:"secret"`

plaid/balance.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package plaid
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
)
7+
8+
// POST /balance
9+
// Retrieves real-time balance for an access token
10+
func (c client) Balance(accessToken string) (postRes *postResponse, err error) {
11+
jsonText, err := json.Marshal(balanceJson{
12+
c.clientID,
13+
c.secret,
14+
accessToken,
15+
})
16+
if err != nil {
17+
return nil, err
18+
}
19+
postRes, _, err = postAndUnmarshal(c.environment, "/balance",
20+
bytes.NewReader(jsonText))
21+
return postRes, err
22+
}
23+
24+
type balanceJson struct {
25+
ClientID string `json:"client_id"`
26+
Secret string `json:"secret"`
27+
AccessToken string `json:"access_token"`
28+
}

plaid/connect.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,47 @@ func (c client) ConnectGet(accessToken string, options *ConnectGetOptions) (post
8181
bytes.NewReader(jsonText))
8282
}
8383

84+
// PATCH /connect
85+
// Update a users credentials
86+
func (c client) ConnectUpdate(username, password, pin, accessToken string) (postRes *postResponse,
87+
mfaRes *mfaResponse, err error) {
88+
89+
jsonText, err := json.Marshal(connectUpdateJson{
90+
c.clientID,
91+
c.secret,
92+
username,
93+
password,
94+
pin,
95+
accessToken,
96+
})
97+
if err != nil {
98+
return nil, nil, err
99+
}
100+
return patchAndUnmarshal(c.environment, "/connect",
101+
bytes.NewReader(jsonText))
102+
}
103+
104+
// PATCH /connect/step
105+
// Send MFA for updating a user
106+
func (c client) ConnectUpdateStep(username, password, pin, mfa, accessToken string) (postRes *postResponse,
107+
mfaRes *mfaResponse, err error) {
108+
109+
jsonText, err := json.Marshal(connectUpdateStepJson{
110+
c.clientID,
111+
c.secret,
112+
username,
113+
password,
114+
pin,
115+
mfa,
116+
accessToken,
117+
})
118+
if err != nil {
119+
return nil, nil, err
120+
}
121+
return patchAndUnmarshal(c.environment, "/connect/step",
122+
bytes.NewReader(jsonText))
123+
}
124+
84125
// DELETE /connect
85126
// Deletes data associated with an access token
86127
func (c client) ConnectDelete(accessToken string) (deleteRes *deleteResponse, err error) {
@@ -147,6 +188,27 @@ type connectGetJson struct {
147188
Options *ConnectGetOptions `json:"options,omitempty"`
148189
}
149190

191+
type connectUpdateJson struct {
192+
ClientID string `json:"client_id"`
193+
Secret string `json:"secret"`
194+
195+
Username string `json:"username"`
196+
Password string `json:"password"`
197+
PIN string `json:"pin,omitempty"`
198+
AccessToken string `json:"access_token"`
199+
}
200+
201+
type connectUpdateStepJson struct {
202+
ClientID string `json:"client_id"`
203+
Secret string `json:"secret"`
204+
205+
Username string `json:"username"`
206+
Password string `json:"password"`
207+
PIN string `json:"pin,omitempty"`
208+
MFA string `json:"mfa"`
209+
AccessToken string `json:"access_token"`
210+
}
211+
150212
type connectDeleteJson struct {
151213
ClientID string `json:"client_id"`
152214
Secret string `json:"secret"`

plaid/plaid.go

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -173,20 +173,84 @@ func postAndUnmarshal(environment environmentURL, endpoint string,
173173
}
174174
res.Body.Close()
175175

176+
return unmarshalPostMFA(res, raw)
177+
}
178+
179+
func patchAndUnmarshal(environment environmentURL, endpoint string,
180+
body io.Reader) (*postResponse, *mfaResponse, error) {
181+
182+
httpClient := &http.Client{}
183+
req, err := http.NewRequest("PATCH", string(environment)+endpoint, body)
184+
if err != nil {
185+
return nil, nil, err
186+
}
187+
req.Header.Add("Content-Type", "application/json")
188+
res, err := httpClient.Do(req)
189+
if err != nil {
190+
return nil, nil, err
191+
}
192+
raw, err := ioutil.ReadAll(res.Body)
193+
if err != nil {
194+
return nil, nil, err
195+
}
196+
res.Body.Close()
197+
198+
return unmarshalPostMFA(res, raw)
199+
}
200+
201+
func deleteAndUnmarshal(environment environmentURL, endpoint string,
202+
body io.Reader) (*deleteResponse, error) {
203+
204+
httpClient := &http.Client{}
205+
req, err := http.NewRequest("DELETE", string(environment)+endpoint, body)
206+
if err != nil {
207+
return nil, err
208+
}
209+
req.Header.Add("Content-Type", "application/json")
210+
res, err := httpClient.Do(req)
211+
if err != nil {
212+
return nil, err
213+
}
214+
raw, err := ioutil.ReadAll(res.Body)
215+
if err != nil {
216+
return nil, err
217+
}
218+
res.Body.Close()
219+
220+
// Successful response
221+
var deleteRes deleteResponse
222+
if res.StatusCode == 200 {
223+
if err = json.Unmarshal(raw, &deleteRes); err != nil {
224+
return nil, err
225+
}
226+
return &deleteRes, nil
227+
}
228+
// Attempt to unmarshal into Plaid error format
229+
var plaidErr plaidError
230+
if err = json.Unmarshal(raw, &plaidErr); err != nil {
231+
return nil, err
232+
}
233+
plaidErr.StatusCode = res.StatusCode
234+
return nil, plaidErr
235+
}
236+
237+
// Unmarshals response into postResponse, mfaResponse, or plaidError
238+
func unmarshalPostMFA(res *http.Response, body []byte) (*postResponse, *mfaResponse, error) {
176239
// Different marshaling cases
177240
var mfaInter mfaIntermediate
178241
var postRes postResponse
242+
var err error
179243
switch {
180244
// Successful response
181245
case res.StatusCode == 200:
182-
if err = json.Unmarshal(raw, &postRes); err != nil {
246+
if err = json.Unmarshal(body, &postRes); err != nil {
183247
return nil, nil, err
184248
}
185249
return &postRes, nil, nil
186250

187251
// MFA case
188252
case res.StatusCode == 201:
189-
if err = json.Unmarshal(raw, &mfaInter); err != nil {
253+
if err = json.Unmarshal(body, &mfaInter); err != nil {
190254
return nil, nil, err
191255
}
192256
mfaRes := mfaResponse{Type: mfaInter.Type, AccessToken: mfaInter.AccessToken}
@@ -277,47 +341,11 @@ func postAndUnmarshal(environment environmentURL, endpoint string,
277341
// Error case, attempt to unmarshal into Plaid error format
278342
case res.StatusCode >= 400:
279343
var plaidErr plaidError
280-
if err = json.Unmarshal(raw, &plaidErr); err != nil {
344+
if err = json.Unmarshal(body, &plaidErr); err != nil {
281345
return nil, nil, err
282346
}
283347
plaidErr.StatusCode = res.StatusCode
284348
return nil, nil, plaidErr
285349
}
286350
return nil, nil, errors.New("Unknown Plaid Error - Status:" + string(res.StatusCode))
287351
}
288-
289-
func deleteAndUnmarshal(environment environmentURL, endpoint string,
290-
body io.Reader) (*deleteResponse, error) {
291-
292-
httpClient := &http.Client{}
293-
req, err := http.NewRequest("DELETE", string(environment)+endpoint, body)
294-
if err != nil {
295-
return nil, err
296-
}
297-
req.Header.Add("Content-Type", "application/json")
298-
res, err := httpClient.Do(req)
299-
if err != nil {
300-
return nil, err
301-
}
302-
raw, err := ioutil.ReadAll(res.Body)
303-
if err != nil {
304-
return nil, err
305-
}
306-
res.Body.Close()
307-
308-
// Successful response
309-
var deleteRes deleteResponse
310-
if res.StatusCode == 200 {
311-
if err = json.Unmarshal(raw, &deleteRes); err != nil {
312-
return nil, err
313-
}
314-
return &deleteRes, nil
315-
}
316-
// Attempt to unmarshal into Plaid error format
317-
var plaidErr plaidError
318-
if err = json.Unmarshal(raw, &plaidErr); err != nil {
319-
return nil, err
320-
}
321-
plaidErr.StatusCode = res.StatusCode
322-
return nil, plaidErr
323-
}

0 commit comments

Comments
 (0)