various
This commit is contained in:
parent
90f5083fb6
commit
8453d5cc03
|
@ -0,0 +1,2 @@
|
|||
load File.expand_path('../discourse_donations/charges_controller.rb', __FILE__)
|
||||
load File.expand_path('../discourse_donations/checkout_controller.rb', __FILE__)
|
|
@ -1,11 +1,18 @@
|
|||
require_dependency 'discourse'
|
||||
|
||||
module DiscourseDonations
|
||||
class ChargesController < ::ApplicationController
|
||||
|
||||
skip_before_action :verify_authenticity_token, only: [:create]
|
||||
skip_before_action :check_xhr
|
||||
before_action :set_user_and_email, only: [:create]
|
||||
before_action :set_user, only: [:index, :create]
|
||||
before_action :set_email, only: [:create]
|
||||
|
||||
def index
|
||||
if @user && @user.stripe_customer_id
|
||||
result = DiscourseDonations::Stripe.new(secret_key, stripe_options).list(@user)
|
||||
else
|
||||
result = {}
|
||||
end
|
||||
|
||||
render json: success_json.merge(result)
|
||||
end
|
||||
|
||||
def create
|
||||
Rails.logger.info user_params.inspect
|
||||
|
@ -30,6 +37,7 @@ module DiscourseDonations
|
|||
|
||||
Rails.logger.debug "Creating a Stripe payment"
|
||||
payment = DiscourseDonations::Stripe.new(secret_key, stripe_options)
|
||||
result = {}
|
||||
|
||||
begin
|
||||
Rails.logger.debug "Creating a Stripe charge for #{user_params[:amount]}"
|
||||
|
@ -40,15 +48,17 @@ module DiscourseDonations
|
|||
}
|
||||
|
||||
if user_params[:type] === 'once'
|
||||
result = payment.charge(@user, opts)
|
||||
result[:payment] = payment.charge(@user, opts)
|
||||
else
|
||||
opts[:type] = user_params[:type]
|
||||
result = payment.subscribe(@user, opts)
|
||||
result[:subscription] = payment.subscribe(@user, opts)
|
||||
end
|
||||
|
||||
rescue ::Stripe::CardError => e
|
||||
err = e.json_body[:error]
|
||||
|
||||
puts "HERE IS THE ERROR: #{e.inspect}"
|
||||
|
||||
output['messages'] << "There was an error (#{err[:type]})."
|
||||
output['messages'] << "Error code: #{err[:code]}" if err[:code]
|
||||
output['messages'] << "Decline code: #{err[:decline_code]}" if err[:decline_code]
|
||||
|
@ -57,8 +67,21 @@ module DiscourseDonations
|
|||
render(json: output) && (return)
|
||||
end
|
||||
|
||||
if result['paid'] == true || result['status'] === 'active'
|
||||
output['messages'] << I18n.l(Time.now(), format: :long) + ': ' + I18n.t('donations.payment.success')
|
||||
if (result[:charge] && result[:charge]['paid'] == true) ||
|
||||
(result[:subscription] && result[:subscription]['status'] === 'active')
|
||||
|
||||
output['messages'] << I18n.t('donations.payment.success')
|
||||
|
||||
if result[:charge]
|
||||
output['messages'] << " #{I18n.t('donations.payment.receipt_sent', email: @email)}"
|
||||
end
|
||||
|
||||
if result[:subscription]
|
||||
output['messages'] << " #{I18n.t('donations.payment.invoice_sent', email: @email)}"
|
||||
end
|
||||
|
||||
output['charge'] = result[:charge] if result[:charge]
|
||||
output['subscription'] = result[:subscription] if result[:subscription]
|
||||
|
||||
output['rewards'] << { type: :group, name: group_name } if group_name
|
||||
output['rewards'] << { type: :badge, name: badge_name } if badge_name
|
||||
|
@ -105,23 +128,23 @@ module DiscourseDonations
|
|||
params.permit(:user_id, :name, :username, :email, :password, :stripeToken, :type, :amount, :create_account)
|
||||
end
|
||||
|
||||
def email
|
||||
end
|
||||
|
||||
def set_user_and_email
|
||||
def set_user
|
||||
user = current_user
|
||||
|
||||
if user_params[:user_id].present?
|
||||
user = User.find(user_params[:user_id])
|
||||
end
|
||||
|
||||
@user = user
|
||||
end
|
||||
|
||||
def set_email
|
||||
if user_params[:email].present?
|
||||
email = user_params[:email]
|
||||
else
|
||||
email = user.try(:email)
|
||||
email = @user.try(:email)
|
||||
end
|
||||
|
||||
@user = user
|
||||
@email = email
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
module DiscourseDonations
|
||||
class PaymentsController < ApplicationController
|
||||
def index
|
||||
render json: {}
|
||||
end
|
||||
|
||||
def show
|
||||
render json: {}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
module DiscourseDonations
|
||||
module ApplicationHelper
|
||||
end
|
||||
end
|
|
@ -1,5 +1,3 @@
|
|||
RECURRING_DONATION_PRODUCT_ID = 'discourse_donation_recurring'
|
||||
|
||||
module DiscourseDonations
|
||||
class Stripe
|
||||
attr_reader :charge, :currency, :description
|
||||
|
@ -30,7 +28,8 @@ module DiscourseDonations
|
|||
customer: customer.id,
|
||||
amount: opts[:amount],
|
||||
description: @description,
|
||||
currency: @currency
|
||||
currency: @currency,
|
||||
receipt_email: customer.email
|
||||
)
|
||||
|
||||
@charge
|
||||
|
@ -56,7 +55,49 @@ module DiscourseDonations
|
|||
@subscription
|
||||
end
|
||||
|
||||
def customer(user, email, source)
|
||||
def list(user)
|
||||
customer = customer(user)
|
||||
result = {}
|
||||
|
||||
raw_invoices = ::Stripe::Invoice.list(customer: customer.id)
|
||||
raw_invoices = raw_invoices.is_a?(Object) ? raw_invoices['data'] : []
|
||||
|
||||
raw_charges = ::Stripe::Charge.list(customer: customer.id)
|
||||
raw_charges = raw_charges.is_a?(Object) ? raw_charges['data'] : []
|
||||
|
||||
if raw_invoices.any?
|
||||
raw_subscriptions = ::Stripe::Subscription.list(customer: customer.id)['data']
|
||||
|
||||
if raw_subscriptions.any?
|
||||
subscriptions = []
|
||||
|
||||
raw_subscriptions.each do |subscription|
|
||||
invoices = raw_invoices.select do |invoice|
|
||||
invoice['subscription'] === subscription['id']
|
||||
end
|
||||
|
||||
subscriptions.push(
|
||||
subscription: subscription,
|
||||
invoices: invoices
|
||||
)
|
||||
end
|
||||
|
||||
result[:subscriptions] = subscriptions
|
||||
end
|
||||
|
||||
## filter out any charges related to subscriptions
|
||||
raw_invoice_ids = raw_invoices.map { |i| i['id'] }
|
||||
raw_charges = raw_charges.select { |c| raw_invoice_ids.exclude?(c['invoice']) }
|
||||
end
|
||||
|
||||
if raw_charges.any?
|
||||
result[:charges] = raw_charges
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def customer(user, email = nil, source = nil)
|
||||
if user && user.stripe_customer_id
|
||||
::Stripe::Customer.retrieve(user.stripe_customer_id)
|
||||
else
|
||||
|
@ -84,8 +125,8 @@ module DiscourseDonations
|
|||
|
||||
products = ::Stripe::Product.list(type: 'service')
|
||||
|
||||
if products['data'] && products['data'].any? { |p| p['id'] === RECURRING_DONATION_PRODUCT_ID }
|
||||
product = RECURRING_DONATION_PRODUCT_ID
|
||||
if products['data'] && products['data'].any? { |p| p['id'] === product_id }
|
||||
product = product_id
|
||||
else
|
||||
result = create_product
|
||||
product = result['id']
|
||||
|
@ -94,7 +135,7 @@ module DiscourseDonations
|
|||
::Stripe::Plan.create(
|
||||
id: id,
|
||||
nickname: nickname,
|
||||
interval: type.tr('ly', ''),
|
||||
interval: type,
|
||||
currency: @currency,
|
||||
product: product,
|
||||
amount: amount.to_i
|
||||
|
@ -103,12 +144,20 @@ module DiscourseDonations
|
|||
|
||||
def create_product
|
||||
::Stripe::Product.create(
|
||||
id: RECURRING_DONATION_PRODUCT_ID,
|
||||
name: "Discourse Donation Recurring",
|
||||
id: product_id,
|
||||
name: product_name,
|
||||
type: 'service'
|
||||
)
|
||||
end
|
||||
|
||||
def product_id
|
||||
@product_id ||= "#{SiteSetting.title}_recurring_donation"
|
||||
end
|
||||
|
||||
def product_name
|
||||
@product_name ||= I18n.t('discourse_donations.recurring', site_title: SiteSetting.title)
|
||||
end
|
||||
|
||||
def create_plan_id(type)
|
||||
"discourse_donation_recurring_#{type}"
|
||||
end
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
load File.expand_path('../discourse_donations/rewards.rb', __FILE__)
|
||||
load File.expand_path('../discourse_donations/stripe.rb', __FILE__)
|
|
@ -0,0 +1,5 @@
|
|||
export default Ember.Component.extend({
|
||||
classNames: 'donation-list',
|
||||
hasSubscriptions: Ember.computed.notEmpty('subscriptions'),
|
||||
hasCharges: Ember.computed.notEmpty('charges')
|
||||
})
|
|
@ -1,5 +1,6 @@
|
|||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { getRegister } from 'discourse-common/lib/get-owner';
|
||||
import { formatAnchor, zeroDecimalCurrencies } from '../lib/donation-utilities';
|
||||
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
|
@ -11,12 +12,13 @@ export default Ember.Component.extend({
|
|||
|
||||
init() {
|
||||
this._super();
|
||||
this.set('anon', (!Discourse.User.current()));
|
||||
this.set('settings', getRegister(this).lookup('site-settings:main'));
|
||||
this.set('create_accounts', this.get('anon') && this.get('settings').discourse_donations_enable_create_accounts);
|
||||
this.set('stripe', Stripe(this.get('settings').discourse_donations_public_key));
|
||||
const user = this.get('currentUser');
|
||||
const settings = Discourse.SiteSettings;
|
||||
|
||||
const types = Discourse.SiteSettings.discourse_donations_types.split('|') || [];
|
||||
this.set('create_accounts', !user && settings.discourse_donations_enable_create_accounts);
|
||||
this.set('stripe', Stripe(settings.discourse_donations_public_key));
|
||||
|
||||
const types = settings.discourse_donations_types.split('|') || [];
|
||||
const amounts = this.get('donateAmounts');
|
||||
|
||||
this.setProperties({
|
||||
|
@ -38,21 +40,7 @@ export default Ember.Component.extend({
|
|||
|
||||
@computed('type')
|
||||
period(type) {
|
||||
let anchor;
|
||||
|
||||
if (type === 'weekly') {
|
||||
anchor = moment().format('dddd');
|
||||
}
|
||||
|
||||
if (type === 'monthly') {
|
||||
anchor = moment().format('Do');
|
||||
}
|
||||
|
||||
if (type === 'yearly') {
|
||||
anchor = moment().format('MMMM D');
|
||||
}
|
||||
|
||||
return I18n.t(`discourse_donations.period.${type}`, { anchor });
|
||||
return I18n.t(`discourse_donations.period.${type}`, { anchor: formatAnchor(type) });
|
||||
},
|
||||
|
||||
@computed
|
||||
|
@ -73,9 +61,23 @@ export default Ember.Component.extend({
|
|||
@computed('stripe')
|
||||
card(stripe) {
|
||||
let elements = stripe.elements();
|
||||
return elements.create('card', {
|
||||
hidePostalCode: !this.get('settings').discourse_donations_zip_code
|
||||
let card = elements.create('card', {
|
||||
hidePostalCode: !Discourse.SiteSettings.discourse_donations_zip_code
|
||||
});
|
||||
|
||||
card.addEventListener('change', (event) => {
|
||||
if (event.error) {
|
||||
this.set('stripeError', event.error.message);
|
||||
} else {
|
||||
this.set('stripeError', '');
|
||||
}
|
||||
|
||||
if (event.elementType === 'card' && event.complete) {
|
||||
this.set('stripeReady', true);
|
||||
}
|
||||
});
|
||||
|
||||
return card;
|
||||
},
|
||||
|
||||
@computed('amount')
|
||||
|
@ -92,6 +94,21 @@ export default Ember.Component.extend({
|
|||
return amount;
|
||||
},
|
||||
|
||||
@computed('currentUser', 'email')
|
||||
userReady(currentUser, email) {
|
||||
return currentUser || email;
|
||||
},
|
||||
|
||||
@computed('userReady', 'stripeReady')
|
||||
formIncomplete(userReady, stripeReady) {
|
||||
return !userReady || !stripeReady;
|
||||
},
|
||||
|
||||
@computed('transactionInProgress', 'formIncomplete')
|
||||
disableSubmit(transactionInProgress, formIncomplete) {
|
||||
return transactionInProgress || formIncomplete;
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
this.get('card').mount('#card-element');
|
||||
|
@ -130,27 +147,52 @@ export default Ember.Component.extend({
|
|||
|
||||
submitStripeCard() {
|
||||
let self = this;
|
||||
self.set('transactionInProgress', true);
|
||||
this.set('transactionInProgress', true);
|
||||
|
||||
this.get('stripe').createToken(this.get('card')).then(data => {
|
||||
self.set('result', []);
|
||||
|
||||
if (data.error) {
|
||||
self.set('result', data.error.message);
|
||||
this.setProperties({
|
||||
stripeError: data.error.message,
|
||||
stripeReady: false
|
||||
});
|
||||
self.endTranscation();
|
||||
} else {
|
||||
const transactionFeeEnabled = Discourse.SiteSettings.discourse_donations_enable_transaction_fee;
|
||||
const amount = transactionFeeEnabled ? this.get('totalAmount') : this.get('amount');
|
||||
const settings = Discourse.SiteSettings;
|
||||
|
||||
const transactionFeeEnabled = settings.discourse_donations_enable_transaction_fee;
|
||||
let amount = transactionFeeEnabled ? this.get('totalAmount') : this.get('amount');
|
||||
|
||||
if (zeroDecimalCurrencies.indexOf(setting.discourse_donations_currency) === -1) {
|
||||
amount = amount * 100;
|
||||
}
|
||||
|
||||
let params = {
|
||||
stripeToken: data.token.id,
|
||||
type: self.get('type'),
|
||||
amount: amount * 100,
|
||||
amount,
|
||||
email: self.get('email'),
|
||||
username: self.get('username'),
|
||||
create_account: self.get('create_accounts')
|
||||
};
|
||||
|
||||
if(!self.get('paymentSuccess')) {
|
||||
ajax('/charges', { data: params, method: 'post' }).then(d => {
|
||||
ajax('/donate/charges', { data: params, method: 'post' }).then(d => {
|
||||
let donation = d.donation;
|
||||
|
||||
if (donation) {
|
||||
if (donation.object === 'subscription') {
|
||||
let subscriptions = this.get('subscriptions') || [];
|
||||
subscriptions.push(donation);
|
||||
this.set('subscriptions', subscriptions);
|
||||
} else if (donation.object === 'charge') {
|
||||
let charges = this.get('charges') || [];
|
||||
charges.push(donation);
|
||||
this.set('charges', charges);
|
||||
}
|
||||
}
|
||||
|
||||
self.concatMessages(d.messages);
|
||||
self.endTranscation();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
loadingDonations: false,
|
||||
|
||||
@computed('charges', 'subscriptions')
|
||||
hasDonations(charges, subscriptions) {
|
||||
return (charges && charges.length > 0) ||
|
||||
(subscriptions && subscriptions.length > 0);
|
||||
}
|
||||
})
|
|
@ -0,0 +1,56 @@
|
|||
import { registerHelper } from "discourse-common/lib/helpers";
|
||||
import { formatAnchor, formatAmount } from '../lib/donation-utilities';
|
||||
|
||||
registerHelper("donation-subscription", function([subscription]) {
|
||||
let currency = subscription.plan.currency.toUpperCase();
|
||||
let html = currency;
|
||||
|
||||
html += ` ${formatAmount(subscription.plan.amount, currency)} `;
|
||||
|
||||
html += I18n.t(`discourse_donations.period.${subscription.plan.interval}`, {
|
||||
anchor: formatAnchor(subscription.plan.interval, moment.unix(subscription.billing_cycle_anchor))
|
||||
});
|
||||
|
||||
return new Handlebars.SafeString(html);
|
||||
});
|
||||
|
||||
registerHelper("donation-invoice", function([invoice]) {
|
||||
let details = invoice.lines.data[0];
|
||||
let html = I18n.t('discourse_donations.invoice_prefix');
|
||||
let currency = details.currency.toUpperCase();
|
||||
|
||||
html += ` ${currency}`;
|
||||
|
||||
html += ` ${formatAmount(details.amount, currency)} `;
|
||||
|
||||
html += I18n.t(`discourse_donations.period.once`, {
|
||||
anchor: formatAnchor('once', moment.unix(invoice.date))
|
||||
});
|
||||
|
||||
if (invoice.invoice_pdf) {
|
||||
html += ` (<a href='${invoice.invoice_pdf}' target='_blank'>${I18n.t('discourse_donations.invoice')}</a>)`;
|
||||
}
|
||||
|
||||
return new Handlebars.SafeString(html);
|
||||
});
|
||||
|
||||
registerHelper("donation-charge", function([charge]) {
|
||||
let html = I18n.t('discourse_donations.invoice_prefix');
|
||||
let currency = charge.currency.toUpperCase();
|
||||
|
||||
html += ` ${currency}`;
|
||||
|
||||
html += ` ${formatAmount(charge.amount, currency)} `;
|
||||
|
||||
html += I18n.t(`discourse_donations.period.once`, {
|
||||
anchor: formatAnchor('once', moment.unix(charge.created))
|
||||
});
|
||||
|
||||
if (charge.receipt_email) {
|
||||
html += `. ${I18n.t('discourse_donations.receipt', {
|
||||
email: charge.receipt_email
|
||||
})}`;
|
||||
}
|
||||
|
||||
return new Handlebars.SafeString(html);
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
const formatAnchor = function(type = null, time = moment()) {
|
||||
let format;
|
||||
|
||||
switch(type) {
|
||||
case 'once':
|
||||
format = 'Do MMMM YYYY';
|
||||
break;
|
||||
case 'week':
|
||||
format = 'dddd';
|
||||
break;
|
||||
case 'month':
|
||||
format = 'Do';
|
||||
break;
|
||||
case 'year':
|
||||
format = 'MMMM D';
|
||||
break;
|
||||
default:
|
||||
format = 'dddd';
|
||||
}
|
||||
|
||||
return moment(time).format(format);
|
||||
}
|
||||
|
||||
const zeroDecimalCurrencies = ['MGA', 'BIF', 'CLP', 'PYG', 'DFJ', 'RWF', 'GNF', 'UGX', 'JPY', 'VND', 'VUV', 'XAF', 'KMF', 'KRW', 'XOF', 'XPF'];
|
||||
|
||||
const formatAmount = function(amount, currency) {
|
||||
let zeroDecimal = zeroDecimalCurrencies.indexOf(currency) > -1;
|
||||
return zeroDecimal ? amount : (amount / 100).toFixed(2);
|
||||
}
|
||||
|
||||
export { formatAnchor, formatAmount, zeroDecimalCurrencies }
|
|
@ -0,0 +1,20 @@
|
|||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
setupController(controller) {
|
||||
controller.set('loadingDonations', true);
|
||||
|
||||
ajax('/donate/charges').then((result) => {
|
||||
if (result && (result.charges || result.subscriptions)) {
|
||||
controller.setProperties({
|
||||
charges: result.charges,
|
||||
subscriptions: result.subscriptions
|
||||
});
|
||||
}
|
||||
}).catch(popupAjaxError).finally(() => {
|
||||
controller.set('loadingDonations', false);
|
||||
})
|
||||
}
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
{{#if hasCharges}}
|
||||
<h4>{{i18n 'discourse_donations.donations.charges'}}</h4>
|
||||
<ul>
|
||||
{{#each charges as |charge|}}
|
||||
<li>{{donation-charge charge}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
|
||||
{{#if hasSubscriptions}}
|
||||
<h4>{{i18n 'discourse_donations.donations.subscriptions'}}</h4>
|
||||
<ul>
|
||||
{{#each subscriptions as |s|}}
|
||||
<li class="underline">{{donation-subscription s.subscription}}</li>
|
||||
|
||||
{{#if s.invoices}}
|
||||
{{#each s.invoices as |invoice|}}
|
||||
<li>{{donation-invoice invoice}}</li>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
|
@ -1,5 +1,4 @@
|
|||
<form id="payment-form" class="form-horizontal">
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
{{i18n 'discourse_donations.type'}}
|
||||
|
@ -48,14 +47,20 @@
|
|||
|
||||
<div class="control-group" style="width: 550px;">
|
||||
<label class="control-label" for="card-element">{{i18n 'discourse_donations.card'}}</label>
|
||||
<div id="card-element" class="controls"></div>
|
||||
<div class="controls">
|
||||
<div id="card-element"></div>
|
||||
{{#if stripeError}}
|
||||
<div class="instructions stripe-error">{{stripeError}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if anon}}
|
||||
{{#unless currentUser}}
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="card-element">{{i18n 'user.email.title'}}</label>
|
||||
<div class="controls">
|
||||
{{text-field value=email}}
|
||||
<div class="instructions">{{i18n 'discourse_donations.email_instructions'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -81,11 +86,11 @@
|
|||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="control-group save-button">
|
||||
<div class="controls">
|
||||
{{#d-button action="submitStripeCard" disabled=transactionInProgress class="btn btn-primary btn-payment"}}
|
||||
{{#d-button action="submitStripeCard" disabled=disableSubmit class="btn btn-primary btn-payment"}}
|
||||
{{#if create_accounts}}
|
||||
{{i18n 'discourse_donations.submit_with_create_account'}}
|
||||
{{else}}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{{#if siteSettings.discourse_donations_enabled}}
|
||||
<a href="/donate">
|
||||
{{i18n 'discourse_donations.nav_item'}}
|
||||
</a>
|
||||
<a href="/donate">
|
||||
{{i18n 'discourse_donations.nav_item'}}
|
||||
</a>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
<h1>{{i18n 'discourse_donations.title' site_name=siteSettings.title}}</h1>
|
||||
<h3>{{i18n 'discourse_donations.title' site_name=siteSettings.title}}</h3>
|
||||
|
||||
<div class="donations-page-description">
|
||||
{{cook-text siteSettings.discourse_donations_page_description}}
|
||||
</div>
|
||||
|
||||
<div class="donations-page-payment">
|
||||
{{stripe-card}}
|
||||
{{stripe-card charges=charges subscriptions=subscriptions}}
|
||||
</div>
|
||||
|
||||
{{#if currentUser}}
|
||||
<div class="donations-page-donations">
|
||||
<h3>{{i18n 'discourse_donations.donations.title'}}</h3>
|
||||
{{#if loadingDonations}}
|
||||
{{loading-spinner size='small'}}
|
||||
{{else}}
|
||||
{{#if hasDonations}}
|
||||
{{donation-list charges=charges subscriptions=subscriptions}}
|
||||
{{else}}
|
||||
{{i18n 'discourse_donations.donations.none'}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -13,7 +13,7 @@ div.stripe-errors {
|
|||
}
|
||||
|
||||
.donations-page-payment {
|
||||
padding-top: 60px;
|
||||
padding: 30px 0;
|
||||
|
||||
#payment-form {
|
||||
.control-label {
|
||||
|
@ -27,6 +27,11 @@ div.stripe-errors {
|
|||
input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.stripe-error {
|
||||
margin-top: 5px;
|
||||
color: $danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,3 +54,19 @@ div.stripe-errors {
|
|||
width: 400px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.body-page .donations-page-donations {
|
||||
margin-bottom: 40px;
|
||||
|
||||
.donation-list {
|
||||
ul {
|
||||
margin-left: 0;
|
||||
list-style: none;
|
||||
|
||||
li.underline {
|
||||
border-bottom: 1px solid $primary-medium;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,16 @@ en:
|
|||
|
||||
js:
|
||||
discourse_donations:
|
||||
title: Donate
|
||||
nav_item: Donate
|
||||
title: "Make a Donation"
|
||||
amount: Amount
|
||||
card: Card
|
||||
submit: Make Payment
|
||||
submit_with_create_account: Make Payment and Create Account
|
||||
invoice: "Invoice"
|
||||
invoice_prefix: "You gave"
|
||||
receipt: "Receipt sent to {{email}}."
|
||||
email_instructions: "Required to send you a receipt. Not used for marketing."
|
||||
transaction_fee:
|
||||
label: "Include transaction fee of {{currency}} {{transactionFee}}"
|
||||
description: "When you make a donation we get charged a transaction fee. If you would like to help us out with this fee, check this box and it will be included in your donation."
|
||||
|
@ -38,11 +42,16 @@ en:
|
|||
type: "Type"
|
||||
types:
|
||||
once: "Once"
|
||||
weekly: "Weekly"
|
||||
monthly: "Monthly"
|
||||
yearly: "Yearly"
|
||||
week: "Weekly"
|
||||
month: "Monthly"
|
||||
year: "Yearly"
|
||||
period:
|
||||
once: "once."
|
||||
weekly: "every week on {{anchor}}."
|
||||
monthly: "on the {{anchor}} of every month."
|
||||
yearly: "every year on {{anchor}}."
|
||||
once: "on {{anchor}}"
|
||||
week: "every week on {{anchor}}"
|
||||
month: "on the {{anchor}} of every month"
|
||||
year: "every year on {{anchor}}"
|
||||
donations:
|
||||
title: "Your Donations"
|
||||
charges: "Once Off"
|
||||
subscriptions: "Recurring"
|
||||
none: "You haven't made a donation yet."
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
en:
|
||||
donations:
|
||||
recurring: "%{site_title} recurring donation"
|
||||
payment:
|
||||
success: 'Thank you. Your donation has been successful'
|
||||
success: 'Thank you, your donation has been successful.'
|
||||
receipt_sent: 'A receipt has been sent to %{email}.'
|
||||
invoice_sent: 'An invoice has been sent to %{email}.'
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
DiscourseDonations::Engine.routes.draw do
|
||||
resources :charges, only: [:create]
|
||||
get '/' => 'charges#index'
|
||||
resources :charges, only: [:index, :create]
|
||||
resources :checkout, only: [:create]
|
||||
get 'users/:username/payments' => 'payments#show'
|
||||
get 'donate' => 'payments#show'
|
||||
end
|
||||
|
|
|
@ -53,9 +53,9 @@ plugins:
|
|||
discourse_donations_types:
|
||||
client: true
|
||||
type: list
|
||||
default: 'monthly|once'
|
||||
default: 'month|once'
|
||||
choices:
|
||||
- yearly
|
||||
- monthly
|
||||
- weekly
|
||||
- year
|
||||
- month
|
||||
- week
|
||||
- once
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
module ::DiscourseDonations
|
||||
class Engine < ::Rails::Engine
|
||||
engine_name 'discourse-donations'
|
||||
|
|
16
plugin.rb
16
plugin.rb
|
@ -2,12 +2,10 @@
|
|||
# about: Integrates Stripe into Discourse to allow forum visitors to make donations
|
||||
# version: 1.11.1
|
||||
# url: https://github.com/chrisbeach/discourse-donations
|
||||
# authors: Rimian Perkins, Chris Beach
|
||||
# authors: Rimian Perkins, Chris Beach, Angus McLeod
|
||||
|
||||
gem 'stripe', '2.8.0'
|
||||
|
||||
load File.expand_path('../lib/discourse_donations/engine.rb', __FILE__)
|
||||
|
||||
register_asset "stylesheets/discourse-donations.scss"
|
||||
|
||||
enabled_site_setting :discourse_donations_enabled
|
||||
|
@ -17,7 +15,15 @@ register_html_builder('server:before-head-close') do
|
|||
end
|
||||
|
||||
after_initialize do
|
||||
load File.expand_path('../lib/discourse_donations/engine.rb', __FILE__)
|
||||
load File.expand_path('../config/routes.rb', __FILE__)
|
||||
load File.expand_path('../app/controllers/controllers.rb', __FILE__)
|
||||
load File.expand_path('../app/jobs/jobs.rb', __FILE__)
|
||||
load File.expand_path('../app/services/services.rb', __FILE__)
|
||||
|
||||
Discourse::Application.routes.append do
|
||||
mount ::DiscourseDonations::Engine, at: 'donate'
|
||||
end
|
||||
|
||||
class ::User
|
||||
def stripe_customer_id
|
||||
|
@ -29,7 +35,3 @@ after_initialize do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Discourse::Application.routes.prepend do
|
||||
mount ::DiscourseDonations::Engine, at: '/'
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue