pesapal 1.5.6 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 066f9356c08b057b12dee36ca4c18ac4ce6e4b2e
4
- data.tar.gz: dd01f73ffa683da11339838be6d73ee1244d6619
3
+ metadata.gz: 8af57eb900f2972e33b0415d47f6dd829bf1e292
4
+ data.tar.gz: 73ea9770d4c51b81fcc92bff9dfaaac46f1779c3
5
5
  SHA512:
6
- metadata.gz: d86aba866c7fe7ee64ca72c6f2a5f865d0d3da2b5f79cad59e71e9da575a09d5e98f7b8f25c3eefc652b71665da1366c66f12ad2f309c49c7992c140f3599324
7
- data.tar.gz: 5a921459134fa6dd99ab76c3d58045e43ad6a20bc8b6d390e6dd17773e422a065701e95e49f5b307afbaf442611d8680a6eb8cc87ef9916db1977495ec48f01b
6
+ metadata.gz: 5594d62643eec3357558ea3f133735be428c682e58e9f3040aaa2196e5aa758999b62e124e9956af5f0b42c96b681fbf0fc71b79077db24a49f222dacd5abe2a
7
+ data.tar.gz: dfe9baaca9c4488dcaa6e4744975e65937ebc013152033fca9912059e8dbbdca7ccfd038ea7acbf81116a3defbe93dc5ca35391471964b8f4a0c1c50a2923b5f
@@ -0,0 +1,3 @@
1
+ ruby:
2
+ enabled: true
3
+ config_file: .rubocop.yml
@@ -0,0 +1,15 @@
1
+ AllCops:
2
+ Include:
3
+ - '**/*.gemspec'
4
+ - '**/Gemfile'
5
+ - '**/Rakefile'
6
+ Exclude:
7
+ - 'vendor/**/*'
8
+ Metrics/LineLength:
9
+ Enabled: false
10
+ Metrics/ClassLength:
11
+ CountComments: false
12
+ Max: 150
13
+ Metrics/MethodLength:
14
+ CountComments: false
15
+ Max: 20
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.1.2
4
+ - 2.1.1
3
5
  - 2.1.0
4
6
  - 2.0.0
5
7
  - 1.9.3
6
- - 1.9.2
7
8
  script: bundle exec rspec spec
@@ -1,6 +1,15 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ v1.6.0
5
+ ------
6
+
7
+ * Enforce minimum required Ruby version, gem is tested for Ruby '>= 1.9.3'
8
+ * Add Rubocop as a development dependency and Hound to the workflow since we will use them to detect style guide violations
9
+ * Code cleanup here and there
10
+ * Avoid using set_ on method name, this changes the API slightly since we can't use set_env which was public
11
+
12
+
4
13
  v1.5.6
5
14
  ------
6
15
 
@@ -0,0 +1,29 @@
1
+ CONTRIBUTING
2
+ ============
3
+
4
+ Submitting a Pull Request
5
+ -------------------------
6
+
7
+ 1. [Fork the repository][fork].
8
+ 2. [Create a topic branch][branch] (`git checkout -b BRANCH_NAME`).
9
+ 3. [Install bundler][bundler].
10
+ 4. Check that tests pass with `rspec spec`.
11
+ 5. Write a failing test to capture existing bug or lack of feature.
12
+ 6. Run `rspec spec` to verify that test fails.
13
+ 7. Implement your feature or bug fix.
14
+ 8. Ensure tests pass.
15
+ 9. If it's a new feature or a bug fix, please add an entry to the CHANGELOG file.
16
+ 10. Check code style violations using [Rubocop][rubocop].
17
+ 11. Add a commit (`git commit -am 'AWESOME COMMIT MESSAGE'`).
18
+ 12. Push your changes to the branch (`git push origin BRANCH_NAME`).
19
+ 13. [Submit a pull request.][pr]
20
+ 14. You will get some feedback and may need to push additional commits
21
+ with more fixes to the same branch; this will update your pull request
22
+ automatically.
23
+
24
+ [branch]: http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches
25
+ [bundler]: http://bundler.io
26
+ [fork]: https://help.github.com/articles/fork-a-repo/
27
+ [pr]: https://help.github.com/articles/using-pull-requests
28
+ [rubocop]: https://github.com/bbatsov/rubocop
29
+
@@ -1,19 +1,20 @@
1
+ # Since generators are not specific to this project, it's preferable you refer
2
+ # to the official documentation on the Rails site here;
3
+ # http://guides.rubyonrails.org/generators.html
1
4
  module Pesapal
2
- # Since generators are not specific to this project, it's preferable you refer
3
- # to the official documentation on the Rails site here;
4
- # http://guides.rubyonrails.org/generators.html
5
5
  module Generators
6
+ # Install pesapal generator
6
7
  class InstallGenerator < Rails::Generators::Base
7
- source_root File.expand_path("../../templates", __FILE__)
8
+ source_root File.expand_path('../../templates', __FILE__)
8
9
 
9
- desc "Creates a Pesapal config file to your application."
10
+ desc 'Creates a Pesapal config file to your application.'
10
11
 
11
12
  def copy_config
12
- copy_file "pesapal.yml", "config/pesapal.yml"
13
+ copy_file 'pesapal.yml', 'config/pesapal.yml'
13
14
  end
14
15
 
15
16
  def show_readme
16
- readme "README.md" if behavior == :invoke
17
+ readme 'README.md' if behavior == :invoke
17
18
  end
18
19
  end
19
20
  end
@@ -9,4 +9,3 @@ require 'pesapal/oauth'
9
9
  require 'pesapal/version'
10
10
 
11
11
  require 'pesapal/railtie' if defined?(Rails)
12
-
@@ -4,9 +4,11 @@ module Pesapal
4
4
  # Contains helper methods relating to any queries for payment details. See
5
5
  # {Pesapal::Merchant#query_payment_details} source.
6
6
  module Details
7
- # Prepares parameters to be used during the QueryPaymentDetails oAuth 1.0 call.
7
+ # Prepares parameters to be used during the QueryPaymentDetails oAuth 1.0
8
+ # call.
8
9
  #
9
- # The QueryPaymentDetails oAuth 1.0 call requires the following parameters;
10
+ # The QueryPaymentDetails oAuth 1.0 call requires the following
11
+ # parameters;
10
12
  #
11
13
  # 1. `oauth_consumer_key` - your Pesapal consumer key sent to you via email or obtained from the dashboard
12
14
  # 2. `oauth_nonce` - a random string, uniquely generated for each request. See [section 8 of the oAuth 1.0 spec][3]
