activemerchant 1.60.0 → 1.61.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +64 -0
  3. data/lib/active_merchant/billing/gateways/authorize_net.rb +1 -1
  4. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +12 -1
  5. data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
  6. data/lib/active_merchant/billing/gateways/blue_snap.rb +1 -1
  7. data/lib/active_merchant/billing/gateways/braintree_blue.rb +8 -0
  8. data/lib/active_merchant/billing/gateways/card_stream.rb +2 -0
  9. data/lib/active_merchant/billing/gateways/citrus_pay.rb +24 -0
  10. data/lib/active_merchant/billing/gateways/clearhaus.rb +12 -4
  11. data/lib/active_merchant/billing/gateways/conekta.rb +6 -1
  12. data/lib/active_merchant/billing/gateways/credorax.rb +234 -0
  13. data/lib/active_merchant/billing/gateways/cyber_source.rb +39 -52
  14. data/lib/active_merchant/billing/gateways/element.rb +13 -2
  15. data/lib/active_merchant/billing/gateways/fat_zebra.rb +12 -3
  16. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +5 -0
  17. data/lib/active_merchant/billing/gateways/global_collect.rb +3 -1
  18. data/lib/active_merchant/billing/gateways/jetpay.rb +11 -3
  19. data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -0
  20. data/lib/active_merchant/billing/gateways/litle.rb +28 -12
  21. data/lib/active_merchant/billing/gateways/mastercard.rb +261 -0
  22. data/lib/active_merchant/billing/gateways/migs.rb +23 -1
  23. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/moneris.rb +13 -0
  25. data/lib/active_merchant/billing/gateways/netbanx.rb +245 -0
  26. data/lib/active_merchant/billing/gateways/nmi.rb +5 -0
  27. data/lib/active_merchant/billing/gateways/openpay.rb +7 -0
  28. data/lib/active_merchant/billing/gateways/opp.rb +362 -0
  29. data/lib/active_merchant/billing/gateways/orbital.rb +13 -0
  30. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +190 -0
  31. data/lib/active_merchant/billing/gateways/payflow.rb +6 -0
  32. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  33. data/lib/active_merchant/billing/gateways/paymill.rb +10 -0
  34. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  35. data/lib/active_merchant/billing/gateways/payu_latam.rb +386 -0
  36. data/lib/active_merchant/billing/gateways/pin.rb +1 -3
  37. data/lib/active_merchant/billing/gateways/redsys.rb +2 -0
  38. data/lib/active_merchant/billing/gateways/sage.rb +22 -0
  39. data/lib/active_merchant/billing/gateways/sage_pay.rb +12 -0
  40. data/lib/active_merchant/billing/gateways/securion_pay.rb +2 -2
  41. data/lib/active_merchant/billing/gateways/stripe.rb +29 -8
  42. data/lib/active_merchant/billing/gateways/telr.rb +275 -0
  43. data/lib/active_merchant/billing/gateways/tns.rb +12 -230
  44. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
  45. data/lib/active_merchant/billing/gateways/vanco.rb +12 -8
  46. data/lib/active_merchant/billing/gateways/worldpay.rb +18 -0
  47. data/lib/active_merchant/country.rb +6 -2
  48. data/lib/active_merchant/version.rb +1 -1
  49. metadata +11 -3
@@ -57,7 +57,9 @@ module ActiveMerchant #:nodoc:
57
57
  "CHF" => '756',
58
58
  "CLP" => '152',
59
59
  "COP" => '170',
60
+ "CRC" => '188',
60
61
  "CZK" => '203',
62
+ "DOP" => '214',
61
63
  "EUR" => '978',
62
64
  "GBP" => '826',
63
65
  "GTQ" => '320',
@@ -90,8 +90,30 @@ module ActiveMerchant #:nodoc:
90
90
  vault.unstore(identification, options)
91
91
  end
92
92
 
