activemerchant_paybox_direct_plus 0.2.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/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "activemerchant", "~> 1.10"
10
+ gem "shoulda", ">= 0"
11
+ gem "bundler"
12
+ gem "jeweler"
13
+ gem "simplecov"
14
+ gem 'money'
15
+ gem 'mocha'
16
+ gem 'activesupport'
17
+ gem 'actionpack', ">=3.0"
18
+ end
@@ -0,0 +1,90 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionpack (3.2.12)
5
+ activemodel (= 3.2.12)
6
+ activesupport (= 3.2.12)
7
+ builder (~> 3.0.0)
8
+ erubis (~> 2.7.0)
9
+ journey (~> 1.0.4)
10
+ rack (~> 1.4.5)
11
+ rack-cache (~> 1.2)
12
+ rack-test (~> 0.6.1)
13
+ sprockets (~> 2.2.1)
14
+ active_utils (1.0.5)
15
+ activesupport (>= 2.3.11)
16
+ i18n
17
+ activemerchant (1.32.1)
18
+ active_utils (>= 1.0.2)
19
+ activesupport (>= 2.3.14)
20
+ builder (>= 2.0.0)
21
+ i18n
22
+ json (>= 1.5.1)
23
+ money
24
+ nokogiri
25
+ activemodel (3.2.12)
26
+ activesupport (= 3.2.12)
27
+ builder (~> 3.0.0)
28
+ activesupport (3.2.12)
29
+ i18n (~> 0.6)
30
+ multi_json (~> 1.0)
31
+ bourne (1.4.0)
32
+ mocha (~> 0.13.2)
33
+ builder (3.0.4)
34
+ erubis (2.7.0)
35
+ git (1.2.5)
36
+ hike (1.2.2)
37
+ i18n (0.6.4)
38
+ jeweler (1.8.4)
39
+ bundler (~> 1.0)
40
+ git (>= 1.2.5)
41
+ rake
42
+ rdoc
43
+ journey (1.0.4)
44
+ json (1.7.7)
45
+ metaclass (0.0.1)
46
+ mocha (0.13.3)
47
+ metaclass (~> 0.0.1)
48
+ money (5.1.1)
49
+ i18n (~> 0.6.0)
50
+ multi_json (1.7.3)
51
+ nokogiri (1.5.9)
52
+ rack (1.4.5)
53
+ rack-cache (1.2)
54
+ rack (>= 0.4)
55
+ rack-test (0.6.2)
56
+ rack (>= 1.0)
57
+ rake (10.0.4)
58
+ rdoc (4.0.1)
59
+ json (~> 1.4)
60
+ shoulda (3.4.0)
61
+ shoulda-context (~> 1.0, >= 1.0.1)
62
+ shoulda-matchers (~> 1.0, >= 1.4.1)
63
+ shoulda-context (1.1.1)
64
+ shoulda-matchers (1.5.6)
65
+ activesupport (>= 3.0.0)
66
+ bourne (~> 1.3)
67
+ simplecov (0.7.1)
68
+ multi_json (~> 1.0)
69
+ simplecov-html (~> 0.7.1)
70
+ simplecov-html (0.7.1)
71
+ sprockets (2.2.2)
72
+ hike (~> 1.2)
73
+ multi_json (~> 1.0)
74
+ rack (~> 1.0)
75
+ tilt (~> 1.1, != 1.3.0)
76
+ tilt (1.4.0)
77
+
78
+ PLATFORMS
79
+ ruby
80
+
81
+ DEPENDENCIES
82
+ actionpack (>= 3.0)
83
+ activemerchant (~> 1.10)
84
+ activesupport
85
+ bundler
86
+ jeweler
87
+ mocha
88
+ money
89
+ shoulda
90
+ simplecov
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011.
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.
@@ -0,0 +1,45 @@
1
+ ## Paybox Direct Plus
2
+
3
+ This is a implementation of Paybox Direct Plus for ActiveMerchant.
4
+ Paybox Direct Plus is a French payment solution allowing recurring payments, subscriptions, etc.
5
+
6
+ ### Use and important information
7
+
8
+ You have to create a Paybox user profile for every user you want to charge :
9
+
10
+ response = @gateway.create_payment_profile(@amount, @credit_card, { :user_reference => "YOUR_USER_REFERENCE" })
11
+
12
+ When creating a user profile, Paybox will do an authorization on the credit card. Thefore Paybox recommends that you give the same amount than your transaction
13
+ when registering a user, so that you can do a `capture` after.
14
+
15
+ The Paybox response contains the identifier `response.params["authorization"]` that may be saved in order to void or capture the transaction.
16
+
17
+ @gateway.capture(@amount, response.params["authorization"], { :user_reference => "YOUR_USER_REFERENCE", :order_id => "ORDER_REFERENCE" })
18
+
19
+ Using the `purchase` method will do an authorization and a capture. Some banks requires some delay between 2 authorizations on the same card. So if you register
20
+ a profile then call `purchase` just after instead of `capture`, it may fail with some banks.
21
+
22
+ When registering a new user, you will get a credit card reference in the response you get from Paybox : `response.params["credit_card_reference"])`.
23
+
24
+ This is the reference you will have to add in the options when calling `purcharse` or `authorization` methods. You still have to pass a credit_card object but it will
25
+ only be used for the validation date and CVV number.
26
+
27
+ @gateway.purchase(@amount, @credit_card, { :user_reference => "YOUR_USER_REFERENCE", :order_id => "ORDER_REFERENCE", :credit_card_reference => @credit_card_reference })
28
+
29
+ ### Compatibility
30
+
31
+ For Ruby 1.8, use version 0.1.0.
32
+ For Ruby 1.9 & 2.0 use latest version (>=0.2.0)
33
+
34
+ ### Tests
35
+
36
+ Remote integrations tests using the Paybox tests logins and server are available and should always pass.
37
+
38
+ ### Credits
39
+
40
+ The base of all this work is Donald Piret's great work on Paybox Direct Gateway implementation.
41
+
42
+ ### Contact
43
+
44
+ Please don't hesitate to contact me if you have any question, any suggestion or if you found any bug.
45
+
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "activemerchant_paybox_direct_plus"
16
+ gem.homepage = "https://github.com/arambert/Paybox-Direct-Plus"
17
+ gem.license = "MIT"
18
+ gem.summary = "Paybox Direct Plus for ActiveMerchant"
19
+ gem.description = "Paybox Direct Plus ActiveMerchant Billing Gateway implementation"
20
+ gem.email = "nospam@nospam.com"
21
+ gem.authors = ["donaldpiret", "arambert", "slainer68"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ gem.add_runtime_dependency 'activemerchant', '~> 1.10'
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rake/testtask'
31
+
32
+ namespace :test do
33
+ Rake::TestTask.new(:test) do |test|
34
+ test.libs << 'lib' << 'test'
35
+ test.pattern = 'test/**/test_*.rb'
36
+ test.verbose = true
37
+ end
38
+
39
+ Rake::TestTask.new(:units) do |t|
40
+ t.pattern = 'test/unit/**/*_test.rb'
41
+ t.ruby_opts << '-rubygems'
42
+ t.libs << 'test'
43
+ t.verbose = true
44
+ end
45
+
46
+ Rake::TestTask.new(:remote) do |t|
47
+ t.pattern = 'test/remote/**/*_test.rb'
48
+ t.ruby_opts << '-rubygems'
49
+ t.libs << 'test'
50
+ t.verbose = true
51
+ end
52
+ end
53
+
54
+ task :default => :test
55
+
56
+ require 'rdoc/task'
57
+ Rake::RDocTask.new do |rdoc|
58
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
59
+
60
+ rdoc.rdoc_dir = 'rdoc'
61
+ rdoc.title = "testyop #{version}"
62
+ rdoc.rdoc_files.include('README*')
63
+ rdoc.rdoc_files.include('lib/**/*.rb')
64
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,77 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "activemerchant_paybox_direct_plus"
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["donaldpiret", "arambert", "slainer68"]
12
+ s.date = "2013-05-06"
13
+ s.description = "Paybox Direct Plus ActiveMerchant Billing Gateway implementation"
14
+ s.email = "nospam@nospam.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE.txt",
23
+ "README.markdown",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "activemerchant_paybox_direct_plus.gemspec",
27
+ "lib/activemerchant_paybox_direct_plus.rb",
28
+ "test/fixtures.yml",
29
+ "test/remote/gateways/remote_paybox_direct_plus_test.rb",
30
+ "test/test_helper.rb"
31
+ ]
32
+ s.homepage = "https://github.com/arambert/Paybox-Direct-Plus"
33
+ s.licenses = ["MIT"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = "1.8.15"
36
+ s.summary = "Paybox Direct Plus for ActiveMerchant"
37
+
38
+ if s.respond_to? :specification_version then
39
+ s.specification_version = 3
40
+
41
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
42
+ s.add_development_dependency(%q<activemerchant>, ["~> 1.10"])
43
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
44
+ s.add_development_dependency(%q<bundler>, [">= 0"])
45
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
46
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
47
+ s.add_development_dependency(%q<money>, [">= 0"])
48
+ s.add_development_dependency(%q<mocha>, [">= 0"])
49
+ s.add_development_dependency(%q<activesupport>, [">= 0"])
50
+ s.add_development_dependency(%q<actionpack>, [">= 3.0"])
51
+ s.add_runtime_dependency(%q<activemerchant>, ["~> 1.10"])
52
+ else
53
+ s.add_dependency(%q<activemerchant>, ["~> 1.10"])
54
+ s.add_dependency(%q<shoulda>, [">= 0"])
55
+ s.add_dependency(%q<bundler>, [">= 0"])
56
+ s.add_dependency(%q<jeweler>, [">= 0"])
57
+ s.add_dependency(%q<simplecov>, [">= 0"])
58
+ s.add_dependency(%q<money>, [">= 0"])
59
+ s.add_dependency(%q<mocha>, [">= 0"])
60
+ s.add_dependency(%q<activesupport>, [">= 0"])
61
+ s.add_dependency(%q<actionpack>, [">= 3.0"])
62
+ s.add_dependency(%q<activemerchant>, ["~> 1.10"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<activemerchant>, ["~> 1.10"])
66
+ s.add_dependency(%q<shoulda>, [">= 0"])
67
+ s.add_dependency(%q<bundler>, [">= 0"])
68
+ s.add_dependency(%q<jeweler>, [">= 0"])
69
+ s.add_dependency(%q<simplecov>, [">= 0"])
70
+ s.add_dependency(%q<money>, [">= 0"])
71
+ s.add_dependency(%q<mocha>, [">= 0"])
72
+ s.add_dependency(%q<activesupport>, [">= 0"])
73
+ s.add_dependency(%q<actionpack>, [">= 3.0"])
74
+ s.add_dependency(%q<activemerchant>, ["~> 1.10"])
75
+ end
76
+ end
77
+
@@ -0,0 +1,270 @@
1
+ require 'active_merchant'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class PayboxDirectPlusGateway < Gateway
6
+ TEST_URL = 'https://preprod-ppps.paybox.com/PPPS.php'
7
+ TEST_URL_BACKUP = 'https://preprod-ppps.paybox.com/PPPS.php'
8
+ LIVE_URL = 'https://ppps.paybox.com/PPPS.php'
9
+ LIVE_URL_BACKUP = 'https://ppps1.paybox.com/PPPS.php'
10
+
11
+ # Payment API Version
12
+ API_VERSION = '00104'
13
+
14
+ # Transactions hash
15
+ TRANSACTIONS = {
16
+ :subscriber_authorization => '00051',
17
+ :subscriber_capture => '00052',
18
+ :subscriber_purchase => '00053',
19
+ :subscriber_credit => '00054',
20
+ :subscriber_void => '00055',
21
+ :subscriber_create => '00056',
22
+ :subscriber_update => '00057',
23
+ :subscriber_destroy => '00058',
24
+ }
25
+
26
+ CURRENCY_CODES = {
27
+ "AUD"=> '036',
28
+ "CAD"=> '124',
29
+ "CZK"=> '203',
30
+ "DKK"=> '208',
31
+ "HKD"=> '344',
32
+ "ICK"=> '352',
33
+ "JPY"=> '392',
34
+ "NOK"=> '578',
35
+ "SGD"=> '702',
36
+ "SEK"=> '752',
37
+ "CHF"=> '756',
38
+ "GBP"=> '826',
39
+ "USD"=> '840',
40
+ "EUR"=> '978'
41
+ }
42
+
43
+ ALREADY_EXISTING_PROFILE_CODES = ['00016']
44
+ UNKNOWN_PROFILE_CODES = ['00017']
45
+ SUCCESS_CODES = ['00000']
46
+ UNAVAILABILITY_CODES = ['00001', '00097', '00098']
47
+ FRAUD_CODES = ['00102','00104','00105','00134','00138','00141','00143','00156','00157','00159']
48
+ SUCCESS_MESSAGE = 'The transaction was approved'
49
+ FAILURE_MESSAGE = 'The transaction failed'
50
+
51
+ # Money is referenced in cents
52
+ self.money_format = :cents
53
+ self.default_currency = 'EUR'
54
+
55
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
56
+ self.supported_countries = ['FR']
57
+
58
+ # The card types supported by the payment gateway
59
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
60
+
61
+ # The homepage URL of the gateway
62
+ self.homepage_url = 'http://www.paybox.com/'
63
+
64
+ # The name of the gateway
65
+ self.display_name = 'Paybox Direct Plus'
66
+
67
+ def initialize(options = {})
68
+ requires!(options, :login, :password)
69
+ @options = options
70
+ super
71
+ end
72
+
73
+ def payment_profiles_supported?
74
+ true
75
+ end
76
+
77
+ def authorize(money, creditcard, options = {})
78
+ requires!(options, :user_reference)
79
+ post = {}
80
+ add_invoice(post, options)
81
+ add_creditcard(post, creditcard, options)
82
+ add_user_reference(post, options)
83
+ commit('subscriber_authorization', money, post)
84
+ end
85
+
86
+ def purchase(money, creditcard, options = {})
87
+ requires!(options, :credit_card_reference, :user_reference)
88
+ post = {}
89
+ add_invoice(post, options)
90
+ add_creditcard(post, creditcard, options)
91
+ add_user_reference(post, options)
92
+ commit('subscriber_purchase', money, post)
93
+ end
94
+
95
+ def capture(money, authorization, options = {})
96
+ requires!(options, :order_id, :user_reference)
97
+ post = {}
98
+ add_invoice(post, options)
99
+ add_reference(post, authorization)
100
+ add_user_reference(post, options)
101
+ commit('subscriber_capture', money, post)
102
+ end
103
+
104
+ def void(money, authorization, options = {})
105
+ requires!(options, :order_id, :user_reference)
106
+ post = {}
107
+ add_invoice(post, options)
108
+ add_reference(post, authorization)
109
+ add_user_reference(post, options)
110
+ post[:porteur] = '000000000000000'
111
+ post[:dateval] = '0000'
112
+ commit('subscriber_void', money, post)
113
+ end
114
+
115
+ def credit(money, identification, options = {})
116
+ post = {}
117
+ add_invoice(post, options)
118
+ add_reference(post, identification)
119
+ add_user_reference(post, options)
120
+ commit('subscriber_credit', money, post)
121
+ end
122
+
123
+ def create_payment_profile(money, creditcard, options = {})
124
+ requires!(options, :user_reference)
125
+ post = {}
126
+ add_creditcard(post, creditcard, options)
127
+ add_user_reference(post, options)
128
+ commit('subscriber_create', money, post)
129
+ end
130
+
131
+ def update_payment_profile(money, creditcard, options = {})
132
+ post = {}
133
+ add_creditcard(post, creditcard, options)
134
+ add_user_reference(post, options)
135
+ commit('subscriber_update', money, post)
136
+ end
137
+
138
+ def destroy_payment_profile(money, options)
139
+ post = {}
140
+ add_user_reference(post, options)
141
+ commit('subscriber_destroy', money, post)
142
+ end
143
+
144
+ def test?
145
+ @options[:test] || Base.gateway_mode == :test
146
+ end
147
+
148
+ private
149
+
150
+ def add_invoice(post, options)
151
+ post[:reference] = options[:order_id]
152
+ end
153
+
154
+ def add_creditcard(post, creditcard, options = {})
155
+ post[:porteur] = options[:credit_card_reference] ? options[:credit_card_reference] : creditcard.number
156
+ post[:dateval] = expdate(creditcard)
157
+ post[:cvv] = creditcard.verification_value if creditcard.verification_value?
158
+ end
159
+
160
+ def add_user_reference(post, options)
161
+ post[:refabonne] = options[:user_reference]
162
+ end
163
+
164
+ def add_reference(post, identification)
165
+ post[:numappel] = identification[0,10]
166
+ post[:numtrans] = identification[10,10]
167
+ end
168
+
169
+ def parse(body)
170
+ if RUBY_VERSION < "1.9"
171
+ require 'iconv'
172
+ body = Iconv.iconv("UTF-8","LATIN1", body.to_s).join
173
+ else
174
+ body.encode!('UTF-8', Encoding::ISO_8859_1)
175
+ end
176
+ results = {}
177
+ body.split(/&/).each do |pair|
178
+ key,val = pair.split(/=/)
179
+ results[key.downcase.to_sym] = CGI.unescape(val) if val
180
+ end
181
+ #Rails.logger.info results.inspect
182
+ results
183
+ end
184
+
185
+ def commit(action, money = nil, parameters = nil)
186
+ parameters[:montant] = ('0000000000' + (money ? amount(money) : ''))[-10..-1]
187
+ parameters[:devise] = CURRENCY_CODES[options[:currency] || currency(money)]
188
+ request_data = post_data(action,parameters)
189
+ #debugger
190
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request_data))
191
+ response = parse(ssl_post(test? ? TEST_URL_BACKUP : LIVE_URL_BACKUP, request_data)) if service_unavailable?(response)
192
+ Response.new(success?(response), message_from(response), response.merge({
193
+ :timestamp => parameters[:dateq],
194
+ :test => test?,
195
+ :authorization => response[:numappel].to_s + response[:numtrans].to_s,
196
+ :cvv_result => '',
197
+ :avs_result => '',
198
+ :fraud_review => fraud_review?(response),
199
+ :unknown_customer_profile => unknown_customer_profile?(response),
200
+ :already_existing_customer_profile => already_existing_customer_profile?(response),
201
+ :credit_card_reference => response[:porteur],
202
+ :sent_params => parameters.delete_if{|key,value| ['porteur','dateval','cvv'].include?(key.to_s)}
203
+ })
204
+ )
205
+ end
206
+
207
+ def success?(response)
208
+ SUCCESS_CODES.include?(response[:codereponse])
209
+ end
210
+
211
+ def fraud_review?(response)
212
+ FRAUD_CODES.include?(response[:codereponse])
213
+ end
214
+
215
+ def service_unavailable?(response)
216
+ UNAVAILABILITY_CODES.include?(response[:codereponse])
217
+ end
218
+
219
+ def unknown_customer_profile?(response)
220
+ UNKNOWN_PROFILE_CODES.include?(response[:codereponse])
221
+ end
222
+
223
+ def already_existing_customer_profile?(response)
224
+ ALREADY_EXISTING_PROFILE_CODES.include?(response[:codereponse])
225
+ end
226
+
227
+ def message_from(response)
228
+ success?(response) ? SUCCESS_MESSAGE : (response[:commentaire] || FAILURE_MESSAGE)
229
+ end
230
+
231
+ def post_data(action, parameters = {})
232
+
233
+ parameters.update(
234
+ :version => API_VERSION,
235
+ :type => TRANSACTIONS[action.to_sym],
236
+ :dateq => Time.now.strftime('%d%m%Y%H%M%S'),
237
+ :numquestion => unique_id(parameters[:reference]),
238
+ :site => @options[:login].to_s[0,7],
239
+ :rang => @options[:login].to_s[7..-1],
240
+ :cle => @options[:password],
241
+ :pays => '',
242
+ :archivage => parameters[:reference]
243
+ )
244
+
245
+ p = parameters.collect { |key, value| "#{key.to_s.upcase}=#{CGI.escape(value.to_s)}" }.join("&")
246
+ #Rails.logger.info "\n***************************"
247
+ #Rails.logger.debug "********** POST DATA IN PAYBOX PLUS ***********"
248
+ #Rails.logger.debug "*** Parameters for post data:"
249
+ #Rails.logger.debug "#{p.inspect}"
250
+ #Rails.logger.info "*****************************"
251
+ p
252
+ end
253
+
254
+ def unique_id(seed = 0)
255
+ randkey = "#{seed.hash}#{Time.now.usec}".to_i % 2147483647 # Max paybox value for the question number
256
+
257
+ "0000000000#{randkey}"[-10..-1]
258
+ end
259
+
260
+ def expdate(credit_card)
261
+ year = sprintf("%.4i", credit_card.year)
262
+ month = sprintf("%.2i", credit_card.month)
263
+
264
+ "#{month}#{year[-2..-1]}"
265
+ end
266
+
267
+ end
268
+ end
269
+ end
270
+
@@ -0,0 +1,4 @@
1
+ paybox_direct_plus:
2
+ login: 199988899
3
+ password: 1999888I
4
+
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+
3
+ class RemotePayboxDirectPlusTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @gateway = PayboxDirectPlusGateway.new(fixtures(:paybox_direct_plus))
7
+
8
+ @amount = 100
9
+ @credit_card = credit_card('1111222233334444')
10
+ @declined_card = credit_card('1111222233334445')
11
+
12
+ @options = {
13
+ :order_id => "REF#{Time.now.usec}",
14
+ :user_reference => "USER#{Time.now.usec}"
15
+ }
16
+ end
17
+
18
+ def test_create_profile
19
+ assert response = @gateway.create_payment_profile(@amount, @credit_card, @options)
20
+ assert_success response
21
+ assert_equal 'The transaction was approved', response.message
22
+ end
23
+
24
+ def test_create_profile_capture_and_void
25
+ assert response = @gateway.create_payment_profile(@amount, @credit_card, @options)
26
+ assert_success response
27
+
28
+ credit_card_reference = response.params["credit_card_reference"]
29
+ assert_not_nil credit_card_reference
30
+
31
+ assert capture = @gateway.capture(@amount, response.params["authorization"], @options)
32
+ assert_success capture
33
+
34
+ assert void = @gateway.void(@amount, capture.params["authorization"], @options)
35
+ assert_equal 'The transaction was approved', void.message
36
+ assert_success void
37
+ end
38
+
39
+ def test_create_profile_and_purchase
40
+ assert response = @gateway.create_payment_profile(@amount, @credit_card, @options)
41
+ assert_success response
42
+
43
+ credit_card_reference = response.params["credit_card_reference"]
44
+ assert_not_nil credit_card_reference
45
+
46
+ @credit_card.number = nil
47
+
48
+ assert_response = @gateway.purchase(@amount, @credit_card, @options.merge({ :credit_card_reference => credit_card_reference }))
49
+ assert_success response
50
+ assert_equal 'The transaction was approved', response.message
51
+ end
52
+
53
+ def test_failed_capture
54
+ assert response = @gateway.capture(@amount, '', :order_id => '1', :user_reference => 'pipomolo')
55
+ assert_failure response
56
+ assert_equal "Mandatory values missing keyword:13 Type:19", response.message
57
+ end
58
+ end
59
+
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'money'
7
+ require 'mocha/setup'
8
+ require 'yaml'
9
+ require 'active_merchant'
10
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'activemerchant_paybox_direct_plus')
11
+
12
+ require 'active_support/core_ext/integer/time'
13
+ require 'active_support/core_ext/numeric/time'
14
+
15
+ begin
16
+ require 'active_support/core_ext/time/acts_like'
17
+ rescue LoadError
18
+ end
19
+
20
+ begin
21
+ gem 'actionpack'
22
+ rescue LoadError
23
+ raise StandardError, "The view tests need ActionPack installed as gem to run"
24
+ end
25
+
26
+ require 'action_controller'
27
+ require "action_view/template"
28
+ begin
29
+ require 'action_dispatch/testing/test_process'
30
+ rescue LoadError
31
+ require 'action_controller/test_process'
32
+ end
33
+ require 'active_merchant/billing/integrations/action_view_helper'
34
+
35
+ ActiveMerchant::Billing::Base.mode = :test
36
+
37
+ require 'logger'
38
+ ActiveMerchant::Billing::Gateway.logger = Logger.new(STDOUT) if ENV['DEBUG_ACTIVE_MERCHANT'] == 'true'
39
+
40
+ # Test gateways
41
+ class SimpleTestGateway < ActiveMerchant::Billing::Gateway
42
+ end
43
+
44
+ class SubclassGateway < SimpleTestGateway
45
+ end
46
+
47
+
48
+ module ActiveMerchant
49
+ module Assertions
50
+ AssertionClass = RUBY_VERSION > '1.9' ? MiniTest::Assertion : Test::Unit::AssertionFailedError
51
+
52
+ def assert_field(field, value)
53
+ clean_backtrace do
54
+ assert_equal value, @helper.fields[field]
55
+ end
56
+ end
57
+
58
+ # Allows the testing of you to check for negative assertions:
59
+ #
60
+ # # Instead of
61
+ # assert !something_that_is_false
62
+ #
63
+ # # Do this
64
+ # assert_false something_that_should_be_false
65
+ #
66
+ # An optional +msg+ parameter is available to help you debug.
67
+ def assert_false(boolean, message = nil)
68
+ message = build_message message, '<?> is not false or nil.', boolean
69
+
70
+ clean_backtrace do
71
+ assert_block message do
72
+ not boolean
73
+ end
74
+ end
75
+ end
76
+
77
+ # A handy little assertion to check for a successful response:
78
+ #
79
+ # # Instead of
80
+ # assert_success response
81
+ #
82
+ # # DRY that up with
83
+ # assert_success response
84
+ #
85
+ # A message will automatically show the inspection of the response
86
+ # object if things go afoul.
87
+ def assert_success(response)
88
+ clean_backtrace do
89
+ assert response.success?, "Response failed: #{response.inspect}"
90
+ end
91
+ end
92
+
93
+ # The negative of +assert_success+
94
+ def assert_failure(response)
95
+ clean_backtrace do
96
+ assert_false response.success?, "Response expected to fail: #{response.inspect}"
97
+ end
98
+ end
99
+
100
+ def assert_valid(validateable)
101
+ clean_backtrace do
102
+ assert validateable.valid?, "Expected to be valid"
103
+ end
104
+ end
105
+
106
+ def assert_not_valid(validateable)
107
+ clean_backtrace do
108
+ assert_false validateable.valid?, "Expected to not be valid"
109
+ end
110
+ end
111
+
112
+ private
113
+ def clean_backtrace(&block)
114
+ yield
115
+ rescue AssertionClass => e
116
+ path = File.expand_path(__FILE__)
117
+ raise AssertionClass, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ }
118
+ end
119
+ end
120
+
121
+ module Fixtures
122
+ HOME_DIR = RUBY_PLATFORM =~ /mswin32/ ? ENV['HOMEPATH'] : ENV['HOME'] unless defined?(HOME_DIR)
123
+ LOCAL_CREDENTIALS = File.join(HOME_DIR.to_s, '.active_merchant/fixtures.yml') unless defined?(LOCAL_CREDENTIALS)
124
+ DEFAULT_CREDENTIALS = File.join(File.dirname(__FILE__), 'fixtures.yml') unless defined?(DEFAULT_CREDENTIALS)
125
+
126
+ private
127
+ def credit_card(number = '4242424242424242', options = {})
128
+ defaults = {
129
+ :number => number,
130
+ :month => 9,
131
+ :year => Time.now.year + 1,
132
+ :first_name => 'Longbob',
133
+ :last_name => 'Longsen',
134
+ :verification_value => '123',
135
+ :type => 'visa'
136
+ }.update(options)
137
+
138
+ Billing::CreditCard.new(defaults)
139
+ end
140
+
141
+ def check(options = {})
142
+ defaults = {
143
+ :name => 'Jim Smith',
144
+ :routing_number => '244183602',
145
+ :account_number => '15378535',
146
+ :account_holder_type => 'personal',
147
+ :account_type => 'checking',
148
+ :number => '1'
149
+ }.update(options)
150
+
151
+ Billing::Check.new(defaults)
152
+ end
153
+
154
+ def address(options = {})
155
+ {
156
+ :name => 'Jim Smith',
157
+ :address1 => '1234 My Street',
158
+ :address2 => 'Apt 1',
159
+ :company => 'Widgets Inc',
160
+ :city => 'Ottawa',
161
+ :state => 'ON',
162
+ :zip => 'K1C2N6',
163
+ :country => 'CA',
164
+ :phone => '(555)555-5555',
165
+ :fax => '(555)555-6666'
166
+ }.update(options)
167
+ end
168
+
169
+ def all_fixtures
170
+ @@fixtures ||= load_fixtures
171
+ end
172
+
173
+ def fixtures(key)
174
+ data = all_fixtures[key] || raise(StandardError, "No fixture data was found for '#{key}'")
175
+
176
+ data.dup
177
+ end
178
+
179
+ def load_fixtures
180
+ file = File.exists?(LOCAL_CREDENTIALS) ? LOCAL_CREDENTIALS : DEFAULT_CREDENTIALS
181
+ yaml_data = YAML.load(File.read(file))
182
+ symbolize_keys(yaml_data)
183
+
184
+ yaml_data
185
+ end
186
+
187
+ def symbolize_keys(hash)
188
+ return unless hash.is_a?(Hash)
189
+
190
+ hash.symbolize_keys!
191
+ hash.each{|k,v| symbolize_keys(v)}
192
+ end
193
+ end
194
+ end
195
+
196
+ Test::Unit::TestCase.class_eval do
197
+ include ActiveMerchant::Billing
198
+ include ActiveMerchant::Assertions
199
+ include ActiveMerchant::Utils
200
+ include ActiveMerchant::Fixtures
201
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activemerchant_paybox_direct_plus
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.2.0
6
+ platform: ruby
7
+ authors:
8
+ - donaldpiret
9
+ - arambert
10
+ - slainer68
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+
15
+ date: 2013-05-06 00:00:00 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: activemerchant
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: "1.10"
25
+ type: :development
26
+ prerelease: false
27
+ version_requirements: *id001
28
+ - !ruby/object:Gem::Dependency
29
+ name: shoulda
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: *id002
39
+ - !ruby/object:Gem::Dependency
40
+ name: bundler
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: *id003
50
+ - !ruby/object:Gem::Dependency
51
+ name: jeweler
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ type: :development
59
+ prerelease: false
60
+ version_requirements: *id004
61
+ - !ruby/object:Gem::Dependency
62
+ name: simplecov
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: *id005
72
+ - !ruby/object:Gem::Dependency
73
+ name: money
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ type: :development
81
+ prerelease: false
82
+ version_requirements: *id006
83
+ - !ruby/object:Gem::Dependency
84
+ name: mocha
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: *id007
94
+ - !ruby/object:Gem::Dependency
95
+ name: activesupport
96
+ requirement: &id008 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: "0"
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: *id008
105
+ - !ruby/object:Gem::Dependency
106
+ name: actionpack
107
+ requirement: &id009 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: "3.0"
113
+ type: :development
114
+ prerelease: false
115
+ version_requirements: *id009
116
+ - !ruby/object:Gem::Dependency
117
+ name: activemerchant
118
+ requirement: &id010 !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ~>
122
+ - !ruby/object:Gem::Version
123
+ version: "1.10"
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: *id010
127
+ description: Paybox Direct Plus ActiveMerchant Billing Gateway implementation
128
+ email: nospam@nospam.com
129
+ executables: []
130
+
131
+ extensions: []
132
+
133
+ extra_rdoc_files:
134
+ - LICENSE.txt
135
+ - README.markdown
136
+ files:
137
+ - Gemfile
138
+ - Gemfile.lock
139
+ - LICENSE.txt
140
+ - README.markdown
141
+ - Rakefile
142
+ - VERSION
143
+ - activemerchant_paybox_direct_plus.gemspec
144
+ - lib/activemerchant_paybox_direct_plus.rb
145
+ - test/fixtures.yml
146
+ - test/remote/gateways/remote_paybox_direct_plus_test.rb
147
+ - test/test_helper.rb
148
+ homepage: https://github.com/arambert/Paybox-Direct-Plus
149
+ licenses:
150
+ - MIT
151
+ post_install_message:
152
+ rdoc_options: []
153
+
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ none: false
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ hash: 3133505809715248030
162
+ segments:
163
+ - 0
164
+ version: "0"
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ none: false
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: "0"
171
+ requirements: []
172
+
173
+ rubyforge_project:
174
+ rubygems_version: 1.8.15
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: Paybox Direct Plus for ActiveMerchant
178
+ test_files: []
179
+