-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathinstallation.go
201 lines (171 loc) · 5.87 KB
/
installation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
package bunq
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"time"
)
type installationResponse struct {
Response []struct {
ID *struct {
ID int `json:"id"`
} `json:"Id,omitempty"`
Token *struct {
ID int `json:"id"`
Created Time `json:"created"`
Updated Time `json:"updated"`
Token string `json:"token"`
} `json:"Token,omitempty"`
ServerPublicKey *struct {
ServerPublicKey string `json:"server_public_key"`
} `json:"ServerPublicKey,omitempty"`
} `json:"Response"`
}
// An InstallationToken is used for authenticating requests to the bunq API.
type InstallationToken struct {
ID int
CreatedAt time.Time
UpdatedAt time.Time
Token string
}
// An Installation represents an installation resource at the bunq API.
type Installation struct {
ID int
Token InstallationToken
ServerPublicKey string
}
// ErrInstallationNotFound is returned when a single Installation resource was
// not found.
var ErrInstallationNotFound = errors.New("installation not found")
// CreateInstallation creates an installation resource at the bunq API.
func (c *Client) CreateInstallation() (*Installation, error) {
publicKey, err := c.publicKey()
if err != nil {
return nil, fmt.Errorf("bunq: could not get public key: %v", err)
}
body := struct {
Field string `json:"client_public_key"`
}{string(publicKey)}
bodyJSON, err := json.Marshal(body)
if err != nil {
return nil, fmt.Errorf("bunq: could not encode request body into JSON: %v", err)
}
endpoint := apiVersion + "/installation"
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%v/%v", c.BaseURL, endpoint), bytes.NewReader(bodyJSON))
if err != nil {
return nil, fmt.Errorf("bunq: could not create new request: %v", err)
}
setCommonHeaders(req)
resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, fmt.Errorf("bunq: could not send HTTP request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("bunq: request was unsuccessful: %v", decodeError(resp.Body))
}
var insResp installationResponse
if err = json.NewDecoder(resp.Body).Decode(&insResp); err != nil {
return nil, fmt.Errorf("bunq: could not decode HTTP response: %v", err)
}
if len(insResp.Response) == 0 {
return nil, errors.New("bunq: api response did not contain results")
}
installation, err := insResp.installation()
if err != nil {
return nil, fmt.Errorf("bunq: could not parse API response: %v", err)
}
return installation, nil
}
// GetInstallation gets an Installation resource at the bunq API.
func (c *Client) GetInstallation(id int) (*Installation, error) {
httpMethod := http.MethodGet
endpoint := apiVersion + "/installation/" + strconv.Itoa(id)
req, err := http.NewRequest(httpMethod, fmt.Sprintf("%v/%v", c.BaseURL, endpoint), nil)
if err != nil {
return nil, fmt.Errorf("bunq: could not create new request: %v", err)
}
setCommonHeaders(req)
req.Header.Set("X-Bunq-Client-Authentication", c.Token)
if err = c.addSignature(req, fmt.Sprintf("%v /%v", httpMethod, endpoint), ""); err != nil {
return nil, fmt.Errorf("bunq: could not add signature: %v", err)
}
resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, fmt.Errorf("bunq: could not send HTTP request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("bunq: request was unsuccessful: %v", decodeError(resp.Body))
}
var insResp installationResponse
if err = json.NewDecoder(resp.Body).Decode(&insResp); err != nil {
return nil, fmt.Errorf("bunq: could not decode HTTP response: %v", err)
}
if len(insResp.Response) == 0 {
return nil, ErrInstallationNotFound
}
installation, err := insResp.installation()
if err != nil {
return nil, fmt.Errorf("bunq: could not parse API response: %v", err)
}
return installation, nil
}
// GetInstallationID gets the installation ID of the Installation used for the
// current session.
func (c *Client) GetInstallationID() (int, error) {
httpMethod := http.MethodGet
endpoint := apiVersion + "/installation"
req, err := http.NewRequest(httpMethod, fmt.Sprintf("%v/%v", c.BaseURL, endpoint), nil)
if err != nil {
return 0, fmt.Errorf("bunq: could not create new request: %v", err)
}
setCommonHeaders(req)
req.Header.Set("X-Bunq-Client-Authentication", c.Token)
if err = c.addSignature(req, fmt.Sprintf("%v /%v", httpMethod, endpoint), ""); err != nil {
return 0, fmt.Errorf("bunq: could not add signature: %v", err)
}
resp, err := c.HTTPClient.Do(req)
if err != nil {
return 0, fmt.Errorf("bunq: could not send HTTP request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return 0, fmt.Errorf("bunq: request was unsuccessful: %v", decodeError(resp.Body))
}
var insResp installationResponse
if err = json.NewDecoder(resp.Body).Decode(&insResp); err != nil {
return 0, fmt.Errorf("bunq: could not decode HTTP response: %v", err)
}
if len(insResp.Response) == 0 {
return 0, ErrInstallationNotFound
}
installation, err := insResp.installation()
if err != nil {
return 0, fmt.Errorf("bunq: could not parse API response: %v", err)
}
return installation.ID, nil
}
func (insResp *installationResponse) installation() (*Installation, error) {
installation := &Installation{}
for i := range insResp.Response {
if insResp.Response[i].ID != nil {
installation.ID = insResp.Response[i].ID.ID
continue
}
if insResp.Response[i].Token != nil {
installation.Token.ID = insResp.Response[i].Token.ID
installation.Token.Token = insResp.Response[i].Token.Token
installation.Token.CreatedAt = time.Time(insResp.Response[i].Token.Created)
installation.Token.UpdatedAt = time.Time(insResp.Response[i].Token.Updated)
continue
}
if insResp.Response[i].ServerPublicKey != nil {
installation.ServerPublicKey = insResp.Response[i].ServerPublicKey.ServerPublicKey
}
}
return installation, nil
}