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
@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