Merge pull request #8 from chrisbeach/associate_stripe_customer_id_with_users

Save and reuse stripe customer id when user is present
This commit is contained in:
Chris Beach 2018-02-02 08:27:56 +00:00 committed by GitHub
commit 9ec48bc6b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 73 additions and 45 deletions

View File

@ -24,7 +24,7 @@ module DiscourseDonations
end end
if output['messages'].present? if output['messages'].present?
render(:json => output.merge(success: false)) and return render(json: output.merge(success: false)) && (return)
end end
Rails.logger.debug "Creating a Stripe payment" Rails.logger.debug "Creating a Stripe payment"
@ -32,7 +32,15 @@ module DiscourseDonations
begin begin
Rails.logger.debug "Creating a Stripe charge for #{user_params[:amount]}" Rails.logger.debug "Creating a Stripe charge for #{user_params[:amount]}"
charge = payment.charge(email, user_params[:stripeToken], user_params[:amount]) charge_params = [user_params[:stripeToken], user_params[:amount]]
if user
charge_params.unshift(user, user.email)
else
charge_params.unshift(nil, email)
end
charge = payment.charge(*charge_params)
rescue ::Stripe::CardError => e rescue ::Stripe::CardError => e
err = e.json_body[:error] err = e.json_body[:error]
@ -41,7 +49,7 @@ module DiscourseDonations
output['messages'] << "Decline code: #{err[:decline_code]}" if err[:decline_code] output['messages'] << "Decline code: #{err[:decline_code]}" if err[:decline_code]
output['messages'] << "Message: #{err[:message]}" if err[:message] output['messages'] << "Message: #{err[:message]}" if err[:message]
render(:json => output) and return render(json: output) && (return)
end end
if charge['paid'] == true if charge['paid'] == true
@ -56,7 +64,7 @@ module DiscourseDonations
end end
end end
render :json => output render json: output
end end
private private
@ -89,11 +97,19 @@ module DiscourseDonations
end end
def user_params def user_params
params.permit(:name, :username, :email, :password, :stripeToken, :amount, :create_account) params.permit(:user_id, :name, :username, :email, :password, :stripeToken, :amount, :create_account)
end end
def email def email
user_params[:email] || current_user.try(:email) user_params[:email] || user.try(:email)
end
def user
if user_params[:user_id]
User.find(user_params[:user_id])
else
current_user
end
end end
end end
end end

View File

@ -11,11 +11,10 @@ module DiscourseDonations
output = { 'messages' => [], 'rewards' => [] } output = { 'messages' => [], 'rewards' => [] }
payment = DiscourseDonations::Stripe.new(secret_key, stripe_options) payment = DiscourseDonations::Stripe.new(secret_key, stripe_options)
user = current_user || nil
begin begin
charge = payment.checkoutCharge(user_params[:stripeEmail], charge = payment.checkoutCharge(user, user_params[:stripeEmail], user_params[:stripeToken], user_params[:amount])
user_params[:stripeToken],
user_params[:amount])
rescue ::Stripe::CardError => e rescue ::Stripe::CardError => e
err = e.json_body[:error] err = e.json_body[:error]
@ -24,7 +23,7 @@ module DiscourseDonations
output['messages'] << "Decline code: #{err[:decline_code]}" if err[:decline_code] output['messages'] << "Decline code: #{err[:decline_code]}" if err[:decline_code]
output['messages'] << "Message: #{err[:message]}" if err[:message] output['messages'] << "Message: #{err[:message]}" if err[:message]
render(:json => output) and return render(json: output) && (return)
end end
if charge['paid'] if charge['paid']
@ -33,12 +32,11 @@ module DiscourseDonations
output['rewards'] << { type: :badge, name: badge_name } if badge_name output['rewards'] << { type: :badge, name: badge_name } if badge_name
end end
render :json => output render json: output
end end
private private
def reward?(payment) def reward?(payment)
payment.present? && payment.successful? payment.present? && payment.successful?
end end
@ -61,6 +59,7 @@ module DiscourseDonations
:stripeToken, :stripeToken,
:stripeTokenType, :stripeTokenType,
:stripeEmail, :stripeEmail,
:stripeCustomerId,
:stripeBillingName, :stripeBillingName,
:stripeBillingAddressLine1, :stripeBillingAddressLine1,
:stripeBillingAddressZip, :stripeBillingAddressZip,
@ -75,7 +74,6 @@ module DiscourseDonations
:stripeShippingAddressCity, :stripeShippingAddressCity,
:stripeShippingAddressCountry, :stripeShippingAddressCountry,
:stripeShippingAddressCountryCode :stripeShippingAddressCountryCode
) )
end end

