Merge pull request #24417 from overleaf/mf-implement-stripe-hosted-checkout-split-test

[web] Implement stripe hosted checkout with split test

GitOrigin-RevId: 25e5ff2a46135f402cdf479623ab38c858c5640c
This commit is contained in:
M Fahru
2025-03-24 07:03:21 -07:00
committed by Copybot
parent 7c84c98d26
commit fdffa41d1c
4 changed files with 226 additions and 1 deletions
@@ -1,6 +1,12 @@
// TODO: This file may be deleted when Stripe is fully implemented to all users, so, consider deleting it
const Settings = require('@overleaf/settings')
const logger = require('@overleaf/logger')
/**
* @typedef {import('../../../../types/subscription/plan').RecurlyPlanCode} RecurlyPlanCode
* @typedef {import('../../../../types/subscription/plan').StripeLookupKey} StripeLookupKey
*/
function ensurePlansAreSetupCorrectly() {
Settings.plans.forEach(plan => {
if (typeof plan.price_in_cents !== 'number') {
@@ -18,6 +24,51 @@ function ensurePlansAreSetupCorrectly() {
})
}
const recurlyPlanCodeToStripeLookupKey = {
'professional-annual': 'professional_annual',
professional: 'professional_monthly',
professional_free_trial_7_days: 'professional_monthly',
'collaborator-annual': 'standard_annual',
collaborator: 'standard_monthly',
collaborator_free_trial_7_days: 'standard_monthly',
'student-annual': 'student_annual',
student: 'student_monthly',
student_free_trial_7_days: 'student_monthly',
}
/**
*
* @param {RecurlyPlanCode} recurlyPlanCode
* @returns {StripeLookupKey}
*/
function mapRecurlyPlanCodeToStripeLookupKey(recurlyPlanCode) {
return recurlyPlanCodeToStripeLookupKey[recurlyPlanCode]
}
const recurlyPlanCodeToPlanTypeAndPeriod = {
collaborator: { planType: 'standard', period: 'monthly' },
collaborator_free_trial_7_days: { planType: 'standard', period: 'monthly' },
'collaborator-annual': { planType: 'standard', period: 'annual' },
professional: { planType: 'professional', period: 'monthly' },
professional_free_trial_7_days: {
planType: 'professional',
period: 'monthly',
},
'professional-annual': { planType: 'professional', period: 'annual' },
student: { planType: 'student', period: 'monthly' },
student_free_trial_7_days: { planType: 'student', period: 'monthly' },
'student-annual': { planType: 'student', period: 'annual' },
}
/**
*
* @param {RecurlyPlanCode} recurlyPlanCode
* @returns {{ planType: 'standard' | 'professional' | 'student', period: 'annual' | 'monthly'}}
*/
function getPlanTypeAndPeriodFromRecurlyPlanCode(recurlyPlanCode) {
return recurlyPlanCodeToPlanTypeAndPeriod[recurlyPlanCode]
}
function findLocalPlanInSettings(planCode) {
for (const plan of Settings.plans) {
if (plan.planCode === planCode) {
@@ -30,4 +81,6 @@ function findLocalPlanInSettings(planCode) {
module.exports = {
ensurePlansAreSetupCorrectly,
findLocalPlanInSettings,
mapRecurlyPlanCodeToStripeLookupKey,
getPlanTypeAndPeriodFromRecurlyPlanCode,
}
@@ -629,7 +629,7 @@ async function getRecommendedCurrency(req, res) {
ip = req.query.ip
}
const currencyLookup = await GeoIpLookup.promises.getCurrencyCode(ip)
const countryCode = currencyLookup.countryCode
let countryCode = currencyLookup.countryCode
const recommendedCurrency = currencyLookup.currencyCode
let currency = null
@@ -640,6 +640,13 @@ async function getRecommendedCurrency(req, res) {
currency = recommendedCurrency
}
const queryCountryCode = req.query.countryCode?.toUpperCase()
// only enable countryCode testing flag on staging or dev environments
if (queryCountryCode && process.env.NODE_ENV !== 'production') {
countryCode = queryCountryCode
}
return {
currency,
recommendedCurrency,
@@ -48,4 +48,150 @@ describe('PlansLocator', function () {
expect(plan).to.be.a('null')
})
})
describe('mapRecurlyPlanCodeToStripeLookupKey', function () {
it('should map "collaborator" plan code to stripe lookup keys', function () {
const planCode = 'collaborator'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('standard_monthly')
})
it('should map "collaborator_free_trial_7_days" plan code to stripe lookup keys', function () {
const planCode = 'collaborator_free_trial_7_days'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('standard_monthly')
})
it('should map "collaborator-annual" plan code to stripe lookup keys', function () {
const planCode = 'collaborator-annual'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('standard_annual')
})
it('should map "professional" plan code to stripe lookup keys', function () {
const planCode = 'professional'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('professional_monthly')
})
it('should map "professional_free_trial_7_days" plan code to stripe lookup keys', function () {
const planCode = 'professional_free_trial_7_days'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('professional_monthly')
})
it('should map "professional-annual" plan code to stripe lookup keys', function () {
const planCode = 'professional-annual'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('professional_annual')
})
it('should map "student" plan code to stripe lookup keys', function () {
const planCode = 'student'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('student_monthly')
})
it('shoult map "student_free_trial_7_days" plan code to stripe lookup keys', function () {
const planCode = 'student_free_trial_7_days'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('student_monthly')
})
it('should map "student-annual" plan code to stripe lookup keys', function () {
const planCode = 'student-annual'
const lookupKey =
this.PlansLocator.mapRecurlyPlanCodeToStripeLookupKey(planCode)
expect(lookupKey).to.equal('student_annual')
})
})
describe('getPlanTypeAndPeriodFromRecurlyPlanCode', function () {
it('should return the plan type and period for "collaborator"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode(
'collaborator'
)
expect(planType).to.equal('standard')
expect(period).to.equal('monthly')
})
it('should return the plan type and period for "collaborator_free_trial_7_days"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode(
'collaborator_free_trial_7_days'
)
expect(planType).to.equal('standard')
expect(period).to.equal('monthly')
})
it('should return the plan type and period for "collaborator-annual"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode(
'collaborator-annual'
)
expect(planType).to.equal('standard')
expect(period).to.equal('annual')
})
it('should return the plan type and period for "professional"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode(
'professional'
)
expect(planType).to.equal('professional')
expect(period).to.equal('monthly')
})
it('should return the plan type and period for "professional_free_trial_7_days"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode(
'professional_free_trial_7_days'
)
expect(planType).to.equal('professional')
expect(period).to.equal('monthly')
})
it('should return the plan type and period for "professional-annual"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode(
'professional-annual'
)
expect(planType).to.equal('professional')
expect(period).to.equal('annual')
})
it('should return the plan type and period for "student"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode('student')
expect(planType).to.equal('student')
expect(period).to.equal('monthly')
})
it('should return the plan type and period for "student_free_trial_7_days"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode(
'student_free_trial_7_days'
)
expect(planType).to.equal('student')
expect(period).to.equal('monthly')
})
it('should return the plan type and period for "student-annual"', function () {
const { planType, period } =
this.PlansLocator.getPlanTypeAndPeriodFromRecurlyPlanCode(
'student-annual'
)
expect(planType).to.equal('student')
expect(period).to.equal('annual')
})
})
})
+19
View File
@@ -68,3 +68,22 @@ export type PriceForDisplayData = {
includesTax: boolean
perUserDisplayPrice?: string
}
export type RecurlyPlanCode =
| 'collaborator'
| 'collaborator-annual'
| 'collaborator_free_trial_7_days'
| 'professional'
| 'professional-annual'
| 'professional_free_trial_7_days'
| 'student'
| 'student-annual'
| 'student_free_trial_7_days'
export type StripeLookupKey =
| 'collaborator_monthly'
| 'collaborator_annual'
| 'professional_monthly'
| 'professional_annual'
| 'student_monthly'
| 'student_annual'