activemerchant-payline 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +5 -0
  3. data/.gitignore +18 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +57 -0
  8. data/Rakefile +1 -0
  9. data/activemerchant-payline.gemspec +33 -0
  10. data/lib/active_merchant/billing/gateways/payline.rb +57 -0
  11. data/lib/active_merchant/billing/gateways/payline/payline_common.rb +368 -0
  12. data/lib/active_merchant/billing/gateways/payline/payline_constants.rb +83 -0
  13. data/lib/active_merchant/billing/gateways/payline/payline_direct_api.rb +78 -0
  14. data/lib/active_merchant/billing/gateways/payline/payline_management_payment_api.rb +154 -0
  15. data/lib/active_merchant/billing/gateways/payline/payline_status_api.rb +36 -0
  16. data/lib/active_merchant/billing/gateways/payline/payline_wallet_management.rb +249 -0
  17. data/lib/active_merchant/billing/gateways/payline/payline_web_api.rb +186 -0
  18. data/lib/active_merchant/billing/iso_4217_currency_codes.rb +32 -0
  19. data/lib/activemerchant-payline.rb +2 -0
  20. data/test/fixtures.yml +8 -0
  21. data/test/fixtures/vcr_cassettes/test_failed_create_wallet.yml +1820 -0
  22. data/test/fixtures/vcr_cassettes/test_failed_disable_payment_record.yml +1821 -0
  23. data/test/fixtures/vcr_cassettes/test_failed_disable_wallet.yml +1820 -0
  24. data/test/fixtures/vcr_cassettes/test_failed_do_authorization.yml +1956 -0
  25. data/test/fixtures/vcr_cassettes/test_failed_do_capture.yml +1890 -0
  26. data/test/fixtures/vcr_cassettes/test_failed_do_credit.yml +1882 -0
  27. data/test/fixtures/vcr_cassettes/test_failed_do_debit.yml +1981 -0
  28. data/test/fixtures/vcr_cassettes/test_failed_do_recurrent_wallet_payment.yml +2033 -0
  29. data/test/fixtures/vcr_cassettes/test_failed_do_refund.yml +1944 -0
  30. data/test/fixtures/vcr_cassettes/test_failed_do_reset.yml +1820 -0
  31. data/test/fixtures/vcr_cassettes/test_failed_do_scheduled_wallet_payment.yml +1927 -0
  32. data/test/fixtures/vcr_cassettes/test_failed_do_web_payment.yml +1822 -0
  33. data/test/fixtures/vcr_cassettes/test_failed_enable_wallet.yml +1819 -0
  34. data/test/fixtures/vcr_cassettes/test_failed_get_payment_record.yml +1821 -0
  35. data/test/fixtures/vcr_cassettes/test_failed_get_wallet.yml +1819 -0
  36. data/test/fixtures/vcr_cassettes/test_failed_get_web_payment_details.yml +1851 -0
  37. data/test/fixtures/vcr_cassettes/test_failed_immediate_wallet_payment.yml +1938 -0
  38. data/test/fixtures/vcr_cassettes/test_failed_manage_web_wallet.yml +1870 -0
  39. data/test/fixtures/vcr_cassettes/test_failed_update_wallet.yml +1820 -0
  40. data/test/fixtures/vcr_cassettes/test_failed_update_web_wallet.yml +1819 -0
  41. data/test/fixtures/vcr_cassettes/test_get_transaction_details.yml +3711 -0
  42. data/test/fixtures/vcr_cassettes/test_get_web_wallet.yml +1871 -0
  43. data/test/fixtures/vcr_cassettes/test_missing_parameters_create_web_wallet.yml +1870 -0
  44. data/test/fixtures/vcr_cassettes/test_missing_parameters_do_web_payment.yml +1822 -0
  45. data/test/fixtures/vcr_cassettes/test_successful_create_wallet.yml +1826 -0
  46. data/test/fixtures/vcr_cassettes/test_successful_create_web_wallet.yml +1822 -0
  47. data/test/fixtures/vcr_cassettes/test_successful_disable_payment_record.yml +1876 -0
  48. data/test/fixtures/vcr_cassettes/test_successful_disable_wallet.yml +1871 -0
  49. data/test/fixtures/vcr_cassettes/test_successful_do_authorization.yml +1837 -0
  50. data/test/fixtures/vcr_cassettes/test_successful_do_bank_transfer.yml +1826 -0
  51. data/test/fixtures/vcr_cassettes/test_successful_do_capture.yml +1889 -0
  52. data/test/fixtures/vcr_cassettes/test_successful_do_credit.yml +1829 -0
  53. data/test/fixtures/vcr_cassettes/test_successful_do_debit.yml +1834 -0
  54. data/test/fixtures/vcr_cassettes/test_successful_do_immediate_wallet_payment.yml +1875 -0
  55. data/test/fixtures/vcr_cassettes/test_successful_do_recurrent_wallet_payment.yml +1827 -0
  56. data/test/fixtures/vcr_cassettes/test_successful_do_refund.yml +1888 -0
  57. data/test/fixtures/vcr_cassettes/test_successful_do_reset.yml +1892 -0
  58. data/test/fixtures/vcr_cassettes/test_successful_do_scheduled_wallet_payment.yml +1821 -0
  59. data/test/fixtures/vcr_cassettes/test_successful_do_web_payment.yml +1821 -0
  60. data/test/fixtures/vcr_cassettes/test_successful_enable_wallet.yml +1924 -0
  61. data/test/fixtures/vcr_cassettes/test_successful_get_payment_record.yml +1891 -0
  62. data/test/fixtures/vcr_cassettes/test_successful_get_wallet.yml +1894 -0
  63. data/test/fixtures/vcr_cassettes/test_successful_get_web_payment_details.yml +1908 -0
  64. data/test/fixtures/vcr_cassettes/test_successful_manage_web_wallet.yml +1821 -0
  65. data/test/fixtures/vcr_cassettes/test_successful_update_wallet.yml +1825 -0
  66. data/test/fixtures/vcr_cassettes/test_successful_update_web_wallet.yml +1820 -0
  67. data/test/run_test.rb +9 -0
  68. data/test/test_helper.rb +350 -0
  69. data/test/unit/gateways/payline/payline_direct_api_test.rb +122 -0
  70. data/test/unit/gateways/payline/payline_management_payment_api_test.rb +197 -0
  71. data/test/unit/gateways/payline/payline_status_api_test.rb +30 -0
  72. data/test/unit/gateways/payline/payline_wallet_management_api_test.rb +297 -0
  73. data/test/unit/gateways/payline/payline_web_api_test.rb +221 -0
  74. metadata +360 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b75d6271696189f8272a67a62ae50f3bd1b912e3
