system_pay 0.0.5 → 0.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/.rspec +3 -0
- data/Rakefile +7 -0
- data/Readme.markdown +66 -57
- data/lib/system_pay/form_helper.rb +10 -11
- data/lib/system_pay/railtie.rb +27 -0
- data/lib/system_pay/vads.rb +229 -0
- data/lib/system_pay/version.rb +3 -2
- data/lib/system_pay.rb +3 -112
- data/spec/spec_helper.rb +4 -0
- data/spec/system_pay_spec.rb +99 -0
- data/system_pay.gemspec +2 -0
- metadata +33 -14
- data/init.rb +0 -2
data/.rspec
ADDED
data/Rakefile
ADDED
data/Readme.markdown
CHANGED
|
@@ -1,42 +1,44 @@
|
|
|
1
1
|
# SystemPay
|
|
2
2
|
|
|
3
|
-
SystemPay is a gem to ease credit card payment with Natixis Paiements / CyberplusPaiement (
|
|
3
|
+
SystemPay is a gem to ease credit card payment with Natixis Paiements / CyberplusPaiement (Banque Populaire) bank system. It's a Ruby on Rails port of the connexion kits published by the bank.
|
|
4
4
|
|
|
5
|
-
* Gem Homepage : [
|
|
6
|
-
* Cyberplus SystemPay documentation : [
|
|
5
|
+
* Gem Homepage : [http://github.com/iMenlo/system_pay](http://github.com/iMenlo/system_pay)
|
|
6
|
+
* Cyberplus SystemPay documentation : [https://systempay.cyberpluspaiement.com](https://systempay.cyberpluspaiement.com)
|
|
7
7
|
|
|
8
8
|
## INSTALL
|
|
9
9
|
|
|
10
|
-
gem install
|
|
10
|
+
gem install system_pay
|
|
11
11
|
|
|
12
12
|
or, in your Gemfile
|
|
13
13
|
|
|
14
|
-
gem 'system_pay'
|
|
14
|
+
gem 'system_pay'
|
|
15
15
|
|
|
16
16
|
## USAGE
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
Create a config yml data file to store your site_id and certificates values:
|
|
19
|
+
|
|
20
|
+
### in config/system_pay.yml:
|
|
21
|
+
|
|
22
|
+
development:
|
|
23
|
+
vads_site_id: '00000000'
|
|
24
|
+
certificat: '0000000000000000'
|
|
25
|
+
vads_validation_mode: 1
|
|
26
|
+
vads_shop_name: 'My shop'
|
|
27
|
+
vads_shop_url: 'www.example.com'
|
|
28
|
+
production:
|
|
29
|
+
vads_site_id: '00000000'
|
|
30
|
+
certificat: '0000000000000000'
|
|
31
|
+
vads_validation_mode: 0
|
|
32
|
+
vads_shop_name: 'My shop'
|
|
33
|
+
vads_shop_url: 'www.example.com'
|
|
34
|
+
vads_ctx_mode: PRODUCTION
|
|
35
|
+
|
|
36
|
+
# NB: you can place here any of the class variables
|
|
27
37
|
|
|
28
|
-
### in production.rb :
|
|
29
|
-
|
|
30
|
-
# Your production certificat
|
|
31
|
-
SystemPay.certificat = '7193156219823756'
|
|
32
|
-
# Set the production mode
|
|
33
|
-
SystemPay.vads_ctx_mode = 'PRODUCTION'
|
|
34
|
-
|
|
35
|
-
|
|
36
38
|
### in order controller :
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
@system_pay = SystemPay::Vads.new(:amount => @order.amount_in_cents, :trans_id => @order.id)
|
|
41
|
+
# NB: nil instance variables are ignored (not transmitted to the bank server)
|
|
40
42
|
|
|
41
43
|
### in order view :
|
|
42
44
|
|
|
@@ -51,42 +53,49 @@ or, in your Gemfile
|
|
|
51
53
|
protect_from_forgery :except => [:bank_callback]
|
|
52
54
|
|
|
53
55
|
def bank_callback
|
|
54
|
-
@
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
order_transaction = OrderTransaction.find_by_reference params[:reference], :last
|
|
58
|
-
order = order_transaction.order
|
|
59
|
-
|
|
60
|
-
return_code = params['vads_result']
|
|
61
|
-
|
|
62
|
-
if return_code == "Annulation"
|
|
63
|
-
order.cancel!
|
|
64
|
-
order.update_attribute :description, "Paiement refusé par la banque."
|
|
65
|
-
|
|
66
|
-
elsif return_code == "payetest"
|
|
67
|
-
order.pay!
|
|
68
|
-
order.update_attribute :description, "TEST accepté par la banque."
|
|
69
|
-
order_transaction.update_attribute :test, true
|
|
70
|
-
|
|
71
|
-
elsif return_code == "00"
|
|
72
|
-
order.pay!
|
|
73
|
-
order.update_attribute :description, "Paiement accepté par la banque."
|
|
74
|
-
order_transaction.update_attribute :test, false
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
order_transaction.update_attribute :success, true
|
|
78
|
-
|
|
79
|
-
receipt = "0"
|
|
56
|
+
@transaction = Transaction.where(:order_id => params[:vads_order_id], :state => ['sent', 'ready']).first if params[:vads_order_id] =~ /^[\d-]+$/
|
|
57
|
+
unless @transaction
|
|
58
|
+
logger.info "bank_callback ignored: no transaction matching order_id '#{params[:vads_order_id]}'."
|
|
80
59
|
else
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
60
|
+
# store whatever returned parameters you need, at least the payment_certificate:
|
|
61
|
+
@transaction.payment_certificate = params[:vads_payment_certificate]
|
|
62
|
+
@transaction.result = params[:vads_result].to_i
|
|
63
|
+
@transaction.auth_result = params[:vads_auth_result].to_i
|
|
64
|
+
@transaction.extra_result = params[:vads_extra_result].to_i
|
|
65
|
+
@transaction.warranty_result = params[:vads_warranty_result]
|
|
66
|
+
@transaction.card_brand = params[:vads_card_brand]
|
|
67
|
+
begin
|
|
68
|
+
@transaction.expiry_date = DateTime.new(params[:vads_expiry_year].to_i, params[:vads_expiry_month].to_i, 1)
|
|
69
|
+
rescue
|
|
70
|
+
@transaction.expiry_date = DateTime.now
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# or store all returned parameters as text:
|
|
74
|
+
@transaction.returned_params = params.to_a.sort.map{|k,v| "#{k}: #{v}"}.join("\n")
|
|
75
|
+
|
|
76
|
+
# get transaction result
|
|
77
|
+
@result = SystemPay::Vads.diagnose(params)
|
|
78
|
+
|
|
79
|
+
# store
|
|
80
|
+
@transaction.tech_msg = @result[:tech_msg]
|
|
81
|
+
@transaction.user_msg = @result[:user_msg]
|
|
82
|
+
@transaction.save
|
|
83
|
+
|
|
84
|
+
# change state
|
|
85
|
+
case @result[:status]
|
|
86
|
+
when :success
|
|
87
|
+
@transaction.success!
|
|
88
|
+
when :cancel
|
|
89
|
+
@transaction.cancel!
|
|
90
|
+
when :error
|
|
91
|
+
@transaction.error!
|
|
92
|
+
when :bad_params
|
|
93
|
+
@transaction.error!
|
|
94
|
+
end
|
|
86
95
|
end
|
|
87
|
-
render :text => "Pragma: no-cache\nContent-type: text/plain\n\nversion=2\ncdr=#{receipt}"
|
|
88
|
-
end
|
|
89
96
|
|
|
97
|
+
render :text => "Pragma: no-cache\nContent-type: text/plain\n\nversion=V2\nOK"
|
|
98
|
+
end
|
|
90
99
|
|
|
91
100
|
## Thanks
|
|
92
101
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module SystemPay
|
|
3
|
+
module FormHelper
|
|
4
|
+
def system_pay_hidden_fields(system_pay)
|
|
5
|
+
res = "\n"
|
|
6
|
+
system_pay.params.each do |key, value|
|
|
7
|
+
res << hidden_field_tag(key, value) << "\n"
|
|
8
|
+
end
|
|
9
|
+
res.html_safe
|
|
10
|
+
end
|
|
11
11
|
end
|
|
12
|
-
|
|
13
12
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'system_pay/form_helper'
|
|
3
|
+
require 'rails'
|
|
4
|
+
|
|
5
|
+
module SystemPay
|
|
6
|
+
class Railtie < ::Rails::Railtie
|
|
7
|
+
initializer "system_pay.form_helper" do
|
|
8
|
+
ActiveSupport.on_load(:action_controller) do
|
|
9
|
+
helper SystemPay::FormHelper
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
=begin
|
|
13
|
+
config.to_prepare do
|
|
14
|
+
self.setup! # &method(:activate).to_proc
|
|
15
|
+
end
|
|
16
|
+
=end
|
|
17
|
+
|
|
18
|
+
system_pay_config_file = File.join(Rails.root,'config','system_pay.yml')
|
|
19
|
+
raise "#{system_pay_config_file} is missing!" unless File.exists? system_pay_config_file
|
|
20
|
+
system_pay_config = YAML.load_file(system_pay_config_file)[Rails.env].symbolize_keys
|
|
21
|
+
|
|
22
|
+
system_pay_config.each_pair do |n, v|
|
|
23
|
+
SystemPay::Vads.class_variable_set("@@#{n}", v)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module SystemPay
|
|
3
|
+
class Vads
|
|
4
|
+
# pre-defined messages (from 2.2 Guide)
|
|
5
|
+
VADS_RISK_CONTROL_RESULT = {
|
|
6
|
+
'' => 'Pas de contrôle effectué.',
|
|
7
|
+
'00' => 'Tous les contrôles se sont déroulés avec succès.',
|
|
8
|
+
'02' => 'La carte a dépassé l’encours autorisé.',
|
|
9
|
+
'03' => 'La carte appartient à la liste grise du commerçant.',
|
|
10
|
+
'04' => 'Le pays d’émission de la carte appartient à la liste grise du commerçant ou le pays d’émission de la carte n’appartient pas à la liste blanche du commerçant.',
|
|
11
|
+
'05' => 'L’adresse IP appartient à la liste grise du commerçant.',
|
|
12
|
+
'07' => 'La carte appartient à la liste grise BIN du commerçant.',
|
|
13
|
+
'99' => 'Problème technique rencontré par le serveur lors du traitement d’un des contrôles locaux.',
|
|
14
|
+
}
|
|
15
|
+
VADS_QUERY_FORMAT_ERROR = {
|
|
16
|
+
'01' => 'vads_version',
|
|
17
|
+
'02' => 'vads_site_id',
|
|
18
|
+
'03' => 'vads_trans_id',
|
|
19
|
+
'04' => 'vads_trans_date',
|
|
20
|
+
'05' => 'vads_validation_mode',
|
|
21
|
+
'06' => 'vads_capture_delay',
|
|
22
|
+
'07' => 'vads_payment_config',
|
|
23
|
+
'08' => 'vads_payment_cards',
|
|
24
|
+
'09' => 'vads_amount',
|
|
25
|
+
'10' => 'vads_currency',
|
|
26
|
+
'11' => 'vads_ctx_mode',
|
|
27
|
+
'12' => 'vads_language',
|
|
28
|
+
'13' => 'vads_order_id',
|
|
29
|
+
'14' => 'vads_order_info',
|
|
30
|
+
'15' => 'vads_cust_email',
|
|
31
|
+
'16' => 'vads_cust_id',
|
|
32
|
+
'17' => 'vads_cust_title',
|
|
33
|
+
'18' => 'vads_cust_name',
|
|
34
|
+
'19' => 'vads_cust_address',
|
|
35
|
+
'20' => 'vads_cust_zip',
|
|
36
|
+
'21' => 'vads_cust_city',
|
|
37
|
+
'22' => 'vads_cust_country',
|
|
38
|
+
'23' => 'vads_cust_phone',
|
|
39
|
+
'24' => 'vads_url_success',
|
|
40
|
+
'25' => 'vads_url_refused',
|
|
41
|
+
'26' => 'vads_url_referral',
|
|
42
|
+
'27' => 'vads_url_cancel',
|
|
43
|
+
'28' => 'vads_url_return',
|
|
44
|
+
'29' => 'vads_url_error',
|
|
45
|
+
'31' => 'vads_contrib',
|
|
46
|
+
'32' => 'vads_theme_config',
|
|
47
|
+
'46' => 'vads_page_action',
|
|
48
|
+
'47' => 'vads_action_mode',
|
|
49
|
+
'48' => 'vads_return_mode',
|
|
50
|
+
'61' => 'vads_user_info',
|
|
51
|
+
'62' => 'vads_contracts',
|
|
52
|
+
'77' => 'vads_cust_cell_phone'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# fixed params per shop are class variables
|
|
56
|
+
@@target_url = "https://paiement.systempay.fr/vads-payment/"
|
|
57
|
+
cattr_accessor :target_url
|
|
58
|
+
|
|
59
|
+
@@vads_action_mode = 'INTERACTIVE'
|
|
60
|
+
cattr_accessor :vads_action_mode
|
|
61
|
+
|
|
62
|
+
@@vads_ctx_mode = 'TEST' # or 'PRODUCTION'
|
|
63
|
+
cattr_accessor :vads_ctx_mode
|
|
64
|
+
|
|
65
|
+
@@vads_contrib = 'Ruby'
|
|
66
|
+
cattr_accessor :vads_contrib
|
|
67
|
+
|
|
68
|
+
@@vads_page_action = 'PAYMENT'
|
|
69
|
+
cattr_accessor :vads_page_action
|
|
70
|
+
|
|
71
|
+
@@vads_payment_config = 'SINGLE'
|
|
72
|
+
cattr_accessor :vads_payment_config
|
|
73
|
+
|
|
74
|
+
@@vads_return_mode = 'POST' # or 'GET', but request in GET could be too large
|
|
75
|
+
cattr_accessor :vads_return_mode
|
|
76
|
+
|
|
77
|
+
@@vads_site_id = '000000'
|
|
78
|
+
cattr_accessor :vads_site_id
|
|
79
|
+
|
|
80
|
+
@@vads_validation_mode = '1'
|
|
81
|
+
cattr_accessor :vads_validation_mode
|
|
82
|
+
|
|
83
|
+
@@vads_version = 'V2'
|
|
84
|
+
cattr_accessor :vads_version
|
|
85
|
+
|
|
86
|
+
@@certificat = '0000000000000000'
|
|
87
|
+
cattr_accessor :certificat
|
|
88
|
+
|
|
89
|
+
@@vads_shop_name = ''
|
|
90
|
+
cattr_accessor :vads_shop_name
|
|
91
|
+
|
|
92
|
+
@@vads_shop_url = ''
|
|
93
|
+
cattr_accessor :vads_shop_url
|
|
94
|
+
|
|
95
|
+
# transaction parameters are instance variables
|
|
96
|
+
attr_accessor :vads_amount, :vads_available_languages, :vads_capture_delay, :vads_contracts, :vads_currency,
|
|
97
|
+
:vads_cust_address, :vads_cust_cell_phone, :vads_cust_city, :vads_cust_country, :vads_cust_email, :vads_cust_id,
|
|
98
|
+
:vads_cust_name, :vads_cust_phone, :vads_cust_title, :vads_cust_zip, :vads_cust_city,
|
|
99
|
+
:vads_language, :vads_order_id, :vads_order_info, :vads_order_info2, :vads_order_info3, :vads_payment_cards,
|
|
100
|
+
:vads_redirect_error_message, :vads_redirect_error_timeout,
|
|
101
|
+
:vads_redirect_success_message, :vads_redirect_success_timeout,
|
|
102
|
+
:vads_ship_to_city, :vads_ship_to_country, :vads_ship_to_name, :vads_ship_to_phone_num, :vads_ship_to_state,
|
|
103
|
+
:vads_ship_to_street, :vads_ship_to_street2, :vads_ship_to_zip, :vads_theme_config, :vads_trans_date,
|
|
104
|
+
:vads_trans_id, :vads_url_cancel, :vads_url_error, :vads_url_referral, :vads_url_refused, :vads_url_success,
|
|
105
|
+
:vads_url_return
|
|
106
|
+
|
|
107
|
+
# Public: Creation of new instance.
|
|
108
|
+
#
|
|
109
|
+
# args - The hash of systempay parameters as described in the implementation
|
|
110
|
+
# document. Note that each key should *not* contain the vads_ prefix.
|
|
111
|
+
# :amount - Should be in cents
|
|
112
|
+
# :trans_id - Will be automatically padded with zeros
|
|
113
|
+
#
|
|
114
|
+
# Examples
|
|
115
|
+
#
|
|
116
|
+
# SystemPay::Vads.new(:amount => 100, :trans_id => 10, :url_return => 'http://mywebsite.com/return_url')
|
|
117
|
+
#
|
|
118
|
+
# Returns a new instance object
|
|
119
|
+
def initialize(args=nil)
|
|
120
|
+
args.each do |k,v|
|
|
121
|
+
if k.to_s.match(/^vads_/)
|
|
122
|
+
instance_variable_set("@#{k}", v) if v.present? && respond_to?(k)
|
|
123
|
+
else
|
|
124
|
+
instance_variable_set("@vads_#{k}", v) if v.present? && respond_to?("vads_#{k}")
|
|
125
|
+
end
|
|
126
|
+
end if args
|
|
127
|
+
|
|
128
|
+
raise ArgumentError.new("You must specify a non blank :amount parameter") unless @vads_amount.present?
|
|
129
|
+
raise ArgumentError.new("You must specify a non blank :trans_id parameter") unless @vads_trans_id.present?
|
|
130
|
+
|
|
131
|
+
@vads_currency ||= '978' # Euros
|
|
132
|
+
@vads_trans_date ||= Time.now.utc.strftime("%Y%m%d%H%M%S")
|
|
133
|
+
@vads_trans_id = (@vads_trans_id % 900000).to_s.rjust(6, '0')
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Public: Compute the signature of the request based on the parameters
|
|
137
|
+
#
|
|
138
|
+
# Returns the signature string
|
|
139
|
+
def signature
|
|
140
|
+
self.class.sign(sorted_values)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Public: Hash with non-nil parameters (and value) and their signature
|
|
144
|
+
#
|
|
145
|
+
# Returns a hash
|
|
146
|
+
def params
|
|
147
|
+
Hash[sorted_array + [['signature', signature]]]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Public: Verify that the returned signature is valid.
|
|
151
|
+
# Return boolean
|
|
152
|
+
def self.valid_signature?(params)
|
|
153
|
+
vads_params = params.sort.select{|value| value[0].to_s.match(/^vads_/)}.map{|value| value[1]}
|
|
154
|
+
sign(vads_params) == params['signature']
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Public: Diagnose result from returned params
|
|
158
|
+
#
|
|
159
|
+
# params - The hash of params returned by the bank.
|
|
160
|
+
#
|
|
161
|
+
# Returns a hash { :status => :error | :success | :canceled | :bad_params,
|
|
162
|
+
# :user_msg => "msg for user",
|
|
163
|
+
# :tech_msg => "msg for back-office" }
|
|
164
|
+
def self.diagnose(params)
|
|
165
|
+
if params[:vads_result].blank?
|
|
166
|
+
{ :status => :bad_params,
|
|
167
|
+
:user_msg => 'Vous allez être redirigé vers la page d’accueil',
|
|
168
|
+
:tech_msg => 'vads_result est vide. Suspicion de tentative de fraude.' }
|
|
169
|
+
elsif !valid_signature?(params)
|
|
170
|
+
{ :status => :bad_params,
|
|
171
|
+
:user_msg => 'Vous allez être redirigé vers la page d’accueil',
|
|
172
|
+
:tech_msg => 'La signature ne correspond pas. Suspicion de tentative de fraude.' }
|
|
173
|
+
else case params[:vads_result]
|
|
174
|
+
when '00'
|
|
175
|
+
{ :status => :success,
|
|
176
|
+
:user_msg => 'Votre paiement a été accepté par la banque.',
|
|
177
|
+
:tech_msg => "Paiement accepté. #{VADS_RISK_CONTROL_RESULT[params[:vads_extra_result]]}" }
|
|
178
|
+
when '02'
|
|
179
|
+
{ :status => :error,
|
|
180
|
+
:user_msg => 'Nous devons entrer en relation avec votre banque avant d’obtenir confirmation du paiement.',
|
|
181
|
+
:tech_msg => 'Le commerçant doit contacter la banque du porteur.' }
|
|
182
|
+
when '05'
|
|
183
|
+
{ :status => :error,
|
|
184
|
+
:user_msg => 'Le paiement a été refusé par la banque.',
|
|
185
|
+
:tech_msg => "Paiement refusé par la banque. #{VADS_RISK_CONTROL_RESULT[params[:vads_extra_result]]}" }
|
|
186
|
+
when '17'
|
|
187
|
+
{ :status => :canceled,
|
|
188
|
+
:user_msg => 'Vous avez annulé votre paiement.',
|
|
189
|
+
:tech_msg => 'Paiement annulé par le client.' }
|
|
190
|
+
when '30'
|
|
191
|
+
{ :status => :bad_params,
|
|
192
|
+
:user_msg => 'En raison d’une erreur technique, le paiement n’a pu être validé.',
|
|
193
|
+
:tech_msg => "Erreur de format dans la requête (champ #{VADS_QUERY_FORMAT_ERROR[params[:vads_extra_result]]}). Signaler au développeur." }
|
|
194
|
+
when '96'
|
|
195
|
+
{ :status => :bad_params,
|
|
196
|
+
:user_msg => 'En raison d’une erreur technique, le paiement n’a pu être validé.',
|
|
197
|
+
:tech_msg => 'Code vads_result inconnu. Signaler au développeur.' }
|
|
198
|
+
else
|
|
199
|
+
{ :status => :bad_params,
|
|
200
|
+
:user_msg => 'En raison d’une erreur technique, le paiement n’a pu être validé.',
|
|
201
|
+
:tech_msg => 'Code vads_result inconnu. Signaler au développeur.' }
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
private
|
|
207
|
+
|
|
208
|
+
def self.sign(values)
|
|
209
|
+
Digest::SHA1.hexdigest((values+[certificat]).join("+"))
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def instance_variables_array
|
|
213
|
+
instance_variables.map { |name| v = instance_variable_get(name) ; v.nil? ? nil : [name[1..-1], v] }.compact
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def self.class_variables_array
|
|
217
|
+
class_variables.select{|name| name.match(/^@@vads_/)}.map { |name| [name[2..-1], class_variable_get(name)] }
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def sorted_array
|
|
221
|
+
(instance_variables_array + self.class.class_variables_array).uniq.sort
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def sorted_values
|
|
225
|
+
sorted_array.map{|value| value[1]}
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
end
|
|
229
|
+
end
|
data/lib/system_pay/version.rb
CHANGED
data/lib/system_pay.rb
CHANGED
|
@@ -1,112 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
@@target_url = "https://paiement.systempay.fr/vads-payment/"
|
|
6
|
-
cattr_accessor :target_url
|
|
7
|
-
|
|
8
|
-
@@vads_action_mode = 'INTERACTIVE'
|
|
9
|
-
cattr_accessor :vads_action_mode
|
|
10
|
-
|
|
11
|
-
@@vads_ctx_mode = 'TEST' # or 'PRODUCTION'
|
|
12
|
-
cattr_accessor :vads_ctx_mode
|
|
13
|
-
|
|
14
|
-
@@vads_contrib = 'Ruby'
|
|
15
|
-
cattr_accessor :vads_contrib
|
|
16
|
-
|
|
17
|
-
@@vads_page_action = 'PAYMENT'
|
|
18
|
-
cattr_accessor :vads_page_action
|
|
19
|
-
|
|
20
|
-
@@vads_payment_config = 'SINGLE'
|
|
21
|
-
cattr_accessor :vads_payment_config
|
|
22
|
-
|
|
23
|
-
@@vads_return_mode = 'GET'
|
|
24
|
-
cattr_accessor :vads_return_mode
|
|
25
|
-
|
|
26
|
-
@@vads_site_id = '123456' # change this value
|
|
27
|
-
cattr_accessor :vads_site_id
|
|
28
|
-
|
|
29
|
-
@@vads_validation_mode = '1'
|
|
30
|
-
cattr_accessor :vads_validation_mode
|
|
31
|
-
|
|
32
|
-
@@vads_version = 'V2'
|
|
33
|
-
cattr_accessor :vads_version
|
|
34
|
-
|
|
35
|
-
@@certificat = '1122334455667788'
|
|
36
|
-
cattr_accessor :certificat
|
|
37
|
-
|
|
38
|
-
attr_accessor :vads_amount, :vads_available_languages, :vads_capture_delay, :vads_contracts, :vads_currency, :vads_cust_address, :vads_cust_cell_phone,
|
|
39
|
-
:vads_cust_email, :vads_redirect_error_message, :vads_redirect_success_message, :vads_trans_date, :vads_trans_id, :vads_url_cancel, :vads_url_error,
|
|
40
|
-
:vads_url_referral, :vads_url_refused, :vads_url_success
|
|
41
|
-
|
|
42
|
-
# Public: Creation of new instance.
|
|
43
|
-
#
|
|
44
|
-
# args - The hash of systempay parameters as describe in the implementation
|
|
45
|
-
# document. Note that each key should *not* contain the vads_ prefix.
|
|
46
|
-
# :amount - Should be in cents
|
|
47
|
-
# :trans_id - Will be automatically padded with zeros
|
|
48
|
-
#
|
|
49
|
-
# Examples
|
|
50
|
-
#
|
|
51
|
-
# SystemPay.new(:amount => 100, :trans_id => 10, :url_return => 'http://mywebsite.com/return_url')
|
|
52
|
-
#
|
|
53
|
-
# Returns a new instance object
|
|
54
|
-
def initialize args=nil
|
|
55
|
-
args.each do |k,v|
|
|
56
|
-
if k.to_s.match(/^vads_/)
|
|
57
|
-
instance_variable_set("@#{k}", v) if v.present? && respond_to?(k)
|
|
58
|
-
else
|
|
59
|
-
instance_variable_set("@vads_#{k}", v) if v.present? && respond_to?("vads_#{k}")
|
|
60
|
-
end
|
|
61
|
-
end if args
|
|
62
|
-
|
|
63
|
-
raise ArgumentError.new("You must specify a non blank :amount parameter") unless @vads_amount.present?
|
|
64
|
-
raise ArgumentError.new("You must specify a non blank :trans_id parameter") unless @vads_trans_id.present?
|
|
65
|
-
|
|
66
|
-
@vads_currency ||= '978' # Euros
|
|
67
|
-
@vads_trans_date ||= Time.now.strftime("%Y%m%d%H%M%S")
|
|
68
|
-
@vads_trans_id = @vads_trans_id.to_s.rjust(6, '0')
|
|
69
|
-
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Public: Perform the signature of the request based on the parameters
|
|
73
|
-
def signature
|
|
74
|
-
self.class.sign(sorted_values)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Public: Hash with parameters and value of the object
|
|
78
|
-
def params
|
|
79
|
-
Hash[sorted_array + [['signature', signature]]]
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Public: Verify that the returned signature is valid.
|
|
83
|
-
# Return boolean
|
|
84
|
-
def self.valid_signature?(params)
|
|
85
|
-
vads_params = params.sort.select{|value| value[0].match(/^vads_/)}.map{|value| value[1]}
|
|
86
|
-
sign(vads_params) == params['signature']
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
private
|
|
91
|
-
|
|
92
|
-
def self.sign(values)
|
|
93
|
-
Digest::SHA1.hexdigest((values+[certificat]).join("+"))
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def instance_variables_array
|
|
97
|
-
instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def self.class_variables_array
|
|
101
|
-
class_variables.select{|name| name.match(/^@@vads_/)}.map { |name| [name[2..-1], class_variable_get(name)] }
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def sorted_array
|
|
105
|
-
(instance_variables_array + self.class.class_variables_array).uniq.sort
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def sorted_values
|
|
109
|
-
sorted_array.map{|value| value[1]}
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
end
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'system_pay/railtie' if defined?(Rails)
|
|
3
|
+
require 'system_pay/vads'
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe SystemPay do
|
|
4
|
+
|
|
5
|
+
context "configuration" do
|
|
6
|
+
before(:each) do
|
|
7
|
+
SystemPay::Vads.vads_site_id = nil
|
|
8
|
+
SystemPay::Vads.certificat = nil
|
|
9
|
+
SystemPay::Vads.vads_ctx_mode = nil
|
|
10
|
+
SystemPay::Vads.vads_contrib = nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should allow setting of the vads_site_id" do
|
|
14
|
+
SystemPay::Vads.vads_site_id = '228159'
|
|
15
|
+
SystemPay::Vads.vads_site_id.should == '228159'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should allow setting of the certificate" do
|
|
19
|
+
SystemPay::Vads.certificat = '1234194862125022'
|
|
20
|
+
SystemPay::Vads.certificat.should == '1234194862125022'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should allow setting of the production mode" do
|
|
24
|
+
SystemPay::Vads.vads_ctx_mode = 'PRODUCTION'
|
|
25
|
+
SystemPay::Vads.vads_ctx_mode.should == 'PRODUCTION'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should allow setting of the contribution name" do
|
|
29
|
+
SystemPay::Vads.vads_contrib = 'Rspec'
|
|
30
|
+
SystemPay::Vads.vads_contrib.should == 'Rspec'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
before(:all) do
|
|
37
|
+
SystemPay::Vads.vads_site_id = '654321'
|
|
38
|
+
SystemPay::Vads.certificat = '8877665544332211'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe '.new' do
|
|
42
|
+
it 'should raise an error if the amount parameter is not set' do
|
|
43
|
+
lambda do
|
|
44
|
+
system_pay = SystemPay::Vads.new(:trans_id => 1)
|
|
45
|
+
end.should raise_error(ArgumentError)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'should raise an error if the trans_id parameter is not set' do
|
|
49
|
+
lambda do
|
|
50
|
+
system_pay = SystemPay::Vads.new(:amount => 100)
|
|
51
|
+
end.should raise_error(ArgumentError)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'should pass with trans_id and amount parameters passed' do
|
|
55
|
+
lambda do
|
|
56
|
+
system_pay = SystemPay::Vads.new(:amount => 100, :trans_id => 2)
|
|
57
|
+
end.should_not raise_error
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe '#signature' do
|
|
63
|
+
|
|
64
|
+
it 'should return a correct signature' do
|
|
65
|
+
system_pay = SystemPay::Vads.new(:amount => 100, :trans_id => 2, :trans_date => "20120420121326")
|
|
66
|
+
system_pay.signature.should == 'f5bec689b57ebefa81c84d184f4bca05e7e8e106'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe '#params' do
|
|
72
|
+
|
|
73
|
+
it 'should return the params to pass to the bank' do
|
|
74
|
+
system_pay = SystemPay::Vads.new(:amount => 100, :trans_id => 2, :trans_date => "20120420121326")
|
|
75
|
+
params = {"vads_payment_config"=>"SINGLE", "vads_ctx_mode"=>nil, "vads_contrib"=>"Rspec", "vads_action_mode"=>"INTERACTIVE", "vads_page_action"=>"PAYMENT", "vads_validation_mode"=>"1", "vads_shop_url"=>"", "vads_trans_id"=>"000002", "vads_site_id"=>nil, "signature"=>"f5bec689b57ebefa81c84d184f4bca05e7e8e106", "vads_return_mode"=>"POST", "vads_currency"=>"978", "vads_shop_name"=>"", "vads_amount"=>100, "vads_version"=>"V2", "vads_trans_date"=>"20120420121326"}
|
|
76
|
+
|
|
77
|
+
system_pay.params.should == params
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe '.valid_signature?' do
|
|
83
|
+
|
|
84
|
+
it 'should return true when valid params are entered' do
|
|
85
|
+
params = {"vads_payment_config"=>"SINGLE", "vads_ctx_mode"=>nil, "vads_contrib"=>"Rspec", "vads_action_mode"=>"INTERACTIVE", "vads_page_action"=>"PAYMENT", "vads_validation_mode"=>"1", "vads_shop_url"=>"", "vads_trans_id"=>"000002", "vads_site_id"=>nil, "signature"=>"f5bec689b57ebefa81c84d184f4bca05e7e8e106", "vads_return_mode"=>"POST", "vads_currency"=>"978", "vads_shop_name"=>"", "vads_amount"=>100, "vads_version"=>"V2", "vads_trans_date"=>"20120420121326"}
|
|
86
|
+
|
|
87
|
+
SystemPay::Vads.valid_signature?(params).should be_true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'should return false when invalid params are entered' do
|
|
91
|
+
params = {"vads_payment_config"=>"SINGLE", "vads_ctx_mode"=>nil, "vads_contrib"=>"Rspec", "vads_action_mode"=>"INTERACTIVE", "vads_page_action"=>"PAYMENT", "vads_validation_mode"=>"1", "vads_shop_url"=>"", "vads_trans_id"=>"000002", "vads_site_id"=>nil, "signature"=>"f6bec689b57ebefa81c84d184f4bca05e7e8e106", "vads_return_mode"=>"POST", "vads_currency"=>"978", "vads_shop_name"=>"", "vads_amount"=>100, "vads_version"=>"V2", "vads_trans_date"=>"20120420121326"}
|
|
92
|
+
|
|
93
|
+
SystemPay::Vads.valid_signature?(params).should be_false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
end
|
data/system_pay.gemspec
CHANGED
|
@@ -14,6 +14,8 @@ Gem::Specification.new do |s|
|
|
|
14
14
|
s.email = ['sylvain@imenlo.com']
|
|
15
15
|
s.homepage = 'https://github.com/iMenlo/system_pay'
|
|
16
16
|
|
|
17
|
+
s.add_dependency "rails", "~> 3.0"
|
|
18
|
+
|
|
17
19
|
s.add_development_dependency "active_support", "~> 3.0.0"
|
|
18
20
|
s.add_development_dependency 'rake', '~> 0.9.2'
|
|
19
21
|
s.add_development_dependency 'rspec', '~> 2.6.0'
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: system_pay
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 27
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
|
+
- 1
|
|
8
9
|
- 0
|
|
9
|
-
|
|
10
|
-
version: 0.0.5
|
|
10
|
+
version: 0.1.0
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Sylvain Gautier (iMenlo)
|
|
@@ -15,13 +15,27 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date:
|
|
19
|
-
default_executable:
|
|
18
|
+
date: 2013-01-11 00:00:00 Z
|
|
20
19
|
dependencies:
|
|
21
20
|
- !ruby/object:Gem::Dependency
|
|
22
|
-
name:
|
|
21
|
+
name: rails
|
|
23
22
|
prerelease: false
|
|
24
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
+
none: false
|
|
25
|
+
requirements:
|
|
26
|
+
- - ~>
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
hash: 7
|
|
29
|
+
segments:
|
|
30
|
+
- 3
|
|
31
|
+
- 0
|
|
32
|
+
version: "3.0"
|
|
33
|
+
type: :runtime
|
|
34
|
+
version_requirements: *id001
|
|
35
|
+
- !ruby/object:Gem::Dependency
|
|
36
|
+
name: active_support
|
|
37
|
+
prerelease: false
|
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
25
39
|
none: false
|
|
26
40
|
requirements:
|
|
27
41
|
- - ~>
|
|
@@ -33,11 +47,11 @@ dependencies:
|
|
|
33
47
|
- 0
|
|
34
48
|
version: 3.0.0
|
|
35
49
|
type: :development
|
|
36
|
-
version_requirements: *
|
|
50
|
+
version_requirements: *id002
|
|
37
51
|
- !ruby/object:Gem::Dependency
|
|
38
52
|
name: rake
|
|
39
53
|
prerelease: false
|
|
40
|
-
requirement: &
|
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
41
55
|
none: false
|
|
42
56
|
requirements:
|
|
43
57
|
- - ~>
|
|
@@ -49,11 +63,11 @@ dependencies:
|
|
|
49
63
|
- 2
|
|
50
64
|
version: 0.9.2
|
|
51
65
|
type: :development
|
|
52
|
-
version_requirements: *
|
|
66
|
+
version_requirements: *id003
|
|
53
67
|
- !ruby/object:Gem::Dependency
|
|
54
68
|
name: rspec
|
|
55
69
|
prerelease: false
|
|
56
|
-
requirement: &
|
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
|
57
71
|
none: false
|
|
58
72
|
requirements:
|
|
59
73
|
- - ~>
|
|
@@ -65,7 +79,7 @@ dependencies:
|
|
|
65
79
|
- 0
|
|
66
80
|
version: 2.6.0
|
|
67
81
|
type: :development
|
|
68
|
-
version_requirements: *
|
|
82
|
+
version_requirements: *id004
|
|
69
83
|
description: SystemPay is a gem to ease credit card payment with Natixis Paiements / CyberplusPaiement bank system. It's a Ruby on Rails port of the connexion kits published by the bank.
|
|
70
84
|
email:
|
|
71
85
|
- sylvain@imenlo.com
|
|
@@ -76,14 +90,18 @@ extensions: []
|
|
|
76
90
|
extra_rdoc_files: []
|
|
77
91
|
|
|
78
92
|
files:
|
|
93
|
+
- .rspec
|
|
79
94
|
- Gemspec
|
|
95
|
+
- Rakefile
|
|
80
96
|
- Readme.markdown
|
|
81
|
-
- init.rb
|
|
82
97
|
- lib/system_pay.rb
|
|
83
98
|
- lib/system_pay/form_helper.rb
|
|
99
|
+
- lib/system_pay/railtie.rb
|
|
100
|
+
- lib/system_pay/vads.rb
|
|
84
101
|
- lib/system_pay/version.rb
|
|
102
|
+
- spec/spec_helper.rb
|
|
103
|
+
- spec/system_pay_spec.rb
|
|
85
104
|
- system_pay.gemspec
|
|
86
|
-
has_rdoc: true
|
|
87
105
|
homepage: https://github.com/iMenlo/system_pay
|
|
88
106
|
licenses: []
|
|
89
107
|
|
|
@@ -113,9 +131,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
113
131
|
requirements: []
|
|
114
132
|
|
|
115
133
|
rubyforge_project:
|
|
116
|
-
rubygems_version: 1.
|
|
134
|
+
rubygems_version: 1.8.24
|
|
117
135
|
signing_key:
|
|
118
136
|
specification_version: 3
|
|
119
137
|
summary: Ruby wrapper for Natixis Paiements / CyberplusPaiement payment api
|
|
120
138
|
test_files: []
|
|
121
139
|
|
|
140
|
+
has_rdoc:
|
data/init.rb
DELETED