-
Notifications
You must be signed in to change notification settings - Fork 1
/
models.go
248 lines (215 loc) · 6.54 KB
/
models.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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
package mpesa_go
import (
"errors"
"log"
"regexp"
"strconv"
"strings"
"time"
)
type B2CRequestBody struct {
//This is the credential/username used to authenticate the transaction request.
InitiatorName string
///Base64 encoded string of the B2C short code and password,
//which is encrypted using M-Pesa public key and validates the
//transaction on M-Pesa Core system.
SecurityCredential string
//Unique command for each transaction type e.g.
//SalaryPayment, BusinessPayment, PromotionPayment
CommandID string
//The amount being transacted
Amount string
//Organization’s shortcode
//initiating the transaction.
PartyA string
//Phone number receiving the transaction
PartyB string
//Comments that are sent along with the transaction.
Remarks string
//The timeout end-point that receives
//a timeout response.
QueueTimeOutURL string
//The end-point that receives
//the response of the transaction
ResultURL string
//Optional
Occassion string
}
func (s *B2CRequestBody) Validate() error {
if IsEmpty(s.PartyA) {
return errors.New("business short code is required")
}
if IsEmpty(s.Amount) {
return errors.New("amount is required")
}
if IsEmpty(s.PartyB) {
return errors.New("phone number is required")
}
if IsEmpty(s.CommandID) {
return errors.New("command id is required")
}
if IsEmpty(s.InitiatorName) {
return errors.New("initiator name is required")
}
if IsEmpty(s.ResultURL) {
return errors.New("result url is required")
}
if IsEmpty(s.QueueTimeOutURL) {
return errors.New("QueueTimeOutURL is required")
}
if IsEmpty(s.Remarks) {
return errors.New("remark is required")
}
//validate amount
i, err := strconv.Atoi(s.Amount)
if err != nil || i < 1 {
return errors.New("amount should be a string number that is greater than 0")
}
log.Println(s.PartyB)
if !CheckKenyaInternationalPhoneNumber(s.PartyB) {
return errors.New("the phone number should be in the format 254000000000 i.e(254 followed by 9 digits)")
}
return nil
}
type B2CCallBackData struct {
Result Result `json:"Result"`
}
type ResultParameter struct {
Key string `json:"Key"`
Value interface{} `json:"Value"`
}
type ResultParameters struct {
ResultParameter []ResultParameter `json:"ResultParameter"`
}
type Result struct {
ResultType int `json:"ResultType"`
ResultCode int `json:"ResultCode"`
ResultDesc string `json:"ResultDesc"`
OriginatorConversationID string `json:"OriginatorConversationID"`
ConversationID string `json:"ConversationID"`
TransactionID string `json:"TransactionID"`
ResultParameters ResultParameters `json:"ResultParameters"`
}
// MpesaResult is returned by every mpesa api
// Here
// i.e that is when we call Mpesa.sendAndProcessMpesaRequest
type MpesaResult struct {
ConversationID string `json:"ConversationID"`
OriginatorCoversationID string `json:"OriginatorCoversationID"`
/// OriginatorConversationID string `json:"OriginatorConversationID"`
ResponseCode string `json:"ResponseCode"`
ResponseDescription string `json:"ResponseDescription"`
///ResponseDescription string `json:"ResponseDescription"`
}
//Start of Mpesa express models<-----------------------------------------------
// StKPushRequestBody this is the body we will send when sending an
//mpesa express request
type StkRequestFullBody struct {
StKPushRequestBody
Password string
Timestamp string
///use only [ CustomerPayBillOnline ]
TransactionType string
PartyA string
///receiver shortcode
PartyB string
}
type StKPushRequestBody struct {
BusinessShortCode string
Amount string
//sender phone number
//i.e where we will show pop up
//format should be (254 followed by 9 digit)
//note do not include + at the beginning of the phone number
PhoneNumber string
///
CallBackURL string
///use this with paybill
AccountReference string
//
TransactionDesc string
}
func (s *StKPushRequestBody) Validate() error {
if IsEmpty(s.BusinessShortCode) {
return errors.New("business short code is required")
}
if IsEmpty(s.Amount) {
return errors.New("amount is required")
}
if IsEmpty(s.PhoneNumber) {
return errors.New("phone number is required")
}
//validate amount
i, err := strconv.Atoi(s.Amount)
if err != nil || i < 1 {
return errors.New("amount should be a string number that is greater than 0")
}
if !CheckKenyaInternationalPhoneNumber(s.PhoneNumber) {
return errors.New("the phone number should be in the format 254000000000 i.e(254 followed by 9 digits)")
}
return nil
}
// StkPushResult is the result returned
//when you send a Mpesa express result
type StkPushResult struct {
///
CheckoutRequestID string
CustomerMessage string
MerchantRequestID string
ResponseCode string
ResponseDescription string
}
// StkPushQueryRequestBody when querying for success/failure(i.e verification)
type StkPushQueryRequestBody struct {
BusinessShortCode string
Password string
Timestamp string
CheckoutRequestID string
}
// StkPushQueryResponseBody returned when yous send mpesa express verification request
type StkPushQueryResponseBody struct {
MerchantRequestID string
CheckoutRequestID string
ResponseCode string
ResultDesc string
ResponseDescription string
ResultCode string
}
type StkPushCallBackResponseBody struct {
Body Body `json:"Body"`
}
type Body struct {
StkCallback StkCallback `json:"stkCallback"`
}
type StkCallback struct {
MerchantRequestID string `json:"MerchantRequestID"`
CheckoutRequestID string `json:"CheckoutRequestID"`
ResultCode int `json:"ResultCode"`
ResultDesc string `json:"ResultDesc"`
CallbackMetadata CallbackMetadata `json:"CallbackMetadata"`
}
type CallbackMetadata struct {
Item []Item `json:"Item"`
}
type Item struct {
Name string `json:"Name"`
Value interface{} `json:"Value,omitempty"`
}
//End of Mpesa express models<-----------------------------------------------
//Start of Token Model-------------------------------------------
type AccessTokenResponse struct {
AccessToken string `json:"access_token"`
ExpiresIn string `json:"expires_in"`
ExpireTime time.Time `json:"expire_time"`
}
//End of access token<-----------------------------------------------
func IsEmpty(s string) bool {
if len(strings.TrimSpace(s)) == 0 {
return true
}
return false
}
func CheckKenyaInternationalPhoneNumber(phone string) bool {
re := regexp.MustCompile(`(^254)\d{9}$`)
return re.MatchString(phone)
}