Skip to content

Instantly share code, notes, and snippets.

@itskingori
Last active October 25, 2016 17:41
Show Gist options
  • Save itskingori/51be3c543dcba43a3a77 to your computer and use it in GitHub Desktop.
Save itskingori/51be3c543dcba43a3a77 to your computer and use it in GitHub Desktop.
Controller example on how to use Pesapal gem ...
module Account
module Payments
class PesapalController < ApplicationController
# GET /account/payments/pesapal/new
def new
# Configure transaction details
pesapal = Pesapal::Merchant.new
pesapal.order_details = {
amount: '<AMOUNT>',
description: '<DESCRIPTION>',
type: 'MERCHANT',
reference: '<REFERENCE>',
first_name:'<FIRST_NAME>',
last_name: '<LAST_NAME>',
email: '<EMAIL>',
phonenumber: '<PHONE_NUMBER>',
currency: 'KES_or_USD'
}
# Configure API settings while passing on the data that we need
pesapal.config = {
callback_url: pesapal_callback_account_payments_url,
consumer_key: Rails.application.secrets.pesapal_consumer_key,
consumer_secret: Rails.application.secrets.pesapal_consumer_secret
}
# Generate iframe
@order_url = pesapal.generate_order_url
end
# GET /account/payments/pesapal/callback
def callback
payment = Payment.new(
user: current_user,
reference_no: params.require(:pesapal_merchant_reference),
tracking_no: params.require(:pesapal_transaction_tracking_id),
amount: "amount",
currency_iso_code: "currency.iso_code",
status: 'pending'
)
if payment.save
redirect_to account_payments_url, notice: "Your payment of XXX has been completed but is still pending confirmation."
return
end
redirect_to new_account_payment_url, alert: "Your payment of XXX was not completed successfully."
end
# GET /account/payments/pesapal/ipn
def ipn
# Initialize Pesapal
pesapal = Pesapal::Merchant.new
pesapal.config = {
consumer_key: Rails.application.secrets.pesapal_consumer_key,
consumer_secret: Rails.application.secrets.pesapal_consumer_secret
}
# Get the pesapal transaction identifiers
reference_no = params.require(:pesapal_merchant_reference)
tracking_no = params.require(:pesapal_transaction_tracking_id)
# Make sure we respond to Pesapal and also, depending on the data from
# Pesapal ... apply our business logic appropriately.
respond_to do |format|
# Do nothing if we don't have what we need
if reference_no.blank? || tracking_no.blank?
format.html { render nothing: true }
# ... else apply business login ...
else
# Get hash with response from the `ipn_listener` helper
# method:
#
# {
# status: "<PAYMENT_STATUS>",
# response: "<IPN_RESPONSE>"
# }
ipn_response = pesapal.ipn_listener 'CHANGE', reference_no, tracking_no
# If payment exists in the DB so we proceed with updating it's
# status. INVALID indicates that the transaction with the reference
# you provided could not be found.
payment = ::Payment.find_by reference_no: reference_no, tracking_no: tracking_no
apply_ipn_update payment, ipn_response[:status] if payment
format.html { render text: ipn_response[:response] }
end
end
end
private
# Apply the update to the payment depending on the response
def apply_ipn_update(payment, ipn_status)
case ipn_status
when 'COMPLETED'
# do something
when 'FAILED'
# do something
when 'PENDING'
# do something
when 'INVALID'
# do somethimg
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def payment_params
if params.key? :payment
params[:payment][:reference_no] = params[:pesapal_merchant_reference] unless params[:pesapal_merchant_reference].blank?
params[:payment][:tracking_no] = params[:pesapal_transaction_tracking_id] unless params[:pesapal_transaction_tracking_id].blank?
end
params.require(:payment).permit(:amount, :currency_iso_code, :payable_type, :reference_no, :tracking_no)
end
end
end
end
@Anyoks
Copy link

Anyoks commented Nov 13, 2015

Been looking through merchant.rb for where the error could be, all I have come up with is, the method pesapal_credentials is not defined. Here is the first occurrence (here is where I think the error emanates):
configure Rails.application.config.pesapal_credentials line 151

Other occurrences are in ``railtie.rblines10` and `19`
Could that be the issue?

@itskingori
Copy link
Author

@Anyoks, the gist up there shows you where and how to set pesapal.config, see line 21. :-)

You don't need to require 'pesapal' anywhere. If the gem is added in your Gemfile Rails will load it automatically. Just like other gems. Simple line like ...

# Make authenticated Pesapal API calls without the fuss!
gem 'pesapal'

@ikiugu
Copy link

ikiugu commented Oct 19, 2016

Thanks for this!!
I was lost for a moment after downloading the gem.
I have an issue though. Posting the transaction to pesapal works well but querying the status keeps returning nil.
@payment_status = pesapal.query_payment_status(@reference)
The variable @payment_status returns nil

@ikiugu
Copy link

ikiugu commented Oct 24, 2016

So I finally managed to get my development whole environment working. The issue was this http://developer.pesapal.com/forum/6-announcements/1788-https-protocol-enabled-on-our-sandbox-application. Since the api's now should be handled via HTTPS, the current gem could not work as it is. What made it work was two things (1) changing the url endpoint for development to https and (2) making sure in the query functions to always check ssl.
i.e

http = Net::HTTP.new(uri.host, uri.port)
#if @env == 'production'
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
#end
response = http.request(Net::HTTP::Get.new(uri.request_uri))

@itskingori
Copy link
Author

@Alfred-W I see! I used the sandbox a long time ago so wouldn't have caught that change. All my stuff is in production. Do you mind filing this as an issue? I can update the gem when I get time.

I also think that setting http.verify_mode to OpenSSL::SSL::VERIFY_NONE is a bad idea because we pretty much disregard the SSL certificate! ๐Ÿ™ˆ ... and I don't quite remember why I did this.

@itskingori
Copy link
Author

@Alfred-W Turns out the issue was already raised and someone had filed a PR! ๐Ÿ™ˆ

Pole sana.

@itskingori
Copy link
Author

@Alfred-W Your issue has been fixed in v1.7.0. There's also v1.8.0 which addresses an important security concern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment