# Blocca l'invio accidentale di numeri di carta completi all'API Stripe dal backend. # I dati carta devono essere raccolti solo da Stripe Checkout / Elements lato browser. module StripePciGuard RAW_CARD_KEYS = %w[number cvc exp_month exp_year].freeze def self.raw_card_hash?(value) return false unless value.is_a?(Hash) key_set = value.keys.map(&:to_s) (key_set & RAW_CARD_KEYS).any? end def self.guard_params!(params) return unless params.is_a?(Hash) type = params[:type] || params["type"] card = params[:card] || params["card"] payment_method_data = params[:payment_method_data] || params["payment_method_data"] if type.to_s == "card" && raw_card_hash?(card) raise_security_error! end pmd_card = payment_method_data.is_a?(Hash) ? (payment_method_data[:card] || payment_method_data["card"]) : nil raise_security_error! if raw_card_hash?(pmd_card) end def self.raise_security_error! raise SecurityError, "PCI: non inviare numeri di carta completi all'API Stripe dal server. " \ "Usa Stripe Checkout (redirect) o Stripe Elements lato client." end end if defined?(Stripe::PaymentMethod) Stripe::PaymentMethod.singleton_class.prepend( Module.new do def create(params = {}, opts = {}) StripePciGuard.guard_params!(params) super end end ) end if defined?(Stripe::Token) Stripe::Token.singleton_class.prepend( Module.new do def create(params = {}, opts = {}) StripePciGuard.guard_params!(params) super end end ) end