start_activemerchant 1.50.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (218) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1769 -0
  3. data/CONTRIBUTORS +540 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +226 -0
  6. data/lib/active_merchant.rb +67 -0
  7. data/lib/active_merchant/billing.rb +15 -0
  8. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  9. data/lib/active_merchant/billing/avs_result.rb +98 -0
  10. data/lib/active_merchant/billing/base.rb +72 -0
  11. data/lib/active_merchant/billing/check.rb +76 -0
  12. data/lib/active_merchant/billing/compatibility.rb +120 -0
  13. data/lib/active_merchant/billing/credit_card.rb +404 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +195 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +291 -0
  18. data/lib/active_merchant/billing/gateways.rb +14 -0
  19. data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
  20. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  21. data/lib/active_merchant/billing/gateways/authorize_net.rb +510 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
  24. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
  25. data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
  26. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  27. data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
  28. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -0
  29. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
  30. data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
  31. data/lib/active_merchant/billing/gateways/beanstream.rb +192 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +389 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +58 -0
  34. data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
  35. data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
  36. data/lib/active_merchant/billing/gateways/borgun.rb +211 -0
  37. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  39. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  40. data/lib/active_merchant/billing/gateways/braintree_blue.rb +574 -0
  41. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  42. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  43. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +238 -0
  45. data/lib/active_merchant/billing/gateways/cashnet.rb +202 -0
  46. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  47. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  48. data/lib/active_merchant/billing/gateways/cenpos.rb +262 -0
  49. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  50. data/lib/active_merchant/billing/gateways/checkout.rb +216 -0
  51. data/lib/active_merchant/billing/gateways/checkout_v2.rb +200 -0
  52. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  53. data/lib/active_merchant/billing/gateways/conekta.rb +210 -0
  54. data/lib/active_merchant/billing/gateways/cyber_source.rb +720 -0
  55. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  56. data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
  57. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  58. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  59. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  60. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  61. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  62. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  63. data/lib/active_merchant/billing/gateways/eway_rapid.rb +522 -0
  64. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  65. data/lib/active_merchant/billing/gateways/ezic.rb +206 -0
  66. data/lib/active_merchant/billing/gateways/fat_zebra.rb +213 -0
  67. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  68. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  69. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  70. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  71. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +413 -0
  72. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  73. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  74. data/lib/active_merchant/billing/gateways/garanti.rb +261 -0
  75. data/lib/active_merchant/billing/gateways/global_transport.rb +179 -0
  76. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  77. data/lib/active_merchant/billing/gateways/hps.rb +287 -0
  78. data/lib/active_merchant/billing/gateways/iats_payments.rb +277 -0
  79. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  80. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  81. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  82. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  83. data/lib/active_merchant/billing/gateways/inspire.rb +219 -0
  84. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  85. data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
  86. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  87. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  88. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  89. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  90. data/lib/active_merchant/billing/gateways/litle.rb +345 -0
  91. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  92. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  93. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  94. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  95. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  96. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  97. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  98. data/lib/active_merchant/billing/gateways/mercury.rb +326 -0
  99. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  100. data/lib/active_merchant/billing/gateways/migs.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  102. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  103. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  104. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  105. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  106. data/lib/active_merchant/billing/gateways/moneris_us.rb +298 -0
  107. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  108. data/lib/active_merchant/billing/gateways/nab_transact.rb +290 -0
  109. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  110. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  111. data/lib/active_merchant/billing/gateways/netbilling.rb +224 -0
  112. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  113. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  114. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  115. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  116. data/lib/active_merchant/billing/gateways/omise.rb +319 -0
  117. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  118. data/lib/active_merchant/billing/gateways/optimal_payment.rb +314 -0
  119. data/lib/active_merchant/billing/gateways/orbital.rb +834 -0
  120. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  121. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  122. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  123. data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
  124. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
  125. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  126. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  127. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  128. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  129. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  130. data/lib/active_merchant/billing/gateways/payflow.rb +308 -0
  131. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +220 -0
  132. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  133. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  134. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  135. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  136. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  137. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  138. data/lib/active_merchant/billing/gateways/paymill.rb +282 -0
  139. data/lib/active_merchant/billing/gateways/paypal.rb +129 -0
  140. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +679 -0
  141. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  142. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  143. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  144. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  145. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  146. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  147. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  148. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  149. data/lib/active_merchant/billing/gateways/payu_in.rb +247 -0
  150. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  151. data/lib/active_merchant/billing/gateways/pin.rb +207 -0
  152. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  153. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  154. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  155. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  156. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  157. data/lib/active_merchant/billing/gateways/quickbooks.rb +280 -0
  158. data/lib/active_merchant/billing/gateways/quickpay.rb +26 -0
  159. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
  160. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
  161. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
  162. data/lib/active_merchant/billing/gateways/qvalent.rb +179 -0
  163. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  164. data/lib/active_merchant/billing/gateways/redsys.rb +406 -0
  165. data/lib/active_merchant/billing/gateways/s5.rb +226 -0
  166. data/lib/active_merchant/billing/gateways/sage.rb +173 -0
  167. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +89 -0
  168. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +115 -0
  169. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  170. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  171. data/lib/active_merchant/billing/gateways/sage_pay.rb +399 -0
  172. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  173. data/lib/active_merchant/billing/gateways/secure_net.rb +263 -0
  174. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  175. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  176. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  177. data/lib/active_merchant/billing/gateways/skip_jack.rb +451 -0
  178. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  179. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  180. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  181. data/lib/active_merchant/billing/gateways/stripe.rb +489 -0
  182. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  183. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  184. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  185. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  186. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  187. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  188. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  189. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  190. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +259 -0
  191. data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
  192. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  193. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  194. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  195. data/lib/active_merchant/billing/gateways/wepay.rb +205 -0
  196. data/lib/active_merchant/billing/gateways/wirecard.rb +420 -0
  197. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  198. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +204 -0
  199. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  200. data/lib/active_merchant/billing/model.rb +30 -0
  201. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +24 -0
  202. data/lib/active_merchant/billing/payment_token.rb +21 -0
  203. data/lib/active_merchant/billing/rails.rb +3 -0
  204. data/lib/active_merchant/billing/response.rb +92 -0
  205. data/lib/active_merchant/connection.rb +172 -0
  206. data/lib/active_merchant/country.rb +332 -0
  207. data/lib/active_merchant/empty.rb +20 -0
  208. data/lib/active_merchant/errors.rb +35 -0
  209. data/lib/active_merchant/network_connection_retries.rb +79 -0
  210. data/lib/active_merchant/post_data.rb +24 -0
  211. data/lib/active_merchant/posts_data.rb +84 -0
  212. data/lib/active_merchant/version.rb +3 -0
  213. data/lib/activemerchant.rb +1 -0
  214. data/lib/certs/cacert.pem +3866 -0
  215. data/lib/support/gateway_support.rb +71 -0
  216. data/lib/support/outbound_hosts.rb +28 -0
  217. data/lib/support/ssl_verify.rb +93 -0
  218. metadata +387 -0
