Skip to content

Commit 928c364

Browse files
authored
Golang quickstart support (plaid#66)
* Add basic golang server * Add index.ejs template and serve from go server * Golang support * Add go mod + README * Server is running! * Fix all requests * add to READEME * update go README
1 parent 3eefa91 commit 928c364

File tree

8 files changed

+975
-0
lines changed

8 files changed

+975
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ jspm_packages
3535

3636
# Optional REPL history
3737
.node_repl_history
38+
39+
# go
40+
go/quickstart

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This repository accompanies Plaid's [**quickstart guide**][quickstart].
44

55
Here you'll find full example integration apps using our [**client libraries**][libraries]:
66

7+
- [Go][go-example]
78
- [Node][node-example]
89
- [Ruby][ruby-example]
910
- [Python][python-example]
@@ -17,3 +18,4 @@ Here you'll find full example integration apps using our [**client libraries**][
1718
[ruby-example]: /ruby
1819
[python-example]: /python
1920
[java-example]: /java
21+
[go-example]: /go

go/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
### plaid-go quickstart
2+
3+
[Quickstart guide](https://plaid.com/docs/quickstart)
4+
5+
## Setup
6+
Copy the following commands to install the golang quickstart.
7+
8+
``` bash
9+
git clone https://github.com/plaid/quickstart.git
10+
cd quickstart/go
11+
go build
12+
```
13+
14+
## Run
15+
Copy the following commands, and replace the given environment variables
16+
with your Plaid API keys to run the local-server.
17+
18+
```bash
19+
# Fill in your Plaid API keys (client ID, secret, public_key)
20+
# to test!
21+
APP_PORT=8000 \
22+
PLAID_CLIENT_ID=[CLIENT_ID] \
23+
PLAID_SECRET=[SECRET] \
24+
PLAID_PUBLIC_KEY=[PUBLIC_KEY]
25+
go run server.go
26+
# Go to http://localhost:8000
27+
```

go/go.mod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module github.com/plaid/quickstart
2+
3+
go 1.12
4+
5+
require (
6+
github.com/gin-gonic/gin v1.4.0
7+
github.com/joho/godotenv v1.3.0
8+
github.com/plaid/plaid-go v0.0.0-20190618232219-dafb04dae7bf
9+
)

go/go.sum

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2+
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g=
3+
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
4+
github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=
5+
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
6+
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
7+
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
8+
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
9+
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
10+
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
11+
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
12+
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
13+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
14+
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
15+
github.com/plaid/plaid-go v0.0.0-20190618232219-dafb04dae7bf h1:leSYdIy6gK+o/KAep9C9a93+qQzpCYgBoVyGKT6XMeA=
16+
github.com/plaid/plaid-go v0.0.0-20190618232219-dafb04dae7bf/go.mod h1:c7cDT1Lkcr0AgKJGVIG+oCa07jOrrg4Um8nduQ1eQN0=
17+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
18+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
19+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
20+
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
21+
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
22+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
23+
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
24+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
25+
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
26+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
27+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
28+
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
29+
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
30+
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
31+
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
32+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

go/server.go

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"os"
7+
"time"
8+
9+
"github.com/gin-gonic/gin"
10+
"github.com/plaid/plaid-go/plaid"
11+
)
12+
13+
// Fill with your Plaid API keys - https://dashboard.plaid.com/account/keys
14+
var (
15+
PLAID_CLIENT_ID = os.Getenv("PLAID_CLIENT_ID")
16+
PLAID_SECRET = os.Getenv("PLAID_SECRET")
17+
PLAID_PUBLIC_KEY = os.Getenv("PLAID_PUBLIC_KEY")
18+
// Use 'sandbox' to test with fake credentials in Plaid's Sandbox environment
19+
// Use `development` to test with real credentials while developing
20+
// Use `production` to go live with real users
21+
APP_PORT = os.Getenv("APP_PORT")
22+
)
23+
24+
var clientOptions = plaid.ClientOptions{
25+
PLAID_CLIENT_ID,
26+
PLAID_SECRET,
27+
PLAID_PUBLIC_KEY,
28+
plaid.Sandbox, // Available environments are Sandbox, Development, and Production
29+
&http.Client{},
30+
}
31+
32+
var client, err = plaid.NewClient(clientOptions)
33+
34+
var accessToken string
35+
var itemID string
36+
37+
func getAccessToken(c *gin.Context) {
38+
publicToken := c.PostForm("public_token")
39+
response, err := client.ExchangePublicToken(publicToken)
40+
accessToken = response.AccessToken
41+
itemID = response.ItemID
42+
43+
if err != nil {
44+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
45+
return
46+
}
47+
48+
fmt.Println("public token: " + publicToken)
49+
fmt.Println("access token: " + accessToken)
50+
fmt.Println("item ID: " + itemID)
51+
52+
c.JSON(http.StatusOK, gin.H{
53+
"access_token": accessToken,
54+
"item_id": itemID,
55+
})
56+
}
57+
58+
func auth(c *gin.Context) {
59+
response, err := client.GetAuth(accessToken)
60+
61+
if err != nil {
62+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
63+
return
64+
}
65+
66+
c.JSON(http.StatusOK, gin.H{
67+
"accounts": response.Accounts,
68+
"numbers": response.Numbers,
69+
})
70+
}
71+
72+
func accounts(c *gin.Context) {
73+
response, err := client.GetAccounts(accessToken)
74+
75+
if err != nil {
76+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
77+
return
78+
}
79+
80+
c.JSON(http.StatusOK, gin.H{
81+
"accounts": response.Accounts,
82+
})
83+
}
84+
85+
func balance(c *gin.Context) {
86+
response, err := client.GetBalances(accessToken)
87+
88+
if err != nil {
89+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
90+
return
91+
}
92+
93+
c.JSON(http.StatusOK, gin.H{
94+
"accounts": response.Accounts,
95+
})
96+
}
97+
98+
func item(c *gin.Context) {
99+
response, err := client.GetItem(accessToken)
100+
101+
if err != nil {
102+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
103+
return
104+
}
105+
106+
institution, err := client.GetInstitutionByID(response.Item.InstitutionID)
107+
108+
if err != nil {
109+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
110+
return
111+
}
112+
113+
c.JSON(http.StatusOK, gin.H{
114+
"item": response.Item,
115+
"institution": institution.Institution,
116+
})
117+
}
118+
119+
func identity(c *gin.Context) {
120+
response, err := client.GetIdentity(accessToken)
121+
122+
if err != nil {
123+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
124+
return
125+
}
126+
127+
c.JSON(http.StatusOK, gin.H{
128+
"identity": response.Accounts,
129+
})
130+
}
131+
132+
func transactions(c *gin.Context) {
133+
// pull transactions for the past 30 days
134+
endDate := time.Now().Local().Format("2006-01-02")
135+
startDate := time.Now().Local().Add(-30 * 24 * time.Hour).Format("2006-01-02")
136+
137+
response, err := client.GetTransactions(accessToken, startDate, endDate)
138+
139+
if err != nil {
140+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
141+
return
142+
}
143+
144+
c.JSON(http.StatusOK, gin.H{
145+
"accounts": response.Accounts,
146+
"transactions": response.Transactions,
147+
})
148+
}
149+
150+
func createPublicToken(c *gin.Context) {
151+
// Create a one-time use public_token for the Item.
152+
// This public_token can be used to initialize Link in update mode for a user
153+
publicToken, err := client.CreatePublicToken(accessToken)
154+
if err != nil {
155+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
156+
return
157+
}
158+
159+
c.JSON(http.StatusOK, gin.H{
160+
"public_token": publicToken,
161+
})
162+
}
163+
164+
func main() {
165+
if APP_PORT == "" {
166+
APP_PORT = "8000"
167+
}
168+
169+
r := gin.Default()
170+
r.LoadHTMLFiles("templates/index.tmpl")
171+
r.Static("/static", "./static")
172+
173+
r.GET("/", func(c *gin.Context) {
174+
c.HTML(http.StatusOK, "index.tmpl", gin.H{
175+
"plaid_environment": "sandbox", // Switch this environment
176+
"plaid_public_key": PLAID_PUBLIC_KEY,
177+
})
178+
})
179+
180+
r.POST("/set_access_token", getAccessToken)
181+
r.GET("/auth", auth)
182+
r.GET("/accounts", accounts)
183+
r.GET("/balance", balance)
184+
r.GET("/item", item)
185+
r.POST("/item", item)
186+
r.GET("/identity", identity)
187+
r.GET("/transactions", transactions)
188+
r.POST("/transactions", transactions)
189+
r.GET("/create_public_token", createPublicToken)
190+
191+
r.Run(":" + APP_PORT)
192+
}

0 commit comments

Comments
 (0)