activemerchant 1.133.0 → 1.137.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +240 -0
  3. data/lib/active_merchant/billing/check.rb +2 -2
  4. data/lib/active_merchant/billing/compatibility.rb +4 -4
  5. data/lib/active_merchant/billing/credit_card.rb +11 -8
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +59 -6
  8. data/lib/active_merchant/billing/gateway.rb +9 -0
  9. data/lib/active_merchant/billing/gateways/adyen.rb +162 -43
  10. data/lib/active_merchant/billing/gateways/airwallex.rb +26 -12
  11. data/lib/active_merchant/billing/gateways/alelo.rb +23 -5
  12. data/lib/active_merchant/billing/gateways/authorize_net.rb +43 -35
  13. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +10 -6
  14. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -3
  15. data/lib/active_merchant/billing/gateways/axcessms.rb +6 -2
  16. data/lib/active_merchant/billing/gateways/banwire.rb +4 -2
  17. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -3
  18. data/lib/active_merchant/billing/gateways/blue_pay.rb +13 -5
  19. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
  20. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
  21. data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
  22. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
  24. data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
  25. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
  26. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  27. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
  28. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  29. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
  30. data/lib/active_merchant/billing/gateways/checkout_v2.rb +238 -34
  31. data/lib/active_merchant/billing/gateways/commerce_hub.rb +63 -6
  32. data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
  33. data/lib/active_merchant/billing/gateways/cyber_source.rb +185 -47
  34. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
  35. data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
  36. data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
  37. data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
  38. data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
  39. data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
  40. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  41. data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
  42. data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
  43. data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
  44. data/lib/active_merchant/billing/gateways/element.rb +36 -7
  45. data/lib/active_merchant/billing/gateways/epay.rb +6 -2
  46. data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
  47. data/lib/active_merchant/billing/gateways/eway.rb +4 -2
  48. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
  49. data/lib/active_merchant/billing/gateways/exact.rb +6 -2
  50. data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
  51. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
  52. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  53. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  54. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  55. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
  56. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
  57. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
  58. data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
  59. data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
  60. data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
  61. data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
  62. data/lib/active_merchant/billing/gateways/hps.rb +1 -1
  63. data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
  64. data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
  65. data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
  66. data/lib/active_merchant/billing/gateways/ipg.rb +9 -5
  67. data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
  68. data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
  69. data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
  70. data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
  71. data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
  72. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
  73. data/lib/active_merchant/billing/gateways/kushki.rb +72 -12
  74. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
  75. data/lib/active_merchant/billing/gateways/litle.rb +33 -50
  76. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  77. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  78. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
  79. data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
  80. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
  81. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
  82. data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
  83. data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
  84. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
  85. data/lib/active_merchant/billing/gateways/migs.rb +6 -2
  86. data/lib/active_merchant/billing/gateways/mit.rb +8 -3
  87. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
  88. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  89. data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
  90. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
  91. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
  92. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  93. data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
  94. data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
  95. data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
  96. data/lib/active_merchant/billing/gateways/nmi.rb +18 -6
  97. data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
  98. data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
  99. data/lib/active_merchant/billing/gateways/opp.rb +1 -2
  100. data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
  101. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
  102. data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
  103. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
  104. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
  105. data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
  106. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
  107. data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
  108. data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
  109. data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
  110. data/lib/active_merchant/billing/gateways/payex.rb +4 -2
  111. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  112. data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
  113. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  114. data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
  115. data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
  116. data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
  117. data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
  118. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  119. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +2 -2
  120. data/lib/active_merchant/billing/gateways/pin.rb +22 -4
  121. data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
  122. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  123. data/lib/active_merchant/billing/gateways/priority.rb +6 -5
  124. data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
  125. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  126. data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
  127. data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
  128. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
  129. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  130. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
  131. data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
  132. data/lib/active_merchant/billing/gateways/reach.rb +11 -4
  133. data/lib/active_merchant/billing/gateways/redsys.rb +2 -10
  134. data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
  135. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  136. data/lib/active_merchant/billing/gateways/safe_charge.rb +36 -16
  137. data/lib/active_merchant/billing/gateways/sage.rb +12 -4
  138. data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
  139. data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
  140. data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
  141. data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
  142. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
  143. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
  144. data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
  145. data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
  146. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  147. data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
  148. data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
  149. data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
  150. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
  151. data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
  152. data/lib/active_merchant/billing/gateways/stripe.rb +53 -21
  153. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +199 -50
  154. data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
  155. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
  156. data/lib/active_merchant/billing/gateways/telr.rb +3 -4
  157. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
  158. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
  159. data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
  160. data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
  161. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
  162. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
  163. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  164. data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
  165. data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
  166. data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
  167. data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
  168. data/lib/active_merchant/billing/gateways/vpos.rb +3 -3
  169. data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
  170. data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
  171. data/lib/active_merchant/billing/gateways/worldpay.rb +140 -73
  172. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
  173. data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
  174. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  175. data/lib/active_merchant/billing/response.rb +2 -2
  176. data/lib/active_merchant/connection.rb +3 -17
  177. data/lib/active_merchant/country.rb +1 -0
  178. data/lib/active_merchant/errors.rb +10 -0
  179. data/lib/active_merchant/version.rb +1 -1
  180. data/lib/support/gateway_support.rb +2 -2
  181. data/lib/support/ssl_verify.rb +4 -4
  182. data/lib/support/ssl_version.rb +6 -6
  183. metadata +30 -9
