1
0
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:
Laurent Cozic 2021-10-07 14:19:40 +01:00
parent be01657ef9
commit 5b58811833
2 changed files with 32 additions and 12 deletions

View File

@ -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) {

View File

@ -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({