4
+ data.tar.gz: 14668c93e6ea755462537b6fa18566737c90a550
5
+ SHA512:
6
+ metadata.gz: 5808ddf102cf04d14b13f395ed8300d14d168dc852e77f563e731d26b9d8391194eb4e4b89ed2b90da7b1fcbc6e93dc238db99dc260cbf13c805bdf9e617a7e5
7
+ data.tar.gz: 273f1057b88d40cee4c5f187dc3cd84e906c2313dfbadd0c9cb3ba8d8a43b0f4b96858c9ef960ba6269e71945d07533b16714aadbee6a57903e67b85b66e342e
@@ -0,0 +1,5 @@
1
+ PAYLINE_MERCHANT_ID="1234567891011"
2
+ PAYLINE_ACCESS_KEY="password"
3
+ PAYLINE_CONTRACT_NUMBER="1234567"
4
+ PAYLINE_RETURN_URL="http://test.com"
5
+ PAYLINE_CANCEL_RETURN_URL="http://test.com"
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .env
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.3
4
+ bundler_args: --jobs=2
5
+ script:
6
+ - ruby test/run_test.rb
7
+ cache: bundler
8
+ notifications:
9
+ slack: c4dna:3PjAjqHWqGxzjKIXZfedtV7U
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in payline-ruby.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012-2013 Goldmund International, Kareea SARL, Samuel Lebeau
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,57 @@
1
+ # ActiveMerchant Payline
2
+
3
+ [![Build Status](https://travis-ci.com/c4ddna/active_merchant_payline.svg?token=TCtHVJZbagUskWponM9C&branch=master)](https://travis-ci.com/c4ddna/active_merchant_payline)
4
+
5
+ ActiveMerchant implementation of the [Payline] [1] Gateway.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'activemerchant-payline'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install activemerchant-payline
20
+
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ payline = PaylineGateway.new(
26
+ merchant_id: "1234567891011" # Your merchant ID,
27
+ merchant_access_key: "your_merchant_api_access_key",
28
+ contract_number: "1234567",
29
+ return_url: "http://test.com",
30
+ cancel_return_url: "http://test.com",
31
+ test: true
32
+ )
33
+
34
+ payline.do_web_payment(100, order_id: "MYORDERID")
35
+ ```
36
+
37
+ Please note that all methods aren't implemented yet. Contributions are welcome.
38
+
39
+ ## Useful payline links
40
+ Test API: http://www.concupourvendre.com/demo/
41
+ Documentation: https://payline.atlassian.net/wiki/display/DT/Documentation
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
50
+
51
+ Test your code:
52
+ - Create a .env file in the test folder and complete it following the .env.example
53
+ - Write your tests and launch tests using the ruby test/run_test.rb command
54
+
55
+
56
+ [1]: http://www.payline.com/
57
+ [2]: https://homologation-admin.payline.com/
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "activemerchant-payline"
7
+ gem.version = "0.1.9"
8
+ gem.authors = ["Samuel Lebeau", "Arpsara", "CT2C"]
9
+ gem.email = ["samuel.lebeau@gmail.com", "contact@ct2c.fr"]
10
+ gem.summary = %q{ActiveMerchant implementation of the Payline Gateway.}
11
+ gem.homepage = "https://github.com/Goldmund/activemerchant-payline"
12
+
13
+ gem.files = `git ls-files`.split("\n")
14
+ gem.require_paths = ["lib"]
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+
18
+ gem.add_dependency 'activemerchant', '~> 1.73.0'
19
+ gem.add_dependency 'savon', '2.11.1'
20
+
21
+ gem.add_dependency('activesupport', '>= 3.2.14')
22
+ gem.add_dependency('i18n', '>= 0.6.9')
23
+ gem.add_dependency('builder', '>= 2.1.2', '< 4.0.0')
24
+ gem.add_dependency('nokogiri', "~> 1.4")
25
+
26
+ gem.add_development_dependency('rake')
27
+ gem.add_development_dependency('test-unit', '> 3.0.0')
28
+ gem.add_development_dependency('mocha', '~> 1')
29
+ gem.add_development_dependency('thor')
30
+ gem.add_development_dependency('dotenv')
31
+ gem.add_development_dependency('vcr')
32
+ gem.add_development_dependency('webmock')
33
+ end
@@ -0,0 +1,57 @@
1
+ require 'activemerchant'
2
+ require_relative 'payline/payline_constants'
3
+ require_relative 'payline/payline_common'
4
+ require_relative 'payline/payline_direct_api'
5
+ require_relative 'payline/payline_management_payment_api'
6
+ require_relative 'payline/payline_wallet_management'
7
+ require_relative 'payline/payline_web_api'
8
+ require_relative 'payline/payline_status_api'
9
+
10
+ module ActiveMerchant
11
+ module Billing
12
+ class PaylineGateway < Gateway
13
+ include PaylineCommon
14
+ include PaylineDirectAPI
15
+ include PaylineWalletManagementAPI
16
+ include PaylineManagementPaymentAPI
17
+ include PaylineWebAPI
18
+ include PaylineStatusAPI
19
+ include ISO4217CurrencyCodes
20
+
21
+ API_VERSION = '4.24'.freeze
22
+
23
+ self.display_name = 'Payline'
24
+ self.homepage_url = 'http://www.payline.com/'
25
+
26
+ self.default_currency = 'EUR'
27
+ self.money_format = :cents
28
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
29
+
30
+ class_attribute :web_live_url, :web_test_url, :instance_writer => false
31
+
32
+ class_attribute :extended_payment_url, :extended_test_payment_url, :instance_writer => false
33
+
34
+ self.live_url = 'https://services.payline.com/V4/services/DirectPaymentAPI'.freeze
35
+ self.test_url = 'https://homologation.payline.com/V4/services/DirectPaymentAPI'.freeze
36
+
37
+ self.web_live_url = 'https://services.payline.com/V4/services/WebPaymentAPI/'.freeze
38
+ self.web_test_url = 'https://homologation.payline.com/V4/services/WebPaymentAPI/'.freeze
39
+
40
+ self.extended_payment_url = 'https://services.payline.com/V4/services/ExtendedAPI'.freeze
41
+ self.extended_test_payment_url = 'https://homologation.payline.com/V4/services/ExtendedAPI'.freeze
42
+
43
+ # :merchant_id [String]
44
+ # :merchant_secret [String]
45
+ # :contract_number [String] Contract Number
46
+ # :return_url [String] Return url - Must begin with http:// or https://
47
+ # :cancel_return_url [String] Cancel url - Must begin with http:// or https://
48
+ # :test [Boolean] Set it to true if you want to point to homologation services
49
+ def initialize(options = {})
50
+ requires!(options, :merchant_id, :merchant_access_key, :contract_number)
51
+ @options = options
52
+ end
53
+ end
54
+
55
+ Payline = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveMerchant::Billing::Payline', PaylineGateway)
56
+ end
57
+ end
@@ -0,0 +1,368 @@
1
+ require_relative '../../iso_4217_currency_codes'
2
+ require 'savon'
3
+
4
+ module ActiveMerchant
5
+ module Billing
6
+ module PaylineCommon
7
+
8
+ include PaylineConstants
9
+
10
+ protected
11
+ # Make a savon request
12
+ def savon_request(client, method_name, data)
13
+ add_shared_data(data)
14
+
15
+ response = client.call :"#{method_name}", { message: data }
16
+
17
+ if response.success?
18
+ response = response.to_hash[:"#{method_name}_response"]
19
+ build_response(response)
20
+ else
21
+ message = (response.soap_fault? ? response.soap_fault : response.http_error).to_s
22
+ Response.new(false, message, {}, { :test => test? })
23
+ end
24
+ end
25
+
26
+ def direct_api_request(method_name, data)
27
+ savon_request(direct_api_savon_client, method_name, data)
28
+ end
29
+
30
+ def direct_api_savon_client
31
+ @direct_api_savon_client ||= create_savon_client(test? ? test_url : live_url)
32
+ end
33
+
34
+ # Create a savon client
35
+ def create_savon_client(endpoint)
36
+ Savon.client(
37
+ wsdl: test? ? WDSL_TEST_URL : WDSL_URL,
38
+ endpoint: endpoint,
39
+ basic_auth: [options[:merchant_id], options[:merchant_access_key]],
40
+ log: options[:log] ? options[:log] : false
41
+ )
42
+ end
43
+
44
+ def build_response(response)
45
+ message = message_from(result = response[:result])
46
+ if transaction = response[:transaction]
47
+ transaction_id = transaction[:id] if String === transaction[:id]
48
+ end
49
+ format_response!(response = response.with_indifferent_access)
50
+ Response.new(success?(result), message, response, {
51
+ :authorization => transaction_id,
52
+ :test => test?
53
+ })
54
+ end
55
+
56
+ def message_from(result)
57
+ message = result[:short_message]
58
+ message << ": " << result[:long_message] unless result[:long_message] == message
59
+ message << " (code #{result[:code]})"
60
+ message
61
+ end
62
+
63
+ def success?(result)
64
+ SUCCESS_CODES.include?(result[:code])
65
+ end
66
+
67
+ def contract_number
68
+ options[:contract_number]
69
+ end
70
+
71
+ def language_code(locale)
72
+ LANGUAGE_CODES[locale.to_s.downcase] if locale
73
+ end
74
+
75
+ def format_date(time)
76
+ time.strftime(DATETIME_FORMAT)
77
+ end
78
+
79
+ def format_boolean(boolean, default = false)
80
+ case boolean.nil? ? default : boolean
81
+ when true, 1
82
+ 1
83
+ else
84
+ 0
85
+ end
86
+ end
87
+
88
+ def format_response!(response)
89
+ unless response.delete("@xmlns") && response.empty?
90
+ response.each do |key, value|
91
+ if Hash === value
92
+ response[key] = format_response!(value)
93
+ elsif Array === value
94
+ value.map! { |el| format_response!(el) }
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ # Merge shared data with data
101
+ # Shared data are version, contract_number and others parameters in add_web_params
102
+ def add_shared_data(data)
103
+ hashes_to_merge = [add_version, add_contract_number, add_web_params(options)]
104
+ shared_data = hashes_to_merge.inject(&:merge)
105
+
106
+ data.merge!(shared_data)
107
+ end
108
+
109
+ # Optional parameters: md, pares, xid, eci, cavv, cavv_algorithm, vads_result, type_securisation, pa_res_status, ve_res_status
110
+ def add_authentication_3D_secure(authentication_3D_secure)
111
+ if authentication_3D_secure
112
+ optional_parameters = ['md',
113
+ 'pares',
114
+ 'xid',
115
+ 'eci',
116
+ 'cavv',
117
+ 'cavvAlgorithm',
118
+ 'vadsResult',
119
+ 'typeSecurisation',
120
+ 'PaResStatus',
121
+ 'VeResStatus'
122
+ ]
123
+
124
+ objects = [add_optional_parameters(authentication_3D_secure, optional_parameters)]
125
+
126
+ data = {
127
+ authentication3DSecure: merged_data(objects)
128
+ }
129
+ end
130
+ data ||= {}
131
+ end
132
+
133
+ def add_contract_number
134
+ { contractNumber: contract_number }
135
+ end
136
+
137
+ def add_contract_number_wallet_list(contract_number)
138
+ if contract_number
139
+ data = { contractNumberWalletList:
140
+ {
141
+ contractNumberWallet: contract_number
142
+ }
143
+ }
144
+ end
145
+ data ||= {}
146
+ end
147
+
148
+ def add_credit_card(card)
149
+ if card
150
+ parameters = {
151
+ number: card[:number],
152
+ type: CARD_BRAND_CODES[card[:brand]],
153
+ expirationDate: expiration_date(card[:month], card[:year]),
154
+ cvx: card[:verification_value]
155
+ }
156
+ data = { card: parameters }
157
+ end
158
+ data ||= { card: {} }
159
+ end
160
+
161
+ def add_version
162
+ {version: WEB_API_VERSION}
163
+ end
164
+
165
+ def add_owner(owner_data)
166
+ optional_parameters = ['lastName', 'firstName', 'issueCardDate']
167
+
168
+ if owner_data
169
+ objects = [
170
+ add_address(owner_data[:billing_address], :billing_address),
171
+ add_optional_parameters(owner_data, optional_parameters)
172
+ ]
173
+ data = { owner: merged_data(objects) }
174
+ end
175
+
176
+ data ||= {}
177
+ end
178
+
179
+ def add_payment(amount, currency, action, mode = nil, options = {})
180
+ optional_parameters = ['differedActionDate', 'method', 'softDescriptor', 'cardBrand']
181
+ required_parameters = {
182
+ amount: amount,
183
+ currency: currency,
184
+ action: action_code(action),
185
+ mode: payment_mode(mode),
186
+ contractNumber: contract_number
187
+ }
188
+
189
+ parameters = [
190
+ required_parameters,
191
+ add_optional_parameters(options, optional_parameters)
192
+ ]
193
+
194
+ data = { payment: merged_data(parameters) }
195
+ end
196
+
197
+ def add_order(amount, currency, ref, options)
198
+ optional_parameters = ['origin',
199
+ 'country',
200
+ 'taxes',
201
+ 'details',
202
+ 'deliveryMode',
203
+ 'deliveryExpectedDate',
204
+ 'deliveryExpectedDelay'
205
+ ]
206
+
207
+ date = options[:date] if !options.blank?
208
+ date ||= Time.now
209
+
210
+ required_parameters = {
211
+ amount: amount,
212
+ currency: currency,
213
+ ref: ref,
214
+ date: format_date(date)
215
+ }
216
+
217
+ details = add_details(options[:details]) if options && options[:details]
218
+
219
+ parameters = [
220
+ required_parameters,
221
+ # Optional parameters
222
+ details,
223
+ add_optional_parameters(options, optional_parameters)
224
+ ]
225
+
226
+ data = { order: merged_data(parameters) }
227
+ end
228
+
229
+ def add_buyer(buyer_data)
230
+ optional_parameters = [
231
+ 'title',
232
+ 'lastName',
233
+ 'firstName',
234
+ 'email',
235
+ 'accountCreateDate',
236
+ 'accountAverageAmount',
237
+ 'accountOrderCount',
238
+ 'walletId',
239
+ 'walletDisplayed',
240
+ 'walletSecured',
241
+ 'walletCardInd',
242
+ 'ip',
243
+ 'mobilePhone',
244
+ 'customerId',
245
+ 'legalStatus',
246
+ 'legalDocument',
247
+ 'birthDate',
248
+ 'fingerprintID',
249
+ 'deviceFingerprint',
250
+ 'isBot',
251
+ 'isIncognito',
252
+ 'isBehindProxy',
253
+ 'isFromTor',
254
+ 'isEmulator',
255
+ 'isRooted',
256
+ 'hasTimezoneMismatch'
257
+ ]
258
+
259
+ if buyer_data
260
+ # Note: Yes, shipping_adress with only one d because of Payline wrong attribute...
261
+ objects = [
262
+ add_address(buyer_data[:shipping_address], :shipping_adress),
263
+ add_address(buyer_data[:billing_address], :billing_address),
264
+ add_optional_parameters(buyer_data, optional_parameters)
265
+ ]
266
+
267
+ data = { buyer: merged_data(objects) }
268
+ end
269
+
270
+ data ||= { buyer: {} }
271
+ end
272
+
273
+ def add_address(address, address_name = :address)
274
+ optional_parameters = [
275
+ 'title',
276
+ 'name',
277
+ 'firstName',
278
+ 'lastName',
279
+ 'street1',
280
+ 'street2',
281
+ 'cityName',
282
+ 'zipCode',
283
+ 'country', # TODO Values
284
+ 'phone',
285
+ 'state',
286
+ 'county',
287
+ 'phoneType' # TODO Values
288
+ ]
289
+
290
+ data = { "#{address_name}": add_optional_parameters(address, optional_parameters) } unless address.blank?
291
+ data ||= {}
292
+ end
293
+
294
+ def action_code(action)
295
+ action = :purchase if action.blank?
296
+ if ACTION_CODES.key?(action)
297
+ ACTION_CODES[action]
298
+ else
299
+ action
300
+ end
301
+ end
302
+
303
+ def payment_mode(mode)
304
+ mode = :direct if mode.blank?
305
+ if PAYMENT_MODES.key?(mode)
306
+ PAYMENT_MODES[mode]
307
+ else
308
+ mode
309
+ end
310
+ end
311
+
312
+ def add_details(details_data)
313
+ optional_parameters = [
314
+ 'ref', 'price', 'quantity', 'comment', 'category', 'brand', 'subcategory1', 'subcategory2', 'additionalData', 'taxRate'
315
+ ]
316
+ data = { details: add_optional_parameters(details_data, optional_parameters) }
317
+ data ||= { details: {} }
318
+ end
319
+
320
+ def add_private_data(private_data)
321
+ data = {}
322
+ if private_data
323
+ i = 0
324
+
325
+ private_data.to_hash.each do |key, value|
326
+ data.merge!({ "privateData_#{i}": { key: key, value: value } })
327
+ i += 1
328
+ end
329
+ data = { privateDataList: data}
330
+ end
331
+ data ||= {}
332
+ end
333
+
334
+ def add_selected_contract_list(contract_number, all_contract_numbers = [])
335
+ if !all_contract_numbers.blank?
336
+ data = { selectedContractList: { selectedContract: all_contract_numbers.uniq } }
337
+ elsif contract_number
338
+ data = { selectedContractList: { selectedContract: contract_number } }
339
+ end
340
+ data ||= {}
341
+ end
342
+
343
+ def underscore(camel_cased_word)
344
+ camel_cased_word.to_s.gsub(/::/, '/').
345
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
346
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
347
+ tr("-", "_").
348
+ downcase
349
+ end
350
+
351
+ def add_optional_parameters(options, optional_parameters=[])
352
+ data = {}
353
+ if options
354
+ optional_parameters.each do |parameter|
355
+ value = options[underscore(parameter).to_sym]
356
+
357
+ data.merge!({"#{parameter}".to_sym => value}) unless value.blank?
358
+ end
359
+ end
360
+ data
361
+ end
362
+
363
+ def merged_data(data = [])
364
+ data.reject{|x| x.blank?}.inject(&:merge)
365
+ end
366
+ end
367
+ end
368
+ end