View File

@ -8,26 +8,19 @@ module DiscourseDonations
@currency = opts[:currency] @currency = opts[:currency]
end end
def checkoutCharge(email, token, amount) def checkoutCharge(user = nil, email, token, amount)
customer = ::Stripe::Customer.create( customer = customer(user, email, token)
:email => email,
:source => token
)
charge = ::Stripe::Charge.create( charge = ::Stripe::Charge.create(
:customer => customer.id, customer: customer.id,
:amount => amount, amount: amount,
:description => @description, description: @description,
:currency => @currency currency: @currency
) )
charge charge
end end
def charge(email, token, amount) def charge(user = nil, email, token, amount)
customer = ::Stripe::Customer.create( customer = customer(user, email, token)
email: email,
source: token
)
@charge = ::Stripe::Charge.create( @charge = ::Stripe::Charge.create(
customer: customer.id, customer: customer.id,
amount: amount, amount: amount,
@ -37,11 +30,8 @@ module DiscourseDonations
@charge @charge
end end
def subscribe(email, opts) def subscribe(user = nil, email, opts)
customer = ::Stripe::Customer.create( customer = customer(user, email, opts[:stripeToken])
email: email,
source: opts[:stripeToken]
)
@subscription = ::Stripe::Subscription.create( @subscription = ::Stripe::Subscription.create(
customer: customer.id, customer: customer.id,
plan: opts[:plan] plan: opts[:plan]
@ -49,6 +39,22 @@ module DiscourseDonations
@subscription @subscription
end end
def customer(user, email, source)
if user && user.stripe_customer_id
::Stripe::Customer.retrieve(user.stripe_customer_id)
else
customer = ::Stripe::Customer.create(
email: email,
source: source
)
if user
user.custom_fields['stripe_customer_id'] = customer.id
user.save_custom_fields(true)
end
customer
end
end
def successful? def successful?
@charge[:paid] @charge[:paid]
end end

View File

@ -63,18 +63,18 @@ export default Ember.Component.extend({
self.endTranscation(); self.endTranscation();
} }
else { else {
let params = { let params = {
stripeToken: data.token.id, stripeToken: data.token.id,
amount: self.get('amount') * 100, amount: self.get('amount') * 100,
user_id: self.get('currentUser.id'),
email: self.get('email'), email: self.get('email'),
username: self.get('username'), username: self.get('username'),
create_account: self.get('create_accounts') create_account: self.get('create_accounts')
}; };
if(!self.get('paymentSuccess')) { if(!self.get('paymentSuccess')) {
ajax('/charges', { data: params, method: 'post' }).then(data => { ajax('/charges', { data: params, method: 'post' }).then(d => {
self.concatMessages(data.messages); self.concatMessages(d.messages);
self.endTranscation(); self.endTranscation();
}); });
} }

View File

@ -18,6 +18,16 @@ end
after_initialize do after_initialize do
load File.expand_path('../app/jobs/jobs.rb', __FILE__) load File.expand_path('../app/jobs/jobs.rb', __FILE__)
class ::User
def stripe_customer_id
if custom_fields['stripe_customer_id']
custom_fields['stripe_customer_id']
else
nil
end
end
end
end end
Discourse::Application.routes.prepend do Discourse::Application.routes.prepend do

View File

View File

@ -44,12 +44,10 @@ module DiscourseDonations
description: stripe_options[:description], description: stripe_options[:description],
currency: stripe_options[:currency] currency: stripe_options[:currency]
).returns( ).returns(
{ paid: true,
paid: true, outcome: { seller_message: 'yay!' }
outcome: { seller_message: 'yay!' }
}
) )
subject.charge(email, params[:stripeToken], params[:amount]) subject.charge(nil, email, params[:stripeToken], params[:amount])
end end
end end
@ -62,14 +60,14 @@ module DiscourseDonations
end end
it 'is successful' do it 'is successful' do
::Stripe::Charge.expects(:create).with(charge_options).returns({paid: true}) ::Stripe::Charge.expects(:create).with(charge_options).returns(paid: true)
subject.charge(email, params[:stripeToken], params[:amount]) subject.charge(nil, email, params[:stripeToken], params[:amount])
expect(subject).to be_successful expect(subject).to be_successful
end end
it 'is not successful' do it 'is not successful' do
::Stripe::Charge.expects(:create).with(charge_options).returns({paid: false}) ::Stripe::Charge.expects(:create).with(charge_options).returns(paid: false)
subject.charge(email, params[:stripeToken], params[:amount]) subject.charge(nil, email, params[:stripeToken], params[:amount])
expect(subject).not_to be_successful expect(subject).not_to be_successful
end end
end end