start_activemerchant 1.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1769 -0
  3. data/CONTRIBUTORS +540 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +226 -0
  6. data/lib/active_merchant.rb +67 -0
  7. data/lib/active_merchant/billing.rb +15 -0
  8. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  9. data/lib/active_merchant/billing/avs_result.rb +98 -0
  10. data/lib/active_merchant/billing/base.rb +72 -0
  11. data/lib/active_merchant/billing/check.rb +76 -0
  12. data/lib/active_merchant/billing/compatibility.rb +120 -0
  13. data/lib/active_merchant/billing/credit_card.rb +404 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +195 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +291 -0
  18. data/lib/active_merchant/billing/gateways.rb +14 -0
  19. data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
  20. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  21. data/lib/active_merchant/billing/gateways/authorize_net.rb +510 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
  24. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
  25. data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
  26. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  27. data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
  28. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -0
  29. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
  30. data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
  31. data/lib/active_merchant/billing/gateways/beanstream.rb +192 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +389 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +58 -0
  34. data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
  35. data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
  36. data/lib/active_merchant/billing/gateways/borgun.rb +211 -0
  37. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  39. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  40. data/lib/active_merchant/billing/gateways/braintree_blue.rb +574 -0
  41. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  42. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  43. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +238 -0
  45. data/lib/active_merchant/billing/gateways/cashnet.rb +202 -0
  46. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  47. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  48. data/lib/active_merchant/billing/gateways/cenpos.rb +262 -0
  49. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  50. data/lib/active_merchant/billing/gateways/checkout.rb +216 -0
  51. data/lib/active_merchant/billing/gateways/checkout_v2.rb +200 -0
  52. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  53. data/lib/active_merchant/billing/gateways/conekta.rb +210 -0
  54. data/lib/active_merchant/billing/gateways/cyber_source.rb +720 -0
  55. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  56. data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
  57. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  58. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  59. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  60. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  61. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  62. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  63. data/lib/active_merchant/billing/gateways/eway_rapid.rb +522 -0
  64. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  65. data/lib/active_merchant/billing/gateways/ezic.rb +206 -0
  66. data/lib/active_merchant/billing/gateways/fat_zebra.rb +213 -0
  67. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  68. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  69. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  70. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  71. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +413 -0
  72. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  73. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  74. data/lib/active_merchant/billing/gateways/garanti.rb +261 -0
  75. data/lib/active_merchant/billing/gateways/global_transport.rb +179 -0
  76. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  77. data/lib/active_merchant/billing/gateways/hps.rb +287 -0
  78. data/lib/active_merchant/billing/gateways/iats_payments.rb +277 -0
  79. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  80. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  81. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  82. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  83. data/lib/active_merchant/billing/gateways/inspire.rb +219 -0
  84. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  85. data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
  86. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  87. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  88. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  89. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  90. data/lib/active_merchant/billing/gateways/litle.rb +345 -0
  91. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  92. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  93. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  94. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  95. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  96. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  97. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  98. data/lib/active_merchant/billing/gateways/mercury.rb +326 -0
  99. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  100. data/lib/active_merchant/billing/gateways/migs.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  102. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  103. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  104. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  105. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  106. data/lib/active_merchant/billing/gateways/moneris_us.rb +298 -0
  107. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  108. data/lib/active_merchant/billing/gateways/nab_transact.rb +290 -0
  109. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  110. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  111. data/lib/active_merchant/billing/gateways/netbilling.rb +224 -0
  112. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  113. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  114. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  115. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  116. data/lib/active_merchant/billing/gateways/omise.rb +319 -0
  117. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  118. data/lib/active_merchant/billing/gateways/optimal_payment.rb +314 -0
  119. data/lib/active_merchant/billing/gateways/orbital.rb +834 -0
  120. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  121. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  122. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  123. data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
  124. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
  125. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  126. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  127. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  128. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  129. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  130. data/lib/active_merchant/billing/gateways/payflow.rb +308 -0
  131. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +220 -0
  132. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  133. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  134. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  135. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  136. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  137. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  138. data/lib/active_merchant/billing/gateways/paymill.rb +282 -0
  139. data/lib/active_merchant/billing/gateways/paypal.rb +129 -0
  140. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +679 -0
  141. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  142. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  143. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  144. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  145. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  146. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  147. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  148. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  149. data/lib/active_merchant/billing/gateways/payu_in.rb +247 -0
  150. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  151. data/lib/active_merchant/billing/gateways/pin.rb +207 -0
  152. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  153. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  154. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  155. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  156. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  157. data/lib/active_merchant/billing/gateways/quickbooks.rb +280 -0
  158. data/lib/active_merchant/billing/gateways/quickpay.rb +26 -0
  159. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
  160. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
  161. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
  162. data/lib/active_merchant/billing/gateways/qvalent.rb +179 -0
  163. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  164. data/lib/active_merchant/billing/gateways/redsys.rb +406 -0
  165. data/lib/active_merchant/billing/gateways/s5.rb +226 -0
  166. data/lib/active_merchant/billing/gateways/sage.rb +173 -0
  167. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +89 -0
  168. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +115 -0
  169. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  170. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  171. data/lib/active_merchant/billing/gateways/sage_pay.rb +399 -0
  172. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  173. data/lib/active_merchant/billing/gateways/secure_net.rb +263 -0
  174. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  175. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  176. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  177. data/lib/active_merchant/billing/gateways/skip_jack.rb +451 -0
  178. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  179. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  180. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  181. data/lib/active_merchant/billing/gateways/stripe.rb +489 -0
  182. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  183. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  184. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  185. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  186. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  187. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  188. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  189. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  190. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +259 -0
  191. data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
  192. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  193. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  194. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  195. data/lib/active_merchant/billing/gateways/wepay.rb +205 -0
  196. data/lib/active_merchant/billing/gateways/wirecard.rb +420 -0
  197. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  198. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +204 -0
  199. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  200. data/lib/active_merchant/billing/model.rb +30 -0
  201. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +24 -0
  202. data/lib/active_merchant/billing/payment_token.rb +21 -0
  203. data/lib/active_merchant/billing/rails.rb +3 -0
  204. data/lib/active_merchant/billing/response.rb +92 -0
  205. data/lib/active_merchant/connection.rb +172 -0
  206. data/lib/active_merchant/country.rb +332 -0
  207. data/lib/active_merchant/empty.rb +20 -0
  208. data/lib/active_merchant/errors.rb +35 -0
  209. data/lib/active_merchant/network_connection_retries.rb +79 -0
  210. data/lib/active_merchant/post_data.rb +24 -0
  211. data/lib/active_merchant/posts_data.rb +84 -0
  212. data/lib/active_merchant/version.rb +3 -0
  213. data/lib/activemerchant.rb +1 -0
  214. data/lib/certs/cacert.pem +3866 -0
  215. data/lib/support/gateway_support.rb +71 -0
  216. data/lib/support/outbound_hosts.rb +28 -0
  217. data/lib/support/ssl_verify.rb +93 -0
  218. metadata +387 -0
