aktivemerchant 2.0.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 (193) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1596 -0
  3. data/CONTRIBUTORS +511 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +18 -0
  6. data/lib/active_merchant.rb +108 -0
  7. data/lib/active_merchant/billing.rb +13 -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 +352 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +160 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +268 -0
  18. data/lib/active_merchant/billing/gateways.rb +17 -0
  19. data/lib/active_merchant/billing/gateways/adyen.rb +209 -0
  20. data/lib/active_merchant/billing/gateways/alfabank.rb +117 -0
  21. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net.rb +419 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  24. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -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 +188 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +393 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -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 +210 -0
  37. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  38. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  39. data/lib/active_merchant/billing/gateways/braintree_blue.rb +515 -0
  40. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  41. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  42. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  43. data/lib/active_merchant/billing/gateways/card_stream.rb +220 -0
  44. data/lib/active_merchant/billing/gateways/cashnet.rb +191 -0
  45. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  46. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  47. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  48. data/lib/active_merchant/billing/gateways/checkout.rb +213 -0
  49. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  50. data/lib/active_merchant/billing/gateways/conekta.rb +209 -0
  51. data/lib/active_merchant/billing/gateways/cyber_source.rb +709 -0
  52. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  53. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  54. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  55. data/lib/active_merchant/billing/gateways/epay.rb +275 -0
  56. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  57. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  58. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  59. data/lib/active_merchant/billing/gateways/eway_rapid.rb +524 -0
  60. data/lib/active_merchant/billing/gateways/exact.rb +218 -0
  61. data/lib/active_merchant/billing/gateways/fat_zebra.rb +173 -0
  62. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  63. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  64. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  65. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  66. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +355 -0
  67. data/lib/active_merchant/billing/gateways/garanti.rb +257 -0
  68. data/lib/active_merchant/billing/gateways/global_transport.rb +183 -0
  69. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  70. data/lib/active_merchant/billing/gateways/hps.rb +288 -0
  71. data/lib/active_merchant/billing/gateways/iats_payments.rb +251 -0
  72. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  73. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  74. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  75. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  76. data/lib/active_merchant/billing/gateways/inspire.rb +213 -0
  77. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  78. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  79. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  80. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  81. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  82. data/lib/active_merchant/billing/gateways/litle.rb +346 -0
  83. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  84. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  85. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  86. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  87. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  88. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  89. data/lib/active_merchant/billing/gateways/mercury.rb +333 -0
  90. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  91. data/lib/active_merchant/billing/gateways/migs.rb +265 -0
  92. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  93. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  94. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  95. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  96. data/lib/active_merchant/billing/gateways/moneris_us.rb +291 -0
  97. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  98. data/lib/active_merchant/billing/gateways/nab_transact.rb +280 -0
  99. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  100. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  101. data/lib/active_merchant/billing/gateways/netbilling.rb +190 -0
  102. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  103. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  104. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  105. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  106. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  107. data/lib/active_merchant/billing/gateways/optimal_payment.rb +313 -0
  108. data/lib/active_merchant/billing/gateways/orbital.rb +803 -0
  109. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  110. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  111. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  112. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +261 -0
  113. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  114. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  115. data/lib/active_merchant/billing/gateways/pay_u_latam.rb +462 -0
  116. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  117. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  118. data/lib/active_merchant/billing/gateways/payflow.rb +304 -0
  119. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +209 -0
  120. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  121. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  122. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  123. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  124. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  125. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  126. data/lib/active_merchant/billing/gateways/paymill.rb +281 -0
  127. data/lib/active_merchant/billing/gateways/paypal.rb +117 -0
  128. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +670 -0
  129. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  130. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  131. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  132. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  133. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  134. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  135. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  136. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  137. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  138. data/lib/active_merchant/billing/gateways/pin.rb +197 -0
  139. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  140. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  141. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  142. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  143. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  144. data/lib/active_merchant/billing/gateways/quickpay.rb +367 -0
  145. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  146. data/lib/active_merchant/billing/gateways/redsys.rb +391 -0
  147. data/lib/active_merchant/billing/gateways/sage.rb +175 -0
  148. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +87 -0
  149. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +114 -0
  150. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  151. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +102 -0
  152. data/lib/active_merchant/billing/gateways/sage_pay.rb +398 -0
  153. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  154. data/lib/active_merchant/billing/gateways/secure_net.rb +252 -0
  155. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  156. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  157. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  158. data/lib/active_merchant/billing/gateways/skip_jack.rb +452 -0
  159. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  160. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  161. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  162. data/lib/active_merchant/billing/gateways/stripe.rb +411 -0
  163. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  164. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  165. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  166. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  167. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  168. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  169. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  170. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  171. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +254 -0
  172. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  173. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  174. data/lib/active_merchant/billing/gateways/vindicia.rb +385 -0
  175. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  176. data/lib/active_merchant/billing/gateways/wepay.rb +189 -0
  177. data/lib/active_merchant/billing/gateways/wirecard.rb +421 -0
  178. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  179. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  180. data/lib/active_merchant/billing/model.rb +30 -0
  181. data/lib/active_merchant/billing/payment_token.rb +21 -0
  182. data/lib/active_merchant/billing/rails.rb +3 -0
  183. data/lib/active_merchant/billing/response.rb +91 -0
  184. data/lib/active_merchant/country.rb +332 -0
  185. data/lib/active_merchant/empty.rb +20 -0
  186. data/lib/active_merchant/errors.rb +29 -0
  187. data/lib/active_merchant/offsite_payments_shim.rb +19 -0
  188. data/lib/active_merchant/version.rb +3 -0
  189. data/lib/activemerchant.rb +1 -0
  190. data/lib/support/gateway_support.rb +71 -0
  191. data/lib/support/outbound_hosts.rb +25 -0
  192. data/lib/support/ssl_verify.rb +93 -0
  193. metadata +400 -0