93
+ def supports_scrubbing?
94
+ true
95
+ end
96
+
97
+ def scrub(transcript)
98
+ force_utf8(transcript).
99
+ gsub(%r((M_id=)[^&]*), '\1[FILTERED]').
100
+ gsub(%r((M_key=)[^&]*), '\1[FILTERED]').
101
+ gsub(%r((C_cardnumber=)[^&]*), '\1[FILTERED]').
102
+ gsub(%r((C_cvv=)[^&]*), '\1[FILTERED]').
103
+ gsub(%r((<ns1:CARDNUMBER>).+(</ns1:CARDNUMBER>)), '\1[FILTERED]\2').
104
+ gsub(%r((<ns1:M_ID>).+(</ns1:M_ID>)), '\1[FILTERED]\2').
105
+ gsub(%r((<ns1:M_KEY>).+(</ns1:M_KEY>)), '\1[FILTERED]\2')
106
+ end
107
+
93
108
  private
94
109
 
110
+ # use the same method as in pay_conex
111
+ def force_utf8(string)
112
+ return nil unless string
113
+ binary = string.encode("BINARY", invalid: :replace, undef: :replace, replace: "?") # Needed for Ruby 2.0 since #encode is a no-op if the string is already UTF-8. It's not needed for Ruby 2.1 and up since it's not a no-op there.
114
+ binary.encode("UTF-8", invalid: :replace, undef: :replace, replace: "?")
115
+ end
116
+
95
117
  def add_credit_card(post, credit_card)
96
118
  post[:C_name] = credit_card.name
97
119
  post[:C_cardnumber] = credit_card.number
@@ -175,6 +175,17 @@ module ActiveMerchant #:nodoc:
175
175
  end
176
176
 
177
177
  private
178
+ def truncate(value, max_size)
179
+ return nil unless value
180
+ return value.to_s if CGI.escape(value.to_s).length <= max_size
181
+
182
+ if value.size > max_size
183
+ truncate(super(value, max_size), max_size)
184
+ else
185
+ truncate(value.to_s.chop, max_size)
186
+ end
187
+ end
188
+
178
189
  def add_reference(post, identification)
179
190
  order_id, transaction_id, authorization, security_key = identification.split(';')
180
191
 
@@ -281,6 +292,7 @@ module ActiveMerchant #:nodoc:
281
292
  def add_token_details(post, token, options)
282
293
  add_token(post, token)
283
294
  add_pair(post, :StoreToken, options[:customer])
295
+ add_pair(post, :CV2, options[:verification_value])
284
296
  end
285
297
 
286
298
  def add_token(post, token)
@@ -5,8 +5,8 @@ module ActiveMerchant #:nodoc:
5
5
  self.live_url = 'https://api.securionpay.com/'
6
6
 
7
7
 
8
- self.supported_countries = %w(AL AD AT BY BE BG HR CY RE DK EE IS FI FR DE GI GR HU IS IE IT LV LI LT LU
9
- MK MT MD MC NL NO PL PT RO RU MA RS SK SI ES SE CH UA KI CI RS RS ME)
8
+ self.supported_countries = %w(AL AD AT BY BE BG HR CY CZ RE DK EE IS FI FR DE GI GR HU IS IE IT IL LV LI LT LU
9
+ MK MT MD MC NL NO PL PT RO RU MA RS SK SI ES SE CH UA GB KI CI ME)
10
10
 
11
11
  self.default_currency = 'USD'
12
12
  self.money_format = :cents
@@ -21,7 +21,7 @@ module ActiveMerchant #:nodoc:
21
21
  'unchecked' => 'P'
22
22
  }
23
23
 
24
- self.supported_countries = %w(AT AU BE CA CH DE DK ES FI FR GB IE IT LU NL NO SE SG US)
24
+ self.supported_countries = %w(AT AU BE BR CA CH DE DK ES FI FR GB HK IE IT JP LU MX NL NO NZ PT SE SG US)
25
25
  self.default_currency = 'USD'
26
26
  self.money_format = :cents
27
27
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
@@ -51,6 +51,22 @@ module ActiveMerchant #:nodoc:
51
51
  "business" => "company",
52
52
  }
53
53
 
54
+ MINIMUM_AUTHORIZE_AMOUNTS = {
55
+ "USD" => 100,
56
+ "CAD" => 100,
57
+ "GBP" => 60,
58
+ "EUR" => 100,
59
+ "DKK" => 500,
60
+ "NOK" => 600,
61
+ "SEK" => 600,
62
+ "CHF" => 100,
63
+ "AUD" => 100,
64
+ "JPY" => 100,
65
+ "MXN" => 2000,
66
+ "SGD" => 100,
67
+ "HKD" => 800
68
+ }
69
+
54
70
  def initialize(options = {})
