Test Setup Failed
Push — main ( 97f3ea...a413d7 )
by Acho
03:05
created

rvice.ValidateAccountHolderStatus   A

Complexity

Conditions 5

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 17
nop 3
dl 0
loc 26
rs 9.0833
c 0
b 0
f 0
1
package mtnmomo
2
3
import (
4
	"context"
5
	"encoding/json"
6
	"fmt"
7
	"net/http"
8
	"time"
9
)
10
11
// collectionService is the API client for the `/collection` endpoint
12
type collectionService service
13
14
// Token is used to create an access token which can then be used to authorize and authenticate towards the other end-points of the API.
15
//
16
// API Docs: https://momodeveloper.mtn.com/docs/services/collection/operations/token-POST
17
func (service *collectionService) Token(ctx context.Context) (*AuthToken, *Response, error) {
18
	request, err := service.client.newRequest(ctx, http.MethodPost, "/collection/token/", nil)
19
	if err != nil {
20
		return nil, nil, err
21
	}
22
23
	service.client.addBasicAuth(request)
24
25
	response, err := service.client.do(request)
26
	if err != nil {
27
		return nil, response, err
28
	}
29
30
	authToken := new(AuthToken)
31
	if err = json.Unmarshal(*response.Body, authToken); err != nil {
32
		return nil, response, err
33
	}
34
35
	return authToken, response, err
36
}
37
38
// RequestToPay is used to request a payment from a consumer (Payer).
39
//
40
// API Docs: https://momodeveloper.mtn.com/docs/services/collection/operations/requesttopay-POST
41
func (service *collectionService) RequestToPay(
42
	ctx context.Context,
43
	referenceID string,
44
	params *RequestToPayParams,
45
	callbackURL *string,
46
) (*Response, error) {
47
	err := service.refreshToken(ctx)
48
	if err != nil {
49
		return nil, err
50
	}
51
52
	request, err := service.client.newRequest(ctx, http.MethodPost, "/collection/v1_0/requesttopay", params)
53
	if err != nil {
54
		return nil, err
55
	}
56
57
	if callbackURL != nil && len(*callbackURL) != 0 {
58
		service.client.addCallbackURL(request, *callbackURL)
59
	}
60
61
	service.client.addTargetEnvironment(request)
62
	service.client.addReferenceID(request, referenceID)
63
	service.client.addAccessToken(request)
64
65
	response, err := service.client.do(request)
66
	return response, err
67
}
68
69
// GetRequestToPayStatus is used to get the status of a request to pay.
70
//
71
// API Docs: https://momodeveloper.mtn.com/docs/services/collection/operations/requesttopay-referenceId-GET
72
func (service *collectionService) GetRequestToPayStatus(
73
	ctx context.Context,
74
	referenceID string,
75
) (*CollectionTransactionStatus, *Response, error) {
76
	err := service.refreshToken(ctx)
77
	if err != nil {
78
		return nil, nil, err
79
	}
80
81
	request, err := service.client.newRequest(ctx, http.MethodGet, "/collection/v1_0/requesttopay/"+referenceID, nil)
82
	if err != nil {
83
		return nil, nil, err
84
	}
85
86
	service.client.addTargetEnvironment(request)
87
	service.client.addAccessToken(request)
88
89
	response, err := service.client.do(request)
90
	if err != nil {
91
		return nil, response, err
92
	}
93
94
	status := new(CollectionTransactionStatus)
95
	if err = json.Unmarshal(*response.Body, status); err != nil {
96
		return nil, response, err
97
	}
98
99
	status.ReferenceID = referenceID
100
	return status, response, err
101
}
102
103
// GetAccountBalance returns the balance of the account.
104
//
105
// API Docs: https://momodeveloper.mtn.com/docs/services/collection/operations/get-v1_0-account-balance?
106
func (service *collectionService) GetAccountBalance(ctx context.Context) (*AccountBalance, *Response, error) {
107
	err := service.refreshToken(ctx)
108
	if err != nil {
109
		return nil, nil, err
110
	}
111
112
	request, err := service.client.newRequest(ctx, http.MethodGet, "/collection/v1_0/account/balance", nil)
113
	if err != nil {
114
		return nil, nil, err
115
	}
116
117
	service.client.addAccessToken(request)
118
	service.client.addTargetEnvironment(request)
119
120
	response, err := service.client.do(request)
121
	if err != nil {
122
		return nil, response, err
123
	}
124
125
	balance := new(AccountBalance)
126
	if err = json.Unmarshal(*response.Body, balance); err != nil {
127
		return nil, response, err
128
	}
129
130
	return balance, response, err
131
}
132
133
// ValidateAccountHolderStatus is used to check if an account holder is registered and active in the system.
134
//
135
// API Docs: https://momodeveloper.mtn.com/api-details#api=collection&operation=ValidateAccountHolderStatus
136
func (service *collectionService) ValidateAccountHolderStatus(ctx context.Context, IDType AccountHolderIDType, ID string) (*AccountHolderStatus, *Response, error) {
137
	err := service.refreshToken(ctx)
138
	if err != nil {
139
		return nil, nil, err
140
	}
141
142
	uri := fmt.Sprintf("/collection/v1_0/accountholder/%s/%s/active", IDType, ID)
143
	request, err := service.client.newRequest(ctx, http.MethodGet, uri, nil)
144
	if err != nil {
145
		return nil, nil, err
146
	}
147
148
	service.client.addAccessToken(request)
149
	service.client.addTargetEnvironment(request)
150
151
	response, err := service.client.do(request)
152
	if err != nil {
153
		return nil, response, err
154
	}
155
156
	status := new(AccountHolderStatus)
157
	if err = json.Unmarshal(*response.Body, status); err != nil {
158
		return nil, response, err
159
	}
160
161
	return status, response, err
162
}
163
164
// GetBasicUserinfo returns personal information of the account holder.
165
//
166
// API Docs: https://momodeveloper.mtn.com/api-details#api=collection&operation=GetBasicUserinfo
167
func (service *collectionService) GetBasicUserinfo(ctx context.Context, IDType AccountHolderIDType, ID string) (*BasicUserInfo, *Response, error) {
168
	err := service.refreshToken(ctx)
169
	if err != nil {
170
		return nil, nil, err
171
	}
172
173
	uri := fmt.Sprintf("/collection/v1_0/accountholder/%s/%s/basicuserinfo", IDType, ID)
174
	request, err := service.client.newRequest(ctx, http.MethodGet, uri, nil)
175
	if err != nil {
176
		return nil, nil, err
177
	}
178
179
	service.client.addAccessToken(request)
180
	service.client.addTargetEnvironment(request)
181
182
	response, err := service.client.do(request)
183
	if err != nil {
184
		return nil, response, err
185
	}
186
187
	status := new(BasicUserInfo)
188
	if err = json.Unmarshal(*response.Body, status); err != nil {
189
		return nil, response, err
190
	}
191
192
	return status, response, err
193
}
194
195
func (service *collectionService) tokenIsValid() bool {
196
	return time.Now().UTC().Unix() < service.client.accessTokenExpiresAt
197
}
198
199
func (service *collectionService) refreshToken(ctx context.Context) error {
200
	service.client.accessTokenLock.Lock()
201
	defer service.client.accessTokenLock.Unlock()
202
203
	if service.tokenIsValid() {
204
		return nil
205
	}
206
207
	token, _, err := service.Token(ctx)
208
	if err != nil {
209
		return err
210
	}
211
212
	service.client.accessToken = token.AccessToken
213
	service.client.accessTokenExpiresAt = time.Now().UTC().Unix() + token.ExpiresIn - 100
214
215
	return nil
216
}
217