@@ -17,10 +19,11 @@ module Pesapal
17
19
  # 7. `pesapal_merchant_reference` - the transaction merchant reference (same as `merchant_reference` defined below)
18
20
  # 8. `pesapal_transaction_tracking_id` - the transaction tracking id (same as `transaction_tracking_id` defined below)
19
21
  #
20
- # This method generates all the above **except** the `oauth_signature` which
21
- # is generated later by {Pesapal::Oauth.generate_oauth_signature} since
22
- # generation of this `oauth_signature` requires these parameters as inputs
23
- # anyway. See [section 9.2.1 of the oAuth 1.0 spec][1] for more details.
22
+ # This method generates all the above **except** the `oauth_signature`
23
+ # which is generated later by {Pesapal::Oauth.generate_oauth_signature}
24
+ # since generation of this `oauth_signature` requires these parameters as
25
+ # inputs anyway. See [section 9.2.1 of the oAuth 1.0 spec][1] for more
26
+ # details.
24
27
  #
25
28
  # [1]: http://oauth.net/core/1.0/#anchor16
26
29
  # [2]: http://oauth.net/core/1.0/#signing_process
@@ -36,16 +39,17 @@ module Pesapal
36
39
  # @param transaction_tracking_id [String] the unique id assigned by Pesapal
37
40
  # to the transaction after it's posted
38
41
  #
39
- # @return [Hash] parameters to be used in generating the oAuth 1.0 URL query parameters and the `oauth_signature` itself.
42
+ # @return [Hash] parameters to be used in generating the oAuth 1.0 URL
43
+ # query parameters and the `oauth_signature` itself.
40
44
  def self.set_parameters(consumer_key, merchant_reference, transaction_tracking_id)
41
45
  timestamp = Time.now.to_i.to_s