55
71
  requires!(options, :login)
56
72
  @api_key = options[:login]
@@ -117,6 +133,7 @@ module ActiveMerchant #:nodoc:
117
133
 
118
134
  def void(identification, options = {})
119
135
  post = {}
136
+ post[:metadata] = options[:metadata] if options[:metadata]
120
137
  post[:expand] = [:charge]
121
138
  commit(:post, "charges/#{CGI.escape(identification)}/refunds", post, options)
122
139
  end
@@ -141,7 +158,7 @@ module ActiveMerchant #:nodoc:
141
158
 
142
159
  def verify(payment, options = {})
143
160
  MultiResponse.run(:use_first_response) do |r|
144
- r.process { authorize(50, payment, options) }
161
+ r.process { authorize(auth_minimum_amount(options), payment, options) }
145
162
  r.process(:ignore_result) { void(r.authorization, options) }
146
163
  end
147
164
  end
@@ -369,14 +386,13 @@ module ActiveMerchant #:nodoc:
369
386
  card[:cvc] = creditcard.verification_value if creditcard.verification_value?
370
387
  card[:name] = creditcard.name if creditcard.name
371
388
  end
372
- post[:card] = card
373
389
 
374
- if creditcard.is_a?(NetworkTokenizationCreditCard) && creditcard.source == :apple_pay
375
- post[:three_d_secure] = {
376
- apple_pay: true,
377
- cryptogram: creditcard.payment_cryptogram
378
- }
390
+ if creditcard.is_a?(NetworkTokenizationCreditCard)
391
+ card[:cryptogram] = creditcard.payment_cryptogram
392
+ card[:eci] = creditcard.eci
393
+ card[:tokenization_method] = creditcard.source.to_s
379
394
  end
395
+ post[:card] = card
380
396
 
381
397
  add_address(post, options)
382
398
  elsif creditcard.kind_of?(String)
@@ -600,6 +616,11 @@ module ActiveMerchant #:nodoc:
600
616
  card_brand(payment_method) == "check"
601
617
  end
602
618
  end
619
+
620
+ def auth_minimum_amount(options)
621
+ return 100 unless options[:currency]
622
+ return MINIMUM_AUTHORIZE_AMOUNTS[options[:currency].upcase] || 100
623
+ end
603
624
  end
604
625
  end
605
626
  end
