activemerchant 1.133.0 → 1.137.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 (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,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)