@@ -0,0 +1,587 @@
1
+ require 'nokogiri'
2
+ require 'securerandom'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ class VantivExpressGateway < Gateway
7
+ self.test_url = 'https://certtransaction.elementexpress.com'
8
+ self.live_url = 'https://transaction.elementexpress.com'
9
+
10
+ self.supported_countries = ['US']
11
+ self.default_currency = 'USD'
12
+ self.supported_cardtypes = %i[visa master american_express discover diners_club jcb]
13
+
14
+ self.homepage_url = 'http://www.elementps.com'
15
+ self.display_name = 'Element'
16
+
17
+ SERVICE_TEST_URL = 'https://certservices.elementexpress.com'
18
+ SERVICE_LIVE_URL = 'https://services.elementexpress.com'
19
+
20
+ NETWORK_TOKEN_TYPE = {
21
+ apple_pay: 2,
22
+ google_pay: 1
23
+ }
24
+
25
+ CARD_PRESENT_CODE = {
26
+ 'Unknown' => 1,
27
+ 'Present' => 2,
28
+ 'NotPresent' => 3
29
+ }
30
+
31
+ MARKET_CODE = {
32
+ 'AutoRental' => 1,
33
+ 'DirectMarketing' => 2,
34
+ 'ECommerce' => 3,
35
+ 'FoodRestaurant' => 4,
36
+ 'HotelLodging' => 5,
37
+ 'Petroleum' => 6,
38
+ 'Retail' => 7,
39
+ 'QSR' => 8,
40
+ 'Grocery' => 9
41
+ }
42
+
43
+ PAYMENT_TYPE = {
44
+ 'NotUsed' => 0,
45
+ 'Recurring' => 1,
46
+ 'Installment' => 2,
47
+ 'CardHolderInitiated' => 3,
48
+ 'CredentialOnFile' => 4
49
+ }
50
+
51
+ REVERSAL_TYPE = {
52
+ 'System' => 0,
53
+ 'Full' => 1,
54
+ 'Partial' => 2
55
+ }
56
+
57
+ SUBMISSION_TYPE = {
58
+ 'NotUsed' => 0,
59
+ 'Initial' => 1,
60
+ 'Subsequent' => 2,
61
+ 'Resubmission' => 3,
62
+ 'ReAuthorization' => 4,
63
+ 'DelayedCharges' => 5,
64
+ 'NoShow' => 6
65
+ }
66
+
67
+ LODGING_PPC = {
68
+ 'NonParticipant' => 0,
69
+ 'DollarLimit500' => 1,
70
+ 'DollarLimit1000' => 2,
71
+ 'DollarLimit1500' => 3
72
+ }
73
+
74
+ LODGING_SPC = {
75
+ 'Default' => 0,
76
+ 'Sale' => 1,
77
+ 'NoShow' => 2,
78
+ 'AdvanceDeposit' => 3
79
+ }
80
+
81
+ LODGING_CHARGE_TYPE = {
82
+ 'Default' => 0,
83
+ 'Restaurant' => 1,
84
+ 'GiftShop' => 2
85
+ }
86
+
87
+ TERMINAL_TYPE = {
88
+ 'Unknown' => 0,
89
+ 'PointOfSale' => 1,
90
+ 'ECommerce' => 2,
91
+ 'MOTO' => 3,
92
+ 'FuelPump' => 4,
93
+ 'ATM' => 5,
94
+ 'Voice' => 6,
95
+ 'Mobile' => 7,
96
+ 'WebSiteGiftCard' => 8
97
+ }
98
+
99
+ CARD_HOLDER_PRESENT_CODE = {
100
+ 'Default' => 0,
101
+ 'Unknown' => 1,
102
+ 'Present' => 2,
103
+ 'NotPresent' => 3,
104
+ 'MailOrder' => 4,
105
+ 'PhoneOrder' => 5,
106
+ 'StandingAuth' => 6,
107
+ 'ECommerce' => 7
108
+ }
109
+
110
+ CARD_INPUT_CODE = {
111
+ 'Default' => 0,
112
+ 'Unknown' => 1,
113
+ 'MagstripeRead' => 2,
114
+ 'ContactlessMagstripeRead' => 3,
115
+ 'ManualKeyed' => 4,
116
+ 'ManualKeyedMagstripeFailure' => 5,
117
+ 'ChipRead' => 6,
118
+ 'ContactlessChipRead' => 7,
119
+ 'ManualKeyedChipReadFailure' => 8,
120
+ 'MagstripeReadChipReadFailure' => 9,
121
+ 'MagstripeReadNonTechnicalFallback' => 10
122
+ }
123
+
124
+ CVV_PRESENCE_CODE = {
125
+ 'UseDefault' => 0,
126
+ 'NotProvided' => 1,
127
+ 'Provided' => 2,
128
+ 'Illegible' => 3,
129
+ 'CustomerIllegible' => 4
130
+ }
131
+
132
+ TERMINAL_CAPABILITY_CODE = {
133
+ 'Default' => 0,
134
+ 'Unknown' => 1,
135
+ 'NoTerminal' => 2,
136
+ 'MagstripeReader' => 3,
137
+ 'ContactlessMagstripeReader' => 4,
138
+ 'KeyEntered' => 5,
139
+ 'ChipReader' => 6,
140
+ 'ContactlessChipReader' => 7
141
+ }
142
+
143
+ TERMINAL_ENVIRONMENT_CODE = {
144
+ 'Default' => 0,
145
+ 'NoTerminal' => 1,
146
+ 'LocalAttended' => 2,
147
+ 'LocalUnattended' => 3,
148
+ 'RemoteAttended' => 4,
149
+ 'RemoteUnattended' => 5,
150
+ 'ECommerce' => 6
151
+ }
152
+
153
+ def initialize(options = {})
154
+ requires!(options, :account_id, :account_token, :application_id, :acceptor_id, :application_name, :application_version)
155
+ super
156
+ end
157
+
158
+ def purchase(money, payment, options = {})
159
+ action = payment.is_a?(Check) ? 'CheckSale' : 'CreditCardSale'
160
+ eci = parse_eci(payment)
161
+
162
+ request = build_xml_request do |xml|
163
+ xml.send(action, xmlns: live_url) do
164
+ add_credentials(xml)
165
+ add_payment_method(xml, payment)
166
+ add_transaction(xml, money, options, eci)
167
+ add_terminal(xml, options, eci)
168
+ add_address(xml, options)
169
+ add_lodging(xml, options)
170
+ end
171
+ end
172
+
173
+ commit(request, money, payment)
174
+ end
175
+
176
+ def authorize(money, payment, options = {})
177
+ eci = parse_eci(payment)
178
+
179
+ request = build_xml_request do |xml|
180
+ xml.CreditCardAuthorization(xmlns: live_url) do
181
+ add_credentials(xml)
182
+ add_payment_method(xml, payment)
183
+ add_transaction(xml, money, options, eci)
184
+ add_terminal(xml, options, eci)
185
+ add_address(xml, options)
186
+ add_lodging(xml, options)
187
+ end
188
+ end
189
+
190
+ commit(request, money, payment)
191
+ end
192
+
193
+ def capture(money, authorization, options = {})
194
+ trans_id, _, eci = authorization.split('|')
195
+ options[:trans_id] = trans_id
196
+
197
+ request = build_xml_request do |xml|
198
+ xml.CreditCardAuthorizationCompletion(xmlns: live_url) do
199
+ add_credentials(xml)
200
+ add_transaction(xml, money, options, eci)
201
+ add_terminal(xml, options, eci)
202
+ end
203
+ end
204
+
205
+ commit(request, money)
206
+ end
207
+
208
+ def refund(money, authorization, options = {})
209
+ trans_id, _, eci = authorization.split('|')
210
+ options[:trans_id] = trans_id
211
+
212
+ request = build_xml_request do |xml|
213
+ xml.CreditCardReturn(xmlns: live_url) do
214
+ add_credentials(xml)
215
+ add_transaction(xml, money, options, eci)
216
+ add_terminal(xml, options, eci)
217
+ end
218
+ end
219
+
220
+ commit(request, money)
221
+ end
222
+
223
+ def credit(money, payment, options = {})
224
+ eci = parse_eci(payment)
225
+
226
+ request = build_xml_request do |xml|
227
+ xml.CreditCardCredit(xmlns: live_url) do
228
+ add_credentials(xml)
229
+ add_payment_method(xml, payment)
230
+ add_transaction(xml, money, options, eci)
231
+ add_terminal(xml, options, eci)
232
+ end
233
+ end
234
+
235
+ commit(request, money, payment)
236
+ end
237
+
238
+ def void(authorization, options = {})
239
+ trans_id, trans_amount, eci = authorization.split('|')
240
+ options.merge!({ trans_id: trans_id, trans_amount: trans_amount, reversal_type: 1 })
241
+
242
+ request = build_xml_request do |xml|
243
+ xml.CreditCardReversal(xmlns: live_url) do
244
+ add_credentials(xml)
245
+ add_transaction(xml, trans_amount, options, eci)
246
+ add_terminal(xml, options, eci)
247
+ end
248
+ end
249
+
250
+ commit(request, trans_amount)
251
+ end
252
+
253
+ def store(payment, options = {})
254
+ request = build_xml_request do |xml|
255
+ xml.PaymentAccountCreate(xmlns: SERVICE_LIVE_URL) do
256
+ add_credentials(xml)
257
+ add_payment_method(xml, payment)
258
+ add_payment_account(xml, payment, options[:payment_account_reference_number] || SecureRandom.hex(20))
259
+ add_address(xml, options)
260
+ end
261
+ end
262
+
263
+ commit(request, payment, nil, :store)
264
+ end
265
+
266
+ def verify(payment, options = {})
267
+ eci = parse_eci(payment)
268
+
269
+ request = build_xml_request do |xml|
270
+ xml.CreditCardAVSOnly(xmlns: live_url) do
271
+ add_credentials(xml)
272
+ add_payment_method(xml, payment)
273
+ add_transaction(xml, 0, options, eci)
274
+ add_terminal(xml, options, eci)
275
+ add_address(xml, options)
276
+ end
277
+ end
278
+
279
+ commit(request)
280
+ end
281
+
282
+ def supports_scrubbing?
283
+ true
284
+ end
285
+
286
+ def scrub(transcript)
287
+ transcript.
288
+ gsub(%r((<AccountToken>).+?(</AccountToken>))i, '\1[FILTERED]\2').
289
+ gsub(%r((<CardNumber>).+?(</CardNumber>))i, '\1[FILTERED]\2').
290
+ gsub(%r((<CVV>).+?(</CVV>))i, '\1[FILTERED]\2').
291
+ gsub(%r((<AccountNumber>).+?(</AccountNumber>))i, '\1[FILTERED]\2').
292
+ gsub(%r((<RoutingNumber>).+?(</RoutingNumber>))i, '\1[FILTERED]\2')
293
+ end
294
+
295
+ private
296
+
297
+ def add_credentials(xml)
298
+ xml.Credentials do
299
+ xml.AccountID @options[:account_id]
300
+ xml.AccountToken @options[:account_token]
301
+ xml.AcceptorID @options[:acceptor_id]
302
+ end
303
+ xml.Application do
304
+ xml.ApplicationID @options[:application_id]
305
+ xml.ApplicationName @options[:application_name]
306
+ xml.ApplicationVersion @options[:application_version]
307
+ end
308
+ end
309
+
310
+ def add_payment_method(xml, payment)
311
+ if payment.is_a?(String)
312
+ add_payment_account_id(xml, payment)
313
+ elsif payment.is_a?(Check)
314
+ add_echeck(xml, payment)
315
+ elsif payment.is_a?(NetworkTokenizationCreditCard)
316
+ add_network_tokenization_card(xml, payment)
317
+ else
318
+ add_credit_card(xml, payment)
319
+ end
320
+ end
321
+
322
+ def add_payment_account(xml, payment, payment_account_reference_number)
323
+ xml.PaymentAccount do
324
+ xml.PaymentAccountType payment_account_type(payment)
325
+ xml.PaymentAccountReferenceNumber payment_account_reference_number
326
+ end
327
+ end
328
+
329
+ def add_payment_account_id(xml, payment)
330
+ xml.PaymentAccount do
331
+ xml.PaymentAccountID payment
332
+ end
333
+ end
334
+
335
+ def add_transaction(xml, money, options = {}, network_token_eci = nil)
336
+ xml.Transaction do
337
+ xml.ReversalType REVERSAL_TYPE[options[:reversal_type]] || options[:reversal_type] if options[:reversal_type]
338
+ xml.TransactionID options[:trans_id] if options[:trans_id]
339
+ xml.TransactionAmount amount(money.to_i) if money
340
+ xml.MarketCode market_code(money, options, network_token_eci) if options[:market_code] || money
341
+ xml.ReferenceNumber options[:order_id].present? ? options[:order_id][0, 50] : SecureRandom.hex(20)
342
+ xml.TicketNumber options[:ticket_number] || rand(1..999999)
343
+ xml.MerchantSuppliedTransactionID options[:merchant_supplied_transaction_id] if options[:merchant_supplied_transaction_id]
344
+ xml.PaymentType PAYMENT_TYPE[options[:payment_type]] || options[:payment_type] if options[:payment_type]
345
+ xml.SubmissionType SUBMISSION_TYPE[options[:submission_type]] || options[:submission_type] if options[:submission_type]
346
+ xml.DuplicateCheckDisableFlag 1 if options[:duplicate_check_disable_flag].to_s == 'true' || options[:duplicate_override_flag].to_s == 'true'
347
+ end
348
+ end
349
+
350
+ def parse_eci(payment)
351
+ return nil unless payment.is_a?(NetworkTokenizationCreditCard)
352
+
353
+ if (eci = payment.eci)
354
+ eci = eci[0] == '0' ? eci.sub!(/^0/, '') : eci
355
+ return eci
356
+ else
357
+ payment.brand == 'american_express' ? '9' : '6'
358
+ end
359
+ end
360
+
361
+ def market_code(money, options, network_token_eci)
362
+ return 3 if network_token_eci
363
+
364
+ MARKET_CODE[options[:market_code]] || options[:market_code] || 0
365
+ end
366
+
367
+ def add_lodging(xml, options)
368
+ if options[:lodging]
369
+ lodging = parse_lodging(options[:lodging])
370
+ xml.ExtendedParameters do
371
+ xml.Lodging do
372
+ xml.LodgingAgreementNumber lodging[:agreement_number] if lodging[:agreement_number]
373
+ xml.LodgingCheckInDate lodging[:check_in_date] if lodging[:check_in_date]
374
+ xml.LodgingCheckOutDate lodging[:check_out_date] if lodging[:check_out_date]
375
+ xml.LodgingRoomAmount lodging[:room_amount] if lodging[:room_amount]
376
+ xml.LodgingRoomTax lodging[:room_tax] if lodging[:room_tax]
377
+ xml.LodgingNoShowIndicator lodging[:no_show_indicator] if lodging[:no_show_indicator]
378
+ xml.LodgingDuration lodging[:duration] if lodging[:duration]
379
+ xml.LodgingCustomerName lodging[:customer_name] if lodging[:customer_name]
380
+ xml.LodgingClientCode lodging[:client_code] if lodging[:client_code]
381
+ xml.LodgingExtraChargesDetail lodging[:extra_charges_detail] if lodging[:extra_charges_detail]
382
+ xml.LodgingExtraChargesAmounts lodging[:extra_charges_amounts] if lodging[:extra_charges_amounts]
383
+ xml.LodgingPrestigiousPropertyCode lodging[:prestigious_property_code] if lodging[:prestigious_property_code]
384
+ xml.LodgingSpecialProgramCode lodging[:special_program_code] if lodging[:special_program_code]
385
+ xml.LodgingChargeType lodging[:charge_type] if lodging[:charge_type]
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ def add_terminal(xml, options, network_token_eci = nil)
392
+ options = parse_terminal(options)
393
+
394
+ xml.Terminal do
395
+ xml.TerminalID options[:terminal_id] || '01'
396
+ xml.TerminalType options[:terminal_type] if options[:terminal_type]
397
+ xml.CardPresentCode options[:card_present_code] || 0
398
+ xml.CardholderPresentCode options[:card_holder_present_code] || 0
399
+ xml.CardInputCode options[:card_input_code] || 0
400
+ xml.CVVPresenceCode options[:cvv_presence_code] || 0
401
+ xml.TerminalCapabilityCode options[:terminal_capability_code] || 0
402
+ xml.TerminalEnvironmentCode options[:terminal_environment_code] || 0
403
+ xml.MotoECICode network_token_eci || 7
404
+ xml.PartialApprovedFlag options[:partial_approved_flag] if options[:partial_approved_flag]
405
+ end
406
+ end
407
+
408
+ def add_credit_card(xml, payment)
409
+ xml.Card do
410
+ xml.CardNumber payment.number
411
+ xml.ExpirationMonth format(payment.month, :two_digits)
412
+ xml.ExpirationYear format(payment.year, :two_digits)
413
+ xml.CardholderName "#{payment.first_name} #{payment.last_name}"
414
+ xml.CVV payment.verification_value
415
+ end
416
+ end
417
+
418
+ def add_echeck(xml, payment)
419
+ xml.DemandDepositAccount do
420
+ xml.AccountNumber payment.account_number
421
+ xml.RoutingNumber payment.routing_number
422
+ xml.DDAAccountType payment.account_type == 'checking' ? 0 : 1
423
+ end
424
+ end
425
+
426
+ def add_network_tokenization_card(xml, payment)
427
+ xml.Card do
428
+ xml.CardNumber payment.number
429
+ xml.ExpirationMonth format(payment.month, :two_digits)
430
+ xml.ExpirationYear format(payment.year, :two_digits)
431
+ xml.CardholderName "#{payment.first_name} #{payment.last_name}"
432
+ xml.Cryptogram payment.payment_cryptogram
433
+ xml.WalletType NETWORK_TOKEN_TYPE[payment.source]
434
+ end
435
+ end
436
+
437
+ def add_address(xml, options)
438
+ address = address = options[:billing_address] || options[:address]
439
+ shipping_address = options[:shipping_address]
440
+
441
+ if address || shipping_address
442
+ xml.Address do
443
+ if address
444
+ address[:email] ||= options[:email]
445
+
446
+ xml.BillingAddress1 address[:address1] if address[:address1]
447
+ xml.BillingAddress2 address[:address2] if address[:address2]
448
+ xml.BillingCity address[:city] if address[:city]
449
+ xml.BillingState address[:state] if address[:state]
450
+ xml.BillingZipcode address[:zip] if address[:zip]
451
+ xml.BillingEmail address[:email] if address[:email]
452
+ xml.BillingPhone address[:phone_number] if address[:phone_number]
453
+ end
454
+
455
+ if shipping_address
456
+ xml.ShippingAddress1 shipping_address[:address1] if shipping_address[:address1]
457
+ xml.ShippingAddress2 shipping_address[:address2] if shipping_address[:address2]
458
+ xml.ShippingCity shipping_address[:city] if shipping_address[:city]
459
+ xml.ShippingState shipping_address[:state] if shipping_address[:state]
460
+ xml.ShippingZipcode shipping_address[:zip] if shipping_address[:zip]
461
+ xml.ShippingEmail shipping_address[:email] if shipping_address[:email]
462
+ xml.ShippingPhone shipping_address[:phone_number] if shipping_address[:phone_number]
463
+ end
464
+ end
465
+ end
466
+ end
467
+
468
+ def parse(xml)
469
+ response = {}
470
+
471
+ doc = Nokogiri::XML(xml)
472
+ doc.remove_namespaces!
473
+ root = doc.root.xpath('//response/*')
474
+
475
+ root = doc.root.xpath('//Response/*') if root.empty?
476
+
477
+ root.each do |node|
478
+ if node.elements.empty?
479
+ response[node.name.downcase] = node.text
480
+ else
481
+ node_name = node.name.downcase
482
+ response[node_name] = {}
483
+
484
+ node.elements.each do |childnode|
485
+ response[node_name][childnode.name.downcase] = childnode.text
486
+ end
487
+ end
488
+ end
489
+
490
+ response
491
+ end
492
+
493
+ def parse_lodging(lodging)
494
+ lodging[:prestigious_property_code] = LODGING_PPC[lodging[:prestigious_property_code]] || lodging[:prestigious_property_code] if lodging[:prestigious_property_code]
495
+ lodging[:special_program_code] = LODGING_SPC[lodging[:special_program_code]] || lodging[:special_program_code] if lodging[:special_program_code]
496
+ lodging[:charge_type] = LODGING_CHARGE_TYPE[lodging[:charge_type]] || lodging[:charge_type] if lodging[:charge_type]
497
+
498
+ lodging
499
+ end
500
+
501
+ def parse_terminal(options)
502
+ options[:terminal_type] = TERMINAL_TYPE[options[:terminal_type]] || options[:terminal_type]
503
+ options[:card_present_code] = CARD_PRESENT_CODE[options[:card_present_code]] || options[:card_present_code]
504
+ options[:card_holder_present_code] = CARD_HOLDER_PRESENT_CODE[options[:card_holder_present_code]] || options[:card_holder_present_code]
505
+ options[:card_input_code] = CARD_INPUT_CODE[options[:card_input_code]] || options[:card_input_code]
506
+ options[:cvv_presence_code] = CVV_PRESENCE_CODE[options[:cvv_presence_code]] || options[:cvv_presence_code]
507
+ options[:terminal_capability_code] = TERMINAL_CAPABILITY_CODE[options[:terminal_capability_code]] || options[:terminal_capability_code]
508
+ options[:terminal_environment_code] = TERMINAL_ENVIRONMENT_CODE[options[:terminal_environment_code]] || options[:terminal_environment_code]
509
+
510
+ options
511
+ end
512
+
513
+ def commit(xml, amount = nil, payment = nil, action = nil)
514
+ response = parse(ssl_post(url(action), xml, headers))
515
+ success = success_from(response)
516
+
517
+ Response.new(
518
+ success,
519
+ message_from(response),
520
+ response,
521
+ authorization: authorization_from(action, response, amount, payment),
522
+ avs_result: success ? avs_from(response) : nil,
523
+ cvv_result: success ? cvv_from(response) : nil,
524
+ test: test?
525
+ )
526
+ end
527
+
528
+ def authorization_from(action, response, amount, payment)
529
+ return response.dig('paymentaccount', 'paymentaccountid') if action == :store
530
+
531
+ if response['transaction']
532
+ authorization = "#{response.dig('transaction', 'transactionid')}|#{amount}"
533
+ authorization << "|#{parse_eci(payment)}" if parse_eci(payment)
534
+ authorization
535
+ end
536
+ end
537
+
538
+ def success_from(response)
539
+ response['expressresponsecode'] == '0'
540
+ end
541
+
542
+ def message_from(response)
543
+ response['expressresponsemessage']
544
+ end
545
+
546
+ def avs_from(response)
547
+ AVSResult.new(code: response['card']['avsresponsecode']) if response['card']
548
+ end
549
+
550
+ def cvv_from(response)
551
+ CVVResult.new(response['card']['cvvresponsecode']) if response['card']
552
+ end
553
+
554
+ def build_xml_request(&block)
555
+ builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8', &block)
556
+
557
+ builder.to_xml
558
+ end
559
+
560
+ def payment_account_type(payment)
561
+ return 0 unless payment.is_a?(Check)
562
+
563
+ if payment.account_type == 'checking'
564
+ 1
565
+ elsif payment.account_type == 'savings'
566
+ 2
567
+ else
568
+ 3
569
+ end
570
+ end
571
+
572
+ def url(action)
573
+ if action == :store
574
+ test? ? SERVICE_TEST_URL : SERVICE_LIVE_URL
575
+ else
576
+ test? ? test_url : live_url
577
+ end
578
+ end
579
+
580
+ def headers
581
+ {
582
+ 'Content-Type' => 'text/xml'
583
+ }
584
+ end
585
+ end
586
+ end
587
+ end
@@ -194,11 +194,15 @@ module ActiveMerchant #:nodoc:
194
194
 
