FEATURE: Add new stripe based pricing table

This commit adds the new stripe based pricing table.
If the user is logged in, the email field will be prepopulated with the users email.

The pricing table can be configured in the stripe dashboard.

Once the discourse_subscriptions_pricing_table setting is filled with the pricing table embed code from the stripe dashboard,
the pricing table will be displayed on /subscriptions

For more details see https://stripe.com/docs/payments/checkout/pricing-table
This commit is contained in:
spirobel 2023-07-09 05:17:06 +08:00 committed by Blake Erickson
parent dcde03d7c4
commit 13d23dc3fa
8 changed files with 92 additions and 4 deletions

View File

@ -0,0 +1,7 @@
module StripeDiscourseSubscriptions
class PricingtableController < ::ApplicationController
def index
head 200
end
end
end

View File

@ -0,0 +1,35 @@
import Controller from "@ember/controller";
import Ember from 'ember';
import I18n from "I18n";
export default Controller.extend({
init() {
// Perform any initialization logic here
this._super(...arguments);
// Additional custom initialization code
if(this.currentUser){
this.currentUser.checkEmail().then((r)=>this.set('email',this.currentUser.email))
}
},
pricingTable: Ember.computed('email', function() {
try{
const pricing_table_info = JSON.parse(this.siteSettings.discourse_subscriptions_pricing_table)
if(this.currentUser){
return`<stripe-pricing-table
pricing-table-id="${pricing_table_info.pricingTableId}"
publishable-key="${pricing_table_info.publishableKey}"
customer-email="${this.email}"></stripe-pricing-table>`;
} else {
return`<stripe-pricing-table
pricing-table-id="${pricing_table_info.pricingTableId}"
publishable-key="${pricing_table_info.publishableKey}"
></stripe-pricing-table>`;
}
} catch(error){
return I18n.t("discourse_subscriptions.subscribe.no_products")
}
}),
});

View File

@ -12,7 +12,7 @@ export default {
api.addNavigationBarItem({
name: "subscribe",
displayName: I18n.t("discourse_subscriptions.navigation.subscribe"),
href: "/s",
href: "/subscriptions",
});
}
@ -23,6 +23,30 @@ export default {
href: `/u/${user.username}/billing/subscriptions`,
content: "Billing",
});
if(user.admin){
api.modifyClassStatic('model:site-setting', {
pluginId: 'discourse-subscriptions',
update(key, value, opts = {}) {
if(key ==="discourse_subscriptions_pricing_table"){
const inputString = value;
// Extract pricing-table-id
const pricingTableIdRegex = /pricing-table-id="([^"]+)"/;
const pricingTableIdMatch = inputString.match(pricingTableIdRegex);
const pricingTableId = pricingTableIdMatch ? pricingTableIdMatch[1] : null;
// Extract publishable-key
const publishableKeyRegex = /publishable-key="([^"]+)"/;
const publishableKeyMatch = inputString.match(publishableKeyRegex);
const publishableKey = publishableKeyMatch ? publishableKeyMatch[1] : null;
if(pricingTableId && publishableKey){
value = JSON.stringify({pricingTableId,publishableKey})
}
}
this._super(key, value, opts);
}
});
}
}
});
},

View File

@ -1,5 +1,3 @@
export default function () {
this.route("subscribe", { path: "/s" }, function () {
this.route("show", { path: "/:subscription-id" });
});
this.route("subscriptions")
}

View File

@ -0,0 +1,3 @@
<div class="container">
{{{pricingTable}}}
</div>

View File

@ -7,6 +7,7 @@ en:
site_settings:
discourse_subscriptions_enabled: Enable the Discourse Subscriptions plugin.
discourse_subscriptions_extra_nav_subscribe: Show the subscribe button in the primary navigation
discourse_subscriptions_pricing_table: Copy and paste the stripe pricing table embed code here
discourse_subscriptions_public_key: Stripe Publishable Key
discourse_subscriptions_secret_key: Stripe Secret Key
discourse_subscriptions_webhook_secret: Stripe Webhook Secret

View File

@ -4,6 +4,10 @@ discourse_subscriptions:
discourse_subscriptions_extra_nav_subscribe:
default: false
client: true
discourse_subscriptions_pricing_table:
default: ''
client: true
refresh: true
discourse_subscriptions_public_key:
default: ''
client: true

View File

@ -21,6 +21,9 @@ register_svg_icon "far-credit-card" if respond_to?(:register_svg_icon)
register_html_builder("server:before-head-close") do |controller|
"<script src='https://js.stripe.com/v3/' nonce='#{controller.helpers.csp_nonce_placeholder}'></script>"
end
register_html_builder("server:before-head-close") do
'<script async src="https://js.stripe.com/v3/pricing-table.js"></script>'
end
extend_content_security_policy(script_src: %w[https://js.stripe.com/v3/ https://hooks.stripe.com])
@ -65,6 +68,19 @@ require_relative "app/controllers/concerns/group"
after_initialize do
::Stripe.api_version = "2024-04-10"
module ::StripeDiscourseSubscriptions
class Engine < ::Rails::Engine
engine_name 'stripe-discourse-subscriptions'
isolate_namespace StripeDiscourseSubscriptions
end
end
StripeDiscourseSubscriptions::Engine.routes.draw do
get "/" => "pricingtable#index"
end
require_relative "app/controllers/discourse_subscriptions/pricingtable_controller.rb"
Discourse::Application.routes.append { mount ::StripeDiscourseSubscriptions::Engine, at: "subscriptions" }
::Stripe.set_app_info(
"Discourse Subscriptions",
version: "2.8.2",