Passed
Push — main ( cad01e...53329a )
by Acho
02:26
created

afrikpay.*Client.do   B

Complexity

Conditions 6

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 14
nop 1
dl 0
loc 23
rs 8.6666
c 0
b 0
f 0
1
package afrikpay
2
3
import (
4
	"bytes"
5
	"context"
6
	"crypto/md5"
7
	"encoding/hex"
8
	"encoding/json"
9
	"fmt"
10
	"io"
11
	"io/ioutil"
12
	"net/http"
13
	"strings"
14
)
15
16
type service struct {
17
	client *Client
18
}
19
20
// Client is the campay API client.
21
// Do not instantiate this client with Client{}. Use the New method instead.
22
type Client struct {
23
	httpClient    *http.Client
24
	common        service
25
	baseURL       string
26
	apiKey        string
27
	agentID       string
28
	agentPlatform string
29
	agentPassword string
30
31
	Airtime *airtimeService
32
	Account *accountService
33
}
34
35
// New creates and returns a new campay.Client from a slice of campay.ClientOption.
36
func New(options ...Option) *Client {
37
	config := defaultClientConfig()
38
39
	for _, option := range options {
40
		option.apply(config)
41
	}
42
43
	client := &Client{
44
		httpClient:    config.httpClient,
45
		baseURL:       config.baseURL,
46
		apiKey:        config.apiKey,
47
		agentID:       config.agentID,
48
		agentPlatform: config.agentPlatform,
49
		agentPassword: config.agentPassword,
50
	}
51
52
	client.common.client = client
53
	client.Airtime = (*airtimeService)(&client.common)
54
	client.Account = (*accountService)(&client.common)
55
	return client
56
}
57
58
// newRequest creates an API request. A relative URL can be provided in uri,
59
// in which case it is resolved relative to the BaseURL of the Client.
60
// URI's should always be specified without a preceding slash.
61
func (client *Client) newRequest(ctx context.Context, method, uri string, body interface{}) (*http.Request, error) {
62
	var buf io.ReadWriter
63
	if body != nil {
64
		buf = &bytes.Buffer{}
65
		enc := json.NewEncoder(buf)
66
		enc.SetEscapeHTML(false)
67
		err := enc.Encode(body)
68
		if err != nil {
69
			return nil, err
70
		}
71
	}
72
73
	req, err := http.NewRequestWithContext(ctx, method, client.baseURL+uri, buf)
74
	if err != nil {
75
		return nil, err
76
	}
77
78
	req.Header.Set("Content-Type", "application/json")
79
	req.Header.Set("Accept", "application/json")
80
81
	return req, nil
82
}
83
84
// do carries out an HTTP request and returns a Response
85
func (client *Client) do(req *http.Request) (*Response, error) {
86
	if req == nil {
87
		return nil, fmt.Errorf("%T cannot be nil", req)
88
	}
89
90
	httpResponse, err := client.httpClient.Do(req)
91
	if err != nil {
92
		return nil, err
93
	}
94
95
	defer func() { _ = httpResponse.Body.Close() }()
96
97
	resp, err := client.newResponse(httpResponse)
98
	if err != nil {
99
		return resp, err
100
	}
101
102
	_, err = io.Copy(ioutil.Discard, httpResponse.Body)
103
	if err != nil {
104
		return resp, err
105
	}
106
107
	return resp, nil
108
}
109
110
// hash does md5 hash of parameters
111
func (client *Client) hash(params ...string) string {
112
	sum := md5.Sum([]byte(strings.Join(params, "")))
113
	return hex.EncodeToString(sum[:])
114
}
115
116
// newResponse converts an *http.Response to *Response
117
func (client *Client) newResponse(httpResponse *http.Response) (*Response, error) {
118
	if httpResponse == nil {
119
		return nil, fmt.Errorf("%T cannot be nil", httpResponse)
120
	}
121
122
	resp := new(Response)
123
	resp.HTTPResponse = httpResponse
124
125
	buf, err := ioutil.ReadAll(resp.HTTPResponse.Body)
126
	if err != nil {
127
		return nil, err
128
	}
129
	resp.Body = &buf
130
131
	return resp, resp.Error()
132
}
133