Giter Club home page Giter Club logo

mpesa's Introduction

Mpesa

Mpesa for Mpesa

made-with-Go GitHub go.mod Go version of a Go module GoDoc reference example

Golang bindings for the Mpesa Payment API. Make your MPESA payments Ready... To... Gooo! (pun intended). Made with love for gophers.

Features

  • Customer to Business (C2B) Single Payment
  • Business to Business (B2B)
  • Business to Customer (B2C)
  • Payment Reversal
  • Query Transaction status
  • Query Beneficiary Name
  • Query Direct Debit
  • Direct Debit Create
  • Direct Debit Payment

Pre-requisites

Installation

Simply install with the go get command:

go get github.com/Golang-Tanzania/mpesa

Then import it to your main package as:

package main

import (
	mpesa "github.com/Golang-Tanzania/mpesa
)

Usage

   // NewClient returns new Client struct
   client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24)
   // "your-api-key" obtained at https://openapiportal.m-pesa.com
   // sandbox is environment type can either be mpesa.Sandbox or mpesa.Production
   // 24 represent hours, its session lifetime before we request another session it can be found in the 
   // https://openapiportal.m-pesa.com/applications where you set for your application,



   // use custom htttp client

   c :=  http.Client{
	      Timeout: 50 * time.Second,
	},

   client.SetHttpClient(c)

Examples

Below are examples on how to make different transactions.

Customer To Business

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {

    client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}

	a := mpesa.C2BPaymentRequest{
		Amount:                   "100",
		CustomerMSISDN:           "000000000001",
		Country:                  "TZN",
		Currency:                 "TZS",
		ServiceProviderCode:      "000000",
		TransactionReference:     "T12344C",
		ThirdPartyConversationID: "asv02e5958774f7ba228d83d0d689761",
		PurchasedItemsDesc:       "Test",
	}
	res, err := client.C2BPayment(context.Background(), a)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Business To Customer

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {

	client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}

	c := mpesa.B2CPaymentRequest{
		Amount:                   "100",
		CustomerMSISDN:           "000000000001",
		Country:                  "TZN",
		Currency:                 "TZS",
		ServiceProviderCode:      "000000",
		TransactionReference:     "T12344C",
		ThirdPartyConversationID: "asv02e5958774f7ba228d83d0d689761",
		PaymentItemsDesc:       "Test",
	}

	res, err := client.B2CPayment(context.Background(), c)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)

}

Business To Business

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {

	client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}


	b := mpesa.B2BPaymentRequest{
		Amount:            "100",
		Country:           "TZN",
		Currency:          "TZS",
		PrimaryPartyCode: "000000",
		ReceiverPartyCode: "000001",
		ThirdPartyConversationID: "8a89835c71f15e99396",
		TransactionReference: "T12344C",
		PurchasedItemsDesc: "Test",
	}

	res, err := client.B2BPayment(context.Background(), b)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Payment Reversal

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {

	client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}


	d :=  mpesa.ReversalRequest{
		TransactionID: "0000000000001",
		Country: "TZN",
		ServiceProviderCode: "000000",
		ReversalAmount: "100",
		ThirdPartyConversationID: "asv02e5958774f7ba228d83d0d689761",
	}

	res, err := client.Reversal(context.Background(), d)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Query Transaction status

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {
	
	client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}


	e := mpesa.QueryTxStatusRequest{
		QueryReference:           "000000000000000000001",
		Country:                  "TZN",
		ServiceProviderCode:      "000000",
		ThirdPartyConversationID: "asv02e5958774f7ba228d83d0d689761",
	}

	res, err := client.QueryTxStatus(context.Background(), e)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Query Beneficiary Name

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {
	
	client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}


	h := mpesa.QueryBenRequest{
		Country:                  "TZN",
		ServiceProviderCode:      "000000",
		ThirdPartyConversationID: "AAA6d1f939c1005v2de053v4912jbasdj1j2kk",
		CustomerMSISDN:           "000000000001",
		KycQueryType:             "Name",
	}

	res, err := client.QueryBeneficiaryName(context.Background(), h)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Query Direct Debit

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {
	
	client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}


	i := mpesa.QueryDirectDBReq{
		QueryBalanceAmount:       true,
		BalanceAmount:            "100",
		Country:                  "TZN",
		CustomerMSISDN:           "255744553111",
		MsisdnToken:              "cvgwUBZ3lAO9ivwhWAFeng==",
		ServiceProviderCode:      "112244",
		ThirdPartyConversationID: "GPO3051656128",
		ThirdPartyReference:      "Test123",
		MandateID:                "15045",
		Currency:                 "TZS",
	}

	res, err := client.QueryDirectDebit(context.Background(), i)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Direct Debit Create

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {
	
	client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}


	f := mpesa.DirectDBCreateReq{
		CustomerMSISDN:         "000000000001",
		Country:                "TZN",
		ServiceProviderCode:    "000000",
		ThirdPartyReference:    "3333",
		ThirdPartyConversationID: "asv02e5958774f7ba228d83d0d689761",
		AgreedTC:               "1",
		FirstPaymentDate:       "20160324",
		Frequency:              "06",
		StartRangeOfDays:       "01",
		EndRangeOfDays:         "22",
		ExpiryDate:             "20161126",
	}

	res, err := client.DirectDebitCreate(context.Background(), f)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Direct Debit Payment

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {

	client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}


	g := mpesa.DebitDBPaymentReq{
		MsisdnToken:              "AbCd123=",
		CustomerMSISDN:           "000000000001",
		Country:                  "TZN",
		ServiceProviderCode:      "000000",
		ThirdPartyReference:      "5db410b459bd433ca8e5",
		ThirdPartyConversationID: "AAA6d1f939c1005v2de053v4912jbasdj1j2kk",
		Amount:                   "10",
		Currency:                 "TZS",
		MandateID:                "15045",
	}

	res, err := client.DirectDebitPayment(context.Background(), g)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Cancel Direct Debit

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/Golang-Tanzania/mpesa"
)

