activemerchant-payline 0.1.9

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.
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