-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmitake.go
128 lines (112 loc) · 3.3 KB
/
mitake.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
package mitake
import (
"errors"
"fmt"
"io"
"log"
"net/http"
"net/url"
)
const (
libraryVersion = "1.0"
defaultUserAgent = "go-mitake/" + libraryVersion
defaultBaseURL = "https://smexpress.mitake.com.tw:9601/"
defaultLongMessageBaseURL = "https://smexpress.mitake.com.tw:7102/"
)
// NewClient returns a new Mitake API client. The username and password are required
// for authentication. If a nil httpClient is provided, http.DefaultClient will be used.
func NewClient(username, password string, httpClient *http.Client) *Client {
if username == "" || password == "" {
log.Fatal("username or password cannot be empty")
}
if httpClient == nil {
httpClient = http.DefaultClient
}
baseURL, _ := url.Parse(defaultBaseURL)
longMessageBaseURL, _ := url.Parse(defaultLongMessageBaseURL)
return &Client{
client: httpClient,
username: username,
password: password,
UserAgent: defaultUserAgent,
BaseURL: baseURL,
LongMessageBaseURL: longMessageBaseURL,
}
}
// A Client manages communication with the Mitake API.
type Client struct {
client *http.Client
username string
password string
BaseURL *url.URL
LongMessageBaseURL *url.URL
UserAgent string
}
// checkErrorResponse checks the API response for errors.
func checkErrorResponse(r *http.Response) error {
c := r.StatusCode
if 200 <= c && c <= 299 {
if r.ContentLength == 0 {
return errors.New("unexpected empty body")
}
return nil
}
// Mitake API always return status code 200
return fmt.Errorf("unexpected status code: %d", c)
}
// Do sends an API request, and returns the API response.
// If the returned error is nil, the Response will contain a non-nil
// Body which the user is expected to close.
func (c *Client) Do(req *http.Request) (*http.Response, error) {
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
if err := checkErrorResponse(resp); err != nil {
resp.Body.Close()
return resp, err
}
return resp, nil
}
// NewRequest creates an API request. A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash.
func (c *Client) NewRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
rel, err := url.Parse(urlStr)
if err != nil {
return nil, err
}
u := c.BaseURL.ResolveReference(rel)
req, err := http.NewRequest(method, u.String(), body)
if err != nil {
return nil, err
}
if c.UserAgent != "" {
req.Header.Set("User-Agent", c.UserAgent)
}
return req, nil
}
// Get method make a GET HTTP request.
func (c *Client) Get(url string) (*http.Response, error) {
req, err := c.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
return c.Do(req)
}
// Post method make a POST HTTP request.
func (c *Client) Post(url string, bodyType string, body io.Reader) (*http.Response, error) {
req, err := c.NewRequest("POST", url, body)
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", bodyType)
return c.Do(req)
}
// buildDefaultQuery returns the default query string with authentication parameters.
func (c *Client) buildDefaultQuery() url.Values {
q := url.Values{}
q.Set("username", c.username)
q.Set("password", c.password)
return q
}