Pesapal Gem

Gem Version

Make authenticated Pesapal API calls without the fuss! Easily post an order, query payment status and fetch payment details.

View the Project on GitHub itskingori/pesapal-gem

Synopsis

Basically it’s a gem that makes it easy to integrate your app with Pesapal’s payment gateway. It Handles all the oAuth stuff abstracting any direct interaction with the API endpoints so that you can focus on what matters. Building awesome.

All this with no 3rd party oAuth library dependencies, it handles all the oAuth flows on its own so your app is one dependency less.

The gem should be up on RubyGems.org, it’s accompanying API reference here, the CHANGELOG here and all the releases here.

Ps: This documentation is based off v2.0.0. For older versions, rely on the version specific documentation. You can find the link on RubyGems.org.

Installation

Add this line to your application’s Gemfile:

gem 'pesapal'

And then execute:

$ bundle

Or install it yourself as:

$ gem install pesapal

Usage

Initialization

Initialize Pesapal object and choose the environment, there are two environments; :development and :production. They determine if the code will interact with the testing or the live Pesapal API.

# Sets environment to :development
pesapal = Pesapal::Merchant.new(:development)

# Sets environment to :production
pesapal = Pesapal::Merchant.new(:production)

Configuration

Use a hash as shown below (please note that Pesapal provides different keys for different environments, make sure you choose the right one).

pesapal.config = {
  callback_url: 'http://0.0.0.0:3000/pesapal/callback',
  consumer_key: '<YOUR_CONSUMER_KEY>',
  consumer_secret: '<YOUR_CONSUMER_SECRET>'
}

Posting An Order

Once you’ve finalized the configuration, set up the order details in a hash as shown in the example below … all keys MUST be present. If there’s one that you wish to ignore just leave it with a blank string but make sure it’s included e.g. the phonenumber.

pesapal.order_details = {
  amount: 1000,
  description: 'this is the transaction description',
  type: 'MERCHANT',
  reference: '808-707-606',
  first_name: 'Swaleh',
  last_name: 'Mdoe',
  email: '[email protected]',
  phonenumber: '+254722222222',
  currency: 'KES'
}

Then generate the transaction url as below. In the example, the value is assigned to the variable order_url which you can pass on to the templating system of your choice to generate an iframe. Please note that this method utilizes all that information set in the previous steps in generating the url so it’s important that it’s the last step in the post order process.

# generate transaction url
order_url = pesapal.generate_order_url

# order_url will a string with the url example;
# http://demo.pesapal.com/API/PostPesapalDirectOrderV4?oauth_callback=http%3A%2F%2F1.2.3.4%3A3000%2Fpesapal%2Fcallback&oauth_consumer_key=A9MXocJiHK1P4w0M%2F%2FYzxgIVMX557Jt4&oauth_nonce=13804335543pDXs4q3djsy&oauth_signature=BMmLR0AVInfoBI9D4C38YDA9eSM%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1380433554&oauth_version=1.0&pesapal_request_data=%26lt%3B%3Fxml%20version%3D%26quot%3B1.0%26quot%3B%20encoding%3D%26quot%3Butf-8%26quot%3B%3F%26gt%3B%26lt%3BPesapalDirectOrderInfo%20xmlns%3Axsi%3D%26quot%3Bhttp%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%26quot%3B%20xmlns%3Axsd%3D%26quot%3Bhttp%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%26quot%3B%20Amount%3D%26quot%3B1000%26quot%3B%20Description%3D%26quot%3Bthis%20is%20the%20transaction%20description%26quot%3B%20Type%3D%26quot%3BMERCHANT%26quot%3B%20Reference%3D%26quot%3B808%26quot%3B%20FirstName%3D%26quot%3BSwaleh%26quot%3B%20LastName%3D%26quot%3BMdoe%26quot%3B%20Email%3D%26quot%3Bj%40kingori.co%26quot%3B%20PhoneNumber%3D%26quot%3B%2B254722222222%26quot%3B%20xmlns%3D%26quot%3Bhttp%3A%2F%2Fwww.pesapal.com%26quot%3B%20%2F%26gt%3B

Ps: Please note the :callback_url value in the pesapal.config hash … after the user successfully posts the order, the response will be sent to this url. Refer to official Pesapal Step-By-Step integration guide for more details.