@@ -0,0 +1,14 @@
1
+ require 'pathname'
2
+
3
+ module ActiveMerchant
4
+ module Billing
5
+ load_path = Pathname.new(__FILE__ + '/../../..')
6
+ Dir[File.dirname(__FILE__) + '/gateways/**/*.rb'].each do |filename|
7
+ gateway_name = File.basename(filename, '.rb')
8
+ gateway_classname = "#{gateway_name}_gateway".camelize
9
+ gateway_filename = Pathname.new(filename).relative_path_from(load_path).sub_ext('')
10
+
11
+ autoload(gateway_classname, gateway_filename)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,203 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class AlliedWalletGateway < Gateway
4
+ self.display_name = "Allied Wallet"
5
+ self.homepage_url = "https://www.alliedwallet.com"
6
+
7
+ self.live_url = "https://api.alliedwallet.com/merchants/"
8
+
9
+ self.supported_countries = ["US"]
10
+ self.default_currency = "USD"
11
+ self.money_format = :dollars
12
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover,
13
+ :diners_club, :jcb, :maestro]
14
+
15
+ def initialize(options={})
16
+ requires!(options, :site_id, :merchant_id, :token)
17
+ super
18
+ end
19
+
20
+ def purchase(amount, payment_method, options={})
21
+ post = {}
22
+ add_invoice(post, amount, options)
23
+ add_payment_method(post, payment_method)
24
+ add_customer_data(post, options)
25
+
26
+ commit(:purchase, post)
27
+ end
28
+
29
+ def authorize(amount, payment_method, options={})
30
+ post = {}
31
+ add_invoice(post, amount, options)
32
+ add_payment_method(post, payment_method)
33
+ add_customer_data(post, options)
34
+
35
+ commit(:authorize, post)
36
+ end
37
+
38
+ def capture(amount, authorization, options={})
39
+ post = {}
40
+ add_invoice(post, amount, options)
41
+ add_reference(post, authorization, :capture)
42
+ add_customer_data(post, options)
43
+
44
+ commit(:capture, post)
45
+ end
46
+
47
+ def void(authorization, options={})
48
+ post = {}
49
+ add_reference(post, authorization, :void)
50
+
51
+ commit(:void, post)
52
+ end
53
+
54
+ def refund(amount, authorization, options={})
55
+ post = {}
56
+ add_invoice(post, amount, options)
57
+ add_reference(post, authorization, :refund)
58
+ add_amount(post, amount)
59
+ add_customer_data(post, options)
60
+
61
+ commit(:refund, post)
62
+ end
63
+
64
+ def verify(credit_card, options={})
65
+ MultiResponse.run(:use_first_response) do |r|
66
+ r.process { authorize(100, credit_card, options) }
67
+ r.process(:ignore_result) { void(r.authorization, options) }
68
+ end
69
+ end
70
+
71
+ def supports_scrubbing?
72
+ true
73
+ end
74
+
75
+ def scrub(transcript)
76
+ transcript.
77
+ gsub(%r((Authorization: Bearer )[a-zA-Z0-9._-]+)i, '\1[FILTERED]').
78
+ gsub(%r(("cardNumber\\?":\\?")[^"]*)i, '\1[FILTERED]').
79
+ gsub(%r(("cVVCode\\?":\\?")[^"]*)i, '\1[FILTERED]')
80
+ end
81
+
82
+ private
83
+
84
+ def add_amount(post, amount)
85
+ post[:amount] = amount
86
+ end
87
+
88
+ def add_invoice(post, money, options)
89
+ post[:siteId] = @options[:site_id]
90
+ post[:amount] = amount(money)
91
+ post[:trackingId] = options[:order_id]
92
+ post[:currency] = options[:currency] || currency(money)
93
+ end
94
+
95
+ def add_payment_method(post, payment_method)
96
+ post[:nameOnCard] = payment_method.name
97
+ post[:cardNumber] = payment_method.number
98
+ post[:cVVCode] = payment_method.verification_value
99
+ post[:expirationYear] = format(payment_method.year, :four_digits)
100
+ post[:expirationMonth] = format(payment_method.month, :two_digits)
101
+ end
102
+
103
+ def add_customer_data(post, options)
104
+ post[:email] = options[:email] || "unspecified@example.com"
105
+ post[:iPAddress] = options[:ip]
106
+ if (billing_address = options[:billing_address])
107
+ post[:firstName], post[:lastName] = billing_address[:name].split
108
+ post[:addressLine1] = billing_address[:address1]
109
+ post[:addressLine2] = billing_address[:address2]
110
+ post[:city] = billing_address[:city]
111
+ post[:state] = billing_address[:state]
112
+ post[:countryId] = billing_address[:country]
113
+ post[:postalCode] = billing_address[:zip]
114
+ post[:phone] = billing_address[:phone]
115
+ end
116
+ end
117
+
118
+ def add_reference(post, authorization, action)
119
+ transactions = {
120
+ capture: :authorizetransactionid,
121
+ void: :authorizeTransactionid,
122
+ refund: :referencetransactionid,
123
+ recurring: :saleTransactionid
124
+ }
125
+ post[transactions[action]] = authorization
126
+ end
127
+
128
+
129
+ ACTIONS = {
130
+ purchase: "SALE",
131
+ authorize: "AUTHORIZE",
132
+ capture: "CAPTURE",
133
+ void: "VOID",
134
+ refund: "REFUND"
135
+ }
136
+
137
+ def commit(action, post)
138
+ begin
139
+ raw_response = ssl_post(url(action), post.to_json, headers)
140
+ response = parse(raw_response)
141
+ rescue ResponseError => e
142
+ raise unless(e.response.code.to_s =~ /4\d\d/)
143
+ response = parse(e.response.body)
144
+ end
145
+
146
+ succeeded = success_from(response["status"])
147
+ Response.new(
148
+ succeeded,
149
+ message_from(succeeded, response),
150
+ response,
151
+ authorization: response["id"],
152
+ :avs_result => AVSResult.new(code: response["avs_response"]),
153
+ :cvv_result => CVVResult.new(response["cvv2_response"]),
154
+ test: test?
155
+ )
156
+ rescue JSON::ParserError
157
+ unparsable_response(raw_response)
158
+ end
159
+
160
+ def unparsable_response(raw_response)
161
+ message = "Unparsable response received from Allied Wallet. Please contact Allied Wallet if you continue to receive this message."
162
+ message += " (The raw response returned by the API was #{raw_response.inspect})"
163
+ return Response.new(false, message)
164
+ end
165
+
166
+ def headers
167
+ {
168
+ "Content-type" => "application/json",
169
+ "Authorization" => "Bearer " + @options[:token]
170
+ }
171
+ end
172
+
173
+ def url(action)
174
+ live_url + CGI.escape(@options[:merchant_id]) + "/" + ACTIONS[action] + "transactions"
175
+ end
176
+
177
+ def parse(body)
178
+ JSON.parse(body)
179
+ end
180
+
181
+ def parse_element(response, node)
182
+ if node.has_elements?
183
+ node.elements.each{|element| parse_element(response, element) }
184
+ else
185
+ response[node.name.underscore.to_sym] = node.text
186
+ end
187
+ end
188
+
189
+ def success_from(response)
190
+ response == "Successful"
191
+ end
192
+
193
+ def message_from(succeeded, response)
194
+ if succeeded
195
+ "Succeeded"
196
+ else
197
+ response["message"] || "Unable to read error message"
198
+ end
199
+ end
200
+
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,176 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class App55Gateway < Gateway
4
+ self.test_url = 'https://sandbox.app55.com/v1/'
5
+ self.live_url = 'https://api.app55.com/v1/'
6
+
7
+ self.supported_countries = ['AU', 'BR', 'CA', 'CH', 'CL', 'CN', 'CO', 'CZ', 'DK', 'GB', 'HK', 'HU', 'ID', 'IS', 'JP', 'KE', 'KR', 'MX', 'MY', 'NO', 'NZ', 'PH', 'PL', 'TH', 'TW', 'US', 'VN', 'ZA']
8
+ self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :maestro, :solo]
9
+ self.default_currency = 'UKP'
10
+ self.money_format = :dollars
11
+ self.homepage_url = 'https://www.app55.com/'
12
+ self.display_name = 'App55'
13
+
14
+ # Create gateway
15
+ #
16
+ # options:
17
+ # :api_key - merchants App55 API Key
18
+ # :api_secret - merchants App55 Secret Key
19
+ def initialize(options = {})
20
+ requires!(options, :api_key, :api_secret)
21
+ @api_key = options[:api_key]
22
+ @api_secret = options[:api_secret]
23
+ super
24
+ end
25
+
26
+ # Make a purchase (authorize and commit)
27
+ #
28
+ # money - The monetary amount of the transaction in cents.
29
+ # payment_method - The CreditCard or the App55 card token.
30
+ # options - A standard ActiveMerchant options hash
31
+ def purchase(money, payment_method, options = {})
32
+ authorize(money, payment_method, options.merge(commit: true))
33
+ end
34
+
35
+ # Authorize a transaction.
36
+ #
37
+ # money - The monetary amount of the transaction in cents.
38
+ # payment_method - The CreditCard or the App55 card token.
39
+ # options - A standard ActiveMerchant options hash
40
+ def authorize(money, payment_method, options = {})
41
+ post = {}
42
+ add_creditcard(post, payment_method, options)
43
+ add_transaction(post, money, options)
44
+
45
+ commit(:post, 'transaction', post)
46
+ end
47
+
48
+ # Commit a pre-authorized transaction.
49
+ #
50
+ # money - The monetary amount of the transaction in cents.
51
+ # authorization - The App55 transaction id string.
52
+ # options - A standard ActiveMerchant options hash
53
+ def capture(money, authorization, options = {})
54
+ commit(:post, "transaction/#{authorization}")
55
+ end
56
+
57
+ private
58
+
59
+ def add_customer_data(post, options)
60
+ metadata_options = [:description, :browser_ip, :user_agent, :referrer]
61
+ post.update(options.slice(*metadata_options))
62
+ end
63
+
64
+ def add_creditcard(post, creditcard, options)
65
+ card = {}
66
+ card[:number] = creditcard.number
67
+ card[:expiry] = ("%02d". % creditcard.month) + '/' + creditcard.year.to_s
68
+ card[:security_code] = creditcard.verification_value if creditcard.verification_value?
69
+ card[:holder_name] = creditcard.name if creditcard.name
70
+ add_address(card, options)
71
+ post[:card] = card
72
+ end
73
+
74
+ def add_address(card, options)
75
+ return unless card && card.kind_of?(Hash)
76
+ address_hash = {}
77
+ if address = (options[:billing_address] || options[:address])
78
+ address_hash[:street] = address[:address1] if address[:address1]
79
+ address_hash[:street2] = address[:address2] if address[:address2]
80
+ address_hash[:country] = address[:country] if address[:country]
81
+ address_hash[:postal_code] = address[:zip] if address[:zip]
82
+ address_hash[:city] = address[:city] if address[:city]
83
+ card[:address] = address_hash
84
+ end
85
+ end
86
+
87
+ def add_transaction(post, money, options)
88
+ transaction = {}
89
+ add_amount(transaction, money, options)
90
+ transaction[:description] = (options[:description] || options[:email])
91
+ transaction[:commit] = options[:commit]
92
+ post[:transaction] = transaction
93
+ end
94
+
95
+ def add_amount(obj, money, options)
96
+ obj[:amount] = amount(money)
97
+ obj[:currency] = (options[:currency] || currency(money))
98
+ end
99
+
100
+ def parse(body)
101
+ JSON.parse(body)
102
+ rescue JSON::ParserError
103
+ json_error(raw_response)
104
+ end
105
+
106
+ def commit(method, resource, parameters=nil, meta={})
107
+ success = false
108
+ begin
109
+ raw_response = ssl_request(
110
+ method,
111
+ url(resource),
112
+ post_data(parameters),
113
+ headers
114
+ )
115
+ response = parse(raw_response)
116
+ success = response.key?("sig")
117
+ rescue ResponseError => e
118
+ response = parse(e.response.body)
119
+ end
120
+
121
+ Response.new(
122
+ success,
123
+ (success ? "OK" : response["error"]["message"]),
124
+ response,
125
+ test: test?,
126
+ authorization: authorization_from(response)
127
+ )
128
+ end
129
+
130
+ def authorization_from(response)
131
+ if response.key?("transaction")
132
+ response["transaction"]["id"]
133
+ elsif response.key?("card")
134
+ response["card"]["token"]
135
+ end
136
+ end
137
+
138
+ def json_error(raw_response)
139
+ msg = "Invalid response from app55 server: Received: #{raw_response.inspect})"
140
+ {
141
+ "error" => {
142
+ "message" => msg
143
+ }
144
+ }
145
+ end
146
+
147
+ def url(resource)
148
+ (test? ? self.test_url : self.live_url) + resource
149
+ end
150
+
151
+ def post_data(params)
152
+ return nil unless params
153
+
154
+ params.map do |key, value|
155
+ next if value.blank?
156
+ if value.is_a?(Hash)
157
+ h = {}
158
+ value.each do |k, v|
159
+ h["#{key}.#{k}"] = v unless v.blank?
160
+ end
161
+ post_data(h)
162
+ else
163
+ "#{key}=#{CGI.escape(value.to_s)}"
164
+ end
165
+ end.compact.join("&")
166
+ end
167
+
168
+ def headers
169
+ {
170
+ "Authorization" => "Basic " + Base64.strict_encode64(@options[:api_key].to_s + ":" + @options[:api_secret].to_s),
171
+ "User-Agent" => user_agent,
172
+ }
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,510 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class AuthorizeNetGateway < Gateway
6
+ include Empty
7
+
8
+ self.test_url = 'https://apitest.authorize.net/xml/v1/request.api'
9
+ self.live_url = 'https://api.authorize.net/xml/v1/request.api'
10
+
11
+ self.supported_countries = %w(AD AT AU BE BG CA CH CY CZ DE DK ES FI FR GB GB GI GR HU IE IT LI LU MC MT NL NO PL PT RO SE SI SK SM TR US VA)
12
+ self.default_currency = 'USD'
13
+ self.money_format = :dollars
14
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro]
15
+
16
+ self.homepage_url = 'http://www.authorize.net/'
17
+ self.display_name = 'Authorize.Net'
18
+
19
+ STANDARD_ERROR_CODE_MAPPING = {
20
+ '36' => STANDARD_ERROR_CODE[:incorrect_number],
21
+ '237' => STANDARD_ERROR_CODE[:invalid_number],
22
+ '2315' => STANDARD_ERROR_CODE[:invalid_number],
23
+ '37' => STANDARD_ERROR_CODE[:invalid_expiry_date],
24
+ '2316' => STANDARD_ERROR_CODE[:invalid_expiry_date],
25
+ '378' => STANDARD_ERROR_CODE[:invalid_cvc],
26
+ '38' => STANDARD_ERROR_CODE[:expired_card],
27
+ '2317' => STANDARD_ERROR_CODE[:expired_card],
28
+ '244' => STANDARD_ERROR_CODE[:incorrect_cvc],
29
+ '227' => STANDARD_ERROR_CODE[:incorrect_address],
30
+ '2127' => STANDARD_ERROR_CODE[:incorrect_address],
31
+ '22' => STANDARD_ERROR_CODE[:card_declined],
32
+ '23' => STANDARD_ERROR_CODE[:card_declined],
33
+ '3153' => STANDARD_ERROR_CODE[:processing_error],
34
+ '235' => STANDARD_ERROR_CODE[:processing_error],
35
+ '24' => STANDARD_ERROR_CODE[:pickup_card]
36
+ }
37
+
38
+ MARKET_TYPE = {
39
+ :moto => '1',
40
+ :retail => '2'
41
+ }
42
+
43
+ class_attribute :duplicate_window
44
+
45
+ APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4
46
+ TRANSACTION_ALREADY_ACTIONED = %w(310 311)
47
+
48
+ CARD_CODE_ERRORS = %w(N S)
49
+ AVS_ERRORS = %w(A E N R W Z)
50
+ AVS_REASON_CODES = %w(27 45)
51
+
52
+ TRACKS = {
53
+ 1 => /^%(?<format_code>.)(?<pan>[\d]{1,19}+)\^(?<name>.{2,26})\^(?<expiration>[\d]{0,4}|\^)(?<service_code>[\d]{0,3}|\^)(?<discretionary_data>.*)\?\Z/,
54
+ 2 => /\A;(?<pan>[\d]{1,19}+)=(?<expiration>[\d]{0,4}|=)(?<service_code>[\d]{0,3}|=)(?<discretionary_data>.*)\?\Z/
55
+ }.freeze
56
+
57
+ APPLE_PAY_DATA_DESCRIPTOR = "COMMON.APPLE.INAPP.PAYMENT"
58
+
59
+ def initialize(options={})
60
+ requires!(options, :login, :password)
61
+ super
62
+ end
63
+
64
+ def purchase(amount, payment, options = {})
65
+ commit("AUTH_CAPTURE") do |xml|
66
+ add_order_id(xml, options)
67
+ xml.transactionRequest do
68
+ xml.transactionType('authCaptureTransaction')
69
+ xml.amount(amount(amount))
70
+
71
+ add_payment_source(xml, payment)
72
+ add_invoice(xml, options)
73
+ add_customer_data(xml, payment, options)
74
+ add_market_type(xml, payment)
75
+ add_settings(xml, payment, options)
76
+ add_user_fields(xml, amount, options)
77
+ end
78
+ end
79
+ end
80
+
81
+ def authorize(amount, payment, options={})
82
+ commit("AUTH_ONLY") do |xml|
83
+ add_order_id(xml, options)
84
+ xml.transactionRequest do
85
+ xml.transactionType('authOnlyTransaction')
86
+ xml.amount(amount(amount))
87
+
88
+ add_payment_source(xml, payment)
89
+ add_invoice(xml, options)
90
+ add_customer_data(xml, payment, options)
91
+ add_market_type(xml, payment)
92
+ add_settings(xml, payment, options)
93
+ add_user_fields(xml, amount, options)
94
+ end
95
+ end
96
+ end
97
+
98
+ def capture(amount, authorization, options={})
99
+ commit("PRIOR_AUTH_CAPTURE") do |xml|
100
+ add_order_id(xml, options)
101
+ xml.transactionRequest do
102
+ xml.transactionType('priorAuthCaptureTransaction')
103
+ xml.amount(amount(amount))
104
+ xml.refTransId(split_authorization(authorization)[0])
105
+
106
+ add_invoice(xml, options)
107
+ add_user_fields(xml, amount, options)
108
+ end
109
+ end
110
+ end
111
+
112
+ def refund(amount, authorization, options={})
113
+ transaction_id, card_number = split_authorization(authorization)
114
+ commit("CREDIT") do |xml|
115
+ xml.transactionRequest do
116
+ xml.transactionType('refundTransaction')
117
+ xml.amount(amount.nil? ? 0 : amount(amount))
118
+ xml.payment do
119
+ xml.creditCard do
120
+ xml.cardNumber(card_number || options[:card_number])
121
+ xml.expirationDate('XXXX')
122
+ end
123
+ end
124
+ xml.refTransId(transaction_id)
125
+
126
+ add_customer_data(xml, nil, options)
127
+ add_user_fields(xml, amount, options)
128
+ end
129
+ end
130
+ end
131
+
132
+ def void(authorization, options={})
133
+ commit("VOID") do |xml|
134
+ add_order_id(xml, options)
135
+ xml.transactionRequest do
136
+ xml.transactionType('voidTransaction')
137
+ xml.refTransId(split_authorization(authorization)[0])
138
+
139
+ add_user_fields(xml, nil, options)
140
+ end
141
+ end
142
+ end
143
+
144
+ def credit(amount, payment, options={})
145
+ if payment.is_a?(String)
146
+ raise ArgumentError, "Reference credits are not supported. Please supply the original credit card or use the #refund method."
147
+ end
148
+
149
+ commit("CREDIT") do |xml|
150
+ add_order_id(xml, options)
151
+ xml.transactionRequest do
152
+ xml.transactionType('refundTransaction')
153
+ xml.amount(amount(amount))
154
+
155
+ add_payment_source(xml, payment)
156
+ add_invoice(xml, options)
157
+ add_customer_data(xml, payment, options)
158
+ add_settings(xml, payment, options)
159
+ add_user_fields(xml, amount, options)
160
+ end
161
+ end
162
+ end
163
+
164
+ def verify(credit_card, options = {})
165
+ MultiResponse.run(:use_first_response) do |r|
166
+ r.process { authorize(100, credit_card, options) }
167
+ r.process(:ignore_result) { void(r.authorization, options) }
168
+ end
169
+ end
170
+
171
+ def supports_scrubbing?
172
+ true
173
+ end
174
+
175
+ def scrub(transcript)
176
+ transcript.
177
+ gsub(%r((<cardNumber>).+(</cardNumber>)), '\1[FILTERED]\2').
178
+ gsub(%r((<cardCode>).+(</cardCode>)), '\1[FILTERED]\2')
179
+ end
180
+
181
+ private
182
+
183
+ def add_payment_source(xml, source)
184
+ return unless source
185
+ if card_brand(source) == 'check'
186
+ add_check(xml, source)
187
+ elsif card_brand(source) == 'apple_pay'
188
+ add_apple_pay_payment_token(xml, source)
189
+ else
190
+ add_credit_card(xml, source)
191
+ end
192
+ end
193
+
194
+ def add_settings(xml, source, options)
195
+ xml.transactionSettings do
196
+ if card_brand(source) == "check" && options[:recurring]
197
+ xml.setting do
198
+ xml.settingName("recurringBilling")
199
+ xml.settingValue("true")
200
+ end
201
+ end
202
+ if options[:duplicate_window]
203
+ set_duplicate_window(xml, options[:duplicate_window])
204
+ elsif self.class.duplicate_window
205
+ ActiveMerchant.deprecated "Using the duplicate_window class_attribute is deprecated. Use the transaction options hash instead."
206
+ set_duplicate_window(xml, self.class.duplicate_window)
207
+ end
208
+ end
209
+ end
210
+
211
+ def set_duplicate_window(xml, value)
212
+ xml.setting do
213
+ xml.settingName("duplicateWindow")
214
+ xml.settingValue(value)
215
+ end
216
+ end
217
+
218
+ def add_user_fields(xml, amount, options)
219
+ xml.userFields do
220
+ if currency = (options[:currency] || currency(amount))
221
+ xml.userField do
222
+ xml.name("x_currency_code")
223
+ xml.value(currency)
224
+ end
225
+ end
226
+ if application_id.present? && application_id != "ActiveMerchant"
227
+ xml.userField do
228
+ xml.name("x_solution_id")
229
+ xml.value(application_id)
230
+ end
231
+ end
232
+ end
233
+ end
234
+
235
+ def add_credit_card(xml, credit_card)
236
+ if credit_card.track_data
237
+ add_swipe_data(xml, credit_card)
238
+ else
239
+ xml.payment do
240
+ xml.creditCard do
241
+ xml.cardNumber(truncate(credit_card.number, 16))
242
+ xml.expirationDate(format(credit_card.month, :two_digits) + '/' + format(credit_card.year, :four_digits))
243
+ if credit_card.valid_card_verification_value?(credit_card.verification_value, credit_card.brand)
244
+ xml.cardCode(credit_card.verification_value)
245
+ end
246
+ if credit_card.is_a?(NetworkTokenizationCreditCard)
247
+ xml.cryptogram(credit_card.payment_cryptogram)
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ def add_swipe_data(xml, credit_card)
255
+ TRACKS.each do |key, regex|
256
+ if regex.match(credit_card.track_data)
257
+ @valid_track_data = true
258
+ xml.payment do
259
+ xml.trackData do
260
+ xml.public_send(:"track#{key}", credit_card.track_data)
261
+ end
262
+ end
263
+ end
264
+ end
265
+ end
266
+
267
+ # http://developer.authorize.net/api/reference/#apple-pay-transactions
268
+ def add_apple_pay_payment_token(xml, apple_pay_payment_token)
269
+ xml.payment do
270
+ xml.opaqueData do
271
+ xml.dataDescriptor(APPLE_PAY_DATA_DESCRIPTOR)
272
+ xml.dataValue(Base64.strict_encode64(apple_pay_payment_token.payment_data.to_json))
273
+ end
274
+ end
275
+ end
276
+
277
+ def add_market_type(xml, payment)
278
+ return if card_brand(payment) == 'check' or card_brand(payment) == 'apple_pay'
279
+ if valid_track_data
280
+ xml.retail do
281
+ xml.marketType(MARKET_TYPE[:retail])
282
+ end
283
+ elsif payment.manual_entry
284
+ xml.retail do
285
+ xml.marketType(MARKET_TYPE[:moto])
286
+ end
287
+ end
288
+ end
289
+
290
+ def valid_track_data
291
+ @valid_track_data ||= false
292
+ end
293
+
294
+ def add_check(xml, check)
295
+ xml.payment do
296
+ xml.bankAccount do
297
+ xml.routingNumber(check.routing_number)
298
+ xml.accountNumber(check.account_number)
299
+ xml.nameOnAccount(check.name)
300
+ xml.echeckType("WEB")
301
+ xml.bankName(check.bank_name)
302
+ xml.checkNumber(check.number)
303
+ end
304
+ end
305
+ end
306
+
307
+ def add_customer_data(xml, payment_source, options)
308
+ billing_address = options[:billing_address] || options[:address] || {}
309
+ shipping_address = options[:shipping_address] || options[:address] || {}
310
+
311
+ xml.customer do
312
+ xml.id(options[:customer]) unless empty?(options[:customer]) || options[:customer] !~ /^\d+$/
313
+ xml.email(options[:email]) unless empty?(options[:email])
314
+ end
315
+
316
+ xml.billTo do
317
+ first_name, last_name = names_from(payment_source, billing_address, options)
318
+ xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
319
+ xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
320
+
321
+ xml.company(truncate(billing_address[:company], 50)) unless empty?(billing_address[:company])
322
+ xml.address(truncate(billing_address[:address1], 60))
323
+ xml.city(truncate(billing_address[:city], 40))
324
+ xml.state(empty?(billing_address[:state]) ? 'n/a' : truncate(billing_address[:state], 40))
325
+ xml.zip(truncate((billing_address[:zip] || options[:zip]), 20))
326
+ xml.country(truncate(billing_address[:country], 60))
327
+ xml.phoneNumber(truncate(billing_address[:phone], 25)) unless empty?(billing_address[:phone])
328
+ xml.faxNumber(truncate(billing_address[:fax], 25)) unless empty?(billing_address[:fax])
329
+ end
330
+
331
+ unless shipping_address.blank?
332
+ xml.shipTo do
333
+ (first_name, last_name) = if shipping_address[:name]
334
+ shipping_address[:name].split
335
+ else
336
+ [shipping_address[:first_name], shipping_address[:last_name]]
337
+ end
338
+ xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
339
+ xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
340
+
341
+ xml.company(truncate(shipping_address[:company], 50)) unless empty?(shipping_address[:company])
342
+ xml.address(truncate(shipping_address[:address1], 60))
343
+ xml.city(truncate(shipping_address[:city], 40))
344
+ xml.state(truncate(shipping_address[:state], 40))
345
+ xml.zip(truncate(shipping_address[:zip], 20))
346
+ xml.country(truncate(shipping_address[:country], 60))
347
+ end
348
+ end
349
+
350
+ xml.customerIP(options[:ip]) unless empty?(options[:ip])
351
+
352
+ xml.cardholderAuthentication do
353
+ xml.authenticationIndicator(options[:authentication_indicator])
354
+ xml.cardholderAuthenticationValue(options[:cardholder_authentication_value])
355
+ end
356
+ end
357
+
358
+ def add_order_id(xml, options)
359
+ xml.refId(truncate(options[:order_id], 20))
360
+ end
361
+
362
+ def add_invoice(xml, options)
363
+ xml.order do
364
+ xml.invoiceNumber(truncate(options[:order_id], 20))
365
+ xml.description(truncate(options[:description], 255))
366
+ end
367
+ end
368
+
369
+ def names_from(payment_source, address, options)
370
+ if payment_source && !payment_source.is_a?(PaymentToken)
371
+ first_name, last_name = (address[:name] || "").split
372
+ [(payment_source.first_name || first_name), (payment_source.last_name || last_name)]
373
+ else
374
+ [options[:first_name], options[:last_name]]
375
+ end
376
+ end
377
+
378
+ def commit(action, &payload)
379
+ url = (test? ? test_url : live_url)
380
+ response = parse(action, ssl_post(url, post_data(&payload), 'Content-Type' => 'text/xml'))
381
+
382
+ avs_result = AVSResult.new(code: response[:avs_result_code])
383
+ cvv_result = CVVResult.new(response[:card_code])
384
+ if using_live_gateway_in_test_mode?(response)
385
+ Response.new(false, "Using a live Authorize.net account in Test Mode is not permitted.")
386
+ else
387
+ Response.new(
388
+ success_from(response),
389
+ message_from(response, avs_result, cvv_result),
390
+ response,
391
+ authorization: authorization_from(response),
392
+ test: test?,
393
+ avs_result: avs_result,
394
+ cvv_result: cvv_result,
395
+ fraud_review: fraud_review?(response),
396
+ error_code: map_error_code(response[:response_code], response[:response_reason_code])
397
+ )
398
+ end
399
+ end
400
+
401
+ def post_data
402
+ Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
403
+ xml.createTransactionRequest('xmlns' => 'AnetApi/xml/v1/schema/AnetApiSchema.xsd') do
404
+ xml.merchantAuthentication do
405
+ xml.name(@options[:login])
406
+ xml.transactionKey(@options[:password])
407
+ end
408
+ yield(xml)
409
+ end
410
+ end.to_xml(indent: 0)
411
+ end
412
+
413
+ def parse(action, body)
414
+ doc = Nokogiri::XML(body)
415
+ doc.remove_namespaces!
416
+
417
+ response = {action: action}
418
+
419
+ response[:response_code] = if(element = doc.at_xpath("//transactionResponse/responseCode"))
420
+ (empty?(element.content) ? nil : element.content.to_i)
421
+ end
422
+
423
+ if(element = doc.at_xpath("//errors/error"))
424
+ response[:response_reason_code] = element.at_xpath("errorCode").content[/0*(\d+)$/, 1]
425
+ response[:response_reason_text] = element.at_xpath("errorText").content.chomp('.')
426
+ elsif(element = doc.at_xpath("//transactionResponse/messages/message"))
427
+ response[:response_reason_code] = element.at_xpath("code").content[/0*(\d+)$/, 1]
428
+ response[:response_reason_text] = element.at_xpath("description").content.chomp('.')
429
+ elsif(element = doc.at_xpath("//messages/message"))
430
+ response[:response_reason_code] = element.at_xpath("code").content[/0*(\d+)$/, 1]
431
+ response[:response_reason_text] = element.at_xpath("text").content.chomp('.')
432
+ else
433
+ response[:response_reason_code] = nil
434
+ response[:response_reason_text] = ""
435
+ end
436
+
437
+ response[:avs_result_code] = if(element = doc.at_xpath("//avsResultCode"))
438
+ (empty?(element.content) ? nil : element.content)
439
+ end
440
+
441
+ response[:transaction_id] = if(element = doc.at_xpath("//transId"))
442
+ (empty?(element.content) ? nil : element.content)
443
+ end
444
+
445
+ response[:card_code] = if(element = doc.at_xpath("//cvvResultCode"))
446
+ (empty?(element.content) ? nil : element.content)
447
+ end
448
+
449
+ response[:authorization_code] = if(element = doc.at_xpath("//authCode"))
450
+ (empty?(element.content) ? nil : element.content)
451
+ end
452
+
453
+ response[:cardholder_authentication_code] = if(element = doc.at_xpath("//cavvResultCode"))
454
+ (empty?(element.content) ? nil : element.content)
455
+ end
456
+
457
+ response[:account_number] = if(element = doc.at_xpath("//accountNumber"))
458
+ (empty?(element.content) ? nil : element.content[-4..-1])
459
+ end
460
+
461
+ response[:test_request] = if(element = doc.at_xpath("//testRequest"))
462
+ (empty?(element.content) ? nil : element.content)
463
+ end
464
+
465
+ response
466
+ end
467
+
468
+ def success_from(response)
469
+ (
470
+ response[:response_code] == APPROVED &&
471
+ TRANSACTION_ALREADY_ACTIONED.exclude?(response[:response_reason_code])
472
+ )
473
+ end
474
+
475
+ def message_from(response, avs_result, cvv_result)
476
+ if response[:response_code] == DECLINED
477
+ if CARD_CODE_ERRORS.include?(cvv_result.code)
478
+ return cvv_result.message
479
+ elsif(AVS_REASON_CODES.include?(response[:response_reason_code]) && AVS_ERRORS.include?(avs_result.code))
480
+ return avs_result.message
481
+ end
482
+ end
483
+
484
+ response[:response_reason_text]
485
+ end
486
+
487
+ def authorization_from(response)
488
+ [response[:transaction_id], response[:account_number]].join("#")
489
+ end
490
+
491
+ def split_authorization(authorization)
492
+ transaction_id, card_number = authorization.split("#")
493
+ [transaction_id, card_number]
494
+ end
495
+
496
+ def fraud_review?(response)
497
+ (response[:response_code] == FRAUD_REVIEW)
498
+ end
499
+
500
+
501
+ def using_live_gateway_in_test_mode?(response)
502
+ !test? && response[:test_request] == "1"
503
+ end
504
+
505
+ def map_error_code(response_code, response_reason_code)
506
+ STANDARD_ERROR_CODE_MAPPING[response_code.to_s << response_reason_code.to_s]
507
+ end
508
+ end
509
+ end
510
+ end