Git Product home page Git Product logo

mtn-pay-js's Introduction

mtn-pay-js Build Status

An unofficial JavaScript/Typescript client package for querying the MTN Mobile Money API

Installation

This is Typescript package that can be used in any of your favorite frameworks like vuejs, react, react-native etc. as long as they use NPM packages.

Install it as usual:

npm install --save mtn-pay

Usage

Please refer to the official MTN Mobile Money Open API docs for more details of how the API works.

According to the docs, MTN Mobile Money API is broken down into four products

Collections
to receive payments for goods and services using MTN Mobile Money
Disbursements
to send money in bulk to different recipients with just one click
Collection Widget
to integrate a checkout button to accept Mobile Money payments on e-commerce sites
Remittances
to transfer or receive funds from the diaspora to Mobile Money recipient's account in local currency

Of the above products, the Collection Widget is accessible manually and requires copy and paste (follow the link for the instructions) as opposed to the others which are accessible programmatically. Each product is subscribed to separately and you get a separate subscription key

The mtn-pay package exposes four entities you can work with:

1. SandboxApiUser

For programmatically generating API USER ID and API USER KEY for sandbox testing.

    import SandboxApiUser from 'mtn-pay/lib/sandboxApiUser';

    const baseURL = "https://ericssonbasicapi2.azure-api.net/v1_0"; // or some other, check the docs
    const subscriptionKey = 'your subscription key for any of the products e.g. "collection" or "disbursement"';
    // check your profile at https://momodeveloper.mtn.com/developer for these keys if you subscribed to any of the products

    const sandboxApiUser = new SandboxApiUser({ baseURL, subscriptionKey });

    // The methods query the API so they should be 'awaited' for in an async function
    const getCredentials = async () => {
        const response: any = await sandboxApiUser.initialize();
        const user: any = await sandboxApiUser.getUser();

        const apiKey = user.apiKey;
        const apiUserId = user.referenceId;
        return { apiKey, apiUserId};
    }

Use the SandboxApiUser to generate an API user ID and API Key when working with the sandbox. You will need these to access any of the other products. Ideally, you will use this entity before the others.

For the production environment, the API user ID and API Key are obtained through the 'Merchant Portal' as referred to in the official API docs

2. Account

For getting the balance and the currency of your merchant account for a given product i.e. 'collection', 'disbursement' or 'remittance'

    import Account, { IAccountConfig, AccountTypes }  from 'mtn-pay/lib/account';

    const accountConfig: IAccountConfig = {
      subscriptionKey: '<Your subscription key for a given product whose account you want to check>',
      targetEnvironment: 'sandbox or production (get this after you go live in your merchant portal)',
      apiuserId: 'your production API User ID or await sandboxApiUser.getUser().referenceId',
      apiKey: 'your production API key or await sandboxApiUser.getUser().apiKey',
      baseURL: 'your API baseURL for the given product',
      authBaseURL:'the baseURL for the /token/ endpoint for the product you subscribed for',
    };

    const getAccountDetails = async (accountType: string, config: IAccountConfig) => {
        const account = new Account(accountType, config);
        return await account.getDetails();
    }
    // AccountTypes {COLLECTION, DISBURSEMENT, REMITTANCE}
    const getCollectionAccountDetails = async () => {
        const details = await getAccountDetails(AccountTypes.COLLECTION, accountConfig);
        const balance = details.balance;
        const currency = details.currency;
    }

3. Transaction

To create a transaction whether it is to request for payment or to disburse money to another person.

    import Transaction, {
        IStatus,
        ITransactionBody,
        ITransactionConfig,
        ITransactionDetails,
        ReceipientTypes,
        ResourceUrls,
        Status,
        TransactionTypes,
        IReceipient
        } from 'mtn-pay/lib/transaction';

        const receipient: IReceipient = {
            partyIdType: 'msisdn',
            partyId: '0770000000' // The phone number of receipient of the request, not your own number
        }

        const TransactionType = TransactionTypes.COLLECTION; 
        // or TransactionTypes.DISBURSEMENT or TransactionTypes.REMITTANCE

        const transactionConfig: ITransactionConfig = {
        amount: 100000, //<money amount to pay or receive>,
        currency: 'UGX', // in sandbox, it is 'EUR'
        externalId: 'your own unique UUID generation 4 Id for easy tracking',
        payeeNote: 'A note for the payee',
        receipient,
        payerMessage: 'A message for the payer',
        subscriptionKey: 'your subscription key for the given product',
        targetEnvironment: 'sandbox or the production one', // for sandbox, put 'sandbox'
        apiuserId: 'Your Api user ID',
        apiKey: 'Your Api  user key',
        timeout: 35000, // the time in milliseconds for polling status to time out; default: 35000
        interval: 31000, // the interval at which status is polled in ms: defaults to 30000; never goes below 30000
        baseURL: 'The baseURL of the API. Get it from the official API docs',
        authBaseURL: 'The baseURL of the /token endpoint for the given product', // Go to API docs
        resourceUrl: resourceUrlsMap[transactionType],
        receipientType: transactionReceipientTypesMap[transactionType],
        };

        const transaction = new Transaction(transactionType, transactionConfig);

        const someAsyncFunction = async() => {
            const details = await transaction.getDetails();
            /*
            * or you could go step by step but why!!!
            * await transaction.initialize();
            * await transaction.pollStatus();
            * const details = await transaction.getDetails();
            */
           const {
               amount,
               currency,
               externalId,
               payee, // or payer if we are requesting for payment i.e. transactionType === 'collection'
               status,
               reason
           } = details;
        }

4. Core

For any future transaction types or if you want to extend the BaseProduct class

    import { BaseProduct, IApiToken } from 'mtn-pay/lib/core';

    export class ChildProduct extends BaseProduct {
        // ...
    }

Advanced Docs

For more details of each class, interface, enum etc, visit the TypeDoc generated docs site

Running Tests

  1. Clone the repo

    git clone https://github.com/sopherapps/mtn-pay-js.git
  2. Enter the directory

    cd mtn-pay-js
  3. Rename the testSetup.example.ts file to testSetup.ts

    mv testSetup.example.ts testSetup.ts
  4. Update the variables in that testSetup.ts file appropriately.

  5. Install dependencies

    npm install
  6. Run npm script for testing

    npm run test

Acknowledgements

This nice post by Carl_Johan Kihl was very helpful when setting up this Typescript project.

License

Copyright (c) 2019 Martin Ahindura Licensed under the MIT License

mtn-pay-js's People

Contributors

tinitto avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

mtn-pay-js's Issues

response status is always 500. server error

This is a great package and nicely written. Though I'm not sure how you're testing this or getting it to work. Momo server seems to enforce title headers yet axiom and most http clients force lowercase header. Therefore each call I've made so far with the exception of getting the access token returns 500 Server Error.

I've verified this behavior with postman. If the headers are anything by titlecase, it returns error 500.
I tested with the collection account balance endpoint.

BTW I didn't make the call for the access token directly as your package does not expose it, I simply printed the response before the call was made.

Can you please let me know if there's a way around it, of if I'm just missing something.
Thanks.

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.