Querying Payment Status

Use this to query the status of the transaction. When a transaction is posted to Pesapal, it may be in a PENDING, COMPLETED, FAILED or INVALID state. If the transaction is PENDING, the payment may complete or fail at a later stage.

Both the unique merchant reference generated by your system (compulsory) and the pesapal transaction tracking id (optional) are input parameters to this method but if you don’t ensure that the merchant reference is unique for each order on your system, you may get INVALID as the response. Because of this, it is recommended that you provide both the merchant reference and transaction tracking id as parameters to guarantee uniqueness.

# option 1: using merchant reference only
payment_status = pesapal.query_payment_status("<MERCHANT_REFERENCE>")

# option 2: using merchant reference and transaction id (recommended)
payment_status = pesapal.query_payment_status("<MERCHANT_REFERENCE>","<TRANSACTION_ID>")

Querying Payment Details

Same as querying payment status above, but the return value contains more information (and is a hash as opposed to a string).

# pass in merchant reference and transaction id
payment_details = pesapal.query_payment_details("<MERCHANT_REFERENCE>","<TRANSACTION_ID>")

The result is a hash that looks something like this …

{
  method: "<PAYMENT_METHOD>",
  status: "<PAYMENT_STATUS>",
  merchant_reference: "<MERCHANT_REFERENCE>",
  transaction_tracking_id: "<TRANSACTION_ID>"
}

IPN Listening

Use the ipn_listener method to listen to Pesapal IPN calls to easily create an appropriate response, example below.

# pass in the notification type, merchant reference and transaction id
response_to_ipn = pesapal.ipn_listener("<NOTIFICATION_TYPE>", "<MERCHANT_REFERENCE>","<TRANSACTION_ID>")

The variable, response_to_ipn, now holds a response as the one shown below. Using the status you can customise any actions (e.g. database inserts and updates) and finally, it’s up to you to send the :response back to pesapal. The hard part is done for you.

{
  status: "<PAYMENT_STATUS>",
  response: "<IPN_RESPONSE>"
}

Ps: Refer to Pesapal official documentation to make sure you understand what data Pesapal sends to IPN and what result they expect back.

Support & Issues

In case you are having any issues using this gem please do not email me directly, I’d rather you submit new issues (and even requests) here … obviously after checking if the issue has already been raised and closed. This way, other people get to share in the conversation that would have been private and out of their reach.

Contributing

To gem’s code

Submitting a pull request;

  1. Fork the repository.
  2. Create a topic branch (git checkout -b BRANCH_NAME).
  3. Install bundler.
  4. Check that tests pass with rspec spec.
  5. Write a failing test to capture existing bug or lack of feature.
  6. Run rspec spec to verify that test fails.
  7. Implement your feature or bug fix.
  8. Ensure tests pass.
  9. If it’s a new feature or a bug fix, please add an entry to the CHANGELOG file.
  10. Check code style violations using Rubocop.
  11. Add a commit (git commit -am 'AWESOME COMMIT MESSAGE').
  12. Push your changes to the branch (git push origin BRANCH_NAME).
  13. Submit a pull request.
  14. You will get some feedback and may need to push additional commits with more fixes to the same branch; this will update your pull request automatically.

To gem’s documentation

Gem documentation is of two types, feel free to contribute to any;

  1. Gem home page at itskingori.github.io/pesapal-gem (simple step-by-step)
  2. API documetation generated by Yard (very comprehensive)

Gem home page is built on Jekyll, which is a fun and easy to use static site generator and hosted on GitHub Pages. The code is in the docs/ folder if you want to have a peek.

Preview the gem API documentation locally by installing Yard (gem install yard) and call $ yard server to set up a local documentation server usually running on http://0.0.0.0:8808. The result should be similar to the API documention up on rubydoc.info/gems/pesapal.

Ps: If you’ve written code and can’t figure out why they aren’t passing (or if you’ve written your own tests … just send a pull a request. We can then do a code review).

Testing

Tests run RSpec which is a Behaviour-Driven Development tool. To run tests, call;

$ bundle exec rspec spec

References

License

King’ori J. Maina © 2013-2018. The MIT License bundled therein is a permissive license that is short and to the point. It lets people do anything they want as long as they provide attribution and waive liability.