├── .gitignore
├── .idea
├── vcs.xml
├── modules.xml
├── mpesa-api-go.iml
└── workspace.xml
├── .circleci
└── config.yml
├── demo
└── main.go
├── LICENSE
├── model.go
├── api.go
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/mpesa-api-go.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | # Golang CircleCI 2.0 configuration file
2 | #
3 | # Check https://circleci.com/docs/2.0/language-go/ for more details
4 | version: 2
5 | jobs:
6 | build:
7 | docker:
8 | # specify the version
9 | - image: circleci/golang:1.9
10 |
11 | # Specify service dependencies here if necessary
12 | # CircleCI maintains a library of pre-built images
13 | # documented at https://circleci.com/docs/2.0/circleci-images/
14 | # - image: circleci/postgres:9.4
15 |
16 | #### TEMPLATE_NOTE: go expects specific checkout path representing url
17 | #### expecting it in the form of
18 | #### /go/src/github.com/circleci/go-tool
19 | #### /go/src/bitbucket.org/circleci/go-tool
20 | working_directory: /go/src/github.com/AndroidStudyOpenSource/mpesa-api-go
21 | steps:
22 | - checkout
23 |
24 | # specify any bash command here prefixed with `run: `
25 | - run: go get -v -t -d ./...
26 | - run: go test -v ./...
--------------------------------------------------------------------------------
/demo/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "github.com/AndroidStudyOpenSource/mpesa-api-go"
6 | )
7 |
8 | const (
9 | appKey = "GvzjNnYgNJtwgwfLBkZh65VPwfuKvs0V" // sandbox --> change to yours
10 | appSecret = "oOpJICRVlyrGSAkM" // sandbox --> change to yours
11 | )
12 |
13 | func main() {
14 | // These examples are taken from the mpesa-java-sdk examples
15 | // at https://github.com/safaricom/mpesa-java-sdk
16 |
17 | svc, err := mpesa.New(appKey, appSecret, mpesa.PRODUCTION)
18 | if err != nil {
19 | panic(err)
20 | }
21 |
22 | res, err := svc.B2BRequest(mpesa.B2B{})
23 | if err != nil {
24 | log.Println(err)
25 | }
26 | log.Println(res)
27 |
28 | c2b := mpesa.C2B{
29 | ShortCode: "600576",
30 | CommandID: "CustomerPayBillOnline",
31 | Amount: "2",
32 | Msisdn: "254708374149",
33 | BillRefNumber: "hkjhjkhjkh"}
34 |
35 | res, err = svc.C2BSimulation(c2b)
36 | if err != nil {
37 | log.Println(err)
38 | }
39 | log.Println(res)
40 | }
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Android Study Open Source
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/model.go:
--------------------------------------------------------------------------------
1 | package mpesa
2 |
3 | type authResponse struct {
4 | AccessToken string `json:"access_token"`
5 | }
6 |
7 | // C2B is a model
8 | type C2B struct {
9 | ShortCode string
10 | CommandID string
11 | Amount string
12 | Msisdn string
13 | BillRefNumber string
14 | }
15 |
16 | // B2C is a model
17 | type B2C struct {
18 | InitiatorName string
19 | SecurityCredential string
20 | CommandID string
21 | Amount string
22 | PartyA string
23 | PartyB string
24 | Remarks string
25 | QueueTimeOutURL string
26 | ResultURL string
27 | Occassion string
28 | }
29 |
30 | // B2B is a model
31 | type B2B struct {
32 | Initiator string
33 | SecurityCredential string
34 | CommandID string
35 | SenderIdentifierType string
36 | RecieverIdentifierType string
37 | Amount string
38 | PartyA string
39 | PartyB string
40 | Remarks string
41 | AccountReference string
42 | QueueTimeOutURL string
43 | ResultURL string
44 | }
45 |
46 | // Express is a model
47 | type Express struct {
48 | BusinessShortCode string
49 | Password string
50 | Timestamp string
51 | TransactionType string
52 | Amount string
53 | PartyA string
54 | PartyB string
55 | PhoneNumber string
56 | CallBackURL string
57 | AccountReference string
58 | TransactionDesc string
59 | }
60 |
61 | // Reversal is a model
62 | type Reversal struct {
63 | Initiator string
64 | SecurityCredential string
65 | CommandID string
66 | TransactionID string
67 | Amount string
68 | ReceiverParty string
69 | ReceiverIdentifierType string
70 | QueueTimeOutURL string
71 | ResultURL string
72 | Remarks string
73 | Occassion string
74 | }
75 |
76 | // BalanceInquiry is a model
77 | type BalanceInquiry struct {
78 | Initiator string
79 | SecurityCredential string
80 | CommandID string
81 | PartyA string
82 | IdentifierType string
83 | Remarks string
84 | QueueTimeOutURL string
85 | ResultURL string
86 | }
87 |
88 | // Pull is a model
89 | type Pull struct {
90 | ShortCode string
91 | StartDate string
92 | EndDate string
93 | PageNumber string
94 | }
95 |
96 | // RegisterURL is a model
97 | type C2BRegisterURL struct {
98 | ShortCode string
99 | ResponseType string
100 | ConfirmationURL string
101 | ValidationURL string
102 | }
103 |
--------------------------------------------------------------------------------
/api.go:
--------------------------------------------------------------------------------
1 | package mpesa
2 |
3 | import (
4 | "bytes"
5 | "encoding/base64"
6 | "encoding/json"
7 | "fmt"
8 | "io/ioutil"
9 | "net/http"
10 | "strings"
11 | "time"
12 | )
13 |
14 | // Env is the environment type
15 | type Env string
16 |
17 | const (
18 | // DEV is the development env tag
19 |
20 | // SANDBOX is the sandbox env tag
21 | SANDBOX = iota
22 | // PRODUCTION is the production env tag
23 | PRODUCTION
24 | )
25 |
26 | // Service is an Mpesa Service
27 | type Service struct {
28 | AppKey string
29 | AppSecret string
30 | Env int
31 | }
32 |
33 | // New return a new Mpesa Service
34 | func New(appKey, appSecret string, env int) (Service, error) {
35 | return Service{appKey, appSecret, env}, nil
36 | }
37 |
38 | //Generate Mpesa Daraja Access Token
39 | func (s Service) auth() (string, error) {
40 | b := []byte(s.AppKey + ":" + s.AppSecret)
41 | encoded := base64.StdEncoding.EncodeToString(b)
42 |
43 | url := s.baseURL() + "oauth/v1/generate?grant_type=client_credentials"
44 | req, err := http.NewRequest(http.MethodGet, url, strings.NewReader(encoded))
45 | if err != nil {
46 | return "", err
47 | }
48 | req.Header.Add("authorization", "Basic "+encoded)
49 | req.Header.Add("cache-control", "no-cache")
50 |
51 | client := &http.Client{Timeout: 60 * time.Second}
52 | res, err := client.Do(req)
53 | if res != nil {
54 | defer res.Body.Close()
55 | }
56 | if err != nil {
57 | return "", fmt.Errorf("could not send auth request: %v", err)
58 | }
59 |
60 | var authResponse authResponse
61 | err = json.NewDecoder(res.Body).Decode(&authResponse)
62 | if err != nil {
63 | return "", fmt.Errorf("could not decode auth response: %v", err)
64 | }
65 |
66 | accessToken := authResponse.AccessToken
67 | return accessToken, nil
68 | }
69 |
70 | // Simulation requests user device for payment
71 | func (s Service) Simulation(express Express) (string, error) {
72 | body, err := json.Marshal(express)
73 | if err != nil {
74 | return "", nil
75 | }
76 | auth, err := s.auth()
77 | if err != nil {
78 | return "", nil
79 | }
80 |
81 | headers := make(map[string]string)
82 | headers["content-type"] = "application/json"
83 | headers["authorization"] = "Bearer " + auth
84 | headers["cache-control"] = "no-cache"
85 |
86 | url := s.baseURL() + "mpesa/stkpush/v1/processrequest"
87 | return s.newReq(url, body, headers)
88 | }
89 |
90 | // TransactionStatus gets status of a transaction
91 | func (s Service) TransactionStatus(express Express) (string, error) {
92 | body, err := json.Marshal(express)
93 | if err != nil {
94 | return "", nil
95 | }
96 |
97 | auth, err := s.auth()
98 | if err != nil {
99 | return "", nil
100 | }
101 |
102 | headers := make(map[string]string)
103 | headers["Content-Type"] = "application/json"
104 | headers["Authorization"] = "Bearer " + auth
105 |
106 | url := s.baseURL() + "mpesa/stkpushquery/v1/query"
107 | return s.newReq(url, body, headers)
108 | }
109 |
110 | // C2BRegisterURL requests
111 | func (s Service) C2BRegisterURL(c2bRegisterURL C2BRegisterURL) (string, error) {
112 | body, err := json.Marshal(c2bRegisterURL)
113 | if err != nil {
114 | return "", err
115 | }
116 |
117 | auth, err := s.auth()
118 | if err != nil {
119 | return "", nil
120 | }
121 |
122 | headers := make(map[string]string)
123 | headers["Content-Type"] = "application/json"
124 | headers["Authorization"] = "Bearer " + auth
125 | headers["Cache-Control"] = "no-cache"
126 |
127 | url := s.baseURL() + "mpesa/c2b/v1/registerurl"
128 | return s.newReq(url, body, headers)
129 | }
130 |
131 | // C2BSimulation sends a new request
132 | func (s Service) C2BSimulation(c2b C2B) (string, error) {
133 | body, err := json.Marshal(c2b)
134 | if err != nil {
135 | return "", err
136 | }
137 |
138 | auth, err := s.auth()
139 | if err != nil {
140 | return "", nil
141 | }
142 |
143 | headers := make(map[string]string)
144 | headers["Content-Type"] = "application/json"
145 | headers["Authorization"] = "Bearer " + auth
146 | headers["cache-control"] = "no-cache"
147 |
148 | url := s.baseURL() + "mpesa/c2b/v1/simulate"
149 | return s.newReq(url, body, headers)
150 | }
151 |
152 | // B2CRequest sends a new request
153 | func (s Service) B2CRequest(b2c B2C) (string, error) {
154 | body, err := json.Marshal(b2c)
155 | if err != nil {
156 | return "", err
157 | }
158 |
159 | auth, err := s.auth()
160 | if err != nil {
161 | return "", nil
162 | }
163 |
164 | headers := make(map[string]string)
165 | headers["Content-Type"] = "application/json"
166 | headers["Authorization"] = "Bearer " + auth
167 | headers["cache-control"] = "no-cache"
168 |
169 | url := s.baseURL() + "mpesa/b2c/v1/paymentrequest"
170 | return s.newReq(url, body, headers)
171 | }
172 |
173 | // B2BRequest sends a new request
174 | func (s Service) B2BRequest(b2b B2B) (string, error) {
175 | body, err := json.Marshal(b2b)
176 | if err != nil {
177 | return "", nil
178 | }
179 | auth, err := s.auth()
180 | if err != nil {
181 | return "", nil
182 | }
183 |
184 | headers := make(map[string]string)
185 | headers["Content-Type"] = "application/json"
186 | headers["Authorization"] = "Bearer " + auth
187 | headers["cache-control"] = "no-cache"
188 |
189 | url := s.baseURL() + "mpesa/b2b/v1/paymentrequest"
190 | return s.newReq(url, body, headers)
191 | }
192 |
193 | // Reversal requests a reversal?
194 | func (s Service) Reversal(reversal Reversal) (string, error) {
195 | body, err := json.Marshal(reversal)
196 | if err != nil {
197 | return "", err
198 | }
199 |
200 | auth, err := s.auth()
201 | if err != nil {
202 | return "", nil
203 | }
204 |
205 | headers := make(map[string]string)
206 | headers["Content-Type"] = "application/json"
207 | headers["Authorization"] = "Bearer " + auth
208 | headers["cache-control"] = "no-cache"
209 |
210 | url := s.baseURL() + "safaricom/reversal/v1/request" //TODO :: CONFIRM THIS URL/ENDPOINT???
211 | return s.newReq(url, body, headers)
212 | }
213 |
214 | // BalanceInquiry sends a balance inquiry
215 | func (s Service) BalanceInquiry(balanceInquiry BalanceInquiry) (string, error) {
216 | auth, err := s.auth()
217 | if err != nil {
218 | return "", nil
219 | }
220 |
221 | body, err := json.Marshal(balanceInquiry)
222 | if err != nil {
223 | return "", err
224 | }
225 |
226 | headers := make(map[string]string)
227 | headers["Content-Type"] = "application/json"
228 | headers["Authorization"] = "Bearer " + auth
229 | headers["cache-control"] = "no-cache"
230 | headers["postman-token"] = "2aa448be-7d56-a796-065f-b378ede8b136"
231 |
232 | url := s.baseURL() + "mpesa/accountbalance/v1/query"
233 | return s.newReq(url, body, headers)
234 | }
235 |
236 | // BalanceInquiry sends a balance inquiry
237 | func (s Service) PullTransactions(pull Pull) (string, error) {
238 | auth, err := s.auth()
239 | if err != nil {
240 | return "", nil
241 | }
242 |
243 | body, err := json.Marshal(pull)
244 | if err != nil {
245 | return "", err
246 | }
247 |
248 | headers := make(map[string]string)
249 | headers["Content-Type"] = "application/json"
250 | headers["Authorization"] = "Bearer " + auth
251 | headers["cache-control"] = "no-cache"
252 |
253 | url := s.baseURL() + "pulltransactions/v1/query"
254 | return s.newReq(url, body, headers)
255 | }
256 |
257 | func (s Service) newReq(url string, body []byte, headers map[string]string) (string, error) {
258 | request, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(body))
259 | if err != nil {
260 | return "", nil
261 | }
262 |
263 | for key, value := range headers {
264 | request.Header.Set(key, value)
265 | }
266 |
267 | client := &http.Client{Timeout: 60 * time.Second}
268 | res, err := client.Do(request)
269 | if res != nil {
270 | defer res.Body.Close()
271 | }
272 | if err != nil {
273 | return "", err
274 | }
275 |
276 | stringBody, err := ioutil.ReadAll(res.Body)
277 | if err != nil {
278 | return "", err
279 | }
280 |
281 | return string(stringBody), nil
282 | }
283 |
284 | func (s Service) baseURL() string {
285 | if s.Env == PRODUCTION {
286 | return "https://api.safaricom.co.ke/"
287 | }
288 | return "https://sandbox.safaricom.co.ke/"
289 | }
290 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MPESA Golang API Wrapper [](https://circleci.com/gh/AndroidStudyOpenSource/mpesa-api-go) [](https://codeclimate.com/github/AndroidStudyOpenSource/mpesa-api-go/maintainability) [](https://codeclimate.com/github/AndroidStudyOpenSource/mpesa-api-go/test_coverage)
2 |
3 |
4 | The wrapper provides convenient access to the [Safaricom MPESA Daraja API](https://developer.safaricom.co.ke/apis-explorer) for applications written in server-side Golang. :rocket:
5 |
6 | ## Installing
7 | You can install the package by running:
8 |
9 | ```
10 | go get github.com/AndroidStudyOpenSource/mpesa-api-go
11 | ```
12 |
13 | ## Usage
14 | The package needs to be configured with your **appKey** and **appSecret** which can be obtained from Safaricom.
15 |
16 | ```
17 | const (
18 | appKey = "YOUR_APP_KEY"
19 | appSecret = "YOUR_APP_SECRET"
20 | )
21 | ```
22 |
23 | The following examples with show you how to make requests to the various api's available.
24 |
25 | ### MPESAExpress (Formerly STKPush)
26 | This api allows you to do Lipa Na M-Pesa payment using STK Push. This is a simple example:
27 | ```go
28 | package main
29 |
30 | import (
31 | "log"
32 | "github.com/AndroidStudyOpenSource/mpesa-api-go"
33 | )
34 |
35 | const (
36 | appKey = ""
37 | appSecret = ""
38 | )
39 |
40 | func main() {
41 |
42 | svc, err := mpesa.New(appKey, appSecret, mpesa.SANDBOX)
43 | if err != nil {
44 | panic(err)
45 | }
46 |
47 | res, err := svc.Simulation(mpesa.Express{
48 | BusinessShortCode: "",
49 | Password: "",
50 | Timestamp: "",
51 | TransactionType: "",
52 | Amount: "",
53 | PartyA: "",
54 | PartyB: "",
55 | PhoneNumber: "",
56 | CallBackURL: "",
57 | AccountReference: "",
58 | TransactionDesc: "",
59 | })
60 |
61 | if err != nil {
62 | log.Println(err)
63 | }
64 | log.Println(res)
65 |
66 | }
67 |
68 | ```
69 |
70 | ### C2B
71 | This api allows you to register C2B Callback URLs to Safaricom, and also Simulate a C2B Transaction in ```Sandbox```
72 |
73 | This is a simple demo to show how to register C2B Callback URL:
74 |
75 | ```go
76 | package main
77 |
78 | import (
79 | "log"
80 | "github.com/AndroidStudyOpenSource/mpesa-api-go"
81 | )
82 |
83 | const (
84 | appKey = ""
85 | appSecret = ""
86 | )
87 |
88 | func main() {
89 |
90 | svc, err := mpesa.New(appKey, appSecret, mpesa.SANDBOX)
91 | if err != nil {
92 | panic(err)
93 | }
94 |
95 | res, err := svc.C2BRegisterURL(mpesa.C2BRegisterURL{
96 | ShortCode: "",
97 | ResponseType: "",
98 | ConfirmationURL: "",
99 | ValidationURL: "",
100 | })
101 |
102 | if err != nil {
103 | log.Println(err)
104 | }
105 | log.Println(res)
106 |
107 | }
108 |
109 | ```
110 | To simulate a C2B Request, use this simple example:
111 |
112 | ```go
113 | package main
114 |
115 | import (
116 | "log"
117 | "github.com/AndroidStudyOpenSource/mpesa-api-go"
118 | )
119 |
120 | const (
121 | appKey = ""
122 | appSecret = ""
123 | )
124 |
125 | func main() {
126 |
127 | svc, err := mpesa.New(appKey, appSecret, mpesa.SANDBOX)
128 | if err != nil {
129 | panic(err)
130 | }
131 |
132 | res, err := svc.C2BSimulation(mpesa.C2B{
133 | ShortCode: "",
134 | CommandID: "",
135 | Amount: "",
136 | Msisdn: "",
137 | BillRefNumber: "",
138 | })
139 |
140 | if err != nil {
141 | log.Println(err)
142 | }
143 | log.Println(res)
144 |
145 | }
146 | ```
147 |
148 | ### B2C
149 | This api allows you to do M-Pesa Transaction from company to client.
150 |
151 | ```go
152 | package main
153 |
154 | import (
155 | "log"
156 | "github.com/AndroidStudyOpenSource/mpesa-api-go"
157 | )
158 |
159 | const (
160 | appKey = ""
161 | appSecret = ""
162 | )
163 |
164 | func main() {
165 |
166 | svc, err := mpesa.New(appKey, appSecret, mpesa.SANDBOX)
167 | if err != nil {
168 | panic(err)
169 | }
170 |
171 | res, err := svc.B2CRequest(mpesa.B2C{
172 | InitiatorName: "",
173 | SecurityCredential: "",
174 | CommandID: "",
175 | Amount: "",
176 | PartyA: "",
177 | PartyB: "",
178 | Remarks: "",
179 | QueueTimeOutURL: "",
180 | ResultURL: "",
181 | Occassion: "",
182 | })
183 |
184 | if err != nil {
185 | log.Println(err)
186 | }
187 | log.Println(res)
188 |
189 | }
190 | ```
191 |
192 | ### B2B
193 | This api allows you to do M-Pesa Transaction from one company to another.
194 |
195 | ```go
196 | package main
197 |
198 | import (
199 | "log"
200 | "github.com/AndroidStudyOpenSource/mpesa-api-go"
201 | )
202 |
203 | const (
204 | appKey = ""
205 | appSecret = ""
206 | )
207 |
208 | func main() {
209 |
210 | svc, err := mpesa.New(appKey, appSecret, mpesa.SANDBOX)
211 | if err != nil {
212 | panic(err)
213 | }
214 |
215 | res, err := svc.B2BRequest(mpesa.B2B{
216 | Initiator: "",
217 | SecurityCredential: "",
218 | CommandID: "",
219 | SenderIdentifierType: "",
220 | RecieverIdentifierType: "",
221 | Remarks: "",
222 | Amount: "",
223 | PartyA: "",
224 | PartyB: "",
225 | AccountReference: "",
226 | QueueTimeOutURL: "",
227 | ResultURL: "",
228 | })
229 |
230 | if err != nil {
231 | log.Println(err)
232 | }
233 | log.Println(res)
234 |
235 | }
236 |
237 | ```
238 |
239 | ### Account Balance
240 | This api allows you to do balance inquiry.
241 |
242 | ```go
243 | package main
244 |
245 | import (
246 | "log"
247 | "github.com/AndroidStudyOpenSource/mpesa-api-go"
248 | )
249 |
250 | const (
251 | appKey = ""
252 | appSecret = ""
253 | )
254 |
255 | func main() {
256 |
257 | svc, err := mpesa.New(appKey, appSecret, mpesa.SANDBOX)
258 | if err != nil {
259 | panic(err)
260 | }
261 |
262 | res, err := svc.BalanceInquiry(mpesa.BalanceInquiry{
263 | Initiator: "",
264 | SecurityCredential: "",
265 | CommandID: "",
266 | PartyA: "",
267 | IdentifierType: "",
268 | Remarks: "",
269 | QueueTimeOutURL: "",
270 | ResultURL: "",
271 | })
272 |
273 | if err != nil {
274 | log.Println(err)
275 | }
276 | log.Println(res)
277 |
278 | }
279 | ```
280 |
281 | ### Transaction Status
282 | This api allows you to check the status of transaction.
283 |
284 | ### Reversal
285 | This api allows you to do a transaction reversal
286 |
287 | ```go
288 | package main
289 |
290 | import (
291 | "log"
292 | "github.com/AndroidStudyOpenSource/mpesa-api-go"
293 | )
294 |
295 | const (
296 | appKey = ""
297 | appSecret = ""
298 | )
299 |
300 | func main() {
301 |
302 | svc, err := mpesa.New(appKey, appSecret, mpesa.SANDBOX)
303 | if err != nil {
304 | panic(err)
305 | }
306 |
307 | res, err := svc.Reversal(mpesa.Reversal{
308 | Initiator: "",
309 | SecurityCredential: "",
310 | CommandID: "",
311 | TransactionID: "",
312 | Amount: "",
313 | ReceiverParty: "",
314 | ReceiverIdentifierType: "",
315 | QueueTimeOutURL: "",
316 | ResultURL: "",
317 | Remarks: "",
318 | Occassion: "",
319 | })
320 |
321 | if err != nil {
322 | log.Println(err)
323 | }
324 | log.Println(res)
325 |
326 | }
327 | ```
328 |
329 | ### Contributing
330 |
331 | We’re glad you’re interested in MPESA Daraja Golang SDK, and we’d love to see where you take it. If you would like to contribute code to this project you can do so through GitHub by Forking the Repository and creating a Pull Request.
332 |
333 | When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. We look forward to you submitting a Pull Request.
334 |
335 | Use [gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow).
336 | Always tag releases to `develop` and `master`.
337 |
338 | Thanks, and please do take it for a joyride!
339 |
340 | ### License
341 |
342 | ```text
343 | MIT License
344 |
345 | Copyright (c) 2018 Android Study Open Source
346 |
347 | Permission is hereby granted, free of charge, to any person obtaining a copy
348 | of this software and associated documentation files (the "Software"), to deal
349 | in the Software without restriction, including without limitation the rights
350 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
351 | copies of the Software, and to permit persons to whom the Software is
352 | furnished to do so, subject to the following conditions:
353 |
354 | The above copyright notice and this permission notice shall be included in all
355 | copies or substantial portions of the Software.
356 |
357 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
358 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
359 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
360 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
361 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
362 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
363 | SOFTWARE.
364 | ```
365 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
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 |
91 |
92 |
93 |
94 |
95 | true
96 | DEFINITION_ORDER
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 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
--------------------------------------------------------------------------------