payr 1.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.
- data/MIT-LICENSE +20 -0
- data/README.md +238 -0
- data/Rakefile +33 -0
- data/app/assets/javascripts/payr/bills.js.coffee +3 -0
- data/app/controllers/payr/bills_controller.rb +63 -0
- data/app/models/payr/bill.rb +3 -0
- data/app/views/payr/bills/cancelled.html.erb +2 -0
- data/app/views/payr/bills/failure.html.erb +2 -0
- data/app/views/payr/bills/paid.html.erb +2 -0
- data/app/views/payr/bills/pay.html.erb +8 -0
- data/app/views/payr/bills/refused.html.erb +2 -0
- data/config/locales/en.yml +12 -0
- data/config/locales/fr.yml +12 -0
- data/config/routes.rb +2 -0
- data/lib/generators/payr/install_generator.rb +25 -0
- data/lib/generators/templates/migration.rb +12 -0
- data/lib/generators/templates/payr.rb +35 -0
- data/lib/payr.rb +70 -0
- data/lib/payr/client.rb +117 -0
- data/lib/payr/controllers/payr_filters.rb +19 -0
- data/lib/payr/controllers/payr_helpers.rb +18 -0
- data/lib/payr/engine.rb +10 -0
- data/lib/payr/keys/pubkey.pem +6 -0
- data/lib/payr/rails/routes.rb +13 -0
- data/lib/payr/version.rb +3 -0
- data/lib/tasks/payr_tasks.rake +4 -0
- metadata +157 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 Pasta
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
# Payr : paybox system paiement made easy
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add the gem payr to your Gemfile
|
6
|
+
```ruby
|
7
|
+
gem "payr"
|
8
|
+
```
|
9
|
+
|
10
|
+
Then in your terminal
|
11
|
+
|
12
|
+
```sh
|
13
|
+
$ > rails generate payr:install
|
14
|
+
create db/migrate/20121016122427_create_bills_table.rb
|
15
|
+
create config/initializers/payr.rb
|
16
|
+
```
|
17
|
+
This should copy a migration file and the initializer payr.rb.
|
18
|
+
|
19
|
+
fill config/initializers/payr.rb with your own values coming from the paybox website
|
20
|
+
you should always use different values for your pre production/production environements.
|
21
|
+
|
22
|
+
```sh
|
23
|
+
$ > rake db:migrate
|
24
|
+
|
25
|
+
== CreateBillsTable: migrating ===============================================
|
26
|
+
-- create_table(:bills)
|
27
|
+
NOTICE: CREATE TABLE will create implicit sequence "bills_id_seq" for serial column "bills.id"
|
28
|
+
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "bills_pkey" for table "bills"
|
29
|
+
-> 0.0246s
|
30
|
+
== CreateBillsTable: migrated (0.0247s) ======================================
|
31
|
+
```
|
32
|
+
|
33
|
+
## Setup
|
34
|
+
|
35
|
+
### Paybox System
|
36
|
+
```ruby
|
37
|
+
Payr.setup do |config|
|
38
|
+
# Put the merchant site ID found on the paybox website
|
39
|
+
#config.site_id = 1999888
|
40
|
+
|
41
|
+
# Put the merchant rang found on the paybox website
|
42
|
+
#config.rang = 32
|
43
|
+
|
44
|
+
# Put the merchant paybox ID found on the paybox website
|
45
|
+
#config.paybox_id = 1686319
|
46
|
+
|
47
|
+
# Put the secret key for the hmac pass found on the paybox website
|
48
|
+
#config.secret_key = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
|
49
|
+
|
50
|
+
# Put the hash algorithm
|
51
|
+
# Possible values are :SHA256 :SHA512 :SHA384 :SHA224
|
52
|
+
config.hash = :sha512
|
53
|
+
|
54
|
+
# The currency
|
55
|
+
# possible values :euro :us_dollar
|
56
|
+
config.currency = :euro
|
57
|
+
|
58
|
+
config.paybox_url = "https://preprod-tpeweb.paybox.com/cgi/MYchoix_pagepaiement.cgi"
|
59
|
+
# config.paybox_url_back_one = nil
|
60
|
+
# config.paybox_url_back_two = nil
|
61
|
+
|
62
|
+
config.callback_values = { amount:"m", ref:"r", auto:"a", error:"e", signature:"k" }
|
63
|
+
|
64
|
+
# Optionnal config : if not null, choose on behalf of the user the type of paiement.
|
65
|
+
# EX: "CARTE". Look at the paybox documentation for more
|
66
|
+
#config.typepaiement = "CARTE"
|
67
|
+
|
68
|
+
# Optionnal config : if not null, choose on behalf of the user the type of CARD.
|
69
|
+
# EX: "CB". Look at the paybox documentation for more
|
70
|
+
#config.typecard = "CB"
|
71
|
+
end
|
72
|
+
|
73
|
+
```
|
74
|
+
|
75
|
+
### Routes And "AutoCustom" Controller =)
|
76
|
+
|
77
|
+
if you just want to use the helpers and don't care about the controllers and the bill model, skip this part
|
78
|
+
|
79
|
+
You can use the routes by default by adding this to your config/routes.rb
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
payr_routes
|
83
|
+
```
|
84
|
+
|
85
|
+
This will generate 4 routes :
|
86
|
+
|
87
|
+
```sh
|
88
|
+
$ > rake routes
|
89
|
+
payr_bills_pay GET /bills/pay(.:format) payr/bills#pay
|
90
|
+
payr_bills_paid GET /bills/paid(.:format) payr/bills#paid
|
91
|
+
payr_bills_refused GET /bills/refused(.:format) payr/bills#refused
|
92
|
+
payr_bills_cancelled GET /bills/cancelled(.:format) payr/bills#cancelled
|
93
|
+
payr_bills_ipn GET /bills/ipn(.:format) payr/bills#ipn
|
94
|
+
```
|
95
|
+
|
96
|
+
And you will use the default controllers.
|
97
|
+
We recommand to override the controllers thoug. For that, define a custom controller by doing :
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
payr_routes callback_controller: "paiement/callbacks"
|
101
|
+
```
|
102
|
+
|
103
|
+
If you created a app/controllers/paiement/callbacks controller.
|
104
|
+
|
105
|
+
This will generate 4 routes :
|
106
|
+
|
107
|
+
```sh
|
108
|
+
$ > rake routes
|
109
|
+
payr_bills_pay GET /paiement/callbacks/pay(.:format) paiement/callbacks#pay
|
110
|
+
payr_bills_paid GET /paiement/callbacks/paid(.:format) paiement/callbacks#paid
|
111
|
+
payr_bills_refused GET /paiement/callbacks/refused(.:format) paiement/callbacks#refused
|
112
|
+
payr_bills_cancelled GET /paiement/callbacks/cancelled(.:format) paiement/callbacks#cancelled
|
113
|
+
payr_bills_ipn GET /paiement/callbacks/ipn(.:format) paiement/callbacks#ipn
|
114
|
+
```
|
115
|
+
|
116
|
+
The controller could look something like this for example :
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
class Paiement::CallbacksController < Payr::BillsController
|
120
|
+
# if you use cancan
|
121
|
+
skip_authorization_check
|
122
|
+
# if you use devise
|
123
|
+
before_filter :authenticate_buyer!
|
124
|
+
layout "simply_blue_simple"
|
125
|
+
|
126
|
+
# But you can also rewrite the actions
|
127
|
+
# to redirect to a specific action, for example :
|
128
|
+
def paid
|
129
|
+
super
|
130
|
+
bill = Payr::Bill.find params[:ref]
|
131
|
+
pack = Pack.find bill.article_id
|
132
|
+
current_buyer.add_pack pack
|
133
|
+
redirect_to new_offer_path
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
Basically, thoses actions do :
|
139
|
+
```ruby
|
140
|
+
#
|
141
|
+
# when calling payr_bills_pay_path (talking about that later)
|
142
|
+
# will create a bill record with the article id, the buyer id
|
143
|
+
# the amount and the paiement status
|
144
|
+
# the render a transitionnal page which redirects to the paiement website
|
145
|
+
def pay
|
146
|
+
end
|
147
|
+
|
148
|
+
# Callbacks methods as defined in paybox system
|
149
|
+
# changes the status of the bill
|
150
|
+
def paid
|
151
|
+
end
|
152
|
+
def refused
|
153
|
+
end
|
154
|
+
def cancelled
|
155
|
+
end
|
156
|
+
# server to server callback
|
157
|
+
def ipn
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
then into your view use the route :
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
payr_bills_pay_path(article_id: pack.id,
|
165
|
+
buyer: { email: current_recruiter.email,
|
166
|
+
id: current_recruiter.id },
|
167
|
+
total_price: pack.price.to_i*100 )
|
168
|
+
```
|
169
|
+
|
170
|
+
This will call the bills#action and then redirect the user to the paybox paiement page.
|
171
|
+
|
172
|
+
You can also override the views by creating the appropriate files :
|
173
|
+
```sh
|
174
|
+
$ > ls app/views/paiement/callbacks
|
175
|
+
paid.html.haml
|
176
|
+
refused.html.haml
|
177
|
+
cancelled.html.haml
|
178
|
+
failure.html.haml
|
179
|
+
```
|
180
|
+
|
181
|
+
|
182
|
+
To finish, you need to add this to the application.js
|
183
|
+
|
184
|
+
```javascript
|
185
|
+
//= require payr/bills
|
186
|
+
```
|
187
|
+
|
188
|
+
# I Don't Care about your super CallbacksController and your Super Bill Model
|
189
|
+
|
190
|
+
## YEAH, I just want the backbone : form helpers, signature checker
|
191
|
+
|
192
|
+
Okay, this is possible :
|
193
|
+
|
194
|
+
- Don't use the rails generator payr:install
|
195
|
+
|
196
|
+
- copy the payr.rb file from the step above into the config/initializers folder.
|
197
|
+
|
198
|
+
|
199
|
+
Use the following helpers :
|
200
|
+
```ruby
|
201
|
+
# to check signature responses in your callback controllers
|
202
|
+
before_filter :check_response
|
203
|
+
before_filter :check_ipn_response
|
204
|
+
|
205
|
+
# To get all the paybox fields in a hash
|
206
|
+
@payr = Payr::Client.new
|
207
|
+
@paybox_params = @payr.get_paybox_params_from command_id: bill.id,
|
208
|
+
buyer_email: params[:buyer_email],
|
209
|
+
total_price: params[:total_price],
|
210
|
+
callbacks: {
|
211
|
+
paid: callback_paid_url,
|
212
|
+
refused: callback_refused_url,
|
213
|
+
cancelled: callback_cancelled_url,
|
214
|
+
ipn: callback_ipn_url
|
215
|
+
}
|
216
|
+
|
217
|
+
# To generate the fields into the view
|
218
|
+
# just the fields
|
219
|
+
paybox_hidden_fields @paybox_params
|
220
|
+
# the entire form
|
221
|
+
paybox_form submit_name, @paybox_params
|
222
|
+
```
|
223
|
+
|
224
|
+
### I WANNA HELP ?
|
225
|
+
|
226
|
+
For this no problem friend :
|
227
|
+
- fork
|
228
|
+
- add tests
|
229
|
+
- run tests
|
230
|
+
|
231
|
+
```sh
|
232
|
+
rake
|
233
|
+
````
|
234
|
+
- pull request
|
235
|
+
|
236
|
+
i'll gladly add your work =)
|
237
|
+
|
238
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Payr'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'bundler/gem_tasks'
|
24
|
+
require 'rspec/core/rake_task'
|
25
|
+
|
26
|
+
RSpec::Core::RakeTask.new(:spec)
|
27
|
+
|
28
|
+
task :default => :spec
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
Bundler::GemHelper.install_tasks
|
33
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Payr::BillsController < ApplicationController
|
2
|
+
before_filter :check_response, except: [:pay, :failure, :ipn]
|
3
|
+
before_filter :check_ipn_response, only: [:ipn]
|
4
|
+
|
5
|
+
UNPROCESSED = "unprocessed"
|
6
|
+
PAID = "paid"
|
7
|
+
REFUSED = "refused"
|
8
|
+
CANCELLED = "cancelled"
|
9
|
+
SIGN_ERROR = "bad_signature"
|
10
|
+
NO_ERROR = "00000"
|
11
|
+
def pay
|
12
|
+
@bill = Payr::Bill.new(buyer_id: params[:buyer][:id],
|
13
|
+
amount: params[:total_price],
|
14
|
+
article_id: params[:article_id],
|
15
|
+
state: UNPROCESSED)
|
16
|
+
@payr = Payr::Client.new
|
17
|
+
if @bill.save
|
18
|
+
@paybox_params = @payr.get_paybox_params_from command_id: @bill.id,
|
19
|
+
buyer_email: params[:buyer][:email],
|
20
|
+
total_price: params[:total_price],
|
21
|
+
callbacks: {
|
22
|
+
paid: payr_bills_paid_url,
|
23
|
+
refused: payr_bills_refused_url,
|
24
|
+
cancelled: payr_bills_cancelled_url,
|
25
|
+
ipn: payr_bills_ipn_url
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def paid
|
31
|
+
change_status params[:ref], PAID
|
32
|
+
end
|
33
|
+
|
34
|
+
def refused
|
35
|
+
change_status params[:ref], REFUSED, params[:error]
|
36
|
+
end
|
37
|
+
|
38
|
+
def cancelled
|
39
|
+
change_status params[:ref], CANCELLED, params[:error]
|
40
|
+
end
|
41
|
+
|
42
|
+
def ipn
|
43
|
+
if params[:error] == NO_ERROR
|
44
|
+
change_status params[:ref], PAID
|
45
|
+
else
|
46
|
+
@bill = Payr::Bill.find(params[:ref])
|
47
|
+
@bill.update_attribute(:error_code, params[:error])
|
48
|
+
end
|
49
|
+
render nothing: true, :status => 200, :content_type => 'text/html'
|
50
|
+
end
|
51
|
+
|
52
|
+
def failure
|
53
|
+
change_status params[:ref], SIGN_ERROR, params[:error]
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
def change_status id, status, error=nil
|
58
|
+
@bill = Payr::Bill.find(id)
|
59
|
+
@bill.update_attribute(:state, status)
|
60
|
+
@bill.update_attribute(:error_code, error) unless error.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
fr:
|
2
|
+
payr:
|
3
|
+
pay:
|
4
|
+
redirected: You are being redirected on the paiement website
|
5
|
+
paid:
|
6
|
+
redirected: Thanks for the paiement.
|
7
|
+
cancelled:
|
8
|
+
redirected: You cancelled you paiement.
|
9
|
+
refused:
|
10
|
+
redirected: Your paiement has been refused.
|
11
|
+
failure:
|
12
|
+
redirected: There was a communication problem with paybox.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
fr:
|
2
|
+
payr:
|
3
|
+
pay:
|
4
|
+
redirected: Vous êtes redirigés vers le site de paiement. Merci de patienter...
|
5
|
+
paid:
|
6
|
+
redirected: Merci de votre paiement.
|
7
|
+
cancelled:
|
8
|
+
redirected: Vous avez annulé le paiement.
|
9
|
+
refused:
|
10
|
+
redirected: Votre paiement à été refusé.
|
11
|
+
failure:
|
12
|
+
redirected: Il y'a eu un problème avec paybox.
|
data/config/routes.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Payr
|
2
|
+
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
include Rails::Generators::Migration
|
5
|
+
source_root File.expand_path("../../templates", __FILE__)
|
6
|
+
desc "This generator creates an initializer file at config/initializers and adds migration file"
|
7
|
+
|
8
|
+
def self.next_migration_number(dirname)
|
9
|
+
if ActiveRecord::Base.timestamped_migrations
|
10
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
11
|
+
else
|
12
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_migration_file
|
17
|
+
migration_template 'migration.rb', 'db/migrate/create_bills_table.rb'
|
18
|
+
end
|
19
|
+
|
20
|
+
def init
|
21
|
+
copy_file "payr.rb", "config/initializers/payr.rb"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Payr.setup do |config|
|
2
|
+
# Put the merchant site ID found on the paybox website
|
3
|
+
#config.site_id = 1999888
|
4
|
+
|
5
|
+
# Put the merchant rang found on the paybox website
|
6
|
+
#config.rang = 32
|
7
|
+
|
8
|
+
# Put the merchant paybox ID found on the paybox website
|
9
|
+
#config.paybox_id = 1686319
|
10
|
+
|
11
|
+
# Put the secret key for the hmac pass found on the paybox website
|
12
|
+
#config.secret_key = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
|
13
|
+
|
14
|
+
# Put the hash algorithm
|
15
|
+
# Possible values are :SHA256 :SHA512 :SHA384 :SHA224
|
16
|
+
config.hash = :sha512
|
17
|
+
|
18
|
+
# The currency
|
19
|
+
# possible values :euro :us_dollar
|
20
|
+
config.currency = :euro
|
21
|
+
|
22
|
+
config.paybox_url = "https://preprod-tpeweb.paybox.com/cgi/MYchoix_pagepaiement.cgi"
|
23
|
+
# config.paybox_url_back_one = nil
|
24
|
+
# config.paybox_url_back_two = nil
|
25
|
+
|
26
|
+
config.callback_values = { amount:"m", ref:"r", auto:"a", error:"e", signature:"k" }
|
27
|
+
|
28
|
+
# Optionnal config : if not null, choose on behalf of the user the type of paiement.
|
29
|
+
# EX: "CARTE". Look at the paybox documentation for more
|
30
|
+
#config.typepaiement = "CARTE"
|
31
|
+
|
32
|
+
# Optionnal config : if not null, choose on behalf of the user the type of CARD.
|
33
|
+
# EX: "CB". Look at the paybox documentation for more
|
34
|
+
#config.typecard = "CB"
|
35
|
+
end
|
data/lib/payr.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'payr/controllers/payr_helpers'
|
2
|
+
require 'payr/controllers/payr_filters'
|
3
|
+
require 'payr/rails/routes'
|
4
|
+
require 'payr/engine'
|
5
|
+
|
6
|
+
|
7
|
+
module Payr
|
8
|
+
autoload :Client, 'payr/client'
|
9
|
+
|
10
|
+
# merchant site id
|
11
|
+
mattr_accessor :site_id
|
12
|
+
@@site_id = nil
|
13
|
+
|
14
|
+
# merchant account secret ID
|
15
|
+
mattr_accessor :secret_key
|
16
|
+
@@secret_key = nil
|
17
|
+
|
18
|
+
# merchant rang number
|
19
|
+
mattr_accessor :rang
|
20
|
+
@@rang = nil
|
21
|
+
|
22
|
+
# merchant paybox identifier
|
23
|
+
mattr_accessor :paybox_id
|
24
|
+
@@paybox_id = nil
|
25
|
+
|
26
|
+
# currency
|
27
|
+
mattr_accessor :currency
|
28
|
+
@@currency = :euro
|
29
|
+
|
30
|
+
mattr_accessor :hash
|
31
|
+
@@hash = :sha512
|
32
|
+
|
33
|
+
mattr_accessor :paybox_url
|
34
|
+
@@paybox_url = nil
|
35
|
+
|
36
|
+
mattr_accessor :paybox_url_back_one
|
37
|
+
@@paybox_url_back_one = nil
|
38
|
+
|
39
|
+
mattr_accessor :paybox_url_back_two
|
40
|
+
@@paybox_url_back_two = nil
|
41
|
+
|
42
|
+
mattr_accessor :callback_values
|
43
|
+
@@callback_values = { amount:"m", ref:"r", auto:"a", error:"e", signature:"k" }
|
44
|
+
|
45
|
+
|
46
|
+
mattr_accessor :typepaiement
|
47
|
+
@@typepaiement = nil
|
48
|
+
|
49
|
+
mattr_accessor :typecard
|
50
|
+
@@typecard = nil
|
51
|
+
|
52
|
+
mattr_accessor :hash
|
53
|
+
@@hash = :sha512
|
54
|
+
|
55
|
+
def self.setup
|
56
|
+
yield self
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.include_helpers(scope)
|
60
|
+
# add methods to action_controller
|
61
|
+
ActiveSupport.on_load(:action_controller) do
|
62
|
+
include scope::PayrFilters
|
63
|
+
end
|
64
|
+
|
65
|
+
# add view helpers
|
66
|
+
ActiveSupport.on_load(:action_view) do
|
67
|
+
include scope::PayrHelpers
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/payr/client.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require "openssl"
|
2
|
+
require "base64"
|
3
|
+
require "net/https"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
module Payr
|
7
|
+
class Client
|
8
|
+
def get_paybox_params_from params
|
9
|
+
raise ArgumentError if params[:command_id].nil? || params[:buyer_email].nil? || params[:total_price].nil?
|
10
|
+
raise ArgumentError if params[:callbacks].nil?
|
11
|
+
command_timestamp = Time.now.utc.iso8601
|
12
|
+
returned_hash = { pbx_site: Payr.site_id,
|
13
|
+
pbx_rang: Payr.rang,
|
14
|
+
pbx_identifiant: Payr.paybox_id,
|
15
|
+
pbx_total: params[:total_price],
|
16
|
+
pbx_devise: convert_currency,
|
17
|
+
pbx_cmd: params[:command_id],
|
18
|
+
pbx_porteur: params[:buyer_email],
|
19
|
+
pbx_retour: build_return_variables(Payr.callback_values),
|
20
|
+
pbx_hash: Payr.hash.upcase,
|
21
|
+
pbx_time: command_timestamp }
|
22
|
+
|
23
|
+
# optionnal parameters
|
24
|
+
returned_hash.merge!(pbx_typepaiement: Payr.typepaiement,
|
25
|
+
pbx_typepcarte: Payr.typecard) unless Payr.typepaiement.nil? || Payr.typecard.nil?
|
26
|
+
|
27
|
+
returned_hash.merge!(pbx_effectue: params[:callbacks][:paid],
|
28
|
+
pbx_refuse: params[:callbacks][:refused],
|
29
|
+
pbx_annule: params[:callbacks][:cancelled],
|
30
|
+
pbx_repondre_a: params[:callbacks][:cancelled])
|
31
|
+
|
32
|
+
returned_hash.merge!(pbx_repondre_a: params[:callbacks][:ipn])
|
33
|
+
|
34
|
+
base_params = self.to_base_params(returned_hash)
|
35
|
+
|
36
|
+
returned_hash.merge(pbx_hmac: self.generate_hmac(base_params))
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def check_response query
|
41
|
+
params = re_build_query query
|
42
|
+
signature = get_signature query
|
43
|
+
signed? params, signature
|
44
|
+
end
|
45
|
+
|
46
|
+
def check_response_ipn params
|
47
|
+
signature = params[:signature]
|
48
|
+
query_params = re_build_ipn_query params
|
49
|
+
signed? query_params, signature
|
50
|
+
end
|
51
|
+
|
52
|
+
def select_server_url
|
53
|
+
[Payr.paybox_url, Payr.paybox_url_back_one, Payr.paybox_url_back_two].each do |url|
|
54
|
+
return url if check_server_availability(url)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
protected
|
60
|
+
def check_server_availability server_url
|
61
|
+
uri = URI.parse(server_url)
|
62
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
63
|
+
http.use_ssl = true
|
64
|
+
|
65
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
66
|
+
response = http.request(request)
|
67
|
+
response.code == "200"
|
68
|
+
end
|
69
|
+
def signed? params, signature
|
70
|
+
public_key = OpenSSL::PKey::RSA.new(File.read(File.expand_path(File.dirname(__FILE__) + '/keys/pubkey.pem')))
|
71
|
+
check_response_verify params, Base64.decode64(Rack::Utils.unescape(signature)), public_key
|
72
|
+
end
|
73
|
+
def get_signature params
|
74
|
+
params[params.index("&signature=")+"&signature=".length..params.length]
|
75
|
+
end
|
76
|
+
def re_build_ipn_query params
|
77
|
+
Payr.callback_values.keys.collect do |key|
|
78
|
+
"#{key}=#{params[key]}" unless key == :signature
|
79
|
+
end.compact.join("&")
|
80
|
+
end
|
81
|
+
def re_build_query params
|
82
|
+
params[params.index("?")+1..params.index("&signature")-1]
|
83
|
+
end
|
84
|
+
def check_response_verify params, signature, pub_key
|
85
|
+
digest = OpenSSL::Digest::SHA1.new
|
86
|
+
pub_key.verify digest, signature, params
|
87
|
+
end
|
88
|
+
|
89
|
+
def generate_hmac base_params
|
90
|
+
binary_key = [Payr.secret_key].pack("H*")
|
91
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(Payr.hash.to_s), binary_key, base_params).upcase
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_base_params params={}
|
95
|
+
params.to_a.collect do |pair|
|
96
|
+
"#{pair[0].upcase}=#{pair[1]}"
|
97
|
+
end.join("&")
|
98
|
+
end
|
99
|
+
|
100
|
+
def build_return_variables variables
|
101
|
+
variables.to_a.collect do |pair|
|
102
|
+
"#{pair[0]}:#{pair[1].capitalize}"
|
103
|
+
end.join(";")
|
104
|
+
end
|
105
|
+
def convert_currency
|
106
|
+
case Payr.currency
|
107
|
+
when :euro
|
108
|
+
978
|
109
|
+
when :us_dollars
|
110
|
+
840
|
111
|
+
else
|
112
|
+
978
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Payr
|
2
|
+
module PayrFilters
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def check_response
|
6
|
+
unless Payr::Client.new.check_response(request.url)
|
7
|
+
redirect_to payr_bills_failure_path
|
8
|
+
return
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def check_ipn_response
|
13
|
+
unless Payr::Client.new.check_response_ipn(params)
|
14
|
+
redirect_to payr_bills_failure_path
|
15
|
+
return
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Payr
|
2
|
+
module PayrHelpers
|
3
|
+
def paybox_hidden_fields opts={}
|
4
|
+
raise ArgumentError if opts.blank?
|
5
|
+
opts.to_a.collect do |pair|
|
6
|
+
hidden_field_tag pair[0].upcase, pair[1]
|
7
|
+
end.join("").html_safe
|
8
|
+
end
|
9
|
+
|
10
|
+
def paybox_form submit_name, opts={}
|
11
|
+
raise ArgumentError if opts.blank?
|
12
|
+
("<form id='payrForm' action='#{Payr::Client.new.select_url}' method='POST'>" +
|
13
|
+
paybox_hidden_fields(opts) +
|
14
|
+
"<input type='submit' value='#{submit_name}'>" +
|
15
|
+
"</form>").html_safe
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/payr/engine.rb
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
-----BEGIN PUBLIC KEY-----
|
2
|
+
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe+hkicNP7ROHUssGNtHwiT2Ew
|
3
|
+
HFrSk/qwrcq8v5metRtTTFPE/nmzSkRnTs3GMpi57rBdxBBJW5W9cpNyGUh0jNXc
|
4
|
+
VrOSClpD5Ri2hER/GcNrxVRP7RlWOqB1C03q4QYmwjHZ+zlM4OUhCCAtSWflB4wC
|
5
|
+
Ka1g88CjFwRw/PB9kwIDAQAB
|
6
|
+
-----END PUBLIC KEY-----
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActionDispatch::Routing
|
2
|
+
class Mapper
|
3
|
+
def payr_routes(options={})
|
4
|
+
["pay", "paid", "refused", "cancelled", "ipn", "failure"].each do |action|
|
5
|
+
if options && options[:callback_controller]
|
6
|
+
get "#{options[:callback_controller]}/#{action}", as: "payr_bills_#{action}"
|
7
|
+
else
|
8
|
+
get "payr/bills/#{action}", as: "payr_bills_#{action}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/payr/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: payr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Vincent Coste
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.8
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.2.8
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sqlite3
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec-rails
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.5'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.5'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: timecop
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: fakeweb
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Paybox System paiement made easy.
|
95
|
+
email:
|
96
|
+
- vincent@chooseyourboss.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- app/assets/javascripts/payr/bills.js.coffee
|
102
|
+
- app/controllers/payr/bills_controller.rb
|
103
|
+
- app/models/payr/bill.rb
|
104
|
+
- app/views/payr/bills/cancelled.html.erb
|
105
|
+
- app/views/payr/bills/failure.html.erb
|
106
|
+
- app/views/payr/bills/paid.html.erb
|
107
|
+
- app/views/payr/bills/pay.html.erb
|
108
|
+
- app/views/payr/bills/refused.html.erb
|
109
|
+
- config/locales/en.yml
|
110
|
+
- config/locales/fr.yml
|
111
|
+
- config/routes.rb
|
112
|
+
- lib/generators/payr/install_generator.rb
|
113
|
+
- lib/generators/templates/migration.rb
|
114
|
+
- lib/generators/templates/payr.rb
|
115
|
+
- lib/payr/client.rb
|
116
|
+
- lib/payr/controllers/payr_filters.rb
|
117
|
+
- lib/payr/controllers/payr_helpers.rb
|
118
|
+
- lib/payr/engine.rb
|
119
|
+
- lib/payr/keys/pubkey.pem
|
120
|
+
- lib/payr/rails/routes.rb
|
121
|
+
- lib/payr/version.rb
|
122
|
+
- lib/payr.rb
|
123
|
+
- lib/tasks/payr_tasks.rake
|
124
|
+
- MIT-LICENSE
|
125
|
+
- Rakefile
|
126
|
+
- README.md
|
127
|
+
homepage: https://github.com/Pasta/payr
|
128
|
+
licenses: []
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ! '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
segments:
|
140
|
+
- 0
|
141
|
+
hash: -750663748071489907
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ! '>='
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
hash: -750663748071489907
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 1.8.24
|
154
|
+
signing_key:
|
155
|
+
specification_version: 3
|
156
|
+
summary: Paybox System paiement made easy..
|
157
|
+
test_files: []
|