From c9c4680ef61c43e2ee8ebc87125ea74dc986a6be Mon Sep 17 00:00:00 2001 From: stveep Date: Mon, 1 May 2017 20:21:30 +0100 Subject: [PATCH] Backend code to create Stripe customers and store their IDs in CreditCards. Page refresh not working --- .../credit_cards_controller.js.coffee | 11 ----- .../darkswarm/services/credit_card.js.coffee | 27 +++++++++-- .../spree/credit_cards_controller.rb | 47 +++++++++++++++++++ config/routes.rb | 1 + .../spree/credit_cards_controller_spec.rb | 31 ++++++++++++ 5 files changed, 101 insertions(+), 16 deletions(-) create mode 100644 app/controllers/spree/credit_cards_controller.rb create mode 100644 spec/controllers/spree/credit_cards_controller_spec.rb diff --git a/app/assets/javascripts/darkswarm/controllers/credit_cards_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/credit_cards_controller.js.coffee index 17193cfd5a..6fd7fa314c 100644 --- a/app/assets/javascripts/darkswarm/controllers/credit_cards_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/credit_cards_controller.js.coffee @@ -10,16 +10,5 @@ Darkswarm.controller "CreditCardsCtrl", ($scope, $timeout, CreditCard, savedCred $scope.secrets = CreditCard.secrets - - $scope.storeCard = => - Loading.message = "Saving" CreditCard.requestToken($scope.secrets) - - - - - - # Need to call Spree::Gateway::StripeConnect#provider.store(creditcard) - # creditcard should be formatted as for a payment - # The token then needs to be associated with the Customer (in Stripe) - can be done in Ruby. diff --git a/app/assets/javascripts/darkswarm/services/credit_card.js.coffee b/app/assets/javascripts/darkswarm/services/credit_card.js.coffee index e5aeec61fc..00c3d8212e 100644 --- a/app/assets/javascripts/darkswarm/services/credit_card.js.coffee +++ b/app/assets/javascripts/darkswarm/services/credit_card.js.coffee @@ -1,16 +1,33 @@ Darkswarm.factory 'CreditCard', ($injector, $rootScope, StripeJS, Navigation, $http, RailsFlashLoader, Loading)-> new class CreditCard errors: {} + secrets: {} requestToken: (secrets) -> - #$scope.secrets.name = $scope.secrets.first_name + " " + $scope.secrets.last_name secrets.name = @full_name(secrets) - StripeJS.requestToken(secrets, @submit) + StripeJS.requestToken(secrets, @submit, t("saving_credit_card")) submit: => - $rootScope.$apply -> - Loading.clear() - Navigation.go '/account' + params = @process_params() + $http.put('/credit_cards/new_from_token', params ) + .success (data, status) -> + $rootScope.$apply -> + Loading.clear() + Navigation.go '/account' + .error (response, status) -> + if response.path + Navigation.go response.path + else + Loading.clear() + @errors = response.errors + RailsFlashLoader.loadFlash(response.flash) full_name: (secrets) -> secrets.first_name + " " + secrets.last_name + + process_params: -> + {"exp_month": @secrets.card.exp_month, + "exp_year": @secrets.card.exp_year, + "last4": @secrets.card.last4, + "token": @secrets.token, + "cc_type": @secrets.card.brand} diff --git a/app/controllers/spree/credit_cards_controller.rb b/app/controllers/spree/credit_cards_controller.rb new file mode 100644 index 0000000000..b49c93ec1c --- /dev/null +++ b/app/controllers/spree/credit_cards_controller.rb @@ -0,0 +1,47 @@ +module Spree + class CreditCardsController < BaseController + + def new_from_token + set_user + # At the moment a new Customer is created for every credit card (even via ActiveMerchant), + # so doing the same here (for now). + if @customer = create_customer(params[:token]) + # Since it's a new customer, the default_source is the card that our original token represented + credit_card_params = format_credit_card_params(params) + .merge({gateway_payment_profile_id: @customer.default_source, + gateway_customer_profile_id: @customer.id, + cc_type: params[:cc_type] + }) + + @credit_card = Spree::CreditCard.new(credit_card_params) + # Can't mass assign these: + @credit_card.cc_type = credit_card_params[:cc_type] + @credit_card.last_digits = credit_card_params[:last_digits] + @credit_card.user_id = @user.id + if @credit_card.save + render json: @credit_card, status: :ok + else + render json: "error saving credit card", status: 500 + end + else + render json: "error creating Stripe customer", status: 500 + end + end + + private + def create_customer(token) + Stripe::Customer.create(email: @user.email, source: token) + end + + def format_credit_card_params(params_hash) + { month: params_hash[:exp_month], + year: params_hash[:exp_year], + last_digits: params_hash[:last4] + } + end + + def set_user + @user = spree_current_user + end + end +end diff --git a/config/routes.rb b/config/routes.rb index d6c4c7330c..90c6534a91 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -234,6 +234,7 @@ Spree::Core::Engine.routes.prepend do match '/admin/reports/xero_invoices' => 'admin/reports#xero_invoices', :as => "xero_invoices_admin_reports", :via => [:get, :post] match '/admin', :to => 'admin/overview#index', :as => :admin match '/admin/payment_methods/show_provider_preferences' => 'admin/payment_methods#show_provider_preferences', :via => :get + put 'credit_cards/new_from_token', to: 'credit_cards#new_from_token' namespace :api, :defaults => { :format => 'json' } do diff --git a/spec/controllers/spree/credit_cards_controller_spec.rb b/spec/controllers/spree/credit_cards_controller_spec.rb new file mode 100644 index 0000000000..dc543f061b --- /dev/null +++ b/spec/controllers/spree/credit_cards_controller_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' +require 'support/request/authentication_workflow' + +describe Spree::CreditCardsController do + include AuthenticationWorkflow + let(:user) { create_enterprise_user } + + it "Creates a credit card from token + params" do + controller.stub(:spree_current_user) { user } + controller.stub(:create_customer) { + sc = Stripe::Customer.new + sc.default_source = "card_1AEEbN2eZvKYlo2CMk6QwrN7" + sc.email = nil + sc.stub(:id) {"cus_AZNMJzuACN3Sgt"} + sc } + + token = "tok_234bd2c22" + expect{ post :new_from_token, { + "exp_month" => 12, + "exp_year" => 2020, + "last4" => 4242, + "token" => token, + "cc_type" => "visa" + } }.to change(Spree::CreditCard, :count).by(1) + + Spree::CreditCard.last.gateway_payment_profile_id.should eq "card_1AEEbN2eZvKYlo2CMk6QwrN7" + Spree::CreditCard.last.gateway_customer_profile_id.should eq "cus_AZNMJzuACN3Sgt" + Spree::CreditCard.last.user_id.should eq user.id + Spree::CreditCard.last.last_digits.should eq "4242" + end +end