func main() {

    client, err := mpesa.NewClient("your-api-key", mpesa.Sandbox, 24) 
	if err != nil {
		panic(err)
	}


	j := mpesa.CancelDirectDBReq{
		MsisdnToken:              "cvgwUBZ3lAO9ivwhWAFeng==",
		CustomerMSISDN:           "000000000001",
		Country:                  "TZN",
		ServiceProviderCode:      "000000",
		ThirdPartyReference:      "00000000000000000001",
		ThirdPartyConversationID: "AAA6d1f939c1005v2de053v4912jbasdj1j2kk",
		MandateID:                "15045",
	}

	res, err := client.CancelDirectDebit(context.Background(), j)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("res", res)
}

Authors

This package is authored and maintained by Hopertz and Mojo. A list of all other contributors can be found here.

Contributing

Contributions are welcome. Please open an issue or submit a pull request.

License

MIT License

Copyright (c) 2023 Golang Tanzania

mpesa's People

Contributors

hopertz avatar avicennajr avatar alphaolomi avatar 1806exe avatar

Stargazers

Steve Muchira avatar Stefan LeBel avatar Astra Boy avatar BAIMAM BOUKAR JEAN JACQUES avatar Dady Nasser 89 avatar Jordan Kalebu avatar Sylvanus Kateile avatar mrisho avatar  avatar Nestory Sylivester avatar Digemi avatar Vicent avatar Simon Machera avatar Davis Tibbz avatar William Mtui Jr avatar Kilala Dashina (KD) avatar Lhusajo Abel avatar Shifu avatar  avatar Onchere Bironga avatar  avatar kisinga avatar Adam Reuben avatar  avatar Eric Muli avatar ABDUL HABIBU KASSIMU avatar Clement Lumumba avatar Brightius Kalokola avatar jack kweyunga avatar  avatar

mpesa's Issues

Very long field names in Structs, refer types.go

mpesa/types.go

Line 80 in 5b6a028

OutputResponseDesc string `json:"output_ResponseDesc"`

I noticed the new structs have "Output..." prefix in each field. I understand the final JSON request body have this, but do we really need this in the struct itself in this go API library ? i think it's too verbose in my opinion. I think the "json.." tag is enough, but the actual struct should be brief.

This applies for both Request and Response structs. as shown here.
So i propose ResponseDesc from OutputResponseDesc

S

Rewrite of the whole package.

Proposal: All public methods should return (result,error): golang style

As i am working on issue #6, i have noticed we simply return string for public methods, and just log the error.

But since this package library may be used as a dependency in OTHER projects, i think it's better let the caller handle the error, and return nil on empty result.

In short, i propose we use the Go convention of returning 2 items: (result , err )

Read config from os ENV variables, not json file

This provides more ways to quickly configure the lib, regardless of environment, either through commandline args, (or through an .env file).

Not just keys, but app Environment setting too (test/prod) should be configured through ENV variables.

Quite useful everywhere: local (natively), Cloud or Docker deployments.

Currently, we are forced to create a JSON file everywhere and hardcode environment type, when we are change environments, whereas with ENV var, can just be passed as CLI args (or, optionally, creating .env file).

We can use package godotenv

Proposal: Allow storing config in os.Env (environment Variables)

Instead of using config.json as it is currently, it would be very useful to be able to store the config values (PRIVATE and PUBLIC keys) from os.GetEnv see official docs, which provides many ways to be able to securely GET config-values as follows:

  1. For example, if used in web application that already uses an existing .env file, the user of this Library can simply append PRIVATE_KEY and PUBLIC_KEY to the .env file. (make sure it is gitignored)

  2. If running from a docker container, a user of this library can simply append --env PRIVATE_KEY=xxxxx, ... to the docker run command

  3. If run from an IDE , a user can simply store the config in the IDE environmental variables settings panel (all major IDE's support this).

  4. If run from the Terminal (when quickly testing), a user can simply pass the config values as Unix shell comands before starting the application.

  5. When run an application from a Cloud Provider, a user can set the env in the Cloud dashboard of host they are using, together with other app secrets.

As you can see, a user can either store the config in a .env file or simply pass as command args to the application.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.