module FakeBraintree class Customer include Helpers def initialize(customer_hash_from_params, options) @customer_hash = { "id" => options[:id], "merchant_id" => options[:merchant_id] }.merge(customer_hash_from_params) set_customer_id end def create if invalid? response_for_invalid_card else credit_cards = customer_hash["credit_cards"] create_customer_with(customer_hash) credit_cards.each { |card| add_credit_card_to_registry(card) } response_for_created_customer(customer_hash) end end def update if customer_exists_in_registry? if credit_card_is_failure? response_for_invalid_card else updates = customer_hash updated_customer = update_existing_customer(updates) response_for_updated_customer(updated_customer) end else response_for_customer_not_found end end def delete delete_customer_with_id(customer_id) deletion_response end private def invalid? credit_card_is_failure? || invalid_credit_card? end def create_customer_with(hash) FakeBraintree.registry.customers[hash["id"]] = hash end def add_credit_card_to_registry(new_credit_card_hash) token = new_credit_card_hash["token"] FakeBraintree.registry.credit_cards[token] = new_credit_card_hash end def update_existing_customer(updates_hash) customer_from_registry.merge!(updates_hash) end def customer_hash @customer_hash.merge("credit_cards" => generate_credit_cards_from(@customer_hash["credit_card"])) end def customer_from_registry FakeBraintree.registry.customers[customer_id] end def customer_exists_in_registry? FakeBraintree.registry.customers.key?(customer_id) end def credit_card_is_failure? has_credit_card? && FakeBraintree.failure?(credit_card_number) end def invalid_credit_card? verify_credit_card?(customer_hash) && has_invalid_credit_card?(customer_hash) end def verify_credit_card?(customer_hash_for_verification) return true if FakeBraintree.verify_all_cards credit_card_hash_for_verification = customer_hash_for_verification["credit_card"] if credit_card_hash_for_verification.is_a?(Hash) && credit_card_hash_for_verification.key?("options") options = credit_card_hash_for_verification["options"] options["verify_card"] == true end end def has_invalid_credit_card?(customer_hash) credit_card_number && ! FakeBraintree::VALID_CREDIT_CARDS.include?(credit_card_number) end def credit_card_number credit_card_hash["number"] end def generate_credit_cards_from(new_credit_card_hash) if new_credit_card_hash.present? && new_credit_card_hash.is_a?(Hash) new_credit_card_hash["last_4"] = new_credit_card_hash["number"][-4..-1] new_credit_card_hash["token"] = credit_card_token(new_credit_card_hash) if credit_card_expiration_month new_credit_card_hash["expiration_month"] = credit_card_expiration_month end if credit_card_expiration_year new_credit_card_hash["expiration_year"] = credit_card_expiration_year end [new_credit_card_hash] else [] end end def credit_card_expiration_month credit_card_expiration_date[0] end def credit_card_expiration_year credit_card_expiration_date[1] end def credit_card_expiration_date if credit_card_hash.key?("expiration_date") credit_card_hash["expiration_date"].split('/') else [] end end def delete_customer_with_id(id) FakeBraintree.registry.customers[id] = nil end def deletion_response gzipped_response(200, '') end def response_for_created_customer(hash) gzipped_response(201, hash.to_xml(:root => 'customer')) end def response_for_updated_customer(hash) gzipped_response(200, hash.to_xml(:root => 'customer')) end def response_for_invalid_card failure_response(422) end def response_for_customer_not_found failure_response(404) end def failure_response(code) gzipped_response(code, FakeBraintree.failure_response(credit_card_number).to_xml(:root => 'api_error_response')) end def customer_id customer_hash["id"] end def has_credit_card? credit_card_hash.present? end def credit_card_hash @customer_hash["credit_card"] || {} end def set_customer_id @customer_hash["id"] ||= create_id(@customer_hash["merchant_id"]) end def credit_card_token(credit_card_hash_without_token) md5("#{credit_card_hash_without_token["number"]}#{@customer_hash["merchant_id"]}") end end end