@@ -0,0 +1,72 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Base
4
+ # Set ActiveMerchant gateways in test mode.
5
+ #
6
+ # ActiveMerchant::Billing::Base.gateway_mode = :test
7
+ mattr_accessor :gateway_mode
8
+
9
+ # Set ActiveMerchant integrations in test mode.
10
+ #
11
+ # ActiveMerchant::Billing::Base.integration_mode = :test
12
+ def self.integration_mode=(mode)
13
+ ActiveMerchant.deprecated(OFFSITE_PAYMENT_EXTRACTION_MESSAGE)
14
+ @@integration_mode = mode
15
+ end
16
+
17
+ def self.integration_mode
18
+ ActiveMerchant.deprecated(OFFSITE_PAYMENT_EXTRACTION_MESSAGE)
19
+ @@integration_mode
20
+ end
21
+
22
+ # Set both the mode of both the gateways and integrations
23
+ # at once
24
+ mattr_reader :mode
25
+
26
+ def self.mode=(mode)
27
+ @@mode = mode
28
+ self.gateway_mode = mode
29
+ @@integration_mode = mode
30
+ end
31
+
32
+ self.mode = :production
33
+
34
+ # Return the matching gateway for the provider
35
+ # * <tt>bogus</tt>: BogusGateway - Does nothing (for testing)
36
+ # * <tt>moneris</tt>: MonerisGateway
37
+ # * <tt>authorize_net</tt>: AuthorizeNetGateway
38
+ # * <tt>trust_commerce</tt>: TrustCommerceGateway
39
+ #
40
+ # ActiveMerchant::Billing::Base.gateway('moneris').new
41
+ def self.gateway(name)
42
+ name_str = name.to_s.strip.downcase
43
+
44
+ raise(ArgumentError, 'A gateway provider must be specified') if name_str.blank?
45
+
46
+ begin
47
+ Billing.const_get("#{name_str}_gateway".camelize)
48
+ rescue
49
+ raise ArgumentError, "The specified gateway is not valid (#{name_str})"
50
+ end
51
+ end
52
+
53
+ # Return the matching integration module
54
+ # You can then get the notification from the module
55
+ # * <tt>bogus</tt>: Bogus - Does nothing (for testing)
56
+ # * <tt>chronopay</tt>: Chronopay
57
+ # * <tt>paypal</tt>: Paypal
58
+ #
59
+ # chronopay = ActiveMerchant::Billing::Base.integration('chronopay')
60
+ # notification = chronopay.notification(raw_post)
61
+ #
62
+ def self.integration(name)
63
+ Billing::Integrations.const_get("#{name.to_s.downcase}".camelize)
64
+ end
65
+
66
+ # A check to see if we're in test mode
67
+ def self.test?
68
+ self.gateway_mode == :test
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,76 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ # The Check object is a plain old Ruby object, similar to CreditCard. It supports validation
4
+ # of necessary attributes such as checkholder's name, routing and account numbers, but it is
5
+ # not backed by any database.
6
+ #
7
+ # You may use Check in place of CreditCard with any gateway that supports it.
8
+ class Check < Model
9
+ attr_accessor :first_name, :last_name,
10
+ :bank_name, :routing_number, :account_number,
11
+ :account_holder_type, :account_type, :number
12
+
13
+ # Used for Canadian bank accounts
14
+ attr_accessor :institution_number, :transit_number
15
+
16
+ def name
17
+ @name ||= "#{first_name} #{last_name}".strip
18
+ end
19
+
20
+ def name=(value)
21
+ return if empty?(value)
22
+
23
+ @name = value
24
+ segments = value.split(' ')
25
+ @last_name = segments.pop
26
+ @first_name = segments.join(' ')
27
+ end
28
+
29
+ def validate
30
+ errors = []
31
+
32
+ [:name, :routing_number, :account_number].each do |attr|
33
+ errors << [attr, "cannot be empty"] if empty?(self.send(attr))
34
+ end
35
+
36
+ errors << [:routing_number, "is invalid"] unless valid_routing_number?
37
+
38
+ if(!empty?(account_holder_type) && !%w[business personal].include?(account_holder_type.to_s))
39
+ errors << [:account_holder_type, "must be personal or business"]
40
+ end
41
+
42
+ if(!empty?(account_type) && !%w[checking savings].include?(account_type.to_s))
43
+ errors << [:account_type, "must be checking or savings"]
44
+ end
45
+
46
+ errors_hash(errors)
47
+ end
48
+
49
+ def type
50
+ 'check'
51
+ end
52
+
53
+ # Routing numbers may be validated by calculating a checksum and dividing it by 10. The
54
+ # formula is:
55
+ # (3(d1 + d4 + d7) + 7(d2 + d5 + d8) + 1(d3 + d6 + d9))mod 10 = 0
56
+ # See http://en.wikipedia.org/wiki/Routing_transit_number#Internal_checksums
57
+ def valid_routing_number?
58
+ digits = routing_number.to_s.split('').map(&:to_i).select{|d| (0..9).include?(d)}
59
+ case digits.size
60
+ when 9
61
+ checksum = ((3 * (digits[0] + digits[3] + digits[6])) +
62
+ (7 * (digits[1] + digits[4] + digits[7])) +
63
+ (digits[2] + digits[5] + digits[8])) % 10
64
+ case checksum
65
+ when 0
66
+ true
67
+ else
68
+ false
69
+ end
70
+ else
71
+ false
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,120 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ module Compatibility
4
+ module Model
5
+ def valid?
6
+ Compatibility.deprecated
7
+ super
8
+ end
9
+
10
+ def errors
11
+ Compatibility.deprecated
12
+ internal_errors
13
+ end
14
+ end
15
+
16
+ @rails_required = false
17
+ def self.rails_required!
18
+ @rails_required = true
19
+ end
20
+
21
+ def self.deprecated
22
+ ActiveMerchant.deprecated(
23
+ %(Implicit inclusion of Rails-specific functionality is deprecated.) +
24
+ %( Explicitly require "active_merchant/billing/rails" if you need it.)
25
+ ) unless @rails_required
26
+ end
27
+
28
+ def self.humanize(lower_case_and_underscored_word)
29
+ result = lower_case_and_underscored_word.to_s.dup
30
+ result.gsub!(/_id$/, "")
31
+ result.gsub!(/_/, ' ')
32
+ result.gsub(/([a-z\d]*)/i) { |match|
33
+ match.downcase
34
+ }.gsub(/^\w/) { $&.upcase }
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ # This lives in compatibility until we remove the deprecation for implicitly
41
+ # requiring Rails
42
+ module ActiveMerchant
43
+ module Billing
44
+ module Rails
45
+ module Model
46
+ def valid?
47
+ internal_errors.clear
48
+
49
+ validate.each do |attribute, errors|
50
+ errors.each do |error|
51
+ internal_errors.add(attribute, error)
52
+ end
53
+ end
54
+
55
+ internal_errors.empty?
56
+ end
57
+
58
+ private
59
+
60
+ def internal_errors
61
+ @errors ||= Errors.new
62
+ end
63
+
64
+ class Errors < Hash
65
+ def initialize
66
+ super(){|h, k| h[k] = []}
67
+ end
68
+
69
+ alias count size
70
+
71
+ def [](key)
72
+ super(key.to_s)
73
+ end
74
+
75
+ def []=(key, value)
76
+ super(key.to_s, value)
77
+ end
78
+
79
+ def empty?
80
+ all?{|k, v| v && v.empty?}
81
+ end
82
+
83
+ def on(field)
84
+ self[field].to_a.first
85
+ end
86
+
87
+ def add(field, error)
88
+ self[field] << error
89
+ end
90
+
91
+ def add_to_base(error)
92
+ add(:base, error)
93
+ end
94
+
95
+ def each_full
96
+ full_messages.each{|msg| yield msg}
97
+ end
98
+
99
+ def full_messages
100
+ result = []
101
+
102
+ self.each do |key, messages|
103
+ next unless(messages && !messages.empty?)
104
+ if key == 'base'
105
+ result << "#{messages.first}"
106
+ else
107
+ result << "#{Compatibility.humanize(key)} #{messages.first}"
108
+ end
109
+ end
110
+
111
+ result
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ Compatibility::Model.send(:include, Rails::Model)
118
+ end
119
+ end
120
+
@@ -0,0 +1,404 @@
1
+ require 'time'
2
+ require 'date'
3
+ require "active_merchant/billing/model"
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ # A +CreditCard+ object represents a physical credit card, and is capable of validating the various
8
+ # data associated with these.
9
+ #
10
+ # At the moment, the following credit card types are supported:
11
+ #
12
+ # * Visa
13
+ # * MasterCard
14
+ # * Discover
15
+ # * American Express
16
+ # * Diner's Club
17
+ # * JCB
18
+ # * Switch
19
+ # * Solo
20
+ # * Dankort
21
+ # * Maestro
22
+ # * Forbrugsforeningen
23
+ # * Laser
24
+ #
25
+ # For testing purposes, use the 'bogus' credit card brand. This skips the vast majority of
26
+ # validations, allowing you to focus on your core concerns until you're ready to be more concerned
27
+ # with the details of particular credit cards or your gateway.
28
+ #
29
+ # == Testing With CreditCard
30
+ # Often when testing we don't care about the particulars of a given card brand. When using the 'test'
31
+ # mode in your {Gateway}, there are six different valid card numbers: 1, 2, 3, 'success', 'fail',
32
+ # and 'error'.
33
+ #
34
+ # For details, see {CreditCardMethods::ClassMethods#valid_number?}
35
+ #
36
+ # == Example Usage
37
+ # cc = CreditCard.new(
38
+ # :first_name => 'Steve',
39
+ # :last_name => 'Smith',
40
+ # :month => '9',
41
+ # :year => '2017',
42
+ # :brand => 'visa',
43
+ # :number => '4242424242424242',
44
+ # :verification_value => '424'
45
+ # )
46
+ #
47
+ # cc.validate # => {}
48
+ # cc.display_number # => XXXX-XXXX-XXXX-4242
49
+ #
50
+ class CreditCard < Model
51
+ include CreditCardMethods
52
+
53
+ class << self
54
+ # Inherited, but can be overridden w/o changing parent's value
55
+ attr_accessor :require_verification_value
56
+ attr_accessor :require_name
57
+ end
58
+
59
+ self.require_name = true
60
+ self.require_verification_value = true
61
+
62
+ # Returns or sets the credit card number.
63
+ #
64
+ # @return [String]
65
+ attr_reader :number
66
+
67
+ def number=(value)
68
+ @number = (empty?(value) ? value : value.to_s.gsub(/[^\d]/, ""))
69
+ end
70
+
71
+ # Returns or sets the expiry month for the card.
72
+ #
73
+ # @return [Integer]
74
+ attr_reader :month
75
+
76
+ # Returns or sets the expiry year for the card.
77
+ #
78
+ # @return [Integer]
79
+ attr_reader :year
80
+
81
+ # Returns or sets the credit card brand.
82
+ #
83
+ # Valid card types are
84
+ #
85
+ # * +'visa'+
86
+ # * +'master'+
87
+ # * +'discover'+
88
+ # * +'american_express'+
89
+ # * +'diners_club'+
90
+ # * +'jcb'+
91
+ # * +'switch'+
92
+ # * +'solo'+
93
+ # * +'dankort'+
94
+ # * +'maestro'+
95
+ # * +'forbrugsforeningen'+
96
+ # * +'laser'+
97
+ #
98
+ # Or, if you wish to test your implementation, +'bogus'+.
99
+ #
100
+ # @return (String) the credit card brand
101
+ def brand
102
+ if !defined?(@brand) || empty?(@brand)
103
+ self.class.brand?(number)
104
+ else
105
+ @brand
106
+ end
107
+ end
108
+
109
+ def brand=(value)
110
+ value = value && value.to_s.dup
111
+ @brand = (value.respond_to?(:downcase) ? value.downcase : value)
112
+ end
113
+
114
+ # Returns or sets the first name of the card holder.
115
+ #
116
+ # @return [String]
117
+ attr_accessor :first_name
118
+
119
+ # Returns or sets the last name of the card holder.
120
+ #
121
+ # @return [String]
122
+ attr_accessor :last_name
123
+
124
+ # Required for Switch / Solo cards
125
+ attr_reader :start_month, :start_year
126
+ attr_accessor :issue_number
127
+
128
+ # Returns or sets the card verification value.
129
+ #
130
+ # This attribute is optional but recommended. The verification value is
131
+ # a {card security code}[http://en.wikipedia.org/wiki/Card_security_code]. If provided,
132
+ # the gateway will attempt to validate the value.
133
+ #
134
+ # @return [String] the verification value
135
+ attr_accessor :verification_value
136
+
137
+ # Returns or sets the track data for the card
138
+ #
139
+ # @return [String]
140
+ attr_accessor :track_data
141
+
142
+ # Returns or sets whether a card has been processed using manual entry.
143
+ #
144
+ # This attribute is optional and is only used by gateways who use this information in their transaction risk
145
+ # calculations. See {this page on 'card not present' transactions}[http://en.wikipedia.org/wiki/Card_not_present_transaction]
146
+ # for further explanation and examples of this kind of transaction.
147
+ #
148
+ # @return [true, false]
149
+ attr_accessor :manual_entry
150
+
151
+ # Returns or sets the ICC/ASN1 credit card data for a EMV transaction, typically this is a BER-encoded TLV string.
152
+ #
153
+ # @return [String]
154
+ attr_accessor :icc_data
155
+
156
+ # Returns or sets a fallback reason for a EMV transaction whereby the customer's card entered a fallback scenario.
157
+ # This can be an arbitrary string.
158
+ #
159
+ # @return [String]
160
+ attr_accessor :fallback_reason
161
+
162
+ # Returns or sets whether card-present card data has been read contactlessly.
163
+ #
164
+ # @return [true, false]
165
+ attr_accessor :contactless
166
+
167
+ # Returns the ciphertext of the card's encrypted PIN.
168
+ #
169
+ # @return [String]
170
+ attr_accessor :encrypted_pin_cryptogram
171
+
172
+ # Returns the Key Serial Number (KSN) of the card's encrypted PIN.
173
+ #
174
+ # @return [String]
175
+ attr_accessor :encrypted_pin_ksn
176
+
177
+ def type
178
+ ActiveMerchant.deprecated "CreditCard#type is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand instead."
179
+ brand
180
+ end
181
+
182
+ def type=(value)
183
+ ActiveMerchant.deprecated "CreditCard#type is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand instead."
184
+ self.brand = value
185
+ end
186
+
187
+ # Provides proxy access to an expiry date object
188
+ #
189
+ # @return [ExpiryDate]
190
+ def expiry_date
191
+ ExpiryDate.new(@month, @year)
192
+ end
193
+
194
+ # Returns whether the credit card has expired.
195
+ #
196
+ # @return +true+ if the card has expired, +false+ otherwise
197
+ def expired?
198
+ expiry_date.expired?
199
+ end
200
+
201
+ # Returns whether either the +first_name+ or the +last_name+ attributes has been set.
202
+ def name?
203
+ first_name? || last_name?
204
+ end
205
+
206
+ # Returns whether the +first_name+ attribute has been set.
207
+ def first_name?
208
+ first_name.present?
209
+ end
210
+
211
+ # Returns whether the +last_name+ attribute has been set.
212
+ def last_name?
213
+ last_name.present?
214
+ end
215
+
216
+ # Returns the full name of the card holder.
217
+ #
218
+ # @return [String] the full name of the card holder
219
+ def name
220
+ [first_name, last_name].compact.join(' ')
221
+ end
222
+
223
+ def name=(full_name)
224
+ names = full_name.split
225
+ self.last_name = names.pop
226
+ self.first_name = names.join(" ")
227
+ end
228
+
229
+ %w(month year start_month start_year).each do |m|
230
+ class_eval %(
231
+ def #{m}=(v)
232
+ @#{m} = case v
233
+ when "", nil, 0
234
+ nil
235
+ else
236
+ v.to_i
237
+ end
238
+ end
239
+ )
240
+ end
241
+
242
+ def verification_value?
243
+ !verification_value.blank?
244
+ end
245
+
246
+ # Returns a display-friendly version of the card number.
247
+ #
248
+ # All but the last 4 numbers are replaced with an "X", and hyphens are
249
+ # inserted in order to improve legibility.
250
+ #
251
+ # @example
252
+ # credit_card = CreditCard.new(:number => "2132542376824338")
253
+ # credit_card.display_number # "XXXX-XXXX-XXXX-4338"
254
+ #
255
+ # @return [String] a display-friendly version of the card number
256
+ def display_number
257
+ self.class.mask(number)
258
+ end
259
+
260
+ def first_digits
261
+ self.class.first_digits(number)
262
+ end
263
+
264
+ def last_digits
265
+ self.class.last_digits(number)
266
+ end
267
+
268
+ # Validates the credit card details.
269
+ #
270
+ # Any validation errors are added to the {#errors} attribute.
271
+ def validate
272
+ errors = validate_essential_attributes + validate_verification_value
273
+
274
+ # Bogus card is pretty much for testing purposes. Lets just skip these extra tests if its used
275
+ return errors_hash(errors) if brand == 'bogus'
276
+
277
+ errors_hash(
278
+ errors +
279
+ validate_card_brand_and_number +
280
+ validate_switch_or_solo_attributes
281
+ )
282
+ end
283
+
284
+ def self.requires_verification_value?
285
+ require_verification_value
286
+ end
287
+
288
+ def self.requires_name?
289
+ require_name
290
+ end
291
+
292
+ def emv?
293
+ icc_data.present?
294
+ end
295
+
296
+ private
297
+
298
+ def validate_essential_attributes #:nodoc:
299
+ errors = []
300
+
301
+ if self.class.requires_name?
302
+ errors << [:first_name, "cannot be empty"] if first_name.blank?
303
+ errors << [:last_name, "cannot be empty"] if last_name.blank?
304
+ end
305
+
306
+ if(empty?(month) || empty?(year))
307
+ errors << [:month, "is required"] if empty?(month)
308
+ errors << [:year, "is required"] if empty?(year)
309
+ else
310
+ errors << [:month, "is not a valid month"] if !valid_month?(month)
311
+
312
+ if expired?
313
+ errors << [:year, "expired"]
314
+ else
315
+ errors << [:year, "is not a valid year"] if !valid_expiry_year?(year)
316
+ end
317
+ end
318
+
319
+ errors
320
+ end
321
+
322
+ def validate_card_brand_and_number #:nodoc:
323
+ errors = []
324
+
325
+ if !empty?(brand)
326
+ errors << [:brand, "is invalid"] if !CreditCard.card_companies.keys.include?(brand)
327
+ end
328
+
329
+ if empty?(number)
330
+ errors << [:number, "is required"]
331
+ elsif !CreditCard.valid_number?(number)
332
+ errors << [:number, "is not a valid credit card number"]
333
+ end
334
+
335
+ if errors.empty?
336
+ errors << [:brand, "does not match the card number"] if !CreditCard.matching_brand?(number, brand)
337
+ end
338
+
339
+ errors
340
+ end
341
+
342
+ def validate_verification_value #:nodoc:
343
+ errors = []
344
+
345
+ if verification_value?
346
+ unless valid_card_verification_value?(verification_value, brand)
347
+ errors << [:verification_value, "should be #{card_verification_value_length(brand)} digits"]
348
+ end
349
+ elsif self.class.requires_verification_value?
350
+ errors << [:verification_value, "is required"]
351
+ end
352
+ errors
353
+ end
354
+
355
+ def validate_switch_or_solo_attributes #:nodoc:
356
+ errors = []
357
+
358
+ if %w[switch solo].include?(brand)
359
+ valid_start_month = valid_month?(start_month)
360
+ valid_start_year = valid_start_year?(start_year)
361
+
362
+ if((!valid_start_month || !valid_start_year) && !valid_issue_number?(issue_number))
363
+ if empty?(issue_number)
364
+ errors << [:issue_number, "cannot be empty"]
365
+ errors << [:start_month, "is invalid"] if !valid_start_month
366
+ errors << [:start_year, "is invalid"] if !valid_start_year
367
+ else
368
+ errors << [:issue_number, "is invalid"] if !valid_issue_number?(issue_number)
369
+ end
370
+ end
371
+ end
372
+
373
+ errors
374
+ end
375
+
376
+ class ExpiryDate #:nodoc:
377
+ attr_reader :month, :year
378
+ def initialize(month, year)
379
+ @month = month.to_i
380
+ @year = year.to_i
381
+ end
382
+
383
+ def expired? #:nodoc:
384
+ Time.now.utc > expiration
385
+ end
386
+
387
+ def expiration #:nodoc:
388
+ begin
389
+ Time.utc(year, month, month_days, 23, 59, 59)
390
+ rescue ArgumentError
391
+ Time.at(0).utc
392
+ end
393
+ end
394
+
395
+ private
396
+ def month_days
397
+ mdays = [nil,31,28,31,30,31,30,31,31,30,31,30,31]
398
+ mdays[2] = 29 if Date.leap?(year)
399
+ mdays[month]
400
+ end
401
+ end
402
+ end
403
+ end
404
+ end