mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Server: Add support for promotion codes
This commit is contained in:
parent
be01657ef9
commit
5b58811833
@ -59,7 +59,7 @@
|
|||||||
<script>
|
<script>
|
||||||
const urlQuery = new URLSearchParams(location.search);
|
const urlQuery = new URLSearchParams(location.search);
|
||||||
let subscriptionPeriod = 'monthly';
|
let subscriptionPeriod = 'monthly';
|
||||||
var stripe = Stripe('{{{stripeConfig.publishableKey}}}');
|
const stripe = Stripe('{{{stripeConfig.publishableKey}}}');
|
||||||
|
|
||||||
let checkoutSessionUser = null;
|
let checkoutSessionUser = null;
|
||||||
|
|
||||||
@ -82,9 +82,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var createCheckoutSession = function(priceId) {
|
var createCheckoutSession = function(priceId) {
|
||||||
const coupon = urlQuery.get('coupon') || '';
|
const promotionCode = urlQuery.get('promo') || '';
|
||||||
|
|
||||||
console.info('Creating Stripe session for price:', priceId, 'Coupon:', coupon);
|
console.info('Creating Stripe session for price:', priceId, 'Promotion code:', promotionCode);
|
||||||
|
|
||||||
return fetch("{{{stripeConfig.webhookBaseUrl}}}/stripe/createCheckoutSession", {
|
return fetch("{{{stripeConfig.webhookBaseUrl}}}/stripe/createCheckoutSession", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -92,8 +92,8 @@
|
|||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
priceId: priceId,
|
priceId,
|
||||||
coupon: coupon,
|
promotionCode,
|
||||||
email: checkoutSessionUser ? checkoutSessionUser.email : '',
|
email: checkoutSessionUser ? checkoutSessionUser.email : '',
|
||||||
})
|
})
|
||||||
}).then(async function(result) {
|
}).then(async function(result) {
|
||||||
|
@ -4,7 +4,7 @@ import { RouteType } from '../../utils/types';
|
|||||||
import { AppContext } from '../../utils/types';
|
import { AppContext } from '../../utils/types';
|
||||||
import { bodyFields } from '../../utils/requestUtils';
|
import { bodyFields } from '../../utils/requestUtils';
|
||||||
import globalConfig from '../../config';
|
import globalConfig from '../../config';
|
||||||
import { ErrorForbidden, ErrorNotFound } from '../../utils/errors';
|
import { ErrorBadRequest, ErrorForbidden, ErrorNotFound } from '../../utils/errors';
|
||||||
import { Stripe } from 'stripe';
|
import { Stripe } from 'stripe';
|
||||||
import Logger from '@joplin/lib/Logger';
|
import Logger from '@joplin/lib/Logger';
|
||||||
import getRawBody = require('raw-body');
|
import getRawBody = require('raw-body');
|
||||||
@ -35,6 +35,7 @@ async function stripeEvent(stripe: Stripe, req: any): Promise<Stripe.Event> {
|
|||||||
interface CreateCheckoutSessionFields {
|
interface CreateCheckoutSessionFields {
|
||||||
priceId: string;
|
priceId: string;
|
||||||
coupon: string;
|
coupon: string;
|
||||||
|
promotionCode: string;
|
||||||
email: string;
|
email: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,15 +146,30 @@ export const postHandlers: PostHandlers = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (fields.coupon) {
|
if (fields.coupon) {
|
||||||
delete checkoutSession.allow_promotion_codes;
|
|
||||||
|
|
||||||
checkoutSession.discounts = [
|
checkoutSession.discounts = [
|
||||||
{
|
{
|
||||||
coupon: fields.coupon.trim(),
|
coupon: fields.coupon.trim(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
} else if (fields.promotionCode) {
|
||||||
|
const p = await stripe.promotionCodes.list({ code: fields.promotionCode });
|
||||||
|
const codes = p.data;
|
||||||
|
if (!codes.length) throw new ErrorBadRequest(`Could not find promotion code: ${fields.promotionCode}`);
|
||||||
|
|
||||||
|
// Should not be possible in our setup since a unique code is
|
||||||
|
// created for each customer.
|
||||||
|
if (codes.length > 1) console.warn(`Found more than one promotion code: ${fields.promotionCode}`);
|
||||||
|
|
||||||
|
checkoutSession.discounts = [
|
||||||
|
{
|
||||||
|
promotion_code: codes[0].id,
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "You may only specify one of these parameters: allow_promotion_codes, discounts"
|
||||||
|
if (checkoutSession.discounts) delete checkoutSession.allow_promotion_codes;
|
||||||
|
|
||||||
if (fields.email) {
|
if (fields.email) {
|
||||||
checkoutSession.customer_email = fields.email.trim();
|
checkoutSession.customer_email = fields.email.trim();
|
||||||
|
|
||||||
@ -184,7 +200,7 @@ export const postHandlers: PostHandlers = {
|
|||||||
|
|
||||||
// # How to test the complete workflow locally
|
// # How to test the complete workflow locally
|
||||||
//
|
//
|
||||||
// - In website/build.ts, set the env to "dev", then build the website - `npm run watch-website`
|
// - In website/build.ts, set the env to "dev", then build the website - `npm run watchWebsite`
|
||||||
// - Start the Stripe CLI tool: `stripe listen --forward-to http://joplincloud.local:22300/stripe/webhook`
|
// - Start the Stripe CLI tool: `stripe listen --forward-to http://joplincloud.local:22300/stripe/webhook`
|
||||||
// - Copy the webhook secret, and paste it in joplin-credentials/server.env (under STRIPE_WEBHOOK_SECRET)
|
// - Copy the webhook secret, and paste it in joplin-credentials/server.env (under STRIPE_WEBHOOK_SECRET)
|
||||||
// - Start the local Joplin Server, `npm run start-dev`, running under http://joplincloud.local:22300
|
// - Start the local Joplin Server, `npm run start-dev`, running under http://joplincloud.local:22300
|
||||||
@ -422,14 +438,15 @@ const getHandlers: Record<string, StripeRouteHandler> = {
|
|||||||
<script>
|
<script>
|
||||||
var stripe = Stripe(${JSON.stringify(stripeConfig().publishableKey)});
|
var stripe = Stripe(${JSON.stringify(stripeConfig().publishableKey)});
|
||||||
|
|
||||||
var createCheckoutSession = function(priceId) {
|
var createCheckoutSession = function(priceId, promotionCode) {
|
||||||
return fetch("/stripe/createCheckoutSession", {
|
return fetch("/stripe/createCheckoutSession", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
priceId: priceId
|
priceId,
|
||||||
|
promotionCode,
|
||||||
})
|
})
|
||||||
}).then(function(result) {
|
}).then(function(result) {
|
||||||
return result.json();
|
return result.json();
|
||||||
@ -438,6 +455,7 @@ const getHandlers: Record<string, StripeRouteHandler> = {
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
Promotion code: <input id="promotion_code" type="text"/> <br/>
|
||||||
<button id="checkout_basic">Subscribe Basic</button>
|
<button id="checkout_basic">Subscribe Basic</button>
|
||||||
<button id="checkout_pro">Subscribe Pro</button>
|
<button id="checkout_pro">Subscribe Pro</button>
|
||||||
<button id="checkout_custom">Subscribe Custom</button>
|
<button id="checkout_custom">Subscribe Custom</button>
|
||||||
@ -455,7 +473,9 @@ const getHandlers: Record<string, StripeRouteHandler> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createSessionAndRedirect(priceId) {
|
function createSessionAndRedirect(priceId) {
|
||||||
createCheckoutSession(priceId).then(function(data) {
|
var promotionCode = document.getElementById('promotion_code').value;
|
||||||
|
|
||||||
|
createCheckoutSession(priceId, promotionCode).then(function(data) {
|
||||||
// Call Stripe.js method to redirect to the new Checkout page
|
// Call Stripe.js method to redirect to the new Checkout page
|
||||||
stripe
|
stripe
|
||||||
.redirectToCheckout({
|
.redirectToCheckout({
|
||||||
|
Loading…
Reference in New Issue
Block a user