require 'braintree' Braintree::Configuration.environment = :production Braintree::Configuration.merchant_id = "xxx" Braintree::Configuration.public_key = "xxx" Braintree::Configuration.private_key = "xxx" require 'digest/md5' require 'sham_rack' class FakeBraintree cattr_accessor :customers, :subscriptions, :failures @@customers = {} @@subscriptions = {} @@failures = {} def self.clear! @@customers = {} @@subscriptions = {} @@failures = {} end def self.failure?(card_number) self.failures.include?(card_number) end def self.failure_response(card_number) failure = self.failures[card_number] failure["errors"] ||= { "errors" => [] } { "message" => failure["message"], "verification" => { "status" => failure["status"], "processor_response_text" => failure["message"], "processor-response-code" => failure["code"], "gateway_rejection_reason" => "cvv", "cvv_response_code" => failure["code"] }, "errors" => failure["errors"], "params" => {}} end end ShamRack.at("www.braintreegateway.com", 443).sinatra do set :show_exceptions, false set :dump_errors, true set :raise_errors, true post "/merchants/:merchant_id/customers" do customer = Hash.from_xml(request.body).delete("customer") if !FakeBraintree.failure?(customer["credit_card"]["number"]) customer["id"] ||= Digest::MD5.hexdigest("#{params[:merchant_id]}#{Time.now.to_f}") customer["merchant-id"] = params[:merchant_id] if customer["credit_card"] && customer["credit_card"].is_a?(Hash) customer["credit_card"]["last_4"] = customer["credit_card"].delete("number")[-4..-1] customer["credit_card"]["token"] = Digest::MD5.hexdigest("#{customer['merchant_id']}#{customer['id']}#{Time.now.to_f}") credit_card = customer.delete("credit_card") customer["credit_cards"] = [credit_card] end FakeBraintree.customers[customer["id"]] = customer [201, { "Content-Encoding" => "gzip" }, ActiveSupport::Gzip.compress(customer.to_xml(:root => 'customer'))] else [422, { "Content-Encoding" => "gzip" }, ActiveSupport::Gzip.compress(FakeBraintree.failure_response(customer["credit_card"]["number"]).to_xml(:root => 'api_error_response'))] end end get "/merchants/:merchant_id/customers/:id" do customer = FakeBraintree.customers[params[:id]] [200, { "Content-Encoding" => "gzip" }, ActiveSupport::Gzip.compress(customer.to_xml(:root => 'customer'))] end put "/merchants/:merchant_id/customers/:id" do customer = Hash.from_xml(request.body).delete("customer") customer["id"] = params[:id] customer["merchant-id"] = params[:merchant_id] if customer["credit_card"] && customer["credit_card"].is_a?(Hash) customer["credit_card"]["last_4"] = customer["credit_card"].delete("number")[-4..-1] customer["credit_card"]["token"] = Digest::MD5.hexdigest("#{customer['merchant_id']}#{customer['id']}#{Time.now.to_f}") credit_card = customer.delete("credit_card") customer["credit_cards"] = [credit_card] end FakeBraintree.customers[params["id"]] = customer [200, { "Content-Encoding" => "gzip" }, ActiveSupport::Gzip.compress(customer.to_xml(:root => 'customer'))] end post "/merchants/:merchant_id/subscriptions" do "\n\n 2\n b22x\n\n" subscription = Hash.from_xml(request.body).delete("subscription") subscription["id"] ||= Digest::MD5.hexdigest("#{subscription["payment_method_token"]}#{Time.now.to_f}") subscription["transactions"] = [] subscription["add_ons"] = [] subscription["discounts"] = [] FakeBraintree.subscriptions[subscription["id"]] = subscription [201, { "Content-Encoding" => "gzip" }, ActiveSupport::Gzip.compress(subscription.to_xml(:root => 'subscription'))] end get "/merchants/:merchant_id/subscriptions/:id" do subscription = FakeBraintree.subscriptions[params[:id]] [200, { "Content-Encoding" => "gzip" }, ActiveSupport::Gzip.compress(subscription.to_xml(:root => 'subscription'))] end put "/merchants/:merchant_id/subscriptions/:id" do subscription = Hash.from_xml(request.body).delete("subscription") subscription["transactions"] = [] subscription["add_ons"] = [] subscription["discounts"] = [] FakeBraintree.subscriptions[params["id"]] = subscription [200, { "Content-Encoding" => "gzip" }, ActiveSupport::Gzip.compress(subscription.to_xml(:root => 'subscription'))] end end