class Pesapal::Merchant
Pesapal
Merchant
object responsible for posting and handling transaction queries.
Attributes
Public Class Methods
Creates a new instance of {Pesapal::Merchant}.
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. Like so …
“`ruby # Sets environment to :development explicitly pesapal = Pesapal::Merchant.new
(:development)
# Sets environment to :production pesapal = Pesapal::Merchant.new
(:production) “`
@param env [Symbol] the environment we want to use i.e. `:development` or
`:production`.
# File lib/pesapal/merchant.rb, line 99 def initialize(env = :development) @env = env.to_s.downcase @config = { callback_url: 'http://0.0.0.0:3000/pesapal/callback', consumer_key: '<YOUR_CONSUMER_KEY>', consumer_secret: '<YOUR_CONSUMER_SECRET>' } end
Public Instance Methods
Generate URL that's used to post a transaction to PesaPal.
PesaPal will present the user with a page which contains the available payment options and will redirect to your site to the _callback url_ once the user has completed the payment process. A tracking id will be returned as a query parameter - this can be used subsequently to track the payment status on Pesapal
for the transaction later on.
Generating the URL is a 3-step process:
-
Initialize {Pesapal::Merchant}, making sure credentials are set. See {#initialize} for details.
-
Set the order details. See {#order_details} for details.
-
Call {#generate_order_url} on the object.
Example:
“`ruby # generate transaction url after step #1 & #2 order_url = pesapal.generate_order_url
@note You MUST set up your order details before you call this method on the object.
@return [String] URL of the Pesapal
post order form
# File lib/pesapal/merchant.rb, line 135 def generate_order_url # build xml with input data, the format is standard so no editing is # required @post_xml = Pesapal::Helper::Post.generate_post_xml @order_details # initialize setting of @params (oauth_signature left empty) @params = Pesapal::Helper::Post.set_parameters(@config[:callback_url], @config[:consumer_key], @post_xml) # generate oauth signature and add signature to the request parameters @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature( 'GET', postpesapaldirectorderv4_url, @params, @config[:consumer_secret], @token_secret ) # change params (with signature) to a query string query_string = Pesapal::Oauth.generate_encoded_params_query_string @params "#{postpesapaldirectorderv4_url}?#{query_string}" end
Generates the appropriate IPN response depending on the status of the transaction.
“`ruby # 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).
“` {
:status => "<PAYMENT_STATUS>", :response => "<IPN_RESPONSE>"
} “`
_Ps: The response you send to PesaPal must be the same as what you received from PesaPal if successful, which the method generates for you and should be in `:response`._
@note It's up to you to send the response back to Pesapal
by providing the
`:response` back to the IPN. The hard part is done.
@param notification_type [String] the IPN notification type, overridden
and set to CHANGE internally. Left here for extensibility.
@param merchant_reference [String] the unique id generated for the
transaction by your application before posting the order
@param transaction_tracking_id [String] the unique id assigned by Pesapal
to the transaction after it's posted
@return [Hash] contains the status and IPN response that should be sent
back to Pesapal
# File lib/pesapal/merchant.rb, line 310 def ipn_listener(notification_type, merchant_reference, transaction_tracking_id) notification_type = 'CHANGE' status = query_payment_status(merchant_reference, transaction_tracking_id) output = { status: status, response: nil } response = "pesapal_notification_type=#{notification_type}" response += "&pesapal_transaction_tracking_id=#{transaction_tracking_id}" response += "&pesapal_merchant_reference=#{merchant_reference}" case status when 'COMPLETED' then output[:response] = response when 'FAILED' then output[:response] = response end output end
Same as {#query_payment_status}, but additional information is returned in a Hash.
Call method on initialized {Pesapal::Merchant} object (see {#initialize} for details):
“`ruby # pass in merchant reference and transaction id payment_details = pesapal.query_payment_details(“<MERCHANT_REFERENCE>”,“<TRANSACTION_ID>”) “`
Response should contain the following:
-
`:method` - the payment method used by the user to make the payment
-
`:status` - one of `PENDING | COMPLETED | FAILED | INVALID`
-
`:merchant_reference` - this is the same as the parameter you sent when making the query
-
`:transaction_tracking_id` - this is the same as the parameter you sent when making the query
Example:
“` {
:method => "<PAYMENT_METHOD>", :status => "<PAYMENT_STATUS>", :merchant_reference => "<MERCHANT_REFERENCE>", :transaction_tracking_id => "<TRANSACTION_ID>"
} “`
@param merchant_reference [String] the unique id generated for the
transaction by your application before posting the order
@param transaction_tracking_id [String] the unique id assigned by Pesapal
to the transaction after it's posted
@return [Hash] transaction payment details
# File lib/pesapal/merchant.rb, line 191 def query_payment_details(merchant_reference, transaction_tracking_id) # initialize setting of @params (oauth_signature left empty) @params = Pesapal::Helper::Details.set_parameters(@config[:consumer_key], merchant_reference, transaction_tracking_id) # generate oauth signature and add signature to the request parameters @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature( 'GET', querypaymentdetails_url, @params, @config[:consumer_secret], @token_secret ) # change params (with signature) to a query string query_string = Pesapal::Oauth.generate_encoded_params_query_string @params # get status response uri = URI.parse "#{querypaymentdetails_url}?#{query_string}" http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER response = http.request(Net::HTTP::Get.new(uri.request_uri)) response = CGI.parse response.body response = response['pesapal_response_data'][0].split(',') { method: response[1], status: response[2], merchant_reference: response[3], transaction_tracking_id: response[0] } end
Query the status of a transaction.
When a transaction is posted to PesaPal, it may be in a `PENDING`, `COMPLETED` or `FAILED` state. If the transaction is `PENDING`, the payment may complete or fail at a later stage.
“`ruby # option 1: using merchant reference only payment_status = pesapal.query_payment_status(“<MERCHANT_REFERENCE>”)
# option 2: using merchant reference and transaction id (recommended, see note for reason why) payment_status = pesapal.query_payment_status(“<MERCHANT_REFERENCE>”,“<TRANSACTION_ID>”) “`
@note 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.
@param merchant_reference [String] the unique id generated for the
transaction by your application before posting the order
@param transaction_tracking_id [String] the unique id assigned by Pesapal
to the transaction after it's posted
@return [String] the status of the transaction. Possible values include
PENDING | COMPLETED | FAILED | INVALID
# File lib/pesapal/merchant.rb, line 249 def query_payment_status(merchant_reference, transaction_tracking_id = nil) # initialize setting of @params (oauth_signature left empty) @params = Pesapal::Helper::Status.set_parameters(@config[:consumer_key], merchant_reference, transaction_tracking_id) # generate oauth signature and add signature to the request parameters @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature( 'GET', querypaymentstatus_url, @params, @config[:consumer_secret], @token_secret ) # change params (with signature) to a query string query_string = Pesapal::Oauth.generate_encoded_params_query_string @params # get status response uri = URI.parse "#{querypaymentstatus_url}?#{query_string}" http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER response = http.request(Net::HTTP::Get.new(uri.request_uri)) response = CGI.parse response.body response['pesapal_response_data'][0] end
Private Instance Methods
# File lib/pesapal/merchant.rb, line 329 def api_domain @env == 'production' ? 'www.pesapal.com' : 'demo.pesapal.com' end
# File lib/pesapal/merchant.rb, line 333 def api_endpoint 'https://' + api_domain end
# File lib/pesapal/merchant.rb, line 69 def params @params ||= nil end
# File lib/pesapal/merchant.rb, line 73 def post_xml @post_xml ||= nil end
# File lib/pesapal/merchant.rb, line 337 def postpesapaldirectorderv4_url api_endpoint + '/API/PostPesapalDirectOrderV4' end
# File lib/pesapal/merchant.rb, line 345 def querypaymentdetails_url api_endpoint + '/API/QueryPaymentDetails' end
# File lib/pesapal/merchant.rb, line 341 def querypaymentstatus_url api_endpoint + '/API/QueryPaymentStatus' end
# File lib/pesapal/merchant.rb, line 77 def token_secret @token_secret ||= nil end