activemerchant 1.130.0 → 1.137.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +268 -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 +13 -8
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +64 -7
  8. data/lib/active_merchant/billing/gateway.rb +9 -0
  9. data/lib/active_merchant/billing/gateways/adyen.rb +240 -41
  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 +44 -36
  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/borgun.rb +6 -4
  21. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
  22. data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
  23. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
  25. data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
  26. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  28. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
  29. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  30. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
  31. data/lib/active_merchant/billing/gateways/checkout_v2.rb +252 -41
  32. data/lib/active_merchant/billing/gateways/commerce_hub.rb +69 -8
  33. data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
  34. data/lib/active_merchant/billing/gateways/cyber_source.rb +192 -41
  35. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
  36. data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
  37. data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
  38. data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
  39. data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
  40. data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
  41. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  42. data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
  43. data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
  44. data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
  45. data/lib/active_merchant/billing/gateways/element.rb +36 -7
  46. data/lib/active_merchant/billing/gateways/epay.rb +6 -2
  47. data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
  48. data/lib/active_merchant/billing/gateways/eway.rb +4 -2
  49. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
  50. data/lib/active_merchant/billing/gateways/exact.rb +6 -2
  51. data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
  52. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
  53. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  54. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  55. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  56. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
  57. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
  58. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
  59. data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
  60. data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
  61. data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
  62. data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
  63. data/lib/active_merchant/billing/gateways/hps.rb +1 -1
  64. data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
  65. data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
  66. data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
  67. data/lib/active_merchant/billing/gateways/ipg.rb +10 -6
  68. data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
  69. data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
  70. data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
  71. data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
  72. data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
  73. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
  74. data/lib/active_merchant/billing/gateways/kushki.rb +73 -13
  75. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
  76. data/lib/active_merchant/billing/gateways/litle.rb +33 -50
  77. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  78. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  79. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
  80. data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
  81. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
  82. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
  83. data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
  84. data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
  85. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
  86. data/lib/active_merchant/billing/gateways/migs.rb +6 -2
  87. data/lib/active_merchant/billing/gateways/mit.rb +25 -20
  88. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
  89. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  90. data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
  91. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
  92. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
  93. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  94. data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
  95. data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
  96. data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
  97. data/lib/active_merchant/billing/gateways/nmi.rb +23 -6
  98. data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
  99. data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
  100. data/lib/active_merchant/billing/gateways/opp.rb +1 -2
  101. data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
  102. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
  103. data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
  104. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
  105. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
  106. data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
  107. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
  108. data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
  109. data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
  110. data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
  111. data/lib/active_merchant/billing/gateways/payex.rb +4 -2
  112. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  113. data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
  114. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  115. data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
  116. data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
  117. data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
  118. data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
  119. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  120. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  121. data/lib/active_merchant/billing/gateways/pin.rb +22 -4
  122. data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
  123. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  124. data/lib/active_merchant/billing/gateways/priority.rb +6 -5
  125. data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
  126. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  127. data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
  128. data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
  129. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
  130. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  131. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
  132. data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
  133. data/lib/active_merchant/billing/gateways/reach.rb +11 -4
  134. data/lib/active_merchant/billing/gateways/redsys.rb +3 -11
  135. data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
  136. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  137. data/lib/active_merchant/billing/gateways/safe_charge.rb +38 -17
  138. data/lib/active_merchant/billing/gateways/sage.rb +12 -4
  139. data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
  140. data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
  141. data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
  142. data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
  143. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
  144. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
  145. data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
  146. data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
  147. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  148. data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
  149. data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
  150. data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
  151. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
  152. data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
  153. data/lib/active_merchant/billing/gateways/stripe.rb +63 -19
  154. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +280 -88
  155. data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
  156. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
  157. data/lib/active_merchant/billing/gateways/telr.rb +3 -4
  158. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
  159. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
  160. data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
  161. data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
  162. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
  163. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
  164. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  165. data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
  166. data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
  167. data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
  168. data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
  169. data/lib/active_merchant/billing/gateways/vpos.rb +4 -4
  170. data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
  171. data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
  172. data/lib/active_merchant/billing/gateways/worldpay.rb +147 -93
  173. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
  174. data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
  175. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  176. data/lib/active_merchant/billing/response.rb +2 -2
  177. data/lib/active_merchant/connection.rb +3 -17
  178. data/lib/active_merchant/country.rb +1 -0
  179. data/lib/active_merchant/errors.rb +10 -0
  180. data/lib/active_merchant/version.rb +1 -1
  181. data/lib/support/gateway_support.rb +2 -2
  182. data/lib/support/ssl_verify.rb +4 -4
  183. data/lib/support/ssl_version.rb +6 -6
  184. metadata +30 -9
