activemerchant 1.56.0 → 1.66.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +331 -0
  3. data/README.md +9 -9
  4. data/lib/active_merchant/billing/check.rb +3 -0
  5. data/lib/active_merchant/billing/credit_card.rb +8 -3
  6. data/lib/active_merchant/billing/credit_card_methods.rb +41 -1
  7. data/lib/active_merchant/billing/gateway.rb +14 -6
  8. data/lib/active_merchant/billing/gateways/adyen.rb +228 -0
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +157 -44
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +7 -4
  11. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +283 -0
  12. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +68 -2
  13. data/lib/active_merchant/billing/gateways/blue_pay.rb +2 -2
  14. data/lib/active_merchant/billing/gateways/blue_snap.rb +348 -0
  15. data/lib/active_merchant/billing/gateways/bpoint.rb +1 -1
  16. data/lib/active_merchant/billing/gateways/braintree_blue.rb +58 -20
  17. data/lib/active_merchant/billing/gateways/bridge_pay.rb +37 -8
  18. data/lib/active_merchant/billing/gateways/card_stream.rb +161 -40
  19. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -0
  20. data/lib/active_merchant/billing/gateways/checkout_v2.rb +5 -2
  21. data/lib/active_merchant/billing/gateways/citrus_pay.rb +24 -0
  22. data/lib/active_merchant/billing/gateways/clearhaus.rb +24 -40
  23. data/lib/active_merchant/billing/gateways/conekta.rb +6 -1
  24. data/lib/active_merchant/billing/gateways/creditcall.rb +1 -1
  25. data/lib/active_merchant/billing/gateways/credorax.rb +310 -0
  26. data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
  27. data/lib/active_merchant/billing/gateways/cyber_source.rb +80 -64
  28. data/lib/active_merchant/billing/gateways/data_cash.rb +10 -304
  29. data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
  30. data/lib/active_merchant/billing/gateways/elavon.rb +40 -26
  31. data/lib/active_merchant/billing/gateways/element.rb +356 -0
  32. data/lib/active_merchant/billing/gateways/fat_zebra.rb +16 -2
  33. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -1
  34. data/lib/active_merchant/billing/gateways/forte.rb +10 -2
  35. data/lib/active_merchant/billing/gateways/global_collect.rb +311 -0
  36. data/lib/active_merchant/billing/gateways/global_transport.rb +1 -0
  37. data/lib/active_merchant/billing/gateways/iats_payments.rb +13 -0
  38. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
  39. data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
  40. data/lib/active_merchant/billing/gateways/jetpay.rb +33 -19
  41. data/lib/active_merchant/billing/gateways/kushki.rb +217 -0
  42. data/lib/active_merchant/billing/gateways/latitude19.rb +416 -0
  43. data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -0
  44. data/lib/active_merchant/billing/gateways/litle.rb +29 -13
  45. data/lib/active_merchant/billing/gateways/mastercard.rb +268 -0
  46. data/lib/active_merchant/billing/gateways/maxipago.rb +145 -122
  47. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +15 -1
  48. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +10 -7
  49. data/lib/active_merchant/billing/gateways/mercury.rb +13 -5
  50. data/lib/active_merchant/billing/gateways/metrics_global.rb +1 -1
  51. data/lib/active_merchant/billing/gateways/migs.rb +23 -1
  52. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  53. data/lib/active_merchant/billing/gateways/moneris.rb +21 -1
  54. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -0
  55. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +165 -0
  56. data/lib/active_merchant/billing/gateways/netbanx.rb +245 -0
  57. data/lib/active_merchant/billing/gateways/nmi.rb +30 -9
  58. data/lib/active_merchant/billing/gateways/omise.rb +9 -5
  59. data/lib/active_merchant/billing/gateways/openpay.rb +10 -1
  60. data/lib/active_merchant/billing/gateways/opp.rb +362 -0
  61. data/lib/active_merchant/billing/gateways/orbital.rb +28 -7
  62. data/lib/active_merchant/billing/gateways/pagarme.rb +248 -0
  63. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +190 -0
  64. data/lib/active_merchant/billing/gateways/payeezy.rb +61 -12
  65. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  66. data/lib/active_merchant/billing/gateways/payflow.rb +6 -0
  67. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  68. data/lib/active_merchant/billing/gateways/paymill.rb +29 -11
  69. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  70. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -6
  71. data/lib/active_merchant/billing/gateways/payu_in.rb +3 -2
  72. data/lib/active_merchant/billing/gateways/payu_latam.rb +402 -0
  73. data/lib/active_merchant/billing/gateways/pin.rb +6 -3
  74. data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
  75. data/lib/active_merchant/billing/gateways/psl_card.rb +3 -3
  76. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +1 -1
  77. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +0 -2
  78. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +1 -1
  79. data/lib/active_merchant/billing/gateways/quickpay.rb +3 -3
  80. data/lib/active_merchant/billing/gateways/qvalent.rb +44 -1
  81. data/lib/active_merchant/billing/gateways/redsys.rb +3 -0
  82. data/lib/active_merchant/billing/gateways/s5.rb +8 -5
  83. data/lib/active_merchant/billing/gateways/safe_charge.rb +220 -0
  84. data/lib/active_merchant/billing/gateways/sage.rb +397 -128
  85. data/lib/active_merchant/billing/gateways/sage_pay.rb +45 -20
  86. data/lib/active_merchant/billing/gateways/secure_net.rb +0 -5
  87. data/lib/active_merchant/billing/gateways/secure_pay.rb +1 -1
  88. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -0
  89. data/lib/active_merchant/billing/gateways/securion_pay.rb +46 -17
  90. data/lib/active_merchant/billing/gateways/stripe.rb +125 -29
  91. data/lib/active_merchant/billing/gateways/telr.rb +275 -0
  92. data/lib/active_merchant/billing/gateways/tns.rb +13 -222
  93. data/lib/active_merchant/billing/gateways/trans_first.rb +40 -16
  94. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +606 -0
  95. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +114 -9
  96. data/lib/active_merchant/billing/gateways/vanco.rb +14 -10
  97. data/lib/active_merchant/billing/gateways/visanet_peru.rb +209 -0
  98. data/lib/active_merchant/billing/gateways/wepay.rb +73 -38
  99. data/lib/active_merchant/billing/gateways/wirecard.rb +1 -0
  100. data/lib/active_merchant/billing/gateways/world_net.rb +344 -0
  101. data/lib/active_merchant/billing/gateways/worldpay.rb +48 -16
  102. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +15 -0
  103. data/lib/active_merchant/country.rb +6 -4
  104. data/lib/active_merchant/posts_data.rb +1 -1
  105. data/lib/active_merchant/version.rb +1 -1
  106. metadata +32 -13
  107. data/lib/active_merchant/billing/gateways/app55.rb +0 -176
  108. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
  109. data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -278
  110. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +0 -89
  111. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +0 -115
  112. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +0 -149
  113. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -97
