lib/pesapal/merchant.rb in pesapal-1.8.0 vs lib/pesapal/merchant.rb in pesapal-2.0.0

- old
+ new

@@ -62,11 +62,11 @@ @order_details ||= {} end private - attr_reader :api_domain, :api_endpoints, :env + attr_reader :env def params @params ||= nil end @@ -85,75 +85,26 @@ # 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 intelligently to 'Rails.env' (if Rails) or :development (if non-Rails) - # pesapal = Pesapal::Merchant.new - # - # # Sets environment to :development + # # Sets environment to :development explicitly # pesapal = Pesapal::Merchant.new(:development) # # # Sets environment to :production # pesapal = Pesapal::Merchant.new(:production) # ``` # - # A few things to note about the constructor as it behaves differently - # depending on the context within which it is called i.e. _Rails_ app vs - # _non-Rails_ app ... - # - # ### Case 1: Rails app - # - # The constructor attempts to set configuration details that should be - # available at runtime from `Rails.application.config.pesapal_credentials`. - # This contains values loaded at application start from a YAML file located - # at `config/pesapal.yml` which typically looks like this: - # - # ```yaml - # development: - # callback_url: 'http://0.0.0.0:3000/pesapal/callback' - # consumer_key: '<YOUR_DEV_CONSUMER_KEY>' - # consumer_secret: '<YOUR_DEV_CONSUMER_SECRET>' - # - # production: - # callback_url: 'http://1.2.3.4:3000/pesapal/callback' - # consumer_key: '<YOUR_PROD_CONSUMER_KEY>' - # consumer_secret: '<YOUR_PROD_CONSUMER_SECRET>' - # ``` - # - # The appropriate credentials are picked and set to {#config} instance - # attribute depending on set environment. The setting of environment is - # explained above. It's worth nothing that if for some reason the YAML file - # could not be read, then it fallbacks to setting {#config} instance - # attribute with default values. The exact definition of default values is - # shown below. - # - # ### Case 2: Non-Rails app - # - # Since (and if) no predefined configuration files are available, the - # constructor sets the {#config} instance attribute up with default values - # as shown below: - # - # ``` - # { :callback_url => 'http://0.0.0.0:3000/pesapal/callback', - # :consumer_key => '<YOUR_CONSUMER_KEY>', - # :consumer_secret => '<YOUR_CONSUMER_SECRET>' - # } - # ``` - # - # @note You can change the environment at runtime using {#change_env} - # # @param env [Symbol] the environment we want to use i.e. `:development` or - # `:production`. Leaving it blank sets environment intelligently to - # `Rails.env` (if Rails) or `:development` (if non-Rails). - def initialize(env = false) - change_env env - if defined?(Rails) - configure Rails.application.config.pesapal_credentials - else - configure - end + # `:production`. + 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 # Generate URL that's used to post a transaction to PesaPal. # # PesaPal will present the user with a page which contains the available @@ -183,21 +134,24 @@ # @return [String] URL of the Pesapal post order form 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', @api_endpoints[:postpesapaldirectorderv4], @params, @config[:consumer_secret], @token_secret) - + @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 - "#{@api_endpoints[:postpesapaldirectorderv4]}?#{query_string}" + "#{postpesapaldirectorderv4_url}?#{query_string}" end # Same as {#query_payment_status}, but additional information is returned in # a Hash. # @@ -235,27 +189,32 @@ # # @return [Hash] transaction payment details 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', @api_endpoints[:querypaymentdetails], @params, @config[:consumer_secret], @token_secret) - + @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 "#{@api_endpoints[:querypaymentdetails]}?#{query_string}" + 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], + { + method: response[1], status: response[2], merchant_reference: response[3], transaction_tracking_id: response[0] } end @@ -288,71 +247,31 @@ # @return [String] the status of the transaction. Possible values include # PENDING | COMPLETED | FAILED | INVALID 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', @api_endpoints[:querypaymentstatus], @params, @config[:consumer_secret], @token_secret) - + @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 "#{@api_endpoints[:querypaymentstatus]}?#{query_string}" + 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 - # Set the environment in use. - # - # Useful especially if you want to change the environment at runtime from - # what was set during initialization in the constructor. It also makes sure - # that we use the appropriate endpoints when making calls to Pesapal. See - # below: - # - # ``` - # # endpoint values set if :development - # { - # :postpesapaldirectorderv4 => "http://demo.pesapal.com/API/PostPesapalDirectOrderV4", - # :querypaymentstatus => "http://demo.pesapal.com/API/QueryPaymentStatus", - # :querypaymentdetails => "http://demo.pesapal.com/API/QueryPaymentDetails" - # } - # - # # endpoint values set if :production - # { - # :postpesapaldirectorderv4 => "https://www.pesapal.com/API/PostPesapalDirectOrderV4", - # :querypaymentstatus => "https://www.pesapal.com/API/QueryPaymentStatus", - # :querypaymentdetails => "https://www.pesapal.com/API/QueryPaymentDetails" - # } - # ``` - # - # @note For a Rails app, you'd expect that calling this would also flip the - # credentials if there was a YAML file containing both environment - # credentials but that's not the case. It could be something that we can - # add later. - # - # @param env [Symbol] the environment we want to use i.e. :development or - # :production - # - # @return [Hash] contains Pesapal endpoints appropriate for the set - # environment - def change_env(env = false) - env = env.to_s.downcase - if env == 'production' - @env = 'production' - else - @env = 'development' - @env = Rails.env if defined?(Rails) - end - assign_endpoints - end - # Generates the appropriate IPN response depending on the status of the # transaction. # # ```ruby # # pass in the notification type, merchant reference and transaction id @@ -391,45 +310,40 @@ 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] = "pesapal_notification_type=#{notification_type}&pesapal_transaction_tracking_id=#{transaction_tracking_id}&pesapal_merchant_reference=#{merchant_reference}" - when 'FAILED' then output[:response] = "pesapal_notification_type=#{notification_type}&pesapal_transaction_tracking_id=#{transaction_tracking_id}&pesapal_merchant_reference=#{merchant_reference}" + when 'COMPLETED' then output[:response] = response + when 'FAILED' then output[:response] = response end output end private - # Assign API endpoints depending on the environment. - def assign_endpoints - if @env == 'production' - @api_domain = 'https://www.pesapal.com' - else - @api_domain = 'https://demo.pesapal.com' - end + def api_domain + @env == 'production' ? 'www.pesapal.com' : 'demo.pesapal.com' + end - @api_endpoints = {} - @api_endpoints[:postpesapaldirectorderv4] = "#{@api_domain}/API/PostPesapalDirectOrderV4" - @api_endpoints[:querypaymentstatus] = "#{@api_domain}/API/QueryPaymentStatus" - @api_endpoints[:querypaymentdetails] = "#{@api_domain}/API/QueryPaymentDetails" + def api_endpoint + 'https://' + api_domain + end - @api_endpoints + def postpesapaldirectorderv4_url + api_endpoint + '/API/PostPesapalDirectOrderV4' end - # Configure credentials through hash that passed in (does a little - # processing to remove unwanted data & uses default if nothing is input). - def configure(consumer_details = {}) - @config = { callback_url: 'http://0.0.0.0:3000/pesapal/callback', - consumer_key: '<YOUR_CONSUMER_KEY>', - consumer_secret: '<YOUR_CONSUMER_SECRET>' - } + def querypaymentstatus_url + api_endpoint + '/API/QueryPaymentStatus' + end - valid_config_keys = @config.keys - - consumer_details.each { |k, v| @config[k.to_sym] = v if valid_config_keys.include? k.to_sym } + def querypaymentdetails_url + api_endpoint + '/API/QueryPaymentDetails' end end end