@@ -0,0 +1,275 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class TelrGateway < Gateway
6
+ self.display_name = "Telr"
7
+ self.homepage_url = "http://www.telr.com/"
8
+
9
+ self.live_url = "https://secure.telr.com/gateway/remote.xml"
10
+
11
+ self.supported_countries = ["AE", "IN", "SA"]
12
+ self.default_currency = "AED"
13
+ self.money_format = :dollars
14
+ self.supported_cardtypes = [:visa, :master, :american_express, :maestro, :solo, :jcb]
15
+
16
+ CVC_CODE_TRANSLATOR = {
17
+ 'Y' => 'M',
18
+ 'N' => 'N',
19
+ 'X' => 'P',
20
+ 'E' => 'U',
21
+ }
22
+
23
+ AVS_CODE_TRANSLATOR = {
24
+ 'Y' => 'M',
25
+ 'P' => 'A',
26
+ 'N' => 'N',
27
+ 'X' => 'I',
28
+ 'E' => 'R'
29
+ }
30
+
31
+ def initialize(options={})
32
+ requires!(options, :merchant_id, :api_key)
33
+ super
34
+ end
35
+
36
+ def purchase(amount, payment_method, options={})
37
+ commit(:purchase, amount, options[:currency]) do |doc|
38
+ add_invoice(doc, "sale", amount, payment_method, options)
39
+ add_payment_method(doc, payment_method, options)
40
+ add_customer_data(doc, payment_method, options)
41
+ end
42
+ end
43
+
44
+ def authorize(amount, payment_method, options={})
45
+ commit(:authorize, amount, options[:currency]) do |doc|
46
+ add_invoice(doc, "auth", amount, payment_method, options)
47
+ add_payment_method(doc, payment_method, options)
48
+ add_customer_data(doc, payment_method, options)
49
+ end
50
+ end
51
+
52
+ def capture(amount, authorization, options={})
53
+ commit(:capture) do |doc|
54
+ add_invoice(doc, "capture", amount, authorization, options)
55
+ end
56
+ end
57
+
58
+ def void(authorization, options={})
59
+ _, amount, currency = split_authorization(authorization)
60
+ commit(:void) do |doc|
61
+ add_invoice(doc, "void", amount.to_i, authorization, options.merge(currency: currency))
62
+ end
63
+ end
64
+
65
+ def refund(amount, authorization, options={})
66
+ commit(:refund) do |doc|
67
+ add_invoice(doc, "refund", amount, authorization, options)
68
+ end
69
+ end
70
+
71
+ def verify(credit_card, options={})
72
+ commit(:verify) do |doc|
73
+ add_invoice(doc, "verify", 100, credit_card, options)
74
+ add_payment_method(doc, credit_card, options)
75
+ add_customer_data(doc, credit_card, options)
76
+ end
77
+ end
78
+
79
+ def verify_credentials
80
+ response = void("0")
81
+ !["01", "04"].include?(response.error_code)
82
+ end
83
+
84
+ def supports_scrubbing?
85
+ true
86
+ end
87
+
88
+ def scrub(transcript)
89
+ transcript.
90
+ gsub(%r((<Number>)[^<]+(<))i, '\1[FILTERED]\2').
91
+ gsub(%r((<CVV>)[^<]+(<))i, '\1[FILTERED]\2').
92
+ gsub(%r((<Key>)[^<]+(<))i, '\1[FILTERED]\2')
93
+ end
94
+
95
+ private
96
+
97
+ def add_invoice(doc, action, money, payment_method, options)
98
+ doc.tran do
99
+ doc.type(action)
100
+ doc.amount(amount(money))
101
+ doc.currency(options[:currency] || currency(money))
102
+ doc.cartid(options[:order_id])
103
+ doc.class_(transaction_class(action, payment_method))
104
+ doc.description(options[:description] || "Description")
105
+ doc.test_(test_mode)
106
+ add_ref(doc, action, payment_method)
107
+ end
108
+ end
109
+
110
+ def add_payment_method(doc, payment_method, options)
111
+ return if payment_method.is_a?(String)
112
+ doc.card do
113
+ doc.number(payment_method.number)
114
+ doc.cvv(payment_method.verification_value)
115
+ doc.expiry do
116
+ doc.month(format(payment_method.month, :two_digits))
117
+ doc.year(format(payment_method.year, :four_digits))
118
+ end
119
+ end
120
+ end
121
+
122
+ def add_customer_data(doc, payment_method, options)
123
+ return if payment_method.is_a?(String)
124
+ doc.billing do
125
+ doc.name do
126
+ doc.first(payment_method.first_name)
127
+ doc.last(payment_method.last_name)
128
+ end
129
+ doc.email(options[:email] || "unspecified@email.com")
130
+ doc.ip(options[:ip]) if options[:ip]
131
+ doc.address do
132
+ add_address(doc, options)
133
+ end
134
+ end
135
+ end
136
+
137
+ def add_address(doc, options)
138
+ address = options[:billing_address] || {}
139
+ doc.country(address[:country] ? lookup_country_code(address[:country]) : "NA")
140
+ doc.city(address[:city] || "City")
141
+ doc.line1(address[:address1] || "Address")
142
+ return unless address
143
+ doc.line2(address[:address2]) if address[:address2]
144
+ doc.zip(address[:zip]) if address[:zip]
145
+ doc.region(address[:state]) if address[:state]
146
+ end
147
+
148
+ def add_ref(doc, action, payment_method)
149
+ if ["capture", "refund", "void"].include?(action) || payment_method.is_a?(String)
150
+ doc.ref(split_authorization(payment_method)[0])
151
+ end
152
+ end
153
+
154
+ def add_authentication(doc)
155
+ doc.store(@options[:merchant_id])
156
+ doc.key(@options[:api_key])
157
+ end
158
+
159
+ def lookup_country_code(code)
160
+ country = Country.find(code) rescue nil
161
+ country.code(:alpha2)
162
+ end
163
+
164
+ def commit(action, amount=nil, currency=nil)
165
+ currency = default_currency if currency == nil
166
+ request = build_xml_request { |doc| yield(doc) }
167
+ response = ssl_post(live_url, request, headers)
168
+ parsed = parse(response)
169
+
170
+ succeeded = success_from(parsed)
171
+ Response.new(
172
+ succeeded,
173
+ message_from(succeeded, parsed),
174
+ parsed,
175
+ authorization: authorization_from(action, parsed, amount, currency),
176
+ avs_result: avs_result(parsed),
177
+ cvv_result: cvv_result(parsed),
178
+ error_code: error_code_from(succeeded, parsed),
179
+ test: test?
180
+ )
181
+ end
182
+
183
+ def root_attributes
184
+ {
185
+ store: @options[:merchant_id],
186
+ key: @options[:api_key]
187
+ }
188
+ end
189
+
190
+ def build_xml_request
191
+ builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
192
+ xml.remote do |doc|
193
+
194
+ add_authentication(doc)
195
+ yield(doc)
196
+ end
197
+ end
198
+
199
+ builder.doc.to_xml
200
+ end
201
+
202
+ def test_mode
203
+ test? ? '1' : '0'
204
+ end
205
+
206
+ def transaction_class(action, payment_method)
207
+ if payment_method.is_a?(String) && action == "sale"
208
+ return "cont"
209
+ else
210
+ return "moto"
211
+ end
212
+ end
213
+
214
+ def parse(xml)
215
+ response = {}
216
+
217
+ doc = Nokogiri::XML(xml)
218
+ doc.root.xpath("*").each do |node|
219
+ if (node.elements.size == 0)
220
+ response[node.name.downcase.to_sym] = node.text
221
+ else
222
+ node.elements.each do |childnode|
223
+ name = "#{childnode.name.downcase}"
224
+ response[name.to_sym] = childnode.text
225
+ end
226
+ end
227
+ end unless doc.root.nil?
228
+
229
+ response
230
+ end
231
+
232
+ def authorization_from(action, response, amount, currency)
233
+ auth = response[:tranref]
234
+ auth = [auth, amount, currency].join('|')
235
+ auth
236
+ end
237
+
238
+ def split_authorization(authorization)
239
+ authorization.split('|')
240
+ end
241
+
242
+ def success_from(response)
243
+ response[:status] == "A"
244
+ end
245
+
246
+ def message_from(succeeded, response)
247
+ if succeeded
248
+ "Succeeded"
249
+ else
250
+ response[:message]
251
+ end
252
+ end
253
+
254
+ def error_code_from(succeeded, response)
255
+ unless succeeded
256
+ response[:code]
257
+ end
258
+ end
259
+
260
+ def cvv_result(parsed)
261
+ CVVResult.new(CVC_CODE_TRANSLATOR[parsed[:cvv]])
262
+ end
263
+
264
+ def avs_result(parsed)
265
+ AVSResult.new(code: AVS_CODE_TRANSLATOR[parsed[:avs]])
266
+ end
267
+
268
+ def headers
269
+ {
270
+ "Content-Type" => "text/xml"
271
+ }
272
+ end
273
+ end
274
+ end
275
+ end
@@ -1,241 +1,23 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant
2
+ module Billing
3
3
  class TnsGateway < Gateway