@@ -77,12 +77,14 @@ module ActiveMerchant #:nodoc:
77
77
  self.homepage_url = 'http://www.usaepay.com/'
78
78
  self.display_name = 'USA ePay Advanced SOAP Interface'
79
79
 
80
- CUSTOMER_OPTIONS = {
80
+ CUSTOMER_PROFILE_OPTIONS = {
81
81
  :id => [:string, 'CustomerID'], # merchant assigned number
82
82
  :notes => [:string, 'Notes'],
83
83
  :data => [:string, 'CustomData'],
84
- :url => [:string, 'URL'],
85
- # Recurring Billing
84
+ :url => [:string, 'URL']
85
+ } #:nodoc:
86
+
87
+ CUSTOMER_RECURRING_BILLING_OPTIONS = {
86
88
  :enabled => [:boolean, 'Enabled'],
87
89
  :schedule => [:string, 'Schedule'],
88
90
  :number_left => [:integer, 'NumLeft'],
@@ -92,18 +94,24 @@ module ActiveMerchant #:nodoc:
92
94
  :user => [:string, 'User'],
93
95
  :source => [:string, 'Source'],
94
96
  :send_receipt => [:boolean, 'SendReceipt'],
95
- :receipt_note => [:string, 'ReceiptNote'],
96
- # Point of Sale
97
+ :receipt_note => [:string, 'ReceiptNote']
98
+ } #:nodoc:
99
+
100
+ CUSTOMER_POINT_OF_SALE_OPTIONS = {
97
101
  :price_tier => [:string, 'PriceTier'],
98
102
  :tax_class => [:string, 'TaxClass'],
99
103
  :lookup_code => [:string, 'LookupCode']
100
104
  } #:nodoc:
101
105
 
102
- ADDRESS_OPTIONS = {
106
+ CUSTOMER_OPTIONS = [
107
+ CUSTOMER_PROFILE_OPTIONS,
108
+ CUSTOMER_RECURRING_BILLING_OPTIONS,
109
+ CUSTOMER_POINT_OF_SALE_OPTIONS
110
+ ].inject(:merge) #:nodoc:
111
+
112
+ COMMON_ADDRESS_OPTIONS = {
103
113
  :first_name => [:string, 'FirstName'],
104
114
  :last_name => [:string, 'LastName'],
105
- :address1 => [:string, 'Street'],
106
- :address2 => [:string, 'Street2'],
107
115
  :city => [:string, 'City'],
108
116
  :state => [:string, 'State'],
109
117
  :zip => [:string, 'Zip'],
@@ -114,6 +122,32 @@ module ActiveMerchant #:nodoc:
114
122
  :company => [:string, 'Company']
115
123
  } #:nodoc:
116
124
 
125
+ ADDRESS_OPTIONS = [
126
+ COMMON_ADDRESS_OPTIONS,
127
+ {
128
+ :address1 => [:string, 'Street'],
129
+ :address2 => [:string, 'Street2'],
130
+ }
131
+ ].inject(:merge) #:nodoc
132
+
133
+ CUSTOMER_UPDATE_DATA_FIELDS = [
134
+ CUSTOMER_PROFILE_OPTIONS,
135
+ CUSTOMER_RECURRING_BILLING_OPTIONS,
136
+ COMMON_ADDRESS_OPTIONS,
137
+ {
138
+ :address1 => [:string, 'Address'],
139
+ :address2 => [:string, 'Address2'],
140
+ },
141
+ {
142
+ :card_number => [:string, 'CardNumber'],
143
+ :card_exp => [:string, 'CardExp'],
144
+ :account => [:string, 'Account'],
145
+ :routing => [:string, 'Routing'],
146
+ :check_format => [:string, 'CheckFormat'],
147
+ :record_type => [:string, 'RecordType'],
148
+ }
149
+ ].inject(:merge) #:nodoc
150
+
117
151
  CUSTOMER_TRANSACTION_REQUEST_OPTIONS = {
118
152
  :command => [:string, 'Command'],
119
153
  :ignore_duplicate => [:boolean, 'IgnoreDuplicate'],
@@ -354,6 +388,55 @@ module ActiveMerchant #:nodoc:
354
388
  commit(__method__, request)
355
389
  end
356
390
 
391
+ # Update a customer by replacing only the provided fields.
392
+ #
393
+ # ==== Required
394
+ # * <tt>:customer_number</tt> -- customer to update
395
+ # * <tt>:update_data</tt> -- FieldValue array of fields to retrieve
396
+ # * <tt>:first_name</tt>
397
+ # * <tt>:last_name</tt>
398
+ # * <tt>:id</tt>
399
+ # * <tt>:company</tt>
400
+ # * <tt>:address</tt>
401
+ # * <tt>:address2</tt>
402
+ # * <tt>:city</tt>
403
+ # * <tt>:state</tt>
404
+ # * <tt>:zip</tt>
405
+ # * <tt>:country</tt>
406
+ # * <tt>:phone</tt>
407
+ # * <tt>:fax</tt>
408
+ # * <tt>:email</tt>
409
+ # * <tt>:url</tt>
410
+ # * <tt>:receipt_note</tt>
411
+ # * <tt>:send_receipt</tt>
412
+ # * <tt>:notes</tt>
413
+ # * <tt>:description</tt>
414
+ # * <tt>:order_id</tt>
415
+ # * <tt>:enabled</tt>
416
+ # * <tt>:schedule</tt>
417
+ # * <tt>:next</tt>
418
+ # * <tt>:num_left</tt>
419
+ # * <tt>:amount</tt>
420
+ # * <tt>:custom_data</tt>
421
+ # * <tt>:source</tt>
422
+ # * <tt>:user</tt>
423
+ # * <tt>:card_number</tt>
424
+ # * <tt>:card_exp</tt>
425
+ # * <tt>:account</tt>
426
+ # * <tt>:routing</tt>
427
+ # * <tt>:check_format</tt> or <tt>:record_type</tt>
428
+ #
429
+ # ==== Response
430
+ # * <tt>#message</tt> -- boolean; Returns true if successful. Exception thrown all failures.
431
+ #
432
+ def quick_update_customer(options={})
433
+ requires! options, :customer_number
434
+ requires! options, :update_data
435
+
436
+ request = build_request(__method__, options)
437
+ commit(__method__, request)
438
+ end
439
+
357
440
  # Enable a customer for recurring billing.
358
441
  #
359
442
  # Note: Customer does not need to have all recurring parameters to succeed.
@@ -1019,6 +1102,14 @@ module ActiveMerchant #:nodoc:
1019
1102
  build_customer(soap, options, 'deleteCustomer')
1020
1103
  end
1021
1104
 
1105
+ def build_quick_update_customer(soap, options)
1106
+ soap.tag! "ns1:quickUpdateCustomer" do
1107
+ build_token soap, options
1108
+ build_tag soap, :integer, 'CustNum', options[:customer_number]
1109
+ build_field_value_array soap, "UpdateData", "FieldValue", options[:update_data], CUSTOMER_UPDATE_DATA_FIELDS
1110
+ end
1111
+ end
1112
+
1022
1113
  def build_add_customer_payment_method(soap, options)
1023
1114
  soap.tag! "ns1:addCustomerPaymentMethod" do
1024
1115
  build_token soap, options
@@ -1408,6 +1499,21 @@ module ActiveMerchant #:nodoc:
1408
1499
  end
1409
1500
  end
1410
1501
 
1502
+ def build_field_value_array(soap, tag_name, type, custom_data, fields)
1503
+ soap.tag! tag_name, 'SOAP-ENC:arryType' => "xsd:#{type}[#{options.length}]", 'xsi:type' => "ns1:#{type}Array" do
1504
+ custom_data.each do |k, v|
1505
+ build_field_value soap, fields[k][1], v, fields[k][0] if fields.keys.include? k
1506
+ end
1507
+ end
1508
+ end
1509
+
1510
+ def build_field_value(soap, field, value, value_type)
1511
+ soap.FieldValue 'xsi:type' => 'ns1:FieldValue' do
1512
+ build_tag soap, :string, 'Field', field
1513
+ build_tag soap, value_type, 'Value', value
1514
+ end
1515
+ end
1516
+
1411
1517
  def build_line_items(soap, options) # TODO
1412
1518
  end
1413
1519
 
@@ -1511,4 +1617,3 @@ module ActiveMerchant #:nodoc:
1511
1617
  end
1512
1618
  end
1513
1619
  end
1514
-
@@ -5,8 +5,8 @@ module ActiveMerchant
5
5
  class VancoGateway < Gateway
6
6
  include Empty
7
7
 
8
- self.test_url = 'https://www.vancodev.com/cgi-bin/wstest2.vps'
9
- self.live_url = 'https://www.vancoservices.com/cgi-bin/ws2.vps'
8
+ self.test_url = 'https://uat.vancopayments.com/cgi-bin/ws2.vps'
9
+ self.live_url = 'https://myvanco.vancopayments.com/cgi-bin/ws2.vps'
10
10
 
11
11
  self.supported_countries = ['US']
12
12
  self.default_currency = 'USD'
@@ -22,15 +22,15 @@ module ActiveMerchant
22
22
 
23
23
  def purchase(money, payment_method, options={})
24
24
  MultiResponse.run do |r|
25
- r.process { commit(login_request) }
26
- r.process { commit(purchase_request(money, payment_method, r.params["response_sessionid"], options)) }
25
+ r.process { login }
26
+ r.process { commit(purchase_request(money, payment_method, r.params["response_sessionid"], options), :response_transactionref) }
27
27
  end
28
28
  end
29
29
 
30
30
  def refund(money, authorization, options={})
31
31
  MultiResponse.run do |r|
32
- r.process { commit(login_request) }
33
- r.process { commit(refund_request(money, authorization, r.params["response_sessionid"])) }
32
+ r.process { login }
33
+ r.process { commit(refund_request(money, authorization, r.params["response_sessionid"]), :response_creditrequestreceived) }
34
34
  end
35
35
  end
36
36
 
@@ -89,10 +89,10 @@ module ActiveMerchant
89
89
  end
90
90
  end
91
91
 
92
- def commit(request)
92
+ def commit(request, success_field_name)
93
93
  response = parse(ssl_post(url, request, headers))
94
+ succeeded = success_from(response, success_field_name)
94
95
 
95
- succeeded = success_from(response)
96
96
  Response.new(
97
97
  succeeded,
98
98
  message_from(succeeded, response),
@@ -102,8 +102,8 @@ module ActiveMerchant
102
102
  )
103
103
  end
104
104
 
105
- def success_from(response)
106
- !response[:response_errors]
105
+ def success_from(response, success_field_name)
106
+ !empty?(response[success_field_name])
107
107
  end
108
108
 
109
109
  def message_from(succeeded, response)
@@ -252,6 +252,10 @@ module ActiveMerchant
252
252
  doc.ClientID(@options[:client_id])
253
253
  end
254
254
 
255
+ def login
256
+ commit(login_request, :response_sessionid)
257
+ end
258
+
255
259
  def login_request
256
260
  build_xml_request do |doc|
257
261
  doc.Auth do
@@ -0,0 +1,209 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class VisanetPeruGateway < Gateway
4
+ include Empty
5
+ self.display_name = "VisaNet Peru Gateway"
6
+ self.homepage_url = "http://www.visanet.com.pe"
7
+
8
+ self.test_url = "https://devapi.vnforapps.com/api.tokenization/api/v2/merchant"
9
+ self.live_url = "https://api.vnforapps.com/api.tokenization/api/v2/merchant"
10
+
11
+ self.supported_countries = ["US", "PE"]
12
+ self.default_currency = "PEN"
13
+ self.money_format = :dollars
14
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
15
+
16
+ def initialize(options={})
17
+ requires!(options, :access_key_id, :secret_access_key, :merchant_id)
18
+ super
19
+ end
20
+
21
+ def purchase(amount, payment_method, options={})
22
+ MultiResponse.run() do |r|
23
+ r.process { authorize(amount, payment_method, options) }
24
+ r.process { capture(r.authorization, options) }
25
+ end
26
+ end
27
+
28
+ def authorize(amount, payment_method, options={})
29
+ params = {}
30
+
31
+ add_invoice(params, amount, options)
32
+ add_payment_method(params, payment_method)
33
+ add_antifraud_data(params, options)
34
+ params[:email] = options[:email] || 'unknown@email.com'
35
+ params[:createAlias] = false
36
+
37
+ commit("authorize", params)
38
+ end
39
+
40
+ def capture(authorization, options={})
41
+ params = {}
42
+ add_auth_order_id(params, authorization, options)
43
+ commit("deposit", params)
44
+ end
45
+
46
+ def void(authorization, options={})
47
+ params = {}
48
+ add_auth_order_id(params, authorization, options)
49
+ commit("void", params)
50
+ end
51
+
52
+ def refund(amount, authorization, options={})
53
+ params = {}
54
+ add_auth_order_id(params, authorization, options)
55
+ commit("cancelDeposit", params)
56
+ end
57
+
58
+ def verify(credit_card, options={})
59
+ MultiResponse.run(:use_first_response) do |r|
60
+ r.process { authorize(100, credit_card, options) }
61
+ r.process(:ignore_result) { void(r.authorization, options) }
62
+ end
63
+ end
64
+
65
+ def supports_scrubbing?
66
+ true
67
+ end
68
+
69
+ def scrub(transcript)
70
+ transcript.
71
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
72
+ gsub(%r((\"cardNumber\\\":\\\")\d+), '\1[FILTERED]').
73
+ gsub(%r((\"cvv2Code\\\":\\\")\d+), '\1[FILTERED]')
74
+ end
75
+
76
+ private
77
+
78
+ CURRENCY_CODES = Hash.new{|h,k| raise ArgumentError.new("Unsupported currency: #{k}")}
79
+ CURRENCY_CODES["USD"] = 840
80
+ CURRENCY_CODES["PEN"] = 604
81
+
82
+ def add_invoice(params, money, options)
83
+ # Visanet Peru expects a 9-digit numeric purchaseNumber
84
+ params[:purchaseNumber] = (SecureRandom.random_number(900_000_000) + 100_000_000).to_s
85
+ params[:externalTransactionId] = options[:order_id]
86
+ params[:amount] = amount(money)
87
+ params[:currencyId] = CURRENCY_CODES[options[:currency] || currency(money)]
88
+ end
89
+
90
+ def add_auth_order_id(params, authorization, options)
91
+ params[:purchaseNumber] = authorization
92
+ params[:externalTransactionId] = options[:order_id]
93
+ end
94
+
95
+ def add_payment_method(params, payment_method)
96
+ params[:firstName] = payment_method.first_name
97
+ params[:lastName] = payment_method.last_name
98
+ params[:cardNumber] = payment_method.number
99
+ params[:cvv2Code] = payment_method.verification_value
100
+ params[:expirationYear] = format(payment_method.year, :four_digits)
101
+ params[:expirationMonth] = format(payment_method.month, :two_digits)
102
+ end
103
+
104
+ def add_antifraud_data(params, options)
105
+ antifraud = {}
106
+
107
+ if billing_address = options[:billing_address] || options[:address]
108
+ antifraud[:billTo_street1] = billing_address[:address1]
109
+ antifraud[:billTo_city] = billing_address[:city]
110
+ antifraud[:billTo_state] = billing_address[:state]
111
+ antifraud[:billTo_country] = billing_address[:country]
112
+ antifraud[:billTo_postalCode] = billing_address[:zip]
113
+ end
114
+
115
+ antifraud[:deviceFingerprintId] = options[:device_fingerprint_id] || SecureRandom.hex(16)
116
+ antifraud[:merchantDefineData] = options[:merchant_define_data] if options[:merchant_define_data]
117
+
118
+ params[:antifraud] = antifraud
119
+ end
120
+
121
+ def commit(action, params)
122
+ begin
123
+ raw_response = ssl_request(method(action), url(action, params), params.to_json, headers)
124
+ response = parse(raw_response)
125
+ rescue ResponseError => e
126
+ raw_response = e.response.body
127
+ response_error(raw_response)
128
+ rescue JSON::ParserError
129
+ unparsable_response(raw_response)
130
+ else
131
+ Response.new(
132
+ success_from(response),
133
+ message_from(response),
134
+ response,
135
+ :test => test?,
136
+ :authorization => authorization_from(params),
137
+ :error_code => response["errorCode"]
138
+ )
139
+ end
140
+ end
141
+
142
+ def headers
143
+ {
144
+ "Authorization" => "Basic " + Base64.strict_encode64("#{@options[:access_key_id]}:#{@options[:secret_access_key]}").strip,
145
+ "Content-Type" => "application/json"
146
+ }
147
+ end
148
+
149
+ def url(action, params)
150
+ if (action == "authorize")
151
+ "#{base_url}/#{@options[:merchant_id]}"
152
+ else
153
+ "#{base_url}/#{@options[:merchant_id]}/#{action}/#{params[:purchaseNumber]}"
154
+ end
155
+ end
156
+
157
+ def method(action)
158
+ (action == "authorize") ? :post : :put
159
+ end
160
+
161
+ def authorization_from(params)
162
+ params[:purchaseNumber]
163
+ end
164
+
165
+ def base_url
166
+ test? ? test_url : live_url
167
+ end
168
+
169
+ def parse(body)
170
+ JSON.parse(body)
171
+ end
172
+
173
+ def success_from(response)
174
+ response["errorCode"] == 0
175
+ end
176
+
177
+ def message_from(response)
178
+ if empty?(response["errorMessage"]) || response["errorMessage"] == "[ ]"
179
+ response["data"]["DSC_COD_ACCION"]
180
+ else
181
+ response["errorMessage"]
182
+ end
183
+ end
184
+
185
+ def response_error(raw_response)
186
+ begin
187
+ response = parse(raw_response)
188
+ rescue JSON::ParserError
189
+ unparsable_response(raw_response)
190
+ else
191
+ return Response.new(
192
+ false,
193
+ message_from(response),
194
+ response,
195
+ :test => test?,
196
+ :authorization => response["transactionUUID"],
197
+ :error_code => response["errorCode"]
198
+ )
199
+ end
200
+ end
201
+
202
+ def unparsable_response(raw_response)
203
+ message = "Invalid JSON response received from VisanetPeruGateway. Please contact VisanetPeruGateway if you continue to receive this message."
204
+ message += " (The raw response returned by the API was #{raw_response.inspect})"
205
+ return Response.new(false, message)
206
+ end
207
+ end
208
+ end
209
+ end
@@ -10,6 +10,8 @@ module ActiveMerchant #:nodoc:
10
10
  self.default_currency = 'USD'
11
11
  self.display_name = 'WePay'
12
12
 
13
+ API_VERSION = "2017-02-01"
14
+
13
15
  def initialize(options = {})
14
16
  requires!(options, :client_id, :account_id, :access_token)
15
17
  super(options)
@@ -18,38 +20,47 @@ module ActiveMerchant #:nodoc:
18
20
  def purchase(money, payment_method, options = {})
19
21
  post = {}
20
22
  if payment_method.is_a?(String)
21
- purchase_with_token(post, money, payment_method, options)
23
+ MultiResponse.run do |r|
24
+ r.process { authorize_with_token(post, money, payment_method, options) }
25
+ r.process { capture(money, r.authorization, options) }
26
+ end
22
27
  else
23
28
  MultiResponse.run do |r|
24
29
  r.process { store(payment_method, options) }
25
- r.process { purchase_with_token(post, money, split_authorization(r.authorization).first, options) }
30
+ r.process { authorize_with_token(post, money, r.authorization, options) }
31
+ r.process { capture(money, r.authorization, options) }
26
32
  end
27
33
  end
28
34
  end
29
35
 
30
36
  def authorize(money, payment_method, options = {})
31
- post = {auto_capture: 0}
37
+ post = {}
32
38
  if payment_method.is_a?(String)
33
- purchase_with_token(post, money, payment_method, options)
39
+ authorize_with_token(post, money, payment_method, options)
34
40
  else
35
41
  MultiResponse.run do |r|
36
42
  r.process { store(payment_method, options) }
37
- r.process { purchase_with_token(post, money, split_authorization(r.authorization).first, options) }
43
+ r.process { authorize_with_token(post, money, r.authorization, options) }
38
44
  end
39
45
  end
40
46
  end
41
47
 
42
48
  def capture(money, identifier, options = {})
49
+ checkout_id, original_amount = split_authorization(identifier)
50
+
43
51
  post = {}
44
- post[:checkout_id] = split_authorization(identifier).first
45
- commit('/checkout/capture', post)
52
+ post[:checkout_id] = checkout_id
53
+ if(money && (original_amount != amount(money)))
54
+ post[:amount] = amount(money)
55
+ end
56
+ commit('/checkout/capture', post, options)
46
57
  end
47
58
 
48
59
  def void(identifier, options = {})
49
60
  post = {}
50
61
  post[:checkout_id] = split_authorization(identifier).first
51
62
  post[:cancel_reason] = (options[:description] || "Void")
52
- commit('/checkout/cancel', post)
63
+ commit('/checkout/cancel', post, options)
53
64
  end
54
65
 
55
66
  def refund(money, identifier, options = {})
@@ -61,10 +72,9 @@ module ActiveMerchant #:nodoc:
61
72
  post[:amount] = amount(money)
62
73
  end
63
74
  post[:refund_reason] = (options[:description] || "Refund")
64
- post[:app_fee] = options[:application_fee] if options[:application_fee]
65
75
  post[:payer_email_message] = options[:payer_email_message] if options[:payer_email_message]
66
76
  post[:payee_email_message] = options[:payee_email_message] if options[:payee_email_message]
67
- commit("/checkout/refund", post)
77
+ commit("/checkout/refund", post, options)
68
78
  end
69
79
 
70
80
  def store(creditcard, options = {})
@@ -76,53 +86,58 @@ module ActiveMerchant #:nodoc:
76
86
  post[:email] = options[:email] || "unspecified@example.com"
77
87
  post[:cc_number] = creditcard.number
78
88
  post[:cvv] = creditcard.verification_value unless options[:recurring]
79
- post[:expiration_month] = "#{creditcard.month}"
80
- post[:expiration_year] = "#{creditcard.year}"
89
+ post[:expiration_month] = creditcard.month
90
+ post[:expiration_year] = creditcard.year
81
91
  post[:original_ip] = options[:ip] if options[:ip]
82
92
  post[:original_device] = options[:device_fingerprint] if options[:device_fingerprint]
93
+
83
94
  if(billing_address = (options[:billing_address] || options[:address]))
84
- post[:address] = {
85
- "address1" => billing_address[:address1],
86
- "city" => billing_address[:city],
87
- "country" => billing_address[:country]
88
- }
89
- if(post[:country] == "US")
90
- post[:address]["zip"] = billing_address[:zip]
91
- post[:address]["state"] = billing_address[:state]
92
- else
93
- post[:address]["region"] = billing_address[:state]
94
- post[:address]["postcode"] = billing_address[:zip]
95
- end
95
+ post[:address] = {}
96
+ post[:address]["address1"] = billing_address[:address1] if billing_address[:address1]
97
+ post[:address]["city"] = billing_address[:city] if billing_address[:city]
98
+ post[:address]["country"] = billing_address[:country] if billing_address[:country]
99
+ post[:address]["region"] = billing_address[:state] if billing_address[:state]
100
+ post[:address]["postal_code"] = billing_address[:zip]
96
101
  end
97
102
 
98
103
  if options[:recurring] == true
99
104
  post[:client_secret] = @options[:client_secret]
100
- commit('/credit_card/transfer', post)
105
+ commit('/credit_card/transfer', post, options)
101
106
  else
102
- commit('/credit_card/create', post)
107
+ commit('/credit_card/create', post, options)
103
108
  end
104
109
  end
105
110
 
111
+ def supports_scrubbing?
112
+ true
113
+ end
114
+
115
+ def scrub(transcript)
116
+ transcript.
117
+ gsub(%r((\\?"cc_number\\?":\\?")[^\\"]+(\\?"))i, '\1[FILTERED]\2').
118
+ gsub(%r((\\?"cvv\\?":\\?")[^\\"]+(\\?"))i, '\1[FILTERED]\2').
119
+ gsub(%r((Authorization: Bearer )\w+)i, '\1[FILTERED]\2')
120
+ end
121
+
106
122
  private
107
123
 
108
- def purchase_with_token(post, money, token, options)
124
+ def authorize_with_token(post, money, token, options)
109
125
  add_token(post, token)
110
126
  add_product_data(post, money, options)
111
- commit('/checkout/create', post)
127
+ commit('/checkout/create', post, options)
112
128
  end
113
129
 
114
130
  def add_product_data(post, money, options)
115
131
  post[:account_id] = @options[:account_id]
116
132
  post[:amount] = amount(money)
117
133
  post[:short_description] = (options[:description] || "Purchase")
118
- post[:type] = (options[:type] || "GOODS")
134
+ post[:type] = (options[:type] || "goods")
119
135
  post[:currency] = (options[:currency] || currency(money))
120
136
  post[:long_description] = options[:long_description] if options[:long_description]
121
137
  post[:payer_email_message] = options[:payer_email_message] if options[:payer_email_message]
122
138
  post[:payee_email_message] = options[:payee_email_message] if options[:payee_email_message]
123
139
  post[:reference_id] = options[:order_id] if options[:order_id]
124
- post[:app_fee] = options[:application_fee] if options[:application_fee]
125
- post[:fee_payer] = options[:fee_payer] if options[:fee_payer]
140
+ post[:unique_id] = options[:unique_id] if options[:unique_id]
126
141
  post[:redirect_uri] = options[:redirect_uri] if options[:redirect_uri]
127
142
  post[:callback_uri] = options[:callback_uri] if options[:callback_uri]
128
143
  post[:fallback_uri] = options[:fallback_uri] if options[:fallback_uri]
@@ -133,11 +148,26 @@ module ActiveMerchant #:nodoc:
133
148
  post[:preapproval_id] = options[:preapproval_id] if options[:preapproval_id]
134
149
  post[:prefill_info] = options[:prefill_info] if options[:prefill_info]
135
150
  post[:funding_sources] = options[:funding_sources] if options[:funding_sources]
151
+ add_fee(post, options)
136
152
  end
137
153
 
138
154
  def add_token(post, token)
139
- post[:payment_method_id] = token
140
- post[:payment_method_type] = "credit_card"
155
+ payment_method = {}
156
+ payment_method[:type] = "credit_card"
157
+ payment_method[:credit_card] = {
158
+ id: token,
159
+ auto_capture: false
160
+ }
161
+
162
+ post[:payment_method] = payment_method
163
+ end
164
+
165
+ def add_fee(post, options)
166
+ if options[:application_fee] || options[:fee_payer]
167
+ post[:fee] = {}
168
+ post[:fee][:app_fee] = options[:application_fee] if options[:application_fee]
169
+ post[:fee][:fee_payer] = options[:fee_payer] if options[:fee_payer]
170
+ end
141
171
  end
142
172
 
143
173
  def parse(response)
@@ -149,7 +179,7 @@ module ActiveMerchant #:nodoc:
149
179
  response = parse(ssl_post(
150
180
  ((test? ? test_url : live_url) + action),
151
181
  params.to_json,
152
- headers
182
+ headers(options)
153
183
  ))
154
184
  rescue ResponseError => e
155
185
  response = parse(e.response.body)
@@ -178,7 +208,8 @@ module ActiveMerchant #:nodoc:
178
208
  def authorization_from(response, params)
179
209
  return response["credit_card_id"].to_s if response["credit_card_id"]
180
210
 
181
- [response["checkout_id"], params[:amount]].join('|')
211
+ original_amount = response["amount"].nil? ? nil : sprintf("%0.02f", response["amount"])
212
+ [response["checkout_id"], original_amount].join('|')
182
213
  end
183
214
 
184
215
  def split_authorization(authorization)
@@ -192,14 +223,18 @@ module ActiveMerchant #:nodoc:
192
223
  return Response.new(false, message)
193
224
  end
194
225
 
195
- def headers
226
+ def headers(options)
196
227
  {
197
228
  "Content-Type" => "application/json",
198
229
  "User-Agent" => "ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
199
- "Authorization" => "Bearer #{@options[:access_token]}"
230
+ "Authorization" => "Bearer #{@options[:access_token]}",
231
+ "Api-Version" => api_version(options)
200
232
  }
201
233
  end
234
+
235
+ def api_version(options)
236
+ options[:version] || API_VERSION
237
+ end
202
238
  end
203
239
  end
204
240
  end
205
-
@@ -239,6 +239,7 @@ module ActiveMerchant #:nodoc:
239
239
  when :reversal
240
240
  xml.tag! 'GuWID', options[:preauthorization]
241
241
  end
242
+ add_customer_data(xml, options)
242
243
  end
243
244
  end
244
245
  end