42
- { :oauth_consumer_key => consumer_key,
43
- :oauth_nonce => "#{timestamp}" + Pesapal::Oauth.generate_nonce(12),
44
- :oauth_signature_method => 'HMAC-SHA1',
45
- :oauth_timestamp => "#{timestamp}",
46
- :oauth_version => '1.0',
47
- :pesapal_merchant_reference => merchant_reference,
48
- :pesapal_transaction_tracking_id => transaction_tracking_id
46
+ { oauth_consumer_key: consumer_key,
47
+ oauth_nonce: "#{timestamp}" + Pesapal::Oauth.generate_nonce(12),
48
+ oauth_signature_method: 'HMAC-SHA1',
49
+ oauth_timestamp: "#{timestamp}",
50
+ oauth_version: '1.0',
51
+ pesapal_merchant_reference: merchant_reference,
52
+ pesapal_transaction_tracking_id: transaction_tracking_id
49
53
  }
50
54
  end
51
55
  end
@@ -82,15 +82,15 @@ module Pesapal
82
82
  #
83
83
  # ```
84
84
  # order_details = {
85
- # :amount => 1000,
86
- # :description => 'this is the transaction description',
87
- # :type => 'MERCHANT',
88
- # :reference => '808-707-606',
89
- # :first_name => 'Swaleh',
90
- # :last_name => 'Mdoe',
91
- # :email => 'user@example.com',
92
- # :phonenumber => '+254722222222',
93
- # :currency => 'KES'
85
+ # amount: 1000,
86
+ # description: 'this is the transaction description',
87
+ # type: 'MERCHANT',
88
+ # reference: '808-707-606',
89
+ # first_name: 'Swaleh',
90
+ # last_name: 'Mdoe',
91
+ # email: 'user@example.com',
92
+ # phonenumber: '+254722222222',
93
+ # currency: 'KES'
94
94
  # }
95
95
  # ```
96
96
  #
@@ -124,7 +124,7 @@ module Pesapal
124
124
 
125
125
  # Encode the XML
126
126
  encoder = HTMLEntities.new(:xhtml1)
127
- post_xml = encoder.encode post_xml
127
+ encoder.encode post_xml
128
128
  end
129
129
 
130
130
  # Prepares parameters to be used during the PostPesapalDirectOrderV4 oAuth 1.0 call.
@@ -163,13 +163,13 @@ module Pesapal
163
163
  # @return [Hash] parameters to be used in generating the oAuth 1.0 URL query parameters and the `oauth_signature` itself.
164
164
  def self.set_parameters(callback_url, consumer_key, post_xml)
165
165
  timestamp = Time.now.to_i.to_s
166
- { :oauth_callback => callback_url,
167
- :oauth_consumer_key => consumer_key,
168
- :oauth_nonce => "#{timestamp}" + Pesapal::Oauth.generate_nonce(12),
169
- :oauth_signature_method => 'HMAC-SHA1',
170
- :oauth_timestamp => "#{timestamp}",
171
- :oauth_version => '1.0',
172
- :pesapal_request_data => post_xml
166
+ { oauth_callback: callback_url,
167
+ oauth_consumer_key: consumer_key,
168
+ oauth_nonce: "#{timestamp}" + Pesapal::Oauth.generate_nonce(12),
169
+ oauth_signature_method: 'HMAC-SHA1',
170
+ oauth_timestamp: "#{timestamp}",
171
+ oauth_version: '1.0',
172
+ pesapal_request_data: post_xml
173
173
  }
174
174
  end
175
175
  end
@@ -39,15 +39,15 @@ module Pesapal
39
39
  # @return [Hash] parameters to be used in generating the oAuth 1.0 URL query parameters and the `oauth_signature` itself.
40
40
  def self.set_parameters(consumer_key, merchant_reference, transaction_tracking_id = nil)
41
41
  timestamp = Time.now.to_i.to_s
42
- params = { :oauth_consumer_key => consumer_key,
43
- :oauth_nonce => "#{timestamp}" + Pesapal::Oauth.generate_nonce(12),
44
- :oauth_signature_method => 'HMAC-SHA1',
45
- :oauth_timestamp => "#{timestamp}",
46
- :oauth_version => '1.0',
47
- :pesapal_merchant_reference => merchant_reference
42
+ params = { oauth_consumer_key: consumer_key,
43
+ oauth_nonce: "#{timestamp}" + Pesapal::Oauth.generate_nonce(12),
44
+ oauth_signature_method: 'HMAC-SHA1',
45
+ oauth_timestamp: "#{timestamp}",
46
+ oauth_version: '1.0',
47
+ pesapal_merchant_reference: merchant_reference
48
48
  }
49
49
  params[:pesapal_transaction_tracking_id] = transaction_tracking_id unless transaction_tracking_id.nil?
50
- return params
50
+ params
51
51
  end
52
52
  end
53
53
  end
@@ -140,17 +140,17 @@ module Pesapal
140
140
  # }
141
141
  # ```
142
142
  #
143
- # @note You can change the environment at runtime using {#set_env}
143
+ # @note You can change the environment at runtime using {#change_env}
144
144
  #
145
145
  # @param env [Symbol] the environment we want to use i.e. `:development` or
146
146
  # `:production`. Leaving it blank sets environment intelligently to
147
147
  # `Rails.env` (if Rails) or `:development` (if non-Rails).
148
148
  def initialize(env = false)
149
- set_env env
149
+ change_env env
150
150
  if defined?(Rails)
151
- set_configuration Rails.application.config.pesapal_credentials
151
+ configure Rails.application.config.pesapal_credentials
152
152
  else
153
- set_configuration
153
+ configure
154
154
  end
155
155
  end
156
156
 
@@ -159,7 +159,7 @@ module Pesapal
159
159
  # PesaPal will present the user with a page which contains the available
160
160
  # payment options and will redirect to your site to the _callback url_ once
161
161
  # the user has completed the payment process. A tracking id will be returned
162
- # as a query parameter this can be used subsequently to track the payment
162
+ # as a query parameter - this can be used subsequently to track the payment
163
163
  # status on Pesapal for the transaction later on.
164
164
  #
165
165
  # Generating the URL is a 3-step process:
@@ -190,7 +190,7 @@ module Pesapal
190
190
  @params = Pesapal::Helper::Post.set_parameters(@config[:callback_url], @config[:consumer_key], @post_xml)
191
191
 
192
192
  # generate oauth signature and add signature to the request parameters
193
- @params[:oauth_signature] = Pesapal::Oauth::generate_oauth_signature("GET", @api_endpoints[:postpesapaldirectorderv4], @params, @config[:consumer_secret], @token_secret)
193
+ @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature('GET', @api_endpoints[:postpesapaldirectorderv4], @params, @config[:consumer_secret], @token_secret)
194
194
 
195
195
  # change params (with signature) to a query string
196
196
  query_string = Pesapal::Oauth.generate_encoded_params_query_string @params
@@ -239,7 +239,7 @@ module Pesapal
239
239
  @params = Pesapal::Helper::Details.set_parameters(@config[:consumer_key], merchant_reference, transaction_tracking_id)
240
240
 
241
241
  # generate oauth signature and add signature to the request parameters
242
- @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature("GET", @api_endpoints[:querypaymentdetails], @params, @config[:consumer_secret], @token_secret)
242
+ @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature('GET', @api_endpoints[:querypaymentdetails], @params, @config[:consumer_secret], @token_secret)
243
243
 
244
244
  # change params (with signature) to a query string
245
245
  query_string = Pesapal::Oauth.generate_encoded_params_query_string @params
@@ -255,10 +255,10 @@ module Pesapal
255
255
  response = CGI.parse response.body
256
256
  response = response['pesapal_response_data'][0].split(',')
257
257
 
258
- { :method => response[1],
259
- :status => response[2],
260
- :merchant_reference => response[3],
261
- :transaction_tracking_id => response[0]
258
+ { method: response[1],
259
+ status: response[2],
260
+ merchant_reference: response[3],
261
+ transaction_tracking_id: response[0]
262
262
  }
263
263
  end
264
264
 
@@ -294,7 +294,7 @@ module Pesapal
294
294
  @params = Pesapal::Helper::Status.set_parameters(@config[:consumer_key], merchant_reference, transaction_tracking_id)
295
295
 
296
296
  # generate oauth signature and add signature to the request parameters
297
- @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature("GET", @api_endpoints[:querypaymentstatus], @params, @config[:consumer_secret], @token_secret)
297
+ @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature('GET', @api_endpoints[:querypaymentstatus], @params, @config[:consumer_secret], @token_secret)
298
298
 
299
299
  # change params (with signature) to a query string
300
300
  query_string = Pesapal::Oauth.generate_encoded_params_query_string @params
@@ -344,7 +344,7 @@ module Pesapal
344
344
  #
345
345
  # @return [Hash] contains Pesapal endpoints appropriate for the set
346
346
  # environment
347
- def set_env(env = false)
347
+ def change_env(env = false)
348
348
  env = env.to_s.downcase
349
349
  if env == 'production'
350
350
  @env = 'production'
@@ -352,7 +352,7 @@ module Pesapal
352
352
  @env = 'development'
353
353
  @env = Rails.env if defined?(Rails)
354
354
  end
355
- set_endpoints
355
+ assign_endpoints
356
356
  end
357
357
 
358
358
  # Generates the appropriate IPN response depending on the status of the
@@ -381,8 +381,8 @@ module Pesapal
381
381
  # @note It's up to you to send the response back to Pesapal by providing the
382
382
  # `:response` back to the IPN. The hard part is done.
383
383
  #
384
- # @param notification_type [String] the IPN notification type, should be set
385
- # to CHANGE always
384
+ # @param notification_type [String] the IPN notification type, overridden
385
+ # and set to CHANGE internally. Left here for extensibility.
386
386
  #
387
387
  # @param merchant_reference [String] the unique id generated for the
388
388
  # transaction by your application before posting the order
@@ -393,12 +393,13 @@ module Pesapal
393
393
  # @return [Hash] contains the status and IPN response that should be sent
394
394
  # back to Pesapal
395
395
  def ipn_listener(notification_type, merchant_reference, transaction_tracking_id)
396
+ notification_type = 'CHANGE'
396
397
  status = query_payment_status(merchant_reference, transaction_tracking_id)
397
- output = { :status => status, :response => nil }
398
+ output = { status: status, response: nil }
398
399
 
399
400
  case status
400
- when 'COMPLETED' then output[:response] = "pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=#{transaction_tracking_id}&pesapal_merchant_reference=#{merchant_reference}"
401
- when 'FAILED' then output[:response] = "pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=#{transaction_tracking_id}&pesapal_merchant_reference=#{merchant_reference}"
401
+ when 'COMPLETED' then output[:response] = "pesapal_notification_type=#{notification_type}&pesapal_transaction_tracking_id=#{transaction_tracking_id}&pesapal_merchant_reference=#{merchant_reference}"
402
+ when 'FAILED' then output[:response] = "pesapal_notification_type=#{notification_type}&pesapal_transaction_tracking_id=#{transaction_tracking_id}&pesapal_merchant_reference=#{merchant_reference}"
402
403
  end
403
404
 
404
405
  output
@@ -406,8 +407,8 @@ module Pesapal
406
407
 
407
408
  private
408
409
 
409
- # Set API endpoints depending on the environment.
410
- def set_endpoints
410
+ # Assign API endpoints depending on the environment.
411
+ def assign_endpoints
411
412
  if @env == 'production'
412
413
  @api_domain = 'https://www.pesapal.com'
413
414
  else
@@ -422,13 +423,12 @@ module Pesapal
422
423
  @api_endpoints
423
424
  end
424
425
 
425
- # Set credentials through hash that passed in (does a little processing to
426
- # remove unwanted data & uses default if nothing is input).
427
- def set_configuration(consumer_details = {})
428
- # set the configuration
429
- @config = { :callback_url => 'http://0.0.0.0:3000/pesapal/callback',
430
- :consumer_key => '<YOUR_CONSUMER_KEY>',
431
- :consumer_secret => '<YOUR_CONSUMER_SECRET>'
426
+ # Configure credentials through hash that passed in (does a little
427
+ # processing to remove unwanted data & uses default if nothing is input).
428
+ def configure(consumer_details = {})
429
+ @config = { callback_url: 'http://0.0.0.0:3000/pesapal/callback',
430
+ consumer_key: '<YOUR_CONSUMER_KEY>',
431
+ consumer_secret: '<YOUR_CONSUMER_SECRET>'
432
432
  }
433
433
 
434
434
  valid_config_keys = @config.keys
@@ -114,7 +114,6 @@ module Pesapal
114
114
  #
115
115
  # @return [String] valid signature base string.
116
116
  def self.generate_signature_base_string(http_method, absolute_url, params)
117
-
118
117
  # step 1: convert the http method to uppercase
119
118
  http_method = http_method.upcase
120
119
 
@@ -156,11 +155,11 @@ module Pesapal
156
155
  # > String MUST include the scheme, authority, and path, and MUST exclude
157
156
  # > the query and fragment as defined by [RFC3986] section 3._
158
157
  #
159
- # > _If the absolute request URL is not available to the Service Provider (it
160
- # > is always available to the Consumer), it can be constructed by combining
161
- # > the scheme being used, the HTTP Host header, and the relative HTTP
162
- # > request URL. If the Host header is not available, the Service Provider
163
- # > SHOULD use the host name communicated to the Consumer in the
158
+ # > _If the absolute request URL is not available to the Service Provider
159
+ # > (it is always available to the Consumer), it can be constructed by
160
+ # > combining the scheme being used, the HTTP Host header, and the relative
161
+ # > HTTP request URL. If the Host header is not available, the Service
162
+ # > Provider SHOULD use the host name communicated to the Consumer in the
164
163
  # > documentation or other means._
165
164
  #
166
165
  # > _The Service Provider SHOULD document the form of URL used in the
@@ -184,7 +183,7 @@ module Pesapal
184
183
  path = u.path
185
184
  port = u.port
186
185
 
187
- port = (scheme == 'http' && port != 80) || (scheme == 'https' && port != 443) ? ":#{port}" : ""
186
+ port = (scheme == 'http' && port != 80) || (scheme == 'https' && port != 443) ? ":#{port}" : ''
188
187
  path = (path && path != '') ? path : '/'
189
188
 
190
189
  "#{scheme}://#{host}#{port}#{path}"
@@ -209,8 +208,8 @@ module Pesapal
209
208
  def self.parameter_encode(str)
210
209
  # reserved character regexp, per section 5.1
211
210
  reserved_characters = /[^a-zA-Z0-9\-\.\_\~]/
212
- # Apparently we can't force_encoding on a frozen string since that would modify it.
213
- # What we can do is work with a copy
211
+ # Apparently we can't force_encoding on a frozen string since that would
212
+ # modify it. What we can do is work with a copy
214
213
  URI.escape(str.dup.to_s.force_encoding(Encoding::UTF_8), reserved_characters)
215
214
  end
216
215
  end
@@ -9,14 +9,16 @@ module Pesapal
9
9
  begin
10
10
  config.pesapal_credentials = YAML.load(IO.read(path_to_yaml))[Rails.env]
11
11
  rescue Errno::ENOENT
12
- logger.info('YAML configuration file couldn\'t be found.'); return
12
+ logger.info('YAML configuration file couldn\'t be found.')
13
+ return
13
14
  rescue Psych::SyntaxError
14
- logger.info('YAML configuration file contains invalid syntax. Will use using defaults.'); return
15
+ logger.info('YAML configuration file contains invalid syntax. Will use using defaults.')
16
+ return
15
17
  end
16
18
  else
17
- config.pesapal_credentials = { :callback_url => 'http://0.0.0.0:3000/pesapal/callback',
18
- :consumer_key => '<YOUR_CONSUMER_KEY>',
19
- :consumer_secret => '<YOUR_CONSUMER_SECRET>'
19
+ config.pesapal_credentials = { callback_url: 'http://0.0.0.0:3000/pesapal/callback',
20
+ consumer_key: '<YOUR_CONSUMER_KEY>',
21
+ consumer_secret: '<YOUR_CONSUMER_SECRET>'
20
22
  }
21
23
  end
22
24
  end
@@ -4,5 +4,5 @@ module Pesapal
4
4
  # This gem's version (learn about [Semantic Versioning][1]).
5
5
  #
6
6
  # [1]: http://semver.org/
7
- VERSION = '1.5.6'
7
+ VERSION = '1.6.0'
8
8
  end
@@ -1,5 +1,6 @@
1
1
  lib = File.expand_path('../lib', __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'english'
3
4
  require 'pesapal/version'
4
5
 
5
6
  Gem::Specification.new do |spec|
@@ -13,17 +14,19 @@ Gem::Specification.new do |spec|
13
14
  spec.homepage = 'http://itsmrwave.github.io/pesapal-gem'
14
15
  spec.license = 'MIT'
15
16
 
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
18
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
20
  spec.require_paths = ['lib']
20
21
 
21
- spec.required_ruby_version = '>= 1.9.2'
22
+ spec.required_ruby_version = '>= 1.9.3'
22
23
 
23
24
  spec.add_development_dependency 'bundler'
24
25
  spec.add_development_dependency 'coveralls'
26
+ spec.add_development_dependency 'faker'
25
27
  spec.add_development_dependency 'rake'
26
28
  spec.add_development_dependency 'rspec'
29
+ spec.add_development_dependency 'rubocop'
27
30
  spec.add_development_dependency 'webmock'
28
31
 
29
32
  spec.add_runtime_dependency 'htmlentities'
@@ -2,401 +2,361 @@ require 'spec_helper'
2
2
 
3
3
  describe Pesapal::Merchant do
4
4
 
5
+ let(:order_details) do
6
+ { amount: 1000,
7
+ description: Faker::Lorem.sentence,
8
+ type: 'MERCHANT',
9
+ reference: '111-222-333',
10
+ first_name: Faker::Name.first_name,
11
+ last_name: Faker::Name.last_name,
12
+ email: Faker::Internet.email,
13
+ phonenumber: Faker::PhoneNumber.phone_number,
14
+ currency: 'KES' # ['USD', 'KES', 'UGX', 'TZA'].sample
15
+ }
16
+ end
17
+
18
+ let(:default_credentials) do
19
+ { callback_url: 'http://0.0.0.0:3000/pesapal/callback',
20
+ consumer_key: '<YOUR_CONSUMER_KEY>',
21
+ consumer_secret: '<YOUR_CONSUMER_SECRET>'
22
+ }
23
+ end
24
+
25
+ let(:demo_endpoints) do
26
+ { postpesapaldirectorderv4: 'http://demo.pesapal.com/API/PostPesapalDirectOrderV4',
27
+ querypaymentstatus: 'http://demo.pesapal.com/API/QueryPaymentStatus',
28
+ querypaymentdetails: 'http://demo.pesapal.com/API/QueryPaymentDetails'
29
+ }
30
+ end
31
+
32
+ let(:production_endpoints) do
33
+ { postpesapaldirectorderv4: 'https://www.pesapal.com/API/PostPesapalDirectOrderV4',
34
+ querypaymentstatus: 'https://www.pesapal.com/API/QueryPaymentStatus',
35
+ querypaymentdetails: 'https://www.pesapal.com/API/QueryPaymentDetails'
36
+ }
37
+ end
38
+
5
39
  context 'when mode not specified' do
6
40
 
7
- before :each do
8
- @pesapal = Pesapal::Merchant.new
9
- end
41
+ let(:pesapal) { Pesapal::Merchant.new }
10
42
 
11
43
  describe '#new' do
12
44
 
13
45
  it 'is valid object' do
14
- expect(@pesapal).to be_an_instance_of(Pesapal::Merchant)
46
+ expect(pesapal).to be_an_instance_of(Pesapal::Merchant)
15
47
  end
16
48
 
17
49
  it 'sets default environment variable' do
18
- expect(@pesapal.send(:env)).to eq 'development'
50
+ expect(pesapal.send(:env)).to eq 'development'
19
51
  end
20
52
 
21
53
  it 'sets default credentials' do
22
- expect(@pesapal.config).to eq(default_credentials)
54
+ expect(pesapal.config).to eq(default_credentials)
23
55
  end
24
56
 
25
57
  it 'sets default order details' do
26
- expect(@pesapal.order_details).to eq({})
58
+ expect(pesapal.order_details).to eq({})
27
59
  end
28
60
  end
29
61
 
30
- describe '#set_env' do
62
+ describe '#change_env' do
31
63
 
32
64
  it 'sets default environment variable' do
33
- @pesapal.set_env
34
- expect(@pesapal.send(:env)).to eq 'development'
65
+ pesapal.change_env
66
+ expect(pesapal.send(:env)).to eq 'development'
35
67
  end
36
68
 
37
69
  it 'sets endpoints for default environment' do
38
- expect(@pesapal.set_env).to eq(demo_endpoints)
70
+ expect(pesapal.change_env).to eq(demo_endpoints)
39
71
  end
40
72
  end
41
73
 
42
74
  describe '#generate_order_url' do
43
75
 
44
76
  it 'generates iframe url string' do
45
- @pesapal.order_details = { :amount => 1000,
46
- :description => 'This is the description for the test transaction.',
47
- :type => 'MERCHANT',
48
- :reference => '111-222-333',
49
- :first_name => 'Swaleh',
50
- :last_name => 'Mdoe',
51
- :email => 'test@example.com',
52
- :phonenumber => '+254711000333',
53
- :currency => 'KES'
54
- }
55
- expect(@pesapal.generate_order_url).to match /http:\/\/demo.pesapal.com\/API\/PostPesapalDirectOrderV4\?oauth_callback=.*oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_request_data=.*/
77
+ pesapal.order_details = order_details
78
+ expect(pesapal.generate_order_url).to match %r{http://demo.pesapal.com/API/PostPesapalDirectOrderV4\?oauth_callback=.*oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_request_data=.*}
56
79
  end
57
80
  end
58
81
 
59
82
  describe '#query_payment_status' do
60
83
 
61
- before :each do
62
- @request = stub_request(:get, /http:\/\/demo.pesapal.com\/API\/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
63
- end
84
+ let(:request) { stub_request(:get, %r{http://demo.pesapal.com/API/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
64
85
 
65
86
  it 'gets pending payment status' do
66
- @request.to_return(:status => 200, :body => 'pesapal_response_data=PENDING')
67
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('PENDING')
87
+ request.to_return(status: 200, body: 'pesapal_response_data=PENDING')
88
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('PENDING')
68
89
  end
69
90
 
70
91
  it 'gets completed payment status' do
71
- @request.to_return(:status => 200, :body => 'pesapal_response_data=COMPLETED')
72
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('COMPLETED')
92
+ request.to_return(status: 200, body: 'pesapal_response_data=COMPLETED')
93
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('COMPLETED')
73
94
  end
74
95
 
75
96
  it 'gets failed payment status' do
76
- @request.to_return(:status => 200, :body => 'pesapal_response_data=FAILED')
77
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('FAILED')
97
+ request.to_return(status: 200, body: 'pesapal_response_data=FAILED')
98
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('FAILED')
78
99
  end
79
100
 
80
101
  it 'gets invalid payment status' do
81
- @request.to_return(:status => 200, :body => 'pesapal_response_data=INVALID')
82
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('INVALID')
102
+ request.to_return(status: 200, body: 'pesapal_response_data=INVALID')
103
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('INVALID')
83
104
  end
84
105
  end
85
106
 
86
107
  describe '#query_payment_details' do
87
108
 
88
- before :each do
89
- @request = stub_request(:get, /http:\/\/demo.pesapal.com\/API\/QueryPaymentDetails\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
90
- end
109
+ let(:request) { stub_request(:get, %r{http://demo.pesapal.com/API/QueryPaymentDetails\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
91
110
 
92
111
  it 'gets pending payment details' do
93
- @request.to_return(:status => 200, :body => 'pesapal_response_data=transaction_tracking_id,payment_method,payment_status,merchant_reference')
94
- expect(@pesapal.query_payment_details('merchant_reference', 'transaction_tracking_id')).to eq({ :method => 'payment_method',
95
- :status => 'payment_status',
96
- :merchant_reference => 'merchant_reference',
97
- :transaction_tracking_id => 'transaction_tracking_id'
98
- })
112
+ request.to_return(status: 200, body: 'pesapal_response_data=transaction_tracking_id,payment_method,payment_status,merchant_reference')
113
+ expect(pesapal.query_payment_details('merchant_reference', 'transaction_tracking_id')).to eq(method: 'payment_method',
114
+ status: 'payment_status',
115
+ merchant_reference: 'merchant_reference',
116
+ transaction_tracking_id: 'transaction_tracking_id'
117
+ )
99
118
  end
100
119
  end
101
120
 
102
121
  describe '#ipn_listener' do
103
122
 
104
- before :each do
105
- @request = stub_request(:get, /http:\/\/demo.pesapal.com\/API\/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
106
- end
123
+ let(:request) { stub_request(:get, %r{http://demo.pesapal.com/API/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
107
124
 
108
125
  it 'gets ipn response for pending status' do
109
- @request.to_return(:status => 200, :body => 'pesapal_response_data=PENDING')
110
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'PENDING', :response => nil})
126
+ request.to_return(status: 200, body: 'pesapal_response_data=PENDING')
127
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'PENDING', response: nil)
111
128
  end
112
129
 
113
130
  it 'gets ipn response for completed status' do
114
- @request.to_return(:status => 200, :body => 'pesapal_response_data=COMPLETED')
115
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'COMPLETED', :response => 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference'})
131
+ request.to_return(status: 200, body: 'pesapal_response_data=COMPLETED')
132
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'COMPLETED', response: 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference')
116
133
  end
117
134
 
118
135
  it 'gets ipn response for failed status' do
119
- @request.to_return(:status => 200, :body => 'pesapal_response_data=FAILED')
120
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'FAILED', :response => 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference'})
136
+ request.to_return(status: 200, body: 'pesapal_response_data=FAILED')
137
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'FAILED', response: 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference')
121
138
  end
122
139
 
123
140
  it 'gets ipn response for invalid status' do
124
- @request.to_return(:status => 200, :body => 'pesapal_response_data=INVALID')
125
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'INVALID', :response => nil})
141
+ request.to_return(status: 200, body: 'pesapal_response_data=INVALID')
142
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'INVALID', response: nil)
126
143
  end
127
144
  end
128
145
  end
129
146
 
130
147
  context 'when mode is specified as development' do
131
148
 
132
- before :each do
133
- @pesapal = Pesapal::Merchant.new(:development)
134
- end
149
+ let(:pesapal) { Pesapal::Merchant.new(:development) }
135
150
 
136
151
  describe '#new(:development)' do
137
152
 
138
153
  it 'is valid object' do
139
- expect(@pesapal).to be_an_instance_of(Pesapal::Merchant)
154
+ expect(pesapal).to be_an_instance_of(Pesapal::Merchant)
140
155
  end
141
156
 
142
157
  it 'sets environment variable' do
143
- expect(@pesapal.send(:env)).to eq 'development'
158
+ expect(pesapal.send(:env)).to eq 'development'
144
159
  end
145
160
 
146
161
  it 'sets credentials' do
147
- expect(@pesapal.config).to eq(default_credentials)
162
+ expect(pesapal.config).to eq(default_credentials)
148
163
  end
149
164
 
150
165
  it 'sets order details' do
151
- expect(@pesapal.order_details).to eq({})
166
+ expect(pesapal.order_details).to eq({})
152
167
  end
153
168
  end
154
169
 
155
- describe '#set_env(:development)' do
170
+ describe '#change_env(:development)' do
156
171
 
157
172
  it 'sets environment variable' do
158
- @pesapal.set_env :development
159
- expect(@pesapal.send(:env)).to eq 'development'
173
+ pesapal.change_env :development
174
+ expect(pesapal.send(:env)).to eq 'development'
160
175
  end
161
176
 
162
177
  it 'sets endpoints for environment' do
163
- expect(@pesapal.set_env :development).to eq(demo_endpoints)
178
+ expect(pesapal.change_env :development).to eq(demo_endpoints)
164
179
  end
165
180
  end
166
181
 
167
182
  describe '#generate_order_url' do
168
183
 
169
184
  it 'generates iframe url string' do
170
- @pesapal.order_details = { :amount => 1000,
171
- :description => 'This is the description for the test transaction.',
172
- :type => 'MERCHANT',
173
- :reference => '111-222-333',
174
- :first_name => 'Swaleh',
175
- :last_name => 'Mdoe',
176
- :email => 'test@example.com',
177
- :phonenumber => '+254711000333',
178
- :currency => 'KES'
179
- }
180
- expect(@pesapal.generate_order_url).to match /http:\/\/demo.pesapal.com\/API\/PostPesapalDirectOrderV4\?oauth_callback=.*oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_request_data=.*/
185
+ pesapal.order_details = order_details
186
+ expect(pesapal.generate_order_url).to match %r{http://demo.pesapal.com/API/PostPesapalDirectOrderV4\?oauth_callback=.*oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_request_data=.*}
181
187
  end
182
188
  end
183
189
 
184
190
  describe '#query_payment_status' do
185
191
 
186
- before :each do
187
- @request = stub_request(:get, /http:\/\/demo.pesapal.com\/API\/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
188
- end
192
+ let(:request) { stub_request(:get, %r{http://demo.pesapal.com/API/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
189
193
 
190
194
  it 'gets pending payment status' do
191
- @request.to_return(:status => 200, :body => 'pesapal_response_data=PENDING')
192
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('PENDING')
195
+ request.to_return(status: 200, body: 'pesapal_response_data=PENDING')
196
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('PENDING')
193
197
  end
194
198
 
195
199
  it 'gets completed payment status' do
196
- @request.to_return(:status => 200, :body => 'pesapal_response_data=COMPLETED')
197
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('COMPLETED')
200
+ request.to_return(status: 200, body: 'pesapal_response_data=COMPLETED')
201
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('COMPLETED')
198
202
  end
199
203
 
200
204
  it 'gets failed payment status' do
201
- @request.to_return(:status => 200, :body => 'pesapal_response_data=FAILED')
202
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('FAILED')
205
+ request.to_return(status: 200, body: 'pesapal_response_data=FAILED')
206
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('FAILED')
203
207
  end
204
208
 
205
209
  it 'gets invalid payment status' do
206
- @request.to_return(:status => 200, :body => 'pesapal_response_data=INVALID')
207
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('INVALID')
210
+ request.to_return(status: 200, body: 'pesapal_response_data=INVALID')
211
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('INVALID')
208
212
  end
209
213
  end
210
214
 
211
215
  describe '#query_payment_details' do
212
216
 
213
- before :each do
214
- @request = stub_request(:get, /http:\/\/demo.pesapal.com\/API\/QueryPaymentDetails\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
215
- end
217
+ let(:request) { stub_request(:get, %r{http://demo.pesapal.com/API/QueryPaymentDetails\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
216
218
 
217
219
  it 'gets pending payment details' do
218
- @request.to_return(:status => 200, :body => 'pesapal_response_data=transaction_tracking_id,payment_method,payment_status,merchant_reference')
219
- expect(@pesapal.query_payment_details('merchant_reference', 'transaction_tracking_id')).to eq({ :method => 'payment_method',
220
- :status => 'payment_status',
221
- :merchant_reference => 'merchant_reference',
222
- :transaction_tracking_id => 'transaction_tracking_id'
223
- })
220
+ request.to_return(status: 200, body: 'pesapal_response_data=transaction_tracking_id,payment_method,payment_status,merchant_reference')
221
+ expect(pesapal.query_payment_details('merchant_reference', 'transaction_tracking_id')).to eq(method: 'payment_method',
222
+ status: 'payment_status',
223
+ merchant_reference: 'merchant_reference',
224
+ transaction_tracking_id: 'transaction_tracking_id'
225
+ )
224
226
  end
225
227
  end
226
228
 
227
229
  describe '#ipn_listener' do
228
230
 
229
- before :each do
230
- @request = stub_request(:get, /http:\/\/demo.pesapal.com\/API\/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
231
- end
231
+ let(:request) { stub_request(:get, %r{http://demo.pesapal.com/API/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
232
232
 
233
233
  it 'gets ipn response for pending status' do
234
- @request.to_return(:status => 200, :body => 'pesapal_response_data=PENDING')
235
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'PENDING', :response => nil})
234
+ request.to_return(status: 200, body: 'pesapal_response_data=PENDING')
235
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'PENDING', response: nil)
236
236
  end
237
237
 
238
238
  it 'gets ipn response for completed status' do
239
- @request.to_return(:status => 200, :body => 'pesapal_response_data=COMPLETED')
240
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'COMPLETED', :response => 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference'})
239
+ request.to_return(status: 200, body: 'pesapal_response_data=COMPLETED')
240
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'COMPLETED', response: 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference')
241
241
  end
242
242
 
243
243
  it 'gets ipn response for failed status' do
244
- @request.to_return(:status => 200, :body => 'pesapal_response_data=FAILED')
245
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'FAILED', :response => 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference'})
244
+ request.to_return(status: 200, body: 'pesapal_response_data=FAILED')
245
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'FAILED', response: 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference')
246
246
  end
247
247
 
248
248
  it 'gets ipn response for invalid status' do
249
- @request.to_return(:status => 200, :body => 'pesapal_response_data=INVALID')
250
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'INVALID', :response => nil})
249
+ request.to_return(status: 200, body: 'pesapal_response_data=INVALID')
250
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'INVALID', response: nil)
251
251
  end
252
252
  end
253
253
  end
254
254
 
255
255
  context 'when mode is specified as production' do
256
256
 
257
- before :each do
258
- @pesapal = Pesapal::Merchant.new(:production)
259
- end
257
+ let(:pesapal) { Pesapal::Merchant.new(:production) }
260
258
 
261
259
  describe '#new(:production)' do
262
260
 
263
261
  it 'is valid object' do
264
- expect(@pesapal).to be_an_instance_of(Pesapal::Merchant)
262
+ expect(pesapal).to be_an_instance_of(Pesapal::Merchant)
265
263
  end
266
264
 
267
265
  it 'sets environment variable' do
268
- expect(@pesapal.send(:env)).to eq 'production'
266
+ expect(pesapal.send(:env)).to eq 'production'
269
267
  end
270
268
 
271
269
  it 'sets credentials' do
272
- expect(@pesapal.config).to eq(default_credentials)
270
+ expect(pesapal.config).to eq(default_credentials)
273
271
  end
274
272
 
275
273
  it 'sets order details' do
276
- expect(@pesapal.order_details).to eq({})
274
+ expect(pesapal.order_details).to eq({})
277
275
  end
278
276
  end
279
277
 
280
- describe '#set_env(:production)' do
278
+ describe '#change_env(:production)' do
281
279
 
282
280
  it 'sets environment variable' do
283
- @pesapal.set_env :production
284
- expect(@pesapal.send(:env)).to eq 'production'
281
+ pesapal.change_env :production
282
+ expect(pesapal.send(:env)).to eq 'production'
285
283
  end
286
284
 
287
285
  it 'sets endpoints for environment' do
288
- expect(@pesapal.set_env :production).to eq(production_endpoints)
286
+ expect(pesapal.change_env :production).to eq(production_endpoints)
289
287
  end
290
288
  end
291
289
 
292
290
  describe '#generate_order_url' do
293
291
 
294
292
  it 'generates iframe url string' do
295
- @pesapal.order_details = { :amount => 1000,
296
- :description => 'This is the description for the test transaction.',
297
- :type => 'MERCHANT',
298
- :reference => '111-222-333',
299
- :first_name => 'Swaleh',
300
- :last_name => 'Mdoe',
301
- :email => 'test@example.com',
302
- :phonenumber => '+254711000333',
303
- :currency => 'KES'
304
- }
305
- expect(@pesapal.generate_order_url).to match /https:\/\/www.pesapal.com\/API\/PostPesapalDirectOrderV4\?oauth_callback=.*oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_request_data=.*/
293
+ pesapal.order_details = order_details
294
+ expect(pesapal.generate_order_url).to match %r{https://www.pesapal.com/API/PostPesapalDirectOrderV4\?oauth_callback=.*oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_request_data=.*}
306
295
  end
307
296
  end
308
297
 
309
298
  describe '#query_payment_status' do
310
299
 
311
- before :each do
312
- @request = stub_request(:get, /https:\/\/www.pesapal.com\/API\/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
313
- end
300
+ let(:request) { stub_request(:get, %r{https://www.pesapal.com/API/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
314
301
 
315
302
  it 'gets pending payment status' do
316
- @request.to_return(:status => 200, :body => 'pesapal_response_data=PENDING')
317
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('PENDING')
303
+ request.to_return(status: 200, body: 'pesapal_response_data=PENDING')
304
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('PENDING')
318
305
  end
319
306
 
320
307
  it 'gets completed payment status' do
321
- @request.to_return(:status => 200, :body => 'pesapal_response_data=COMPLETED')
322
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('COMPLETED')
308
+ request.to_return(status: 200, body: 'pesapal_response_data=COMPLETED')
309
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('COMPLETED')
323
310
  end
324
311
 
325
312
  it 'gets failed payment status' do
326
- @request.to_return(:status => 200, :body => 'pesapal_response_data=FAILED')
327
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('FAILED')
313
+ request.to_return(status: 200, body: 'pesapal_response_data=FAILED')
314
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('FAILED')
328
315
  end
329
316
 
330
317
  it 'gets invalid payment status' do
331
- @request.to_return(:status => 200, :body => 'pesapal_response_data=INVALID')
332
- expect(@pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('INVALID')
318
+ request.to_return(status: 200, body: 'pesapal_response_data=INVALID')
319
+ expect(pesapal.query_payment_status('merchant_reference', 'transaction_tracking_id')).to eq('INVALID')
333
320
  end
334
321
  end
335
322
 
336
323
  describe '#query_payment_details' do
337
324
 
338
- before :each do
339
- @request = stub_request(:get, /https:\/\/www.pesapal.com\/API\/QueryPaymentDetails\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
340
- end
325
+ let(:request) { stub_request(:get, %r{https://www.pesapal.com/API/QueryPaymentDetails\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
341
326
 
342
327
  it 'gets pending payment details' do
343
- @request.to_return(:status => 200, :body => 'pesapal_response_data=transaction_tracking_id,payment_method,payment_status,merchant_reference')
344
- expect(@pesapal.query_payment_details('merchant_reference', 'transaction_tracking_id')).to eq({ :method => 'payment_method',
345
- :status => 'payment_status',
346
- :merchant_reference => 'merchant_reference',
347
- :transaction_tracking_id => 'transaction_tracking_id'
348
- })
328
+ request.to_return(status: 200, body: 'pesapal_response_data=transaction_tracking_id,payment_method,payment_status,merchant_reference')
329
+ expect(pesapal.query_payment_details('merchant_reference', 'transaction_tracking_id')).to eq(method: 'payment_method',
330
+ status: 'payment_status',
331
+ merchant_reference: 'merchant_reference',
332
+ transaction_tracking_id: 'transaction_tracking_id'
333
+ )
349
334
  end
350
335
  end
351
336
 
352
337
  describe '#ipn_listener' do
353
338
 
354
- before :each do
355
- @request = stub_request(:get, /https:\/\/www.pesapal.com\/API\/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*/)
356
- end
339
+ let(:request) { stub_request(:get, %r{https://www.pesapal.com/API/QueryPaymentStatus\?oauth_consumer_key=.*oauth_nonce=.*oauth_signature=.*oauth_signature_method=HMAC-SHA1&oauth_timestamp.*oauth_version=1.0&pesapal_merchant_reference=.*&pesapal_transaction_tracking_id=.*}) }
357
340
 
358
341
  it 'gets ipn response for pending status' do
359
- @request.to_return(:status => 200, :body => 'pesapal_response_data=PENDING')
360
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'PENDING', :response => nil})
342
+ request.to_return(status: 200, body: 'pesapal_response_data=PENDING')
343
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'PENDING', response: nil)
361
344
  end
362
345
 
363
346
  it 'gets ipn response for completed status' do
364
- @request.to_return(:status => 200, :body => 'pesapal_response_data=COMPLETED')
365
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'COMPLETED', :response => 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference'})
347
+ request.to_return(status: 200, body: 'pesapal_response_data=COMPLETED')
348
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'COMPLETED', response: 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference')
366
349
  end
367
350
 
368
351
  it 'gets ipn response for failed status' do
369
- @request.to_return(:status => 200, :body => 'pesapal_response_data=FAILED')
370
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'FAILED', :response => 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference'})
352
+ request.to_return(status: 200, body: 'pesapal_response_data=FAILED')
353
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'FAILED', response: 'pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=transaction_tracking_id&pesapal_merchant_reference=merchant_reference')
371
354
  end
372
355
 
373
356
  it 'gets ipn response for invalid status' do
374
- @request.to_return(:status => 200, :body => 'pesapal_response_data=INVALID')
375
- expect(@pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq({:status => 'INVALID', :response => nil})
357
+ request.to_return(status: 200, body: 'pesapal_response_data=INVALID')
358
+ expect(pesapal.ipn_listener('CHANGE', 'merchant_reference', 'transaction_tracking_id')).to eq(status: 'INVALID', response: nil)
376
359
  end
377
360
  end
378
361
  end
379
-
380
- private
381
-
382
- def default_credentials
383
- { :callback_url => 'http://0.0.0.0:3000/pesapal/callback',
384
- :consumer_key => '<YOUR_CONSUMER_KEY>',
385
- :consumer_secret => '<YOUR_CONSUMER_SECRET>'
386
- }
387
- end
388
-
389
- def demo_endpoints
390
- { :postpesapaldirectorderv4 => 'http://demo.pesapal.com/API/PostPesapalDirectOrderV4',
391
- :querypaymentstatus=>'http://demo.pesapal.com/API/QueryPaymentStatus',
392
- :querypaymentdetails=>'http://demo.pesapal.com/API/QueryPaymentDetails'
393
- }
394
- end
395
-
396
- def production_endpoints
397
- { :postpesapaldirectorderv4 => 'https://www.pesapal.com/API/PostPesapalDirectOrderV4',
398
- :querypaymentstatus=>'https://www.pesapal.com/API/QueryPaymentStatus',
399
- :querypaymentdetails=>'https://www.pesapal.com/API/QueryPaymentDetails'
400
- }
401
- end
402
362
  end
@@ -3,6 +3,7 @@
3
3
  require 'coveralls'
4
4
  Coveralls.wear!
5
5
 
6
+ require 'faker'
6
7
  require 'webmock/rspec'
7
8
  require_relative '../lib/pesapal'
8
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pesapal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.6
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Job King'ori Maina
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-26 00:00:00.000000000 Z
11
+ date: 2014-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faker
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,20 @@ dependencies:
66
80
  - - '>='
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: webmock
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -103,10 +131,13 @@ extra_rdoc_files: []
103
131
  files:
104
132
  - .coveralls.yml
105
133
  - .gitignore
134
+ - .hound.yml
106
135
  - .rspec
136
+ - .rubocop.yml
107
137
  - .travis.yml
108
138
  - .yardopts
109
139
  - CHANGELOG.md
140
+ - CONTRIBUTING.md
110
141
  - Gemfile
111
142
  - LICENSE.md
112
143
  - README.md
@@ -137,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
168
  requirements:
138
169
  - - '>='
139
170
  - !ruby/object:Gem::Version
140
- version: 1.9.2
171
+ version: 1.9.3
141
172
  required_rubygems_version: !ruby/object:Gem::Requirement
142
173
  requirements:
143
174
  - - '>='