4
- class_attribute :live_na_url, :live_ap_url
4
+ include MastercardGateway
5
5
 
6
- self.display_name = 'TNS'
7
- self.homepage_url = 'http://www.tnsi.com/'
6
+ class_attribute :live_na_url, :live_ap_url, :test_na_url, :test_ap_url
8
7
 
9
- # Testing is partitioned by account.
10
- self.live_na_url = 'https://secure.na.tnspayments.com/api/rest/version/22/'
11
- self.live_ap_url = 'https://secure.ap.tnspayments.com/api/rest/version/22/'
8
+ self.live_na_url = 'https://secure.na.tnspayments.com/api/rest/version/36/'
9
+ self.test_na_url = 'https://secure.na.tnspayments.com/api/rest/version/36/'
12
10
 
13
- self.supported_countries = %w(AR AU BR FR DE HK MX NZ SG GB US)
11
+ self.live_ap_url = 'https://secure.ap.tnspayments.com/api/rest/version/36/'
12
+ self.test_ap_url = 'https://secure.ap.tnspayments.com/api/rest/version/36/'
14
13
 
14
+ self.display_name = 'TNS'
15
+ self.homepage_url = 'http://www.tnsi.com/'
16
+ self.supported_countries = %w(AR AU BR FR DE HK MX NZ SG GB US)
15
17
  self.default_currency = 'USD'