195
195
  response = parse(ssl_post(self.live_url, post_data(trx_type, post)))
196
196
 
197
- Response.new(response[:response].to_i == SUCCESS, message_from(response), response,
197
+ Response.new(
198
+ response[:response].to_i == SUCCESS,
199
+ message_from(response),
200
+ response,
198
201
  test: test?,
199
202
  authorization: response[:transactionid],
200
203
  avs_result: { code: response[:avsresponse] },
201
- cvv_result: response[:cvvresponse])
204
+ cvv_result: response[:cvvresponse]
205
+ )
202
206
  end
203
207
 
204
208
  def message_from(response)
@@ -136,11 +136,15 @@ module ActiveMerchant #:nodoc:
136
136
 
137
137
  response = parse(ssl_post(test? ? self.test_url : self.live_url, post_data(parameters)))
138
138
 
139
- Response.new(response['result'] == APPROVED, message_from(response), response,
139
+ Response.new(
140
+ response['result'] == APPROVED,
141
+ message_from(response),
142
+ response,
140
143
  test: @options[:test] || test?,
141
144
  authorization: authorization_from(response),
142
145
  avs_result: { code: response['avs_response'] },
143
- cvv_result: response['cvv2_response'])
146
+ cvv_result: response['cvv2_response']
147
+ )
144
148
  end