@@ -0,0 +1,382 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class DeepstackGateway < Gateway
4
+ self.test_url = 'https://api.sandbox.deepstack.io'
5
+ self.live_url = 'https://api.deepstack.io'
6
+
7
+ self.supported_countries = ['US']
8
+ self.default_currency = 'USD'
9
+ self.supported_cardtypes = %i[visa master american_express discover]
10
+ self.money_format = :cents
11
+
12
+ self.homepage_url = 'https://deepstack.io/'
13
+ self.display_name = 'Deepstack Gateway'
14
+
15
+ STANDARD_ERROR_CODE_MAPPING = {}
16
+
17
+ def initialize(options = {})
18
+ requires!(options, :publishable_api_key, :app_id, :shared_secret)
19
+ @publishable_api_key, @app_id, @shared_secret = options.values_at(:publishable_api_key, :app_id, :shared_secret)
20
+ super
21
+ end
22
+
23
+ def purchase(money, payment, options = {})
24
+ post = {}
25
+ add_payment(post, payment, options)
26
+ add_order(post, money, options)
27
+ add_purchase_capture(post)
28
+ add_address(post, payment, options)
29
+ add_customer_data(post, options)
30
+ commit('sale', post)
31
+ end
32
+
33
+ def authorize(money, payment, options = {})
34
+ post = {}
35
+ add_payment(post, payment, options)
36
+ add_order(post, money, options)
37
+ add_address(post, payment, options)
38
+ add_customer_data(post, options)
39
+
40
+ commit('auth', post)
41
+ end
42
+
43
+ def capture(money, authorization, options = {})
44
+ post = {}
45
+ add_invoice(post, money, authorization, options)
46
+
47
+ commit('capture', post)
48
+ end
49
+
50
+ def refund(money, authorization, options = {})
51
+ post = {}
52
+ add_invoice(post, money, authorization, options)
53
+ commit('refund', post)
54
+ end
55
+
56
+ def void(money, authorization, options = {})
57
+ post = {}
58
+ add_invoice(post, money, authorization, options)
59
+ commit('void', post)
60
+ end
61
+
62
+ def verify(credit_card, options = {})
63
+ MultiResponse.run(:use_first_response) do |r|
64
+ r.process { authorize(100, credit_card, options) }
65
+ r.process(:ignore_result) { void(0, r.authorization, options) }
66
+ end
67
+ end
68
+
69
+ def get_token(credit_card, options = {})
70
+ post = {}
71
+ add_payment_instrument(post, credit_card, options)
72
+ add_address_payment_instrument(post, credit_card, options)
73
+ commit('gettoken', post)
74
+ end
75
+
76
+ def supports_scrubbing?
77
+ true
78
+ end
79
+
80
+ def scrub(transcript)
81
+ transcript.
82
+ gsub(%r((Authorization: Bearer )\w+), '\1[FILTERED]').
83
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
84
+ gsub(%r((Hmac: )[\w=]+), '\1[FILTERED]').
85
+ gsub(%r((\\"account_number\\":\\")[\w*]+), '\1[FILTERED]').
86
+ gsub(%r((\\"cvv\\":\\")\w+), '\1[FILTERED]').
87
+ gsub(%r((\\"expiration\\":\\")\w+), '\1[FILTERED]')
88
+ end
89
+
90
+ private
91
+
92
+ def add_customer_data(post, options)
93
+ post[:meta] ||= {}
94
+
95
+ add_shipping(post, options) if options.key?(:shipping_address)
96
+ post[:meta][:client_customer_id] = options[:customer] if options[:customer]
97
+ post[:meta][:client_transaction_id] = options[:order_id] if options[:order_id]
98
+ post[:meta][:client_transaction_description] = options[:description] if options[:description]
99
+ post[:meta][:client_invoice_id] = options[:invoice] if options[:invoice]
100
+ post[:meta][:card_holder_ip_address] = options[:ip] if options[:ip]
101
+ end
102
+
103
+ def add_address(post, creditcard, options)
104
+ return post unless options.key?(:address) || options.key?(:billing_address)
105
+
106
+ billing_address = options[:address] || options[:billing_address]
107
+ post[:source] ||= {}
108
+
109
+ post[:source][:billing_contact] = {}
110
+ post[:source][:billing_contact][:first_name] = billing_address[:first_name] if billing_address[:first_name]
111
+ post[:source][:billing_contact][:last_name] = billing_address[:last_name] if billing_address[:last_name]
112
+ post[:source][:billing_contact][:phone] = billing_address[:phone] if billing_address[:phone]
113
+ post[:source][:billing_contact][:email] = options[:email] if options[:email]
114
+ post[:source][:billing_contact][:address] = {}
115
+ post[:source][:billing_contact][:address][:line_1] = billing_address[:address1] if billing_address[:address1]
116
+ post[:source][:billing_contact][:address][:line_2] = billing_address[:address2] if billing_address[:address2]
117
+ post[:source][:billing_contact][:address][:city] = billing_address[:city] if billing_address[:city]
118
+ post[:source][:billing_contact][:address][:state] = billing_address[:state] if billing_address[:state]
119
+ post[:source][:billing_contact][:address][:postal_code] = billing_address[:zip] if billing_address[:zip]
120
+ post[:source][:billing_contact][:address][:country_code] = billing_address[:country] if billing_address[:country]
121
+ end
122
+
123
+ def add_address_payment_instrument(post, creditcard, options)
124
+ return post unless options.key?(:address) || options.key?(:billing_address)
125
+
126
+ billing_address = options[:address] || options[:billing_address]
127
+ post[:source] = {} unless post.key?(:payment_instrument)
128
+
129
+ post[:payment_instrument][:billing_contact] = {}
130
+ post[:payment_instrument][:billing_contact][:first_name] = billing_address[:first_name] if billing_address[:first_name]
131
+ post[:payment_instrument][:billing_contact][:last_name] = billing_address[:last_name] if billing_address[:last_name]
132
+ post[:payment_instrument][:billing_contact][:phone] = billing_address[:phone] if billing_address[:phone]
133
+ post[:payment_instrument][:billing_contact][:email] = billing_address[:email] if billing_address[:email]
134
+ post[:payment_instrument][:billing_contact][:address] = {}
135
+ post[:payment_instrument][:billing_contact][:address][:line_1] = billing_address[:address1] if billing_address[:address1]
136
+ post[:payment_instrument][:billing_contact][:address][:line_2] = billing_address[:address2] if billing_address[:address2]
137
+ post[:payment_instrument][:billing_contact][:address][:city] = billing_address[:city] if billing_address[:city]
138
+ post[:payment_instrument][:billing_contact][:address][:state] = billing_address[:state] if billing_address[:state]
139
+ post[:payment_instrument][:billing_contact][:address][:postal_code] = billing_address[:zip] if billing_address[:zip]
140
+ post[:payment_instrument][:billing_contact][:address][:country_code] = billing_address[:country] if billing_address[:country]
141
+ end
142
+
143
+ def add_shipping(post, options = {})
144
+ return post unless options.key?(:shipping_address)
145
+
146
+ shipping = options[:shipping_address]
147
+ post[:meta][:shipping_info] = {}
148
+ post[:meta][:shipping_info][:first_name] = shipping[:first_name] if shipping[:first_name]
149
+ post[:meta][:shipping_info][:last_name] = shipping[:last_name] if shipping[:last_name]
150
+ post[:meta][:shipping_info][:phone] = shipping[:phone] if shipping[:phone]
151
+ post[:meta][:shipping_info][:email] = shipping[:email] if shipping[:email]
152
+ post[:meta][:shipping_info][:address] = {}
153
+ post[:meta][:shipping_info][:address][:line_1] = shipping[:address1] if shipping[:address1]
154
+ post[:meta][:shipping_info][:address][:line_2] = shipping[:address2] if shipping[:address2]
155
+ post[:meta][:shipping_info][:address][:city] = shipping[:city] if shipping[:city]
156
+ post[:meta][:shipping_info][:address][:state] = shipping[:state] if shipping[:state]
157
+ post[:meta][:shipping_info][:address][:postal_code] = shipping[:zip] if shipping[:zip]
158
+ post[:meta][:shipping_info][:address][:country_code] = shipping[:country] if shipping[:country]
159
+ end
160
+
161
+ def add_invoice(post, money, authorization, options)
162
+ post[:amount] = amount(money)
163
+ post[:charge] = authorization
164
+ end
165
+
166
+ def add_payment(post, payment, options)
167
+ if payment.kind_of?(String)
168
+ post[:source] = {}
169
+ post[:source][:type] = 'card_on_file'
170
+ post[:source][:card_on_file] = {}
171
+ post[:source][:card_on_file][:id] = payment
172
+ post[:source][:card_on_file][:cvv] = options[:verification_value] || ''
173
+ post[:source][:card_on_file][:customer_id] = options[:customer_id] || ''
174
+ # credit card object
175
+ elsif payment.respond_to?(:number)
176
+ post[:source] = {}
177
+ post[:source][:type] = 'credit_card'
178
+ post[:source][:credit_card] = {}
179
+ post[:source][:credit_card][:account_number] = payment.number
180
+ post[:source][:credit_card][:cvv] = payment.verification_value || ''
181
+ post[:source][:credit_card][:expiration] = '%02d%02d' % [payment.month, payment.year % 100]
182
+ post[:source][:credit_card][:customer_id] = options[:customer_id] || ''
183
+ end
184
+ end
185
+
186
+ def add_payment_instrument(post, creditcard, options)
187
+ if creditcard.kind_of?(String)
188
+ post[:source] = creditcard
189
+ return post
190
+ end
191
+ return post unless creditcard.respond_to?(:number)
192
+
193
+ post[:payment_instrument] = {}
194
+ post[:payment_instrument][:type] = 'credit_card'
195
+ post[:payment_instrument][:credit_card] = {}
196
+ post[:payment_instrument][:credit_card][:account_number] = creditcard.number
197
+ post[:payment_instrument][:credit_card][:expiration] = '%02d%02d' % [creditcard.month, creditcard.year % 100]
198
+ post[:payment_instrument][:credit_card][:cvv] = creditcard.verification_value
199
+ end
200
+
201
+ def add_order(post, amount, options)
202
+ post[:transaction] ||= {}
203
+
204
+ post[:transaction][:amount] = amount
205
+ post[:transaction][:cof_type] = options.key?(:cof_type) ? options[:cof_type].upcase : 'UNSCHEDULED_CARDHOLDER'
206
+ post[:transaction][:capture] = false # Change this in the request (auth/charge)
207
+ post[:transaction][:currency_code] = (options[:currency] || currency(amount).upcase)
208
+ post[:transaction][:avs] = options[:avs] || true # default avs to true unless told otherwise
209
+ post[:transaction][:save_payment_instrument] = options[:save_payment_instrument] || false
210
+ end
211
+
212
+ def add_purchase_capture(post)
213
+ post[:transaction] ||= {}
214
+ post[:transaction][:capture] = true
215
+ end
216
+
217
+ def parse(body)
218
+ return {} if !body || body.empty?
219
+
220
+ JSON.parse(body)
221
+ end
222
+
223
+ def commit(action, parameters, method = 'POST')
224
+ url = (test? ? test_url : live_url)
225
+ if no_hmac(action)
226
+ request_headers = headers.merge(create_basic(parameters, action))
227
+ else
228
+ request_headers = headers.merge(create_hmac(parameters, method))
229
+ end
230
+ request_url = url + get_url(action)
231
+ begin
232
+ response = parse(ssl_post(request_url, post_data(action, parameters), request_headers))
233
+ Response.new(
234
+ success_from(response),
235
+ message_from(response),
236
+ response,
237
+ authorization: authorization_from(response),
238
+ avs_result: AVSResult.new(code: response['avs_result']),
239
+ cvv_result: CVVResult.new(response['cvv_result']),
240
+ test: test?,
241
+ error_code: error_code_from(response)
242
+ )
243
+ rescue ResponseError => e
244
+ Response.new(
245
+ false,
246
+ message_from_error(e.response.body),
247
+ response_error(e.response.body)
248
+ )
249
+ rescue JSON::ParserError
250
+ Response.new(
251
+ false,
252
+ message_from(response),
253
+ json_error(response)
254
+ )
255
+ end
256
+ end
257
+
258
+ def headers
259
+ {
260
+ 'Accept' => 'text/plain',
261
+ 'Content-Type' => 'application/json'
262
+ }
263
+ end
264
+
265
+ def response_error(response)
266
+ parse(response)
267
+ rescue JSON::ParserError
268
+ json_error(response)
269
+ end
270
+
271
+ def json_error(response)
272
+ msg = 'Invalid response received from the Conekta API.'
273
+ msg += " (The raw response returned by the API was #{response.inspect})"
274
+ {
275
+ 'message' => msg
276
+ }
277
+ end
278
+
279
+ def success_from(response)
280
+ success = false
281
+ if response.key?('response_code')
282
+ success = response['response_code'] == '00'
283
+ # Hack because token/payment instrument methods do not return a response_code
284
+ elsif response.key?('id')
285
+ success = true if response['id'].start_with?('tok', 'card')
286
+ end
287
+
288
+ return success
289
+ end
290
+
291
+ def message_from(response)
292
+ response = JSON.parse(response) if response.is_a?(String)
293
+ if response.key?('message')
294
+ return response['message']
295
+ elsif response.key?('detail')
296
+ return response['detail']
297
+ end
298
+ end
299
+
300
+ def message_from_error(response)
301
+ if response.is_a?(String)
302
+ response.gsub!('\\"', '"')
303
+ response = JSON.parse(response)
304
+ end
305
+
306
+ if response.key?('detail')
307
+ return response['detail']
308
+ elsif response.key?('message')
309
+ return response['message']
310
+ end
311
+ end
312
+
313
+ def authorization_from(response)
314
+ response['id']
315
+ end
316
+
317
+ def post_data(action, parameters = {})
318
+ return JSON.generate(parameters)
319
+ end
320
+
321
+ def error_code_from(response)
322
+ error_code = nil
323
+ error_code = response['response_code'] unless success_from(response)
324
+ if error = response.dig('detail')
325
+ error_code = error
326
+ elsif error = response.dig('error')
327
+ error_code = error.dig('reason', 'id')
328
+ end
329
+ error_code
330
+ end
331
+
332
+ def get_url(action)
333
+ base = '/api/v1/'
334
+ case action
335
+ when 'sale'
336
+ return base + 'payments/charge'
337
+ when 'auth'
338
+ return base + 'payments/charge'
339
+ when 'capture'
340
+ return base + 'payments/capture'
341
+ when 'void'
342
+ return base + 'payments/refund'
343
+ when 'refund'
344
+ return base + 'payments/refund'
345
+ when 'gettoken'
346
+ return base + 'vault/token'
347
+ when 'vault'
348
+ return base + 'vault/payment-instrument/token'
349
+ else
350
+ return base + 'noaction'
351
+ end
352
+ end
353
+
354
+ def no_hmac(action)
355
+ case action
356
+ when 'gettoken'
357
+ return true
358
+ else
359
+ return false
360
+ end
361
+ end
362
+
363
+ def create_basic(post, method)
364
+ return { 'Authorization' => "Bearer #{@publishable_api_key}" }
365
+ end
366
+
367
+ def create_hmac(post, method)
368
+ # Need requestDate, requestMethod, Nonce, AppIDKey
369
+ app_id_key = @app_id
370
+ request_method = method.upcase
371
+ uuid = SecureRandom.uuid
372
+ request_time = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%S.%LZ')
373
+
374
+ string_to_hash = "#{app_id_key}|#{request_method}|#{request_time}|#{uuid}|#{JSON.generate(post)}"
375
+ signature = OpenSSL::HMAC.digest(OpenSSL::Digest.new('SHA256'), Base64.strict_decode64(@shared_secret), string_to_hash)
376
+ base64_signature = Base64.strict_encode64(signature)
377
+ hmac_header = Base64.strict_encode64("#{app_id_key}|#{request_method}|#{request_time}|#{uuid}|#{base64_signature}")
378
+ return { 'hmac' => hmac_header }
379
+ end
380
+ end
381
+ end
382
+ end
@@ -4,7 +4,7 @@ module ActiveMerchant #:nodoc:
4
4
  self.test_url = 'https://sandbox.ebanxpay.com/ws/'
5
5
  self.live_url = 'https://api.ebanxpay.com/ws/'
6
6
 
7
- self.supported_countries = %w(BR MX CO CL AR PE)
7
+ self.supported_countries = %w(BR MX CO CL AR PE BO EC)
8
8
  self.default_currency = 'USD'
9
9
  self.supported_cardtypes = %i[visa master american_express discover diners_club elo hipercard]
10
10
 
@@ -20,7 +20,8 @@ module ActiveMerchant #:nodoc:
20
20
  refund: 'refund',
21
21
  void: 'cancel',
22
22
  store: 'token',
23
- inquire: 'query'
23
+ inquire: 'query',
24
+ verify: 'verifycard'
24
25
  }
25
26
 
26
27
  HTTP_METHOD = {
@@ -30,16 +31,8 @@ module ActiveMerchant #:nodoc:
30
31
  refund: :post,
31
32
  void: :get,
32
33
  store: :post,
33
- inquire: :get
34
- }
35
-
36
- VERIFY_AMOUNT_PER_COUNTRY = {
37
- 'br' => 100,
38
- 'ar' => 100,
39
- 'co' => 50000,
40
- 'pe' => 300,
41
- 'mx' => 2000,
42
- 'cl' => 80000
34
+ inquire: :get,
35
+ verify: :post
43
36
  }
44
37
 
45
38
  def initialize(options = {})
@@ -107,17 +100,22 @@ module ActiveMerchant #:nodoc:
107
100
  def store(credit_card, options = {})
108
101
  post = {}
109
102
  add_integration_key(post)
110
- add_payment_details(post, credit_card)
111
- post[:country] = customer_country(options)
103
+ customer_country(post, options)
104
+ add_payment_type(post)
105
+ post[:creditcard] = payment_details(credit_card)
112
106
 
113
107
  commit(:store, post)
114
108
  end
115
109
 
116
110
  def verify(credit_card, options = {})
117
- MultiResponse.run(:use_first_response) do |r|
118
- r.process { authorize(VERIFY_AMOUNT_PER_COUNTRY[customer_country(options)], credit_card, options) }
119
- r.process(:ignore_result) { void(r.authorization, options) }
120
- end
111
+ post = {}
112
+ add_integration_key(post)
113
+ add_payment_type(post)
114
+ customer_country(post, options)
115
+ post[:card] = payment_details(credit_card)
116
+ post[:device_id] = options[:device_id] if options[:device_id]
117
+
118
+ commit(:verify, post)
121
119
  end
122
120
 
123
121
  def inquire(authorization, options = {})
@@ -192,14 +190,13 @@ module ActiveMerchant #:nodoc:
192
190
 
193
191
  def add_card_or_token(post, payment, options)
194
192
  payment = payment.split('|')[0] if payment.is_a?(String)
195
- post[:payment][:payment_type_code] = 'creditcard'
193
+ add_payment_type(post[:payment])
196
194
  post[:payment][:creditcard] = payment_details(payment)
197
195
  post[:payment][:creditcard][:soft_descriptor] = options[:soft_descriptor] if options[:soft_descriptor]
198
196
  end
199
197
 
200
- def add_payment_details(post, payment)
198
+ def add_payment_type(post)
201
199
  post[:payment_type_code] = 'creditcard'
202
- post[:creditcard] = payment_details(payment)
203
200
  end
204
201
 
205
202
  def payment_details(payment)
@@ -237,7 +234,7 @@ module ActiveMerchant #:nodoc:
237
234
 
238
235
  Response.new(
239
236
  success,
240
- message_from(response),
237
+ message_from(action, response),
241
238
  response,
242
239
  authorization: authorization_from(action, parameters, response),
243
240
  test: test?,
@@ -259,25 +256,32 @@ module ActiveMerchant #:nodoc:
259
256
  end
260
257
 
261
258
  def success_from(action, response)
262
- payment_status = response.try(:[], 'payment').try(:[], 'status')
263
-
264
- if %i[purchase capture refund].include?(action)
265
- payment_status == 'CO'
266
- elsif action == :authorize
267
- payment_status == 'PE'
268
- elsif action == :void
269
- payment_status == 'CA'
270
- elsif %i[store inquire].include?(action)
271
- response.try(:[], 'status') == 'SUCCESS'
259
+ status = response.dig('payment', 'status')
260
+
261
+ case action
262
+ when :purchase, :capture, :refund
263
+ status == 'CO'
264
+ when :authorize
265
+ status == 'PE'
266
+ when :void
267
+ status == 'CA'
268
+ when :verify
269
+ response.dig('card_verification', 'transaction_status', 'code') == 'OK'
270
+ when :store, :inquire
271
+ response.dig('status') == 'SUCCESS'
272
272
  else
273
273
  false
274
274
  end
275
275
  end
276
276
 
277
- def message_from(response)
277
+ def message_from(action, response)
278
278
  return response['status_message'] if response['status'] == 'ERROR'
279
279
 
280
- response.try(:[], 'payment').try(:[], 'transaction_status').try(:[], 'description')
280
+ if action == :verify
281
+ response.dig('card_verification', 'transaction_status', 'description')
282
+ else
283
+ response.dig('payment', 'transaction_status', 'description')
284
+ end
281
285
  end
282
286
 
283
287
  def authorization_from(action, parameters, response)
@@ -327,9 +331,9 @@ module ActiveMerchant #:nodoc:
327
331
  end
328
332
  end
329
333
 
330
- def customer_country(options)
334
+ def customer_country(post, options)
331
335
  if country = options[:country] || (options[:billing_address][:country] if options[:billing_address])
332
- country.downcase
336
+ post[:country] = country.downcase
333
337
  end
334
338
  end
335
339
 
@@ -145,11 +145,15 @@ module ActiveMerchant #:nodoc:
145
145
  def commit(action, parameters)
146
146
  response = parse(ssl_post(test? ? self.test_url : self.live_url, post_data(action, parameters), 'Content-Type' => 'text/xml'))
147
147
 
148
- Response.new(success?(response), message_from(response[:result_message]), response,
148
+ Response.new(
149
+ success?(response),
150
+ message_from(response[:result_message]),
151
+ response,
149
152
  test: test?,
150
153
  authorization: authorization_from(response, parameters),
151
154
  avs_result: { code: response[:avs_response_code] },
152
- cvv_result: response[:cvv_response_code])
155
+ cvv_result: response[:cvv_response_code]
156
+ )
153
157
  end
154
158
 
155
159
  def success?(response)