16
18
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro, :laser]
19
+ self.ssl_version = :TLSv1
17
20
 
18
- self.ssl_version = :TLSv1_2
19
-
20
- def initialize(options={})
21
- requires!(options, :userid, :password)
22
-
23
- options[:region] = 'north_america' unless options[:region]
24
-
25
- super
26
- end
27
-
28
- def purchase(amount, payment_method, options={})
29
- MultiResponse.run do |r|
30
- r.process { authorize(amount, payment_method, options) }
31
- r.process { capture(amount, r.authorization, options) }
32
- end
33
- end
34
-
35
- def authorize(amount, payment_method, options={})
36
- post = new_post
37
- add_invoice(post, amount, options)
38
- add_reference(post, *new_authorization)
39
- add_payment_method(post, payment_method)
40
- add_customer_data(post, options)
41
-
42
- commit('authorize', post)
43
- end
44
-
45
- def capture(amount, authorization, options={})
46
- post = new_post
47
- add_invoice(post, amount, options, :transaction)
48
- add_reference(post, *next_authorization(authorization))
49
- add_customer_data(post, options)
50
-
51
- commit('capture', post)
52
- end
53
-
54
- def refund(amount, authorization, options={})
55
- post = new_post
56
- add_invoice(post, amount, options, :transaction)
57
- add_reference(post, *next_authorization(authorization))
58
- add_customer_data(post, options)
59
-
60
- commit('refund', post)
61
- end
62
-
63
- def void(authorization, options={})
64
- post = new_post
65
- add_reference(post, *next_authorization(authorization), :targetTransactionId)
66
-
67
- commit('void', post)
68
- end
69
-
70
- def verify(credit_card, options={})
71
- MultiResponse.run(:use_first_response) do |r|
72
- r.process { authorize(100, credit_card, options) }
73
- r.process(:ignore_result) { void(r.authorization, options) }
74
- end
75
- end
76
-
77
- private
78
-
79
- def new_post
80
- {
81
- order: {},
82
- sourceOfFunds: {
83
- provided: {
84
- card: {
85
- }
86
- }
87
- },
88
- customer: {},
89
- billing: {},
90
- shipping: {},
91
- transaction: {},
92
- }
93
- end
94
-
95
- def add_invoice(post, amount, options, node=:order)
96
- post[node][:amount] = amount(amount)
97
- post[node][:currency] = (options[:currency] || currency(amount))
98
- end
99
-
100
- def add_reference(post, orderid, transactionid, transaction_reference, reference_key=:reference)
101
- post[:orderid] = orderid
102
- post[:transactionid] = transactionid
103
- post[:transaction][reference_key] = transaction_reference if transaction_reference
104
- end
105
-
106
- def add_payment_method(post, payment_method)
107
- card = {}
108
- card[:expiry] = {}
109
- card[:number] = payment_method.number
110
- card[:securityCode] = payment_method.verification_value
111
- card[:expiry][:year] = format(payment_method.year, :two_digits)
112
- card[:expiry][:month] = format(payment_method.month, :two_digits)
113
-
114
- post[:sourceOfFunds][:type] = 'CARD'
115
- post[:sourceOfFunds][:provided][:card].merge!(card)
116
- end
117
-
118
- def add_customer_data(post, options)
119
- billing = {}
120
- shipping = {}
121
- customer = {}
122
- if(billing_address = (options[:billing_address] || options[:address]))
123
- billing[:address] = {}
124
- billing[:address][:street] = billing_address[:address1]
125
- billing[:address][:street2] = billing_address[:address2]
126
- billing[:address][:city] = billing_address[:city]
127
- billing[:address][:stateProvince] = billing_address[:state]
128
- billing[:address][:postcodeZip] = billing_address[:zip]
129
- billing[:address][:country] = country_code(billing_address[:country])
130
- billing[:phone] = billing_address[:phone]
131
-
132
- customer[:email] = options[:email] if options[:email]
133
- customer[:ipAddress] = options[:ip] if options[:ip]
134
- end
135
-
136
- if(shipping_address = options[:shipping_address])
137
- shipping[:address] = {}
138
- shipping[:address][:street] = shipping_address[:address1]
139
- shipping[:address][:street2] = shipping_address[:address2]
140
- shipping[:address][:city] = shipping_address[:city]
141
- shipping[:address][:stateProvince] = shipping_address[:state]
142
- shipping[:address][:postcodeZip] = shipping_address[:zip]
143
- shipping[:address][:shipcountry] = country_code(shipping_address[:country])
144
-
145
- first_name, last_name = split_names(shipping_address[:name])
146
- shipping[:firstName] = first_name if first_name
147
- shipping[:lastName] = last_name if last_name
148
- end
149
- post[:billing].merge!(billing)
150
- post[:shipping].merge!(shipping)
151
- post[:customer].merge!(customer)
152
- end
153
-
154
- def country_code(country)
155
- if country
156
- country = ActiveMerchant::Country.find(country)
157
- country.code(:alpha3).value
158
- end
159
- rescue InvalidCountryCodeError
160
- end
161
-
162
- def commit(action, post)
163
- url = build_url(post.delete(:orderid), post.delete(:transactionid))
164
- headers = {
165
- 'Authorization' => 'Basic ' + Base64.encode64("merchant.#{@options[:userid]}:#{@options[:password]}").strip.delete("\r\n"),
166
- 'Content-Type' => 'application/json',
167
- }
168
- post[:apiOperation] = action.upcase
169
- begin
170
- raw = parse(ssl_request(:put, url, build_request(post), headers))
171
- rescue ResponseError => e
172
- raw = parse(e.response.body)
173
- end
174
- succeeded = success_from(raw['result'])
175
- Response.new(
176
- succeeded,
177
- message_from(succeeded, raw),
178
- raw,
179
- :authorization => authorization_from(post, raw),
180
- :test => test?
181
- )
182
- end
183
-
184
- def build_url(orderid, transactionid)
185
- base_url = @options[:region] == 'asia_pacific' ? live_ap_url : live_na_url
186
- "#{base_url}merchant/#{@options[:userid]}/order/#{orderid}/transaction/#{transactionid}"
187
- end
188
-
189
- def build_request(post = {})
190
- post.to_json
191
- end
192
-
193
- def parse(body)
194
- JSON.parse(body)
195
- end
196
-
197
- def success_from(response)
198
- response == 'SUCCESS'
199
- end
200
-
201
- def message_from(succeeded, response)
202
- if succeeded
203
- 'Succeeded'
204
- else
205
- [
206
- response['result'],
207
- response['response'] && response['response']['gatewayCode'],
208
- response['error'] && response['error']['cause'],
209
- response['error'] && response['error']['explanation']
210
- ].compact.join(' - ')
211
- end
212
- end
213
-
214
- def authorization_from(request, response)
215
- [response['order']['id'], response['transaction']['id']].join('|') if response['order']
216
- end
217
-
218
- def split_authorization(authorization)
219
- authorization.split('|')
220
- end
221
-
222
- def new_authorization
223
- # Must be unique within a merchant id.
224
- orderid = SecureRandom.uuid
225
-
226
- # Must be unique within an order id.
227
- transactionid = '1'
228
-
229
- # New transactions have no previous reference.
230
- transaction_reference = nil
231
- [orderid, transactionid, transaction_reference]
232
- end
233
-
234
- def next_authorization(authorization)
235
- orderid, prev_transactionid = split_authorization(authorization)
236
- next_transactionid = SecureRandom.uuid
237
- [orderid, next_transactionid, prev_transactionid]
238
- end
239
21
  end
240
22
  end
241
23
  end