145
149
 
146
150
  def authorization_from(response)
@@ -143,12 +143,12 @@ module ActiveMerchant #:nodoc:
143
143
  end
144
144
 
145
145
  def generate_purchase_number_stamp
146
- Time.now.to_f.to_s.delete('.')[1..10] + rand(99).to_s
146
+ rand(('9' * 12).to_i).to_s.center(12, rand(9).to_s)
147
147
  end
148
148
 
149
149
  def commit(action, params, options = {})
150
150
  raw_response = ssl_request(method(action), url(action, params, options), params.to_json, headers)
151
- response = parse(raw_response)
151
+ response = parse(raw_response).merge('purchaseNumber' => params[:purchaseNumber])
152
152
  rescue ResponseError => e
153
153
  raw_response = e.response.body
154
154
  response_error(raw_response, options, action)
@@ -137,7 +137,7 @@ module ActiveMerchant #:nodoc:
137
137
  card_number = payment.number
138
138
  cvv = payment.verification_value
139
139
 
140
- payload = { card_number: card_number, 'cvv': cvv }.to_json
140
+ payload = { card_number: card_number, cvv: cvv }.to_json
141
141
 
142
142
  encryption_key = @encryption_key || OpenSSL::PKey::RSA.new(one_time_public_key)
143
143
 
