Merge pull request #2 from rimian/feature/subscriptions
Feature/subscriptions
This commit is contained in:
@@ -11,13 +11,10 @@ This is a newer version of https://github.com/rimian/discourse-donations.
|
||||
* Be sure your site is enforcing https.
|
||||
* Follow the install instructions here: https://meta.discourse.org/t/install-a-plugin/19157
|
||||
* Add your Stripe public and private keys in settings and set the currency to your local value.
|
||||
* Enable the plugin and wait for people to donate money.
|
||||
|
||||
## Usage
|
||||
## Creating Subscription Plans
|
||||
|
||||
Enable the plugin and enter your Stripe API keys in the settings. You can also configure amounts and the default currency.
|
||||
|
||||
Visit `/patrons`
|
||||
When users subscribe to your Discourse application, they are added to a user group. You can create new user groups or use existing ones. Of course, you should be careful what permissions you apply to the user group.
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
module Admin
|
||||
class PlansController < ::Admin::AdminController
|
||||
include DiscoursePatrons::Stripe
|
||||
|
||||
before_action :set_api_key
|
||||
|
||||
def index
|
||||
begin
|
||||
plans = ::Stripe::Plan.list(product_params)
|
||||
|
||||
render_json_dump plans.data
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
begin
|
||||
plan = ::Stripe::Plan.create(
|
||||
nickname: params[:nickname],
|
||||
amount: params[:amount],
|
||||
interval: params[:interval],
|
||||
product: params[:product],
|
||||
trial_period_days: params[:trial_period_days],
|
||||
currency: SiteSetting.discourse_patrons_currency,
|
||||
active: params[:active],
|
||||
metadata: { group_name: params[:metadata][:group_name] }
|
||||
)
|
||||
|
||||
render_json_dump plan
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
begin
|
||||
plan = ::Stripe::Plan.retrieve(params[:id])
|
||||
|
||||
render_json_dump plan
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
begin
|
||||
plan = ::Stripe::Plan.update(
|
||||
params[:id],
|
||||
nickname: params[:nickname],
|
||||
trial_period_days: params[:trial_period_days],
|
||||
active: params[:active],
|
||||
metadata: { group_name: params[:metadata][:group_name] }
|
||||
)
|
||||
|
||||
render_json_dump plan
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
begin
|
||||
plan = ::Stripe::Plan.delete(params[:id])
|
||||
|
||||
render_json_dump plan
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def product_params
|
||||
{ product: params[:product_id] } if params[:product_id]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,87 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
module Admin
|
||||
class ProductsController < ::Admin::AdminController
|
||||
include DiscoursePatrons::Stripe
|
||||
|
||||
before_action :set_api_key
|
||||
|
||||
def index
|
||||
begin
|
||||
products = ::Stripe::Product.list
|
||||
|
||||
render_json_dump products.data
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
begin
|
||||
create_params = product_params.merge!(type: 'service')
|
||||
|
||||
if params[:statement_descriptor].blank?
|
||||
create_params.except!(:statement_descriptor)
|
||||
end
|
||||
|
||||
product = ::Stripe::Product.create(create_params)
|
||||
|
||||
render_json_dump product
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
begin
|
||||
product = ::Stripe::Product.retrieve(params[:id])
|
||||
|
||||
render_json_dump product
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
begin
|
||||
product = ::Stripe::Product.update(
|
||||
params[:id],
|
||||
product_params
|
||||
)
|
||||
|
||||
render_json_dump product
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
begin
|
||||
product = ::Stripe::Product.delete(params[:id])
|
||||
|
||||
render_json_dump product
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def product_params
|
||||
params.permit!
|
||||
|
||||
{
|
||||
name: params[:name],
|
||||
active: params[:active],
|
||||
statement_descriptor: params[:statement_descriptor],
|
||||
metadata: { description: params.dig(:metadata, :description) }
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
module Admin
|
||||
class SubscriptionsController < ::Admin::AdminController
|
||||
include DiscoursePatrons::Stripe
|
||||
|
||||
before_action :set_api_key
|
||||
|
||||
def index
|
||||
begin
|
||||
subscriptions = ::Stripe::Subscription.list
|
||||
|
||||
render_json_dump subscriptions
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,27 +3,7 @@
|
||||
module DiscoursePatrons
|
||||
class AdminController < ::Admin::AdminController
|
||||
def index
|
||||
payments = Payment.all.order(payments_order)
|
||||
|
||||
render_serialized(payments, PaymentSerializer)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def payments_order
|
||||
if %w(created_at amount).include?(params[:order])
|
||||
{ params[:order] => ascending }
|
||||
else
|
||||
{ created_at: :desc }
|
||||
end
|
||||
end
|
||||
|
||||
def ascending
|
||||
if params[:descending] == 'false'
|
||||
:desc
|
||||
else
|
||||
:asc
|
||||
end
|
||||
head 200
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
module Stripe
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def set_api_key
|
||||
::Stripe.api_key = SiteSetting.discourse_patrons_secret_key
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
class CustomersController < ::ApplicationController
|
||||
include DiscoursePatrons::Stripe
|
||||
|
||||
before_action :set_api_key
|
||||
|
||||
def create
|
||||
begin
|
||||
customer = ::Stripe::Customer.create(
|
||||
email: current_user.email,
|
||||
source: params[:source]
|
||||
)
|
||||
|
||||
DiscoursePatrons::Customer.create_customer(
|
||||
current_user,
|
||||
customer
|
||||
)
|
||||
|
||||
render_json_dump customer
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,35 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
class InvoicesController < ::ApplicationController
|
||||
include DiscoursePatrons::Stripe
|
||||
before_action :set_api_key
|
||||
requires_login
|
||||
|
||||
def index
|
||||
begin
|
||||
customer = find_customer
|
||||
|
||||
if viewing_own_invoices && customer.present?
|
||||
invoices = ::Stripe::Invoice.list(customer: customer.customer_id)
|
||||
|
||||
render_json_dump invoices.data
|
||||
else
|
||||
render_json_dump []
|
||||
end
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def viewing_own_invoices
|
||||
current_user.id == params[:user_id].to_i
|
||||
end
|
||||
|
||||
def find_customer
|
||||
DiscoursePatrons::Customer.find_user(current_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
module DiscoursePatrons
|
||||
class PatronsController < ::ApplicationController
|
||||
include DiscoursePatrons::Stripe
|
||||
|
||||
skip_before_action :verify_authenticity_token, only: [:create]
|
||||
before_action :set_api_key
|
||||
|
||||
@@ -15,18 +17,6 @@ module DiscoursePatrons
|
||||
render json: result
|
||||
end
|
||||
|
||||
def show
|
||||
payment_intent = Stripe::PaymentIntent.retrieve(params[:pid])
|
||||
|
||||
if current_user && (current_user.admin || payment_intent[:customer] == current_user.id)
|
||||
result = payment_intent
|
||||
else
|
||||
result = { error: 'Not found' }
|
||||
end
|
||||
|
||||
render json: result
|
||||
end
|
||||
|
||||
def create
|
||||
begin
|
||||
|
||||
@@ -41,15 +31,6 @@ module DiscoursePatrons
|
||||
metadata: { user_id: user_id }
|
||||
)
|
||||
|
||||
Payment.create(
|
||||
user_id: response[:metadata][:user_id],
|
||||
payment_intent_id: response[:id],
|
||||
receipt_email: response[:receipt_email],
|
||||
url: response[:charges][:url],
|
||||
amount: response[:amount],
|
||||
currency: response[:currency]
|
||||
)
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
response = { error: e }
|
||||
rescue ::Stripe::CardError => e
|
||||
@@ -61,10 +42,6 @@ module DiscoursePatrons
|
||||
|
||||
private
|
||||
|
||||
def set_api_key
|
||||
::Stripe.api_key = SiteSetting.discourse_patrons_secret_key
|
||||
end
|
||||
|
||||
def param_currency_to_number
|
||||
params[:amount].to_s.sub('.', '').to_i
|
||||
end
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
class PlansController < ::ApplicationController
|
||||
include DiscoursePatrons::Stripe
|
||||
|
||||
before_action :set_api_key
|
||||
|
||||
def index
|
||||
begin
|
||||
if params[:product_id].present?
|
||||
plans = ::Stripe::Plan.list(active: true, product: params[:product_id])
|
||||
else
|
||||
plans = ::Stripe::Plan.list(active: true)
|
||||
end
|
||||
|
||||
serialized = plans[:data].map do |plan|
|
||||
plan.to_h.slice(:id, :amount, :currency, :interval)
|
||||
end.sort_by { |plan| plan[:amount] }
|
||||
|
||||
render_json_dump serialized
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
class ProductsController < ::ApplicationController
|
||||
include DiscoursePatrons::Stripe
|
||||
|
||||
before_action :set_api_key
|
||||
|
||||
def index
|
||||
begin
|
||||
response = ::Stripe::Product.list(active: true)
|
||||
|
||||
products = response[:data].map do |p|
|
||||
serialize(p)
|
||||
end
|
||||
|
||||
render_json_dump products
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
begin
|
||||
product = ::Stripe::Product.retrieve(params[:id])
|
||||
|
||||
render_json_dump serialize(product)
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serialize(product)
|
||||
{
|
||||
id: product[:id],
|
||||
name: product[:name],
|
||||
description: product[:metadata][:description]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
class SubscriptionsController < ::ApplicationController
|
||||
include DiscoursePatrons::Stripe
|
||||
before_action :set_api_key
|
||||
requires_login
|
||||
|
||||
def index
|
||||
begin
|
||||
products = ::Stripe::Product.list(active: true)
|
||||
|
||||
subscriptions = products[:data].map do |p|
|
||||
{
|
||||
id: p[:id],
|
||||
description: p.dig(:metadata, :description)
|
||||
}
|
||||
end
|
||||
|
||||
render_json_dump subscriptions
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
begin
|
||||
plan = ::Stripe::Plan.retrieve(params[:plan])
|
||||
|
||||
@subscription = ::Stripe::Subscription.create(
|
||||
customer: params[:customer],
|
||||
items: [ { plan: params[:plan] } ]
|
||||
)
|
||||
|
||||
group = plan_group(plan)
|
||||
|
||||
if subscription_ok && group
|
||||
group.add(current_user)
|
||||
end
|
||||
|
||||
unless DiscoursePatrons::Customer.exists?(user_id: current_user.id)
|
||||
DiscoursePatrons::Customer.create(user_id: current_user.id, customer_id: params[:customer])
|
||||
end
|
||||
|
||||
render_json_dump @subscription
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def plan_group(plan)
|
||||
Group.find_by_name(plan[:metadata][:group_name])
|
||||
end
|
||||
|
||||
def subscription_ok
|
||||
['active', 'trialing'].include?(@subscription[:status])
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
module User
|
||||
class SubscriptionsController < ::ApplicationController
|
||||
include DiscoursePatrons::Stripe
|
||||
before_action :set_api_key
|
||||
requires_login
|
||||
|
||||
def index
|
||||
begin
|
||||
customers = ::Stripe::Customer.list(
|
||||
email: current_user.email,
|
||||
expand: ['data.subscriptions']
|
||||
)
|
||||
|
||||
# TODO: Serialize and remove stuff
|
||||
subscriptions = customers[:data].map do |customer|
|
||||
customer[:subscriptions][:data]
|
||||
end.flatten(1)
|
||||
|
||||
render_json_dump subscriptions
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
begin
|
||||
subscription = ::Stripe::Subscription.delete(params[:id])
|
||||
|
||||
render_json_dump subscription
|
||||
|
||||
rescue ::Stripe::InvalidRequestError => e
|
||||
return render_json_error e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module DiscoursePatrons
|
||||
class Customer < ActiveRecord::Base
|
||||
scope :find_user, ->(user) { find_by_user_id(user.id) }
|
||||
|
||||
class << self
|
||||
table_name = "discourse_patrons_customers"
|
||||
|
||||
def create_customer(user, customer)
|
||||
create(customer_id: customer[:id], user_id: user.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Payment < ActiveRecord::Base
|
||||
end
|
||||
@@ -10,7 +10,7 @@ export default Ember.Component.extend({
|
||||
this._super(...arguments);
|
||||
|
||||
const settings = Discourse.SiteSettings;
|
||||
const amounts = Discourse.SiteSettings.discourse_patrons_amounts.split("|");
|
||||
const amounts = settings.discourse_patrons_amounts.split("|");
|
||||
|
||||
this.setProperties({
|
||||
confirmation: false,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export default Ember.Component.extend({
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
this.cardElement.mount("#card-element");
|
||||
},
|
||||
didDestroyElement() {}
|
||||
});
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
editPlan(id) {
|
||||
return DiscourseURL.redirectTo(
|
||||
`/admin/plugins/discourse-patrons/plans/${id}`
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
createPlan() {
|
||||
if (this.get("model.plan.product_id") === undefined) {
|
||||
const productID = this.get("model.products.firstObject.id");
|
||||
this.set("model.plan.product_id", productID);
|
||||
}
|
||||
|
||||
this.get("model.plan")
|
||||
.save()
|
||||
.then(() => {
|
||||
this.transitionToRoute("adminPlugins.discourse-patrons.plans");
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
export default Ember.Controller.extend({});
|
||||
+1
@@ -0,0 +1 @@
|
||||
export default Ember.Controller.extend({});
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
@computed("model.plan.isNew")
|
||||
planFieldDisabled(isNew) {
|
||||
return !isNew;
|
||||
},
|
||||
|
||||
@computed("model.product.id")
|
||||
productId(id) {
|
||||
return id;
|
||||
},
|
||||
|
||||
redirect(product_id) {
|
||||
DiscourseURL.redirectTo(
|
||||
`/admin/plugins/discourse-patrons/products/${product_id}`
|
||||
);
|
||||
},
|
||||
|
||||
actions: {
|
||||
cancelPlan(product_id) {
|
||||
this.redirect(product_id);
|
||||
},
|
||||
|
||||
createPlan() {
|
||||
// TODO: set default group name beforehand
|
||||
if (this.get("model.plan.metadata.group_name") === undefined) {
|
||||
this.set("model.plan.metadata", {
|
||||
group_name: this.get("model.groups.firstObject.name")
|
||||
});
|
||||
}
|
||||
|
||||
this.get("model.plan")
|
||||
.save()
|
||||
.then(() => this.redirect(this.productId))
|
||||
.catch(data =>
|
||||
bootbox.alert(data.jqXHR.responseJSON.errors.join("\n"))
|
||||
);
|
||||
},
|
||||
|
||||
updatePlan() {
|
||||
this.get("model.plan")
|
||||
.update()
|
||||
.then(() => this.redirect(this.productId))
|
||||
.catch(data =>
|
||||
bootbox.alert(data.jqXHR.responseJSON.errors.join("\n"))
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
cancelProduct() {
|
||||
this.transitionToRoute("adminPlugins.discourse-patrons.products");
|
||||
},
|
||||
|
||||
createProduct() {
|
||||
this.get("model.product")
|
||||
.save()
|
||||
.then(product => {
|
||||
this.transitionToRoute(
|
||||
"adminPlugins.discourse-patrons.products.show",
|
||||
product.id
|
||||
);
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
|
||||
updateProduct() {
|
||||
this.get("model.product")
|
||||
.update()
|
||||
.then(() => {
|
||||
this.transitionToRoute("adminPlugins.discourse-patrons.products");
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
}
|
||||
}
|
||||
});
|
||||
+1
@@ -0,0 +1 @@
|
||||
export default Ember.Controller.extend({});
|
||||
@@ -1,4 +1,3 @@
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
@@ -12,8 +11,12 @@ export default Ember.Controller.extend({
|
||||
});
|
||||
},
|
||||
|
||||
paymentSuccessHandler(paymentIntentId) {
|
||||
DiscourseURL.redirectTo(`patrons/${paymentIntentId}`);
|
||||
paymentSuccessHandler(/* paymentIntentId */) {
|
||||
bootbox.alert(I18n.t("discourse_patrons.transactions.payment.success"));
|
||||
this.transitionToRoute(
|
||||
"user.billing",
|
||||
Discourse.User.current().username.toLowerCase()
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
goBack() {
|
||||
return DiscourseURL.redirectTo("/patrons");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.set(
|
||||
"stripe",
|
||||
Stripe(Discourse.SiteSettings.discourse_patrons_public_key)
|
||||
);
|
||||
const elements = this.get("stripe").elements();
|
||||
this.set("cardElement", elements.create("card", { hidePostalCode: true }));
|
||||
},
|
||||
|
||||
actions: {
|
||||
stripePaymentHandler() {
|
||||
this.stripe.createToken(this.get("cardElement")).then(result => {
|
||||
if (result.error) {
|
||||
bootbox.alert(result.error.message);
|
||||
} else {
|
||||
const customerData = {
|
||||
source: result.token.id
|
||||
};
|
||||
|
||||
return ajax("/patrons/customers", {
|
||||
method: "post",
|
||||
data: customerData
|
||||
}).then(customer => {
|
||||
const subscription = this.get("model.subscription");
|
||||
|
||||
subscription.set("customer", customer.id);
|
||||
|
||||
if (subscription.get("plan") === undefined) {
|
||||
subscription.set("plan", this.get("model.plans.firstObject.id"));
|
||||
}
|
||||
|
||||
subscription.save().then(() => {
|
||||
bootbox.alert(
|
||||
I18n.t("discourse_patrons.transactions.payment.success")
|
||||
);
|
||||
this.transitionToRoute(
|
||||
"user.subscriptions",
|
||||
Discourse.User.current().username.toLowerCase()
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,7 +1,20 @@
|
||||
export default {
|
||||
resource: "admin.adminPlugins",
|
||||
path: "/plugins",
|
||||
|
||||
map() {
|
||||
this.route("discourse-patrons");
|
||||
this.route("discourse-patrons", function() {
|
||||
this.route("dashboard");
|
||||
|
||||
this.route("products", function() {
|
||||
this.route("show", { path: "/:product-id" }, function() {
|
||||
this.route("plans", function() {
|
||||
this.route("show", { path: "/:plan-id" });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.route("subscriptions");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
resource: "user",
|
||||
path: "users/:username",
|
||||
map() {
|
||||
this.route("billing");
|
||||
this.route("subscriptions");
|
||||
}
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user