Class: Pesapal::Merchant
- Inherits:
-
Object
- Object
- Pesapal::Merchant
- Defined in:
- lib/pesapal/merchant.rb
Overview
Pesapal Merchant object responsible for posting and handling transaction queries.
Instance Attribute Summary collapse
-
#config ⇒ Hash
Holds configuration details for the Pesapal object.
-
#order_details ⇒ Hash
Holds the order details for the transaction.
Instance Method Summary collapse
-
#generate_order_url ⇒ String
Generate URL that's used to post a transaction to PesaPal.
-
#initialize(env = :development) ⇒ Merchant
constructor
Creates a new instance of Merchant.
-
#ipn_listener(notification_type, merchant_reference, transaction_tracking_id) ⇒ Hash
Generates the appropriate IPN response depending on the status of the transaction.
-
#query_payment_details(merchant_reference, transaction_tracking_id) ⇒ Hash
Same as #query_payment_status, but additional information is returned in a Hash.
-
#query_payment_status(merchant_reference, transaction_tracking_id = nil) ⇒ String
Query the status of a transaction.
Constructor Details
#initialize(env = :development) ⇒ Merchant
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 ...
# Sets environment to :development explicitly
pesapal = Pesapal::Merchant.new(:development)
# Sets environment to :production
pesapal = Pesapal::Merchant.new(:production)
99 100 101 102 103 104 105 106 |
# 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 |
Instance Attribute Details
#config ⇒ Hash
Holds configuration details for the Pesapal object.
:callback_url
- the page on your site that users will be redirected to, after they have made the payment on PesaPal:consumer_key
- your Pesapal consumer key sent to you via email or obtained from the dashboard:consumer_secret
- your Pesapal consumer secret sent to you via email or obtained from the dashboard
It typically looks like this:
{ :callback_url => 'http://0.0.0.0:3000/pesapal/callback',
:consumer_key => '<YOUR_CONSUMER_KEY>',
:consumer_secret => '<YOUR_CONSUMER_SECRET>'
}
23 24 25 |
# File 'lib/pesapal/merchant.rb', line 23 def config @config end |
#order_details ⇒ Hash
Make sure ALL expected hash attributes are present, the method
assumes they are and no checks are done to certify that this has been
done nor are any fallbacks built in. Also the :amount
should be a
number, no commas, or else Pesapal will convert the comma to a period (.)
which will result in the incorrect amount for the transaction.
Holds the order details for the transaction.
:amount
- the order amount:description
- a note about the order:type
- MERCHANT:reference
- the unique id generated for the transaction by your application before posting the order:first_name
- first name of the customer:last_name
- second name of the customer:email
- email of the customer:phonenumber
- phone number of the customer:currency
- ISO code for the currency
It typically looks like this:
{ :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'
}
61 62 63 |
# File 'lib/pesapal/merchant.rb', line 61 def order_details @order_details end |
Instance Method Details
#generate_order_url ⇒ String
You MUST set up your order details before you call this method on the object.
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:
# generate transaction url after step #1 & #2
order_url = pesapal.generate_order_url
# order_url now contains a string with the order url.
# 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
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# 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 |
#ipn_listener(notification_type, merchant_reference, transaction_tracking_id) ⇒ Hash
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.
Generates the appropriate IPN response depending on the status of the transaction.
# 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
.
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# 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 |
#query_payment_details(merchant_reference, transaction_tracking_id) ⇒ Hash
Same as #query_payment_status, but additional information is returned in a Hash.
Call method on initialized Pesapal::Merchant object (see #initialize for details):
# 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 ofPENDING | 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>"
}
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# 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_payment_status(merchant_reference, transaction_tracking_id = nil) ⇒ String
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.
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.
# 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>")
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# 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 |