@@ -158,10 +158,10 @@ module ActiveMerchant #:nodoc:
158
158
  url = build_request_url(action)
159
159
  begin
160
160
  response = parse(ssl_post(url, post_data(parameters)))
161
- rescue ResponseError => response
161
+ rescue ResponseError => e
162
162
  # Errors are returned with helpful data,
163
163
  # but get filtered out by `ssl_post` because of their HTTP status.
164
- response = parse(response.response.body)
164
+ response = parse(e.response.body)
165
165
  end
166
166
 
167
167
  Response.new(
@@ -179,11 +179,15 @@ module ActiveMerchant #:nodoc:
179
179
  message = response[:Message]
180
180
  authorization = response[:GuWID]
181
181
 
182
- Response.new(success, message, response,
182
+ Response.new(
183
+ success,
184
+ message,
185
+ response,
183
186
  test: test?,
184
187
  authorization: authorization,
185
188
  avs_result: { code: avs_code(response, options) },
186
- cvv_result: response[:CVCResponseCode])
189
+ cvv_result: response[:CVCResponseCode]
190
+ )
187
191
  rescue ResponseError => e
188
192
  if e.response.code == '401'
189
193
  return Response.new(false, 'Invalid Login')
@@ -405,7 +409,7 @@ module ActiveMerchant #:nodoc:
405
409
  'N' => 'I', # CSC Match
406
410
  'U' => 'U', # Data Not Checked
407
411
  'Y' => 'D', # All Data Matched
408
- 'Z' => 'P', # CSC and Postcode Matched
412
+ 'Z' => 'P' # CSC and Postcode Matched
409
413
  }
410
414
 
411
415
  # Amex have different AVS response codes to visa etc