@@ -0,0 +1,38 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ # Result of the Card Verification Value check
4
+ # http://www.bbbonline.org/eExport/doc/MerchantGuide_cvv2.pdf
5
+ # Check additional codes from cybersource website
6
+ class CVVResult
7
+
8
+ MESSAGES = {
9
+ 'D' => 'CVV check flagged transaction as suspicious',
10
+ 'I' => 'CVV failed data validation check',
11
+ 'M' => 'CVV matches',
12
+ 'N' => 'CVV does not match',
13
+ 'P' => 'CVV not processed',
14
+ 'S' => 'CVV should have been present',
15
+ 'U' => 'CVV request unable to be processed by issuer',
16
+ 'X' => 'CVV check not supported for card'
17
+ }
18
+
19
+ def self.messages
20
+ MESSAGES
21
+ end
22
+
23
+ attr_reader :code, :message
24
+
25
+ def initialize(code)
26
+ @code = (code.blank? ? nil : code.upcase)
27
+ @message = MESSAGES[@code]
28
+ end
29
+
30
+ def to_hash
31
+ {
32
+ 'code' => code,
33
+ 'message' => message
34
+ }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,268 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'active_merchant/billing/response'
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ #
8
+ # == Description
9
+ # The Gateway class is the base class for all ActiveMerchant gateway implementations.
10
+ #
11
+ # The standard list of gateway functions that most concrete gateway subclasses implement is:
12
+ #
13
+ # * <tt>purchase(money, credit_card, options = {})</tt>
14
+ # * <tt>authorize(money, credit_card, options = {})</tt>
15
+ # * <tt>capture(money, authorization, options = {})</tt>
16
+ # * <tt>void(identification, options = {})</tt>
17
+ # * <tt>refund(money, identification, options = {})</tt>
18
+ # * <tt>verify(credit_card, options = {})</tt>
19
+ #
20
+ # Some gateways also support features for storing credit cards:
21
+ #
22
+ # * <tt>store(credit_card, options = {})</tt>
23
+ # * <tt>unstore(identification, options = {})</tt>
24
+ #
25
+ # === Gateway Options
26
+ # The options hash consists of the following options:
27
+ #
28
+ # * <tt>:order_id</tt> - The order number
29
+ # * <tt>:ip</tt> - The IP address of the customer making the purchase
30
+ # * <tt>:customer</tt> - The name, customer number, or other information that identifies the customer
31
+ # * <tt>:invoice</tt> - The invoice number
32
+ # * <tt>:merchant</tt> - The name or description of the merchant offering the product
33
+ # * <tt>:description</tt> - A description of the transaction
34
+ # * <tt>:email</tt> - The email address of the customer
35
+ # * <tt>:currency</tt> - The currency of the transaction. Only important when you are using a currency that is not the default with a gateway that supports multiple currencies.
36
+ # * <tt>:billing_address</tt> - A hash containing the billing address of the customer.
37
+ # * <tt>:shipping_address</tt> - A hash containing the shipping address of the customer.
38
+ #
39
+ # The <tt>:billing_address</tt>, and <tt>:shipping_address</tt> hashes can have the following keys:
40
+ #
41
+ # * <tt>:name</tt> - The full name of the customer.
42
+ # * <tt>:company</tt> - The company name of the customer.
43
+ # * <tt>:address1</tt> - The primary street address of the customer.
44
+ # * <tt>:address2</tt> - Additional line of address information.
45
+ # * <tt>:city</tt> - The city of the customer.
46
+ # * <tt>:state</tt> - The state of the customer. The 2 digit code for US and Canadian addresses. The full name of the state or province for foreign addresses.
47
+ # * <tt>:country</tt> - The [ISO 3166-1-alpha-2 code](http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm) for the customer.
48
+ # * <tt>:zip</tt> - The zip or postal code of the customer.
49
+ # * <tt>:phone</tt> - The phone number of the customer.
50
+ #
51
+ # == Implmenting new gateways
52
+ #
53
+ # See the {ActiveMerchant Guide to Contributing}[https://github.com/Shopify/active_merchant/wiki/Contributing]
54
+ #
55
+ class Gateway
56
+ include PostsData
57
+ include CreditCardFormatting
58
+
59
+ DEBIT_CARDS = [ :switch, :solo ]
60
+ CURRENCIES_WITHOUT_FRACTIONS = [ 'BIF', 'BYR', 'CLP', 'CVE', 'DJF', 'GNF', 'HUF', 'ISK', 'JPY', 'KMF', 'KRW', 'PYG', 'RWF', 'TWD', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF' ]
61
+
62
+ CREDIT_DEPRECATION_MESSAGE = "Support for using credit to refund existing transactions is deprecated and will be removed from a future release of ActiveMerchant. Please use the refund method instead."
63
+ RECURRING_DEPRECATION_MESSAGE = "Recurring functionality in ActiveMerchant is deprecated and will be removed in a future version. Please contact the ActiveMerchant maintainers if you have an interest in taking ownership of a separate gem that continues support for it."
64
+
65
+ # == Standardized Error Codes
66
+ #
67
+ # :incorrect_number - Card number does not comply with ISO/IEC 7812 numbering standard
68
+ # :invalid_number - Card number was not matched by processor
69
+ # :invalid_expiry_date - Expiry date deos not match correct formatting
70
+ # :invalid_cvc - Security codes does not match correct format (3-4 digits)
71
+ # :expired_card - Card number is expired
72
+ # :incorrect_cvc - Secerity code was not matched by the processor
73
+ # :incorrect_zip - Zip code is not in correct format
74
+ # :incorrect_address - Billing address info was not matched by the processor
75
+ # :card_declined - Card number declined by processor
76
+ # :processing_error - Processor error
77
+ # :call_issuer - Transaction requires voice authentication, call issuer
78
+ # :pickup_card - Issuer requests that you pickup the card from merchant
79
+
80
+ STANDARD_ERROR_CODE = {
81
+ :incorrect_number => 'incorrect_number',
82
+ :invalid_number => 'invalid_number',
83
+ :invalid_expiry_date => 'invalid_expiry_date',
84
+ :invalid_cvc => 'invalid_cvc',
85
+ :expired_card => 'expired_card',
86
+ :incorrect_cvc => 'incorrect_cvc',
87
+ :incorrect_zip => 'incorrect_zip',
88
+ :incorrect_address => 'incorrect_address',
89
+ :card_declined => 'card_declined',
90
+ :processing_error => 'processing_error',
91
+ :call_issuer => 'call_issuer',
92
+ :pickup_card => 'pick_up_card'
93
+ }
94
+
95
+ cattr_reader :implementations
96
+ @@implementations = []
97
+
98
+ def self.inherited(subclass)
99
+ super
100
+ @@implementations << subclass
101
+ end
102
+
103
+ def generate_unique_id
104
+ SecureRandom.hex(16)
105
+ end
106
+
107
+ # The format of the amounts used by the gateway
108
+ # :dollars => '12.50'
109
+ # :cents => '1250'
110
+ class_attribute :money_format
111
+ self.money_format = :dollars
112
+
113
+ # The default currency for the transactions if no currency is provided
114
+ class_attribute :default_currency
115
+
116
+ # The supported card types for the gateway
117
+ class_attribute :supported_cardtypes
118
+ self.supported_cardtypes = []
119
+
120
+ class_attribute :homepage_url
121
+ class_attribute :display_name
122
+
123
+ class_attribute :test_url, :live_url
124
+
125
+ class_attribute :abstract_class
126
+
127
+ self.abstract_class = false
128
+
129
+ # The application making the calls to the gateway
130
+ # Useful for things like the PayPal build notation (BN) id fields
131
+ superclass_delegating_accessor :application_id
132
+ self.application_id = 'ActiveMerchant'
133
+
134
+ attr_reader :options
135
+
136
+ # Use this method to check if your gateway of interest supports a credit card of some type
137
+ def self.supports?(card_type)
138
+ supported_cardtypes.include?(card_type.to_sym)
139
+ end
140
+
141
+ def self.card_brand(source)
142
+ result = source.respond_to?(:brand) ? source.brand : source.type
143
+ result.to_s.downcase
144
+ end
145
+
146
+ def self.non_fractional_currency?(currency)
147
+ CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s)
148
+ end
149
+
150
+ def self.supported_countries=(country_codes)
151
+ country_codes.each do |country_code|
152
+ unless ActiveMerchant::Country.find(country_code)
153
+ raise ActiveMerchant::InvalidCountryCodeError, "No country could be found for the country #{country_code}"
154
+ end
155
+ end
156
+ @supported_countries = country_codes.dup
157
+ end
158
+
159
+ def self.supported_countries
160
+ @supported_countries ||= []
161
+ end
162
+
163
+ def supported_countries
164
+ self.class.supported_countries
165
+ end
166
+
167
+ def card_brand(source)
168
+ self.class.card_brand(source)
169
+ end
170
+
171
+ # Initialize a new gateway.
172
+ #
173
+ # See the documentation for the gateway you will be using to make sure there are no other
174
+ # required options.
175
+ def initialize(options = {})
176
+ @options = options
177
+ end
178
+
179
+ # Are we running in test mode?
180
+ def test?
181
+ (@options.has_key?(:test) ? @options[:test] : Base.test?)
182
+ end
183
+
184
+ protected # :nodoc: all
185
+
186
+ def normalize(field)
187
+ case field
188
+ when "true" then true
189
+ when "false" then false
190
+ when "" then nil
191
+ when "null" then nil
192
+ else field
193
+ end
194
+ end
195
+
196
+ def user_agent
197
+ @@ua ||= JSON.dump({
198
+ :bindings_version => ActiveMerchant::VERSION,
199
+ :lang => 'ruby',
200
+ :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
201
+ :platform => RUBY_PLATFORM,
202
+ :publisher => 'active_merchant'
203
+ })
204
+ end
205
+
206
+ private # :nodoc: all
207
+
208
+ def name
209
+ self.class.name.scan(/\:\:(\w+)Gateway/).flatten.first
210
+ end
211
+
212
+ def amount(money)
213
+ return nil if money.nil?
214
+ cents = if money.respond_to?(:cents)
215
+ ActiveMerchant.deprecated "Support for Money objects is deprecated and will be removed from a future release of ActiveMerchant. Please use an Integer value in cents"
216
+ money.cents
217
+ else
218
+ money
219
+ end
220
+
221
+ if money.is_a?(String)
222
+ raise ArgumentError, 'money amount must be a positive Integer in cents.'
223
+ end
224
+
225
+ if self.money_format == :cents
226
+ cents.to_s
227
+ else
228
+ sprintf("%.2f", cents.to_f / 100)
229
+ end
230
+ end
231
+
232
+ def localized_amount(money, currency)
233
+ amount = amount(money)
234
+
235
+ return amount unless Gateway.non_fractional_currency?(currency)
236
+
237
+ if self.money_format == :cents
238
+ sprintf("%.0f", amount.to_f / 100)
239
+ else
240
+ amount.split('.').first
241
+ end
242
+ end
243
+
244
+
245
+ def currency(money)
246
+ money.respond_to?(:currency) ? money.currency : self.default_currency
247
+ end
248
+
249
+ def requires_start_date_or_issue_number?(credit_card)
250
+ return false if card_brand(credit_card).blank?
251
+ DEBIT_CARDS.include?(card_brand(credit_card).to_sym)
252
+ end
253
+
254
+ def requires!(hash, *params)
255
+ params.each do |param|
256
+ if param.is_a?(Array)
257
+ raise ArgumentError.new("Missing required parameter: #{param.first}") unless hash.has_key?(param.first)
258
+
259
+ valid_options = param[1..-1]
260
+ raise ArgumentError.new("Parameter: #{param.first} must be one of #{valid_options.to_sentence(:words_connector => 'or')}") unless valid_options.include?(hash[param.first])
261
+ else
262
+ raise ArgumentError.new("Missing required parameter: #{param}") unless hash.has_key?(param)
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ autoload :Gateway, 'active_merchant/billing/gateway'
4
+
5
+ Dir[File.dirname(__FILE__) + '/gateways/**/*.rb'].each do |f|
6
+ # Get camelized class name
7
+ filename = File.basename(f, '.rb')
8
+ # Add _gateway suffix
9
+ gateway_name = filename + '_gateway'
10
+ # Camelize the string to get the class name
11
+ gateway_class = gateway_name.camelize
12
+
13
+ # Register for autoloading
14
+ autoload gateway_class, f
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,209 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class AdyenGateway < Gateway
4
+ self.test_url = 'https://pal-test.adyen.com/pal/adapter/httppost'
5
+ self.live_url = 'https://pal-live.adyen.com/pal/adapter/httppost'
6
+
7
+ self.supported_countries = ['AR', 'AT', 'BE', 'BR', 'CA', 'CH', 'CL', 'CN', 'CO', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'HK', 'ID', 'IE', 'IL', 'IN', 'IT', 'JP', 'KR', 'LU', 'MX', 'MY', 'NL', 'NO', 'PA', 'PE', 'PH', 'PL', 'PT', 'RU', 'SE', 'SG', 'TH', 'TR', 'TW', 'US', 'VN', 'ZA']
8
+ self.default_currency = 'EUR'
9
+ self.money_format = :cents
10
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro]
11
+
12
+ self.homepage_url = 'https://www.adyen.com/'
13
+ self.display_name = 'Adyen'
14
+
15
+ def initialize(options = {})
16
+ requires!(options, :company, :merchant, :password)
17
+ super
18
+ end
19
+
20
+ def purchase(money, creditcard, options = {})
21
+ requires!(options, :order_id)
22
+
23
+ MultiResponse.run do |r|
24
+ r.process { authorize(money, creditcard, options) }
25
+ r.process { capture(money, r.authorization, options) }
26
+ end
27
+ end
28
+
29
+ def authorize(money, creditcard, options = {})
30
+ requires!(options, :order_id)
31
+
32
+ post = {}
33
+ post[:paymentRequest] = payment_request(money, options)
34
+ post[:paymentRequest][:amount] = amount_hash(money, options[:currency])
35
+ post[:paymentRequest][:card] = credit_card_hash(creditcard)
36
+
37
+ if address = (options[:billing_address] || options[:address])
38
+ post[:paymentRequest][:billingAddress] = address_hash(address)
39
+ end
40
+
41
+ if options[:shipping_address]
42
+ post[:paymentRequest][:deliveryAddress] = address_hash(options[:shipping_address])
43
+ end
44
+
45
+ commit('Payment.authorise', post)
46
+ end
47
+
48
+ def capture(money, authorization, options = {})
49
+ requires!(options, :order_id)
50
+
51
+ post = {}
52
+ post[:modificationRequest] = modification_request(authorization, options)
53
+ post[:modificationRequest][:modificationAmount] = amount_hash(money, options[:currency])
54
+
55
+ commit('Payment.capture', post)
56
+ end
57
+
58
+ def refund(money, authorization, options = {})
59
+ requires!(options, :order_id)
60
+
61
+ post = {}
62
+ post[:modificationRequest] = modification_request(authorization, options)
63
+ post[:modificationRequest][:modificationAmount] = amount_hash(money, options[:currency])
64
+
65
+ commit('Payment.refund', post)
66
+ end
67
+
68
+ def void(identification, options = {})
69
+ requires!(options, :order_id)
70
+
71
+ post = {}
72
+ post[:modificationRequest] = modification_request(identification, options)
73
+
74
+ commit('Payment.cancel', post)
75
+ end
76
+
77
+ def verify(creditcard, options = {})
78
+ authorize(0, creditcard, options)
79
+ end
80
+
81
+ private
82
+
83
+ def commit(action, post)
84
+ request = post_data(flatten_hash(post.merge(:action => action)))
85
+ raw_response = ssl_post(url, request, headers)
86
+ response = parse(raw_response)
87
+
88
+ Response.new(
89
+ success_from(response),
90
+ message_from(response),
91
+ response,
92
+ test: test?,
93
+ authorization: response['pspReference']
94
+ )
95
+
96
+ rescue ResponseError => e
97
+ case e.response.code
98
+ when '401'
99
+ return Response.new(false, 'Invalid credentials', {}, :test => test?)
100
+ when '500'
101
+ if e.response.body.split(' ')[0] == 'validation'
102
+ return Response.new(false, e.response.body.split(' ', 3)[2], {}, :test => test?)
103
+ end
104
+ end
105
+ raise
106
+ end
107
+
108
+ def flatten_hash(hash, prefix = nil)
109
+ flat_hash = {}
110
+ hash.each_pair do |key, val|
111
+ conc_key = prefix.nil? ? key : "#{prefix}.#{key}"
112
+ if val.is_a?(Hash)
113
+ flat_hash.merge!(flatten_hash(val, conc_key))
114
+ else
115
+ flat_hash[conc_key] = val
116
+ end
117
+ end
118
+ flat_hash
119
+ end
120
+
121
+ def headers
122
+ {
123
+ 'Authorization' => 'Basic ' + Base64.encode64("ws@Company.#{@options[:company]}:#{@options[:password]}").strip
124
+ }
125
+ end
126
+
127
+ def parse(response)
128
+ Hash[
129
+ response.split('&').map do |x|
130
+ key, val = x.split('=', 2)
131
+ [key.split('.').last, CGI.unescape(val)]
132
+ end
133
+ ]
134
+ end
135
+
136
+ def post_data(data)
137
+ data.map do |key, val|
138
+ "#{key}=#{CGI.escape(val.to_s)}"
139
+ end.reduce do |x, y|
140
+ "#{x}&#{y}"
141
+ end
142
+ end
143
+
144
+ def message_from(response)
145
+ return response['resultCode'] if response.has_key?('resultCode') # Payment request
146
+ return response['response'] if response['response'] # Modification request
147
+ "Failure" # Negative fallback in case of error
148
+ end
149
+
150
+ def success_from(response)
151
+ return true if response.has_key?('authCode')
152
+
153
+ successful_responses = %w([capture-received] [cancel-received] [refund-received])
154
+ successful_responses.include?(response['response'])
155
+ end
156
+
157
+ def url
158
+ test? ? self.test_url : self.live_url
159
+ end
160
+
161
+ def address_hash(address)
162
+ full_address = "#{address[:address1]} #{address[:address2]}"
163
+
164
+ {
165
+ :city => address[:city],
166
+ :street => full_address.split(/\s+/).keep_if { |x| x !~ /\d/ }.join(' '),
167
+ :houseNumberOrName => full_address.split(/\s+/).keep_if { |x| x =~ /\d/ }.join(' '),
168
+ :postalCode => address[:zip],
169
+ :stateOrProvince => address[:state],
170
+ :country => address[:country]
171
+ }
172
+ end
173
+
174
+ def amount_hash(money, currency)
175
+ {
176
+ :currency => (currency || currency(money)),
177
+ :value => amount(money)
178
+ }
179
+ end
180
+
181
+ def credit_card_hash(creditcard)
182
+ {
183
+ :cvc => creditcard.verification_value,
184
+ :expiryMonth => format(creditcard.month, :two_digits),
185
+ :expiryYear => format(creditcard.year, :four_digits),
186
+ :holderName => creditcard.name,
187
+ :number => creditcard.number
188
+ }
189
+ end
190
+
191
+ def modification_request(reference, options)
192
+ {
193
+ :merchantAccount => @options[:merchant],
194
+ :originalReference => reference
195
+ }.keep_if { |_, v| v }
196
+ end
197
+
198
+ def payment_request(money, options)
199
+ {
200
+ :merchantAccount => @options[:merchant],
201
+ :reference => options[:order_id],
202
+ :shopperEmail => options[:email],
203
+ :shopperIP => options[:ip],
204
+ :shopperReference => options[:customer]
205
+ }.keep_if { |_, v| v }
206
+ end
207
+ end
208
+ end
209
+ end