pesapal 1.8.0 → 2.0.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.
Binary file
@@ -0,0 +1,302 @@
1
+ ---
2
+ title: Get
3
+ layout: default
4
+ ---
5
+
6
+ Synopsis
7
+ --------
8
+
9
+ Basically it's a gem that makes it easy to integrate your app with
10
+ [Pesapal's][24] payment gateway. It Handles all the [oAuth stuff][1] abstracting
11
+ any direct interaction with the API endpoints so that you can focus on what
12
+ matters. _Building awesome_.
13
+
14
+ All this with no 3rd party oAuth library dependencies, it handles all the oAuth
15
+ flows on its own so your app is one dependency less.
16
+
17
+ The gem should be [up on RubyGems.org][7], it's [accompanying API reference
18
+ here][13], the [CHANGELOG here][21] and [all the releases here][12].
19
+
20
+ Ps: This documentation is based off `v2.0.0`. For older versions, rely on the
21
+ version specific documentation. You can find the link on [RubyGems.org][7].
22
+
23
+ Installation
24
+ ------------
25
+
26
+ Add this line to your application's Gemfile:
27
+
28
+ gem 'pesapal'
29
+
30
+ And then execute:
31
+
32
+ $ bundle
33
+
34
+ Or install it yourself as:
35
+
36
+ $ gem install pesapal
37
+
38
+ Usage
39
+ -----
40
+
41
+ ### Initialization
42
+
43
+ Initialize Pesapal object and choose the environment, there are two environments;
44
+ `:development` and `:production`. They determine if the code will interact
45
+ with the testing or the live Pesapal API.
46
+
47
+ ```ruby
48
+ # Sets environment to :development
49
+ pesapal = Pesapal::Merchant.new(:development)
50
+
51
+ # Sets environment to :production
52
+ pesapal = Pesapal::Merchant.new(:production)
53
+ ```
54
+
55
+ ### Configuration
56
+
57
+ Use a hash as shown below (please note that Pesapal provides different keys for
58
+ different environments, make sure you choose the right one).
59
+
60
+ ```ruby
61
+ pesapal.config = {
62
+ callback_url: 'http://0.0.0.0:3000/pesapal/callback',
63
+ consumer_key: '<YOUR_CONSUMER_KEY>',
64
+ consumer_secret: '<YOUR_CONSUMER_SECRET>'
65
+ }
66
+ ```
67
+
68
+ ### Posting An Order
69
+
70
+ Once you've finalized the configuration, set up the order details in a hash as
71
+ shown in the example below ... all keys **MUST** be present. If there's one that
72
+ you wish to ignore just leave it with a blank string but make sure it's included
73
+ e.g. the phonenumber.
74
+
75
+ ```ruby
76
+ pesapal.order_details = {
77
+ amount: 1000,
78
+ description: 'this is the transaction description',
79
+ type: 'MERCHANT',
80
+ reference: '808-707-606',
81
+ first_name: 'Swaleh',
82
+ last_name: 'Mdoe',
83
+ email: 'user@example.com',
84
+ phonenumber: '+254722222222',
85
+ currency: 'KES'
86
+ }
87
+ ```
88
+
89
+ Then generate the transaction url as below. In the example, the value is
90
+ assigned to the variable `order_url` which you can pass on to the templating
91
+ system of your choice to generate an iframe. Please note that this method
92
+ utilizes all that information set in the previous steps in generating the url so
93
+ it's important that it's the last step in the post order process.
94
+
95
+ ```ruby
96
+ # generate transaction url
97
+ order_url = pesapal.generate_order_url
98
+
99
+ # order_url will a string with the url example;
100
+ # 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
101
+ ```
102
+
103
+ _Ps: Please note the `:callback_url` value in the `pesapal.config` hash ...
104
+ after the user successfully posts the order, the response will be sent to this
105
+ url. Refer to [official Pesapal Step-By-Step integration guide][18] for more
106
+ details._
107
+
108
+ ### Querying Payment Status
109
+
110
+ Use this to query the status of the transaction. When a transaction is posted to
111
+ Pesapal, it may be in a PENDING, COMPLETED, FAILED or INVALID state. If the
112
+ transaction is PENDING, the payment may complete or fail at a later stage.
113
+
114
+ Both the unique merchant reference generated by your system (compulsory) and the
115
+ pesapal transaction tracking id (optional) are input parameters to this method
116
+ but if you don't ensure that the merchant reference is unique for each order on
117
+ your system, you may get INVALID as the response. Because of this, it is
118
+ recommended that you provide both the merchant reference and transaction
119
+ tracking id as parameters to guarantee uniqueness.
120
+
121
+ ```ruby
122
+ # option 1: using merchant reference only
123
+ payment_status = pesapal.query_payment_status("<MERCHANT_REFERENCE>")
124
+
125
+ # option 2: using merchant reference and transaction id (recommended)
126
+ payment_status = pesapal.query_payment_status("<MERCHANT_REFERENCE>","<TRANSACTION_ID>")
127
+ ```
128
+
129
+ ### Querying Payment Details
130
+
131
+ Same as querying payment status above, but the return value contains more
132
+ information (and is a hash as opposed to a string).
133
+
134
+ ```ruby
135
+ # pass in merchant reference and transaction id
136
+ payment_details = pesapal.query_payment_details("<MERCHANT_REFERENCE>","<TRANSACTION_ID>")
137
+ ```
138
+
139
+ The result is a hash that looks something like this ...
140
+
141
+ ```ruby
142
+ {
143
+ method: "<PAYMENT_METHOD>",
144
+ status: "<PAYMENT_STATUS>",
145
+ merchant_reference: "<MERCHANT_REFERENCE>",
146
+ transaction_tracking_id: "<TRANSACTION_ID>"
147
+ }
148
+ ```
149
+
150
+ ### IPN Listening
151
+
152
+ Use the `ipn_listener` method to listen to Pesapal IPN calls to easily create an
153
+ appropriate response, example below.
154
+
155
+ ```ruby
156
+ # pass in the notification type, merchant reference and transaction id
157
+ response_to_ipn = pesapal.ipn_listener("<NOTIFICATION_TYPE>", "<MERCHANT_REFERENCE>","<TRANSACTION_ID>")
158
+ ```
159
+
160
+ The variable, `response_to_ipn`, now holds a response as the one shown below.
161
+ Using the status you can customise any actions (e.g. database inserts and
162
+ updates) and finally, it's up to you to send the `:response` back to pesapal. The
163
+ hard part is done for you.
164
+
165
+ ```ruby
166
+ {
167
+ status: "<PAYMENT_STATUS>",
168
+ response: "<IPN_RESPONSE>"
169
+ }
170
+ ```
171
+
172
+ _Ps: Refer to Pesapal official documentation to make sure you understand what
173
+ data Pesapal sends to IPN and what result they expect back._
174
+
175
+
176
+ Support & Issues
177
+ ----------------
178
+
179
+ In case you are having any issues using this gem please **_do not_** email me
180
+ directly, I'd rather you [submit new issues (and even requests) here][23] ...
181
+ obviously after [checking if the issue has already been raised and closed][6].
182
+ This way, other people get to share in the conversation that would have been
183
+ private and out of their reach.
184
+
185
+
186
+ Contributing
187
+ ------------
188
+
189
+ ### To gem's code
190
+
191
+ Submitting a pull request;
192
+
193
+ 1. [Fork the repository][fork].
194
+ 2. [Create a topic branch][branch] (`git checkout -b BRANCH_NAME`).
195
+ 3. [Install bundler][bundler].
196
+ 4. Check that tests pass with `rspec spec`.
197
+ 5. Write a failing test to capture existing bug or lack of feature.
198
+ 6. Run `rspec spec` to verify that test fails.
199
+ 7. Implement your feature or bug fix.
200
+ 8. Ensure tests pass.
201
+ 9. If it's a new feature or a bug fix, please add an entry to the CHANGELOG file.
202
+ 10. Check code style violations using [Rubocop][rubocop].
203
+ 11. Add a commit (`git commit -am 'AWESOME COMMIT MESSAGE'`).
204
+ 12. Push your changes to the branch (`git push origin BRANCH_NAME`).
205
+ 13. [Submit a pull request.][pr]
206
+ 14. You will get some feedback and may need to push additional commits
207
+ with more fixes to the same branch; this will update your pull request
208
+ automatically.
209
+
210
+ [branch]: http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches
211
+ [bundler]: http://bundler.io
212
+ [fork]: https://help.github.com/articles/fork-a-repo/
213
+ [pr]: https://help.github.com/articles/using-pull-requests
214
+ [rubocop]: https://github.com/bbatsov/rubocop
215
+
216
+
217
+ ### To gem's documentation
218
+
219
+ Gem documentation is of two types, feel free to contribute to any;
220
+
221
+ 1. Gem home page at [itskingori.github.io/pesapal-gem][26] _(simple step-by-step)_
222
+ 2. API documetation generated by [Yard][25] _(very comprehensive)_
223
+
224
+ Gem home page is built on [Jekyll][27], which is a fun and easy to use static
225
+ site generator and [hosted on GitHub Pages][30]. The code is in the `docs/`
226
+ folder if you want to have a peek.
227
+
228
+ Preview the gem API documentation locally by installing [Yard][25] (`gem install
229
+ yard`) and call `$ yard server` to set up a local documentation server usually
230
+ running on `http://0.0.0.0:8808`. The result should be similar to the API
231
+ documention up on [rubydoc.info/gems/pesapal][13].
232
+
233
+ _Ps: If you've written code and can't figure out why they aren't passing (or if
234
+ you've written your own tests ... just send a pull a request. We can then do a
235
+ [code review][32])_.
236
+
237
+
238
+ Testing
239
+ -------
240
+
241
+ Tests run [RSpec][31] which is a Behaviour-Driven Development tool. To run
242
+ tests, call;
243
+
244
+ ```bash
245
+ $ bundle exec rspec spec
246
+ ```
247
+
248
+
249
+ References
250
+ ----------
251
+
252
+ * [oAuth 1.0 Spec][1]
253
+ * [Developing a RubyGem using Bundler][2]
254
+ * [RailsGuides][20]
255
+ * [Make your own gem][3]
256
+ * [Getting started with RSpec][33]
257
+ * [Pesapal API Reference (Official)][4]
258
+ * [Pesapal Step-By-Step Reference (Official)][18]
259
+ * [Pesapal PHP API Reference (Unofficial)][5]
260
+
261
+
262
+ License
263
+ -------
264
+
265
+ [King'ori J. Maina][10] © 2013-{{ 'now' | date: "%Y" }}. The [MIT License bundled therein][11] is a
266
+ permissive license that is short and to the point. It lets people do anything
267
+ they want as long as they provide attribution and waive liability.
268
+
269
+
270
+ [1]: http://oauth.net/core/1.0/
271
+ [2]: https://github.com/radar/guides/blob/master/gem-development.md
272
+ [3]: http://guides.rubygems.org/make-your-own-gem/
273
+ [4]: http://developer.pesapal.com/how-to-integrate/api-reference
274
+ [5]: https://github.com/itskingori/pesapal-php#pesapal-php-api-reference-unofficial
275
+ [6]: https://github.com/itskingori/pesapal-gem/issues?state=closed
276
+ [7]: https://rubygems.org/gems/pesapal
277
+ [8]: https://github.com/itskingori/pesapal-gem/fork
278
+ [9]: https://github.com/itskingori/pesapal-gem#contributing--testing
279
+ [10]: http://kingori.co/
280
+ [11]: https://raw.githubusercontent.com/itskingori/pesapal-gem/master/LICENSE.txt
281
+ [12]: https://github.com/itskingori/pesapal-gem/releases/
282
+ [13]: http://rubydoc.info/gems/pesapal/frames/file/README.md
283
+ [14]: https://github.com/itskingori/mo
284
+ [15]: https://github.com/itskingori/mo/tree/master/convention#-convention
285
+ [16]: http://kingori.co/articles/2013/09/modus-operandi/
286
+ [17]: https://github.com/itskingori/pesapal-gem/pulls
287
+ [18]: http://developer.pesapal.com/how-to-integrate/step-by-step
288
+ [19]: https://github.com/itskingori/pesapal-gem/graphs/contributors
289
+ [20]: http://guides.rubyonrails.org/
290
+ [21]: https://raw.githubusercontent.com/itskingori/pesapal-gem/master/CHANGELOG.md
291
+ [22]: https://travis-ci.org/itskingori/pesapal-gem/pull_requests
292
+ [23]: https://github.com/itskingori/pesapal-gem/issues/new
293
+ [24]: https://www.pesapal.com/
294
+ [25]: http://yardoc.org/
295
+ [26]: https://itskingori.github.io/pesapal-gem
296
+ [27]: http://jekyllrb.com/
297
+ [28]: http://jekyllrb.com/docs/home/
298
+ [29]: https://github.com/itskingori/pesapal-gem/tree/gh-pages
299
+ [30]: https://pages.github.com/
300
+ [31]: https://relishapp.com/rspec/
301
+ [32]: http://en.wikipedia.org/wiki/Code_review
302
+ [33]: https://relishapp.com/rspec/docs/gettingstarted
@@ -7,5 +7,3 @@ require 'pesapal/helper/status'
7
7
  require 'pesapal/merchant'
8
8
  require 'pesapal/oauth'
9
9
  require 'pesapal/version'
10
-
11
- require 'pesapal/railtie' if defined?(Rails)
@@ -43,10 +43,12 @@ module Pesapal
43
43
  # query parameters and the `oauth_signature` itself.
44
44
  def self.set_parameters(consumer_key, merchant_reference, transaction_tracking_id)
45
45
  timestamp = Time.now.to_i.to_s
46
- { oauth_consumer_key: consumer_key,
47
- oauth_nonce: "#{timestamp}" + Pesapal::Oauth.generate_nonce(12),
46
+
47
+ {
48
+ oauth_consumer_key: consumer_key,
49
+ oauth_nonce: timestamp + Pesapal::Oauth.generate_nonce(12),
48
50
  oauth_signature_method: 'HMAC-SHA1',
49
- oauth_timestamp: "#{timestamp}",
51
+ oauth_timestamp: timestamp,
50
52
  oauth_version: '1.0',
51
53
  pesapal_merchant_reference: merchant_reference,
52
54
  pesapal_transaction_tracking_id: transaction_tracking_id
@@ -163,11 +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,
166
+
167
+ {
168
+ oauth_callback: callback_url,
167
169
  oauth_consumer_key: consumer_key,
168
- oauth_nonce: "#{timestamp}" + Pesapal::Oauth.generate_nonce(12),
170
+ oauth_nonce: timestamp + Pesapal::Oauth.generate_nonce(12),
169
171
  oauth_signature_method: 'HMAC-SHA1',
170
- oauth_timestamp: "#{timestamp}",
172
+ oauth_timestamp: timestamp,
171
173
  oauth_version: '1.0',
172
174
  pesapal_request_data: post_xml
173
175
  }
@@ -39,13 +39,14 @@ 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
48
- }
42
+ params = {
43
+ oauth_consumer_key: consumer_key,
44
+ oauth_nonce: timestamp + Pesapal::Oauth.generate_nonce(12),
45
+ oauth_signature_method: 'HMAC-SHA1',
46
+ oauth_timestamp: timestamp,
47
+ oauth_version: '1.0',
48
+ pesapal_merchant_reference: merchant_reference
49
+ }
49
50
  params[:pesapal_transaction_tracking_id] = transaction_tracking_id unless transaction_tracking_id.nil?
50
51
  params
51
52
  end
@@ -64,7 +64,7 @@ module Pesapal
64
64
 
65
65
  private
66
66
 
67
- attr_reader :api_domain, :api_endpoints, :env
67
+ attr_reader :env
68
68
 
69
69
  def params
70
70
  @params ||= nil
@@ -87,71 +87,22 @@ module Pesapal
87
87
  # will interact with the testing or the live Pesapal API. Like so ...
88
88
  #
89
89
  # ```ruby
90
- # # Sets environment intelligently to 'Rails.env' (if Rails) or :development (if non-Rails)
91
- # pesapal = Pesapal::Merchant.new
92
- #
93
- # # Sets environment to :development
90
+ # # Sets environment to :development explicitly
94
91
  # pesapal = Pesapal::Merchant.new(:development)
95
92
  #
96
93
  # # Sets environment to :production
97
94
  # pesapal = Pesapal::Merchant.new(:production)
98
95
  # ```
99
96
  #
100
- # A few things to note about the constructor as it behaves differently
101
- # depending on the context within which it is called i.e. _Rails_ app vs
102
- # _non-Rails_ app ...
103
- #
104
- # ### Case 1: Rails app
105
- #
106
- # The constructor attempts to set configuration details that should be
107
- # available at runtime from `Rails.application.config.pesapal_credentials`.
108
- # This contains values loaded at application start from a YAML file located
109
- # at `config/pesapal.yml` which typically looks like this:
110
- #
111
- # ```yaml
112
- # development:
113
- # callback_url: 'http://0.0.0.0:3000/pesapal/callback'
114
- # consumer_key: '<YOUR_DEV_CONSUMER_KEY>'
115
- # consumer_secret: '<YOUR_DEV_CONSUMER_SECRET>'
116
- #
117
- # production:
118
- # callback_url: 'http://1.2.3.4:3000/pesapal/callback'
119
- # consumer_key: '<YOUR_PROD_CONSUMER_KEY>'
120
- # consumer_secret: '<YOUR_PROD_CONSUMER_SECRET>'
121
- # ```
122
- #
123
- # The appropriate credentials are picked and set to {#config} instance
124
- # attribute depending on set environment. The setting of environment is
125
- # explained above. It's worth nothing that if for some reason the YAML file
126
- # could not be read, then it fallbacks to setting {#config} instance
127
- # attribute with default values. The exact definition of default values is
128
- # shown below.
129
- #
130
- # ### Case 2: Non-Rails app
131
- #
132
- # Since (and if) no predefined configuration files are available, the
133
- # constructor sets the {#config} instance attribute up with default values
134
- # as shown below:
135
- #
136
- # ```
137
- # { :callback_url => 'http://0.0.0.0:3000/pesapal/callback',
138
- # :consumer_key => '<YOUR_CONSUMER_KEY>',
139
- # :consumer_secret => '<YOUR_CONSUMER_SECRET>'
140
- # }
141
- # ```
142
- #
143
- # @note You can change the environment at runtime using {#change_env}
144
- #
145
97
  # @param env [Symbol] the environment we want to use i.e. `:development` or
146
- # `:production`. Leaving it blank sets environment intelligently to
147
- # `Rails.env` (if Rails) or `:development` (if non-Rails).
148
- def initialize(env = false)
149
- change_env env
150
- if defined?(Rails)
151
- configure Rails.application.config.pesapal_credentials
152
- else
153
- configure
154
- end
98
+ # `:production`.
99
+ def initialize(env = :development)
100
+ @env = env.to_s.downcase
101
+ @config = {
102
+ callback_url: 'http://0.0.0.0:3000/pesapal/callback',
103
+ consumer_key: '<YOUR_CONSUMER_KEY>',
104
+ consumer_secret: '<YOUR_CONSUMER_SECRET>'
105
+ }
155
106
  end
156
107
 
157
108
  # Generate URL that's used to post a transaction to PesaPal.
@@ -185,17 +136,20 @@ module Pesapal
185
136
  # build xml with input data, the format is standard so no editing is
186
137
  # required
187
138
  @post_xml = Pesapal::Helper::Post.generate_post_xml @order_details
188
-
189
139
  # initialize setting of @params (oauth_signature left empty)
190
140
  @params = Pesapal::Helper::Post.set_parameters(@config[:callback_url], @config[:consumer_key], @post_xml)
191
-
192
141
  # 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)
194
-
142
+ @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature(
143
+ 'GET',
144
+ postpesapaldirectorderv4_url,
145
+ @params,
146
+ @config[:consumer_secret],
147
+ @token_secret
148
+ )
195
149
  # change params (with signature) to a query string
196
150
  query_string = Pesapal::Oauth.generate_encoded_params_query_string @params
197
151
 
198
- "#{@api_endpoints[:postpesapaldirectorderv4]}?#{query_string}"
152
+ "#{postpesapaldirectorderv4_url}?#{query_string}"
199
153
  end
200
154
 
201
155
  # Same as {#query_payment_status}, but additional information is returned in
@@ -237,15 +191,19 @@ module Pesapal
237
191
  def query_payment_details(merchant_reference, transaction_tracking_id)
238
192
  # initialize setting of @params (oauth_signature left empty)
239
193
  @params = Pesapal::Helper::Details.set_parameters(@config[:consumer_key], merchant_reference, transaction_tracking_id)
240
-
241
194
  # 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)
243
-
195
+ @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature(
196
+ 'GET',
197
+ querypaymentdetails_url,
198
+ @params,
199
+ @config[:consumer_secret],
200
+ @token_secret
201
+ )
244
202
  # change params (with signature) to a query string
245
203
  query_string = Pesapal::Oauth.generate_encoded_params_query_string @params
246
204
 
247
205
  # get status response
248
- uri = URI.parse "#{@api_endpoints[:querypaymentdetails]}?#{query_string}"
206
+ uri = URI.parse "#{querypaymentdetails_url}?#{query_string}"
249
207
  http = Net::HTTP.new(uri.host, uri.port)
250
208
  http.use_ssl = true
251
209
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -253,7 +211,8 @@ module Pesapal
253
211
  response = CGI.parse response.body
254
212
  response = response['pesapal_response_data'][0].split(',')
255
213
 
256
- { method: response[1],
214
+ {
215
+ method: response[1],
257
216
  status: response[2],
258
217
  merchant_reference: response[3],
259
218
  transaction_tracking_id: response[0]
@@ -290,15 +249,19 @@ module Pesapal
290
249
  def query_payment_status(merchant_reference, transaction_tracking_id = nil)
291
250
  # initialize setting of @params (oauth_signature left empty)
292
251
  @params = Pesapal::Helper::Status.set_parameters(@config[:consumer_key], merchant_reference, transaction_tracking_id)
293
-
294
252
  # generate oauth signature and add signature to the request parameters
295
- @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature('GET', @api_endpoints[:querypaymentstatus], @params, @config[:consumer_secret], @token_secret)
296
-
253
+ @params[:oauth_signature] = Pesapal::Oauth.generate_oauth_signature(
254
+ 'GET',
255
+ querypaymentstatus_url,
256
+ @params,
257
+ @config[:consumer_secret],
258
+ @token_secret
259
+ )
297
260
  # change params (with signature) to a query string
298
261
  query_string = Pesapal::Oauth.generate_encoded_params_query_string @params
299
262
 
300
263
  # get status response
301
- uri = URI.parse "#{@api_endpoints[:querypaymentstatus]}?#{query_string}"
264
+ uri = URI.parse "#{querypaymentstatus_url}?#{query_string}"
302
265
  http = Net::HTTP.new(uri.host, uri.port)
303
266
  http.use_ssl = true
304
267
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -307,50 +270,6 @@ module Pesapal
307
270
  response['pesapal_response_data'][0]
308
271
  end
309
272
 
310
- # Set the environment in use.
311
- #
312
- # Useful especially if you want to change the environment at runtime from
313
- # what was set during initialization in the constructor. It also makes sure
314
- # that we use the appropriate endpoints when making calls to Pesapal. See
315
- # below:
316
- #
317
- # ```
318
- # # endpoint values set if :development
319
- # {
320
- # :postpesapaldirectorderv4 => "http://demo.pesapal.com/API/PostPesapalDirectOrderV4",
321
- # :querypaymentstatus => "http://demo.pesapal.com/API/QueryPaymentStatus",
322
- # :querypaymentdetails => "http://demo.pesapal.com/API/QueryPaymentDetails"
323
- # }
324
- #
325
- # # endpoint values set if :production
326
- # {
327
- # :postpesapaldirectorderv4 => "https://www.pesapal.com/API/PostPesapalDirectOrderV4",
328
- # :querypaymentstatus => "https://www.pesapal.com/API/QueryPaymentStatus",
329
- # :querypaymentdetails => "https://www.pesapal.com/API/QueryPaymentDetails"
330
- # }
331
- # ```
332
- #
333
- # @note For a Rails app, you'd expect that calling this would also flip the
334
- # credentials if there was a YAML file containing both environment
335
- # credentials but that's not the case. It could be something that we can
336
- # add later.
337
- #
338
- # @param env [Symbol] the environment we want to use i.e. :development or
339
- # :production
340
- #
341
- # @return [Hash] contains Pesapal endpoints appropriate for the set
342
- # environment
343
- def change_env(env = false)
344
- env = env.to_s.downcase
345
- if env == 'production'
346
- @env = 'production'
347
- else
348
- @env = 'development'
349
- @env = Rails.env if defined?(Rails)
350
- end
351
- assign_endpoints
352
- end
353
-
354
273
  # Generates the appropriate IPN response depending on the status of the
355
274
  # transaction.
356
275
  #
@@ -393,9 +312,13 @@ module Pesapal
393
312
  status = query_payment_status(merchant_reference, transaction_tracking_id)
394
313
  output = { status: status, response: nil }
395
314
 
315
+ response = "pesapal_notification_type=#{notification_type}"
316
+ response += "&pesapal_transaction_tracking_id=#{transaction_tracking_id}"
317
+ response += "&pesapal_merchant_reference=#{merchant_reference}"
318
+
396
319
  case status
397
- when 'COMPLETED' then output[:response] = "pesapal_notification_type=#{notification_type}&pesapal_transaction_tracking_id=#{transaction_tracking_id}&pesapal_merchant_reference=#{merchant_reference}"
398
- when 'FAILED' then output[:response] = "pesapal_notification_type=#{notification_type}&pesapal_transaction_tracking_id=#{transaction_tracking_id}&pesapal_merchant_reference=#{merchant_reference}"
320
+ when 'COMPLETED' then output[:response] = response
321
+ when 'FAILED' then output[:response] = response
399
322
  end
400
323
 
401
324
  output
@@ -403,33 +326,24 @@ module Pesapal
403
326
 
404
327
  private
405
328
 
406
- # Assign API endpoints depending on the environment.
407
- def assign_endpoints
408
- if @env == 'production'
409
- @api_domain = 'https://www.pesapal.com'
410
- else
411
- @api_domain = 'https://demo.pesapal.com'
412
- end
413
-
414
- @api_endpoints = {}
415
- @api_endpoints[:postpesapaldirectorderv4] = "#{@api_domain}/API/PostPesapalDirectOrderV4"
416
- @api_endpoints[:querypaymentstatus] = "#{@api_domain}/API/QueryPaymentStatus"
417
- @api_endpoints[:querypaymentdetails] = "#{@api_domain}/API/QueryPaymentDetails"
329
+ def api_domain
330
+ @env == 'production' ? 'www.pesapal.com' : 'demo.pesapal.com'
331
+ end
418
332
 
419
- @api_endpoints
333
+ def api_endpoint
334
+ 'https://' + api_domain
420
335
  end
421
336
 
422
- # Configure credentials through hash that passed in (does a little
423
- # processing to remove unwanted data & uses default if nothing is input).
424
- def configure(consumer_details = {})
425
- @config = { callback_url: 'http://0.0.0.0:3000/pesapal/callback',
426
- consumer_key: '<YOUR_CONSUMER_KEY>',
427
- consumer_secret: '<YOUR_CONSUMER_SECRET>'
428
- }
337
+ def postpesapaldirectorderv4_url
338
+ api_endpoint + '/API/PostPesapalDirectOrderV4'
339
+ end
429
340
 
430
- valid_config_keys = @config.keys
341
+ def querypaymentstatus_url
342
+ api_endpoint + '/API/QueryPaymentStatus'
343
+ end
431
344
 
432
- consumer_details.each { |k, v| @config[k.to_sym] = v if valid_config_keys.include? k.to_sym }
345
+ def querypaymentdetails_url
346
+ api_endpoint + '/API/QueryPaymentDetails'
433
347
  end
434
348
  end
435
349
  end