diff --git a/services/web/app/src/Features/Subscription/RecurlyWrapper.js b/services/web/app/src/Features/Subscription/RecurlyWrapper.js index 9660a8c5dd..5830b69bb2 100644 --- a/services/web/app/src/Features/Subscription/RecurlyWrapper.js +++ b/services/web/app/src/Features/Subscription/RecurlyWrapper.js @@ -286,6 +286,14 @@ const promises = { { userId: user._id }, 'starting process of creating paypal subscription' ) + if (subscriptionDetails.subscription_add_ons) { + // TODO: support flexible licensing in paypal flow + const err = new Error('Add-on purchase not supported') + OError.tag(err, 'error in paypal subscription creation process', { + user_id: user._id, + }) + throw err + } // We use waterfall through each of these actions in sequence // passing a `cache` object along the way. The cache is initialized // with required data, and `async.apply` to pass the cache to the first function @@ -343,6 +351,10 @@ const promises = { data.account.billing_info.three_d_secure_action_result_token_id = recurlyTokenIds.threeDSecureActionResult } + if (subscriptionDetails.subscription_add_ons) { + data.subscription_add_ons = subscriptionDetails.subscription_add_ons + } + const customFields = getCustomFieldsFromSubscriptionDetails(subscriptionDetails) if (customFields) { diff --git a/services/web/frontend/js/utils/meta.ts b/services/web/frontend/js/utils/meta.ts index 941cfd32c6..b1b8fc948d 100644 --- a/services/web/frontend/js/utils/meta.ts +++ b/services/web/frontend/js/utils/meta.ts @@ -130,6 +130,7 @@ export interface Meta { 'ol-languages': SpellCheckLanguage[] 'ol-learnedWords': string[] 'ol-legacyEditorThemes': string[] + 'ol-licenseQuantity': number | undefined 'ol-linkSharingEnforcement': boolean 'ol-linkSharingWarning': boolean 'ol-loadingText': string diff --git a/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js b/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js index be55517aed..b2144b039b 100644 --- a/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js +++ b/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js @@ -579,6 +579,9 @@ describe('RecurlyWrapper', function () { state: 'some_state', zip: 'some_zip', }, + subscription_add_ons: [ + { subscription_add_on: { add_on_code: 'test_add_on', quantity: 2 } }, + ], ITMCampaign: 'itm-campaign-value', ITMContent: 'itm-content-value', ITMReferrer: 'itm-referrer-value', @@ -633,6 +636,12 @@ describe('RecurlyWrapper', function () { a-3d-token-id + + + test_add_on + 2 + + itm_campaign @@ -884,6 +893,31 @@ describe('RecurlyWrapper', function () { this.createSubscription.callCount.should.equal(0) }) }) + + it('throw error if purchase with addon', async function () { + this.subscriptionDetails = { + currencyCode: 'EUR', + plan_code: 'some_plan_code', + coupon_code: '', + isPaypal: true, + address: { + address1: 'addr_one', + address2: 'addr_two', + country: 'some_country', + state: 'some_state', + zip: 'some_zip', + }, + subscription_add_ons: [ + { subscription_add_on: { add_on_code: 'test_add_on', quantity: 2 } }, + ], + } + await expect(this.call()).to.be.rejected + this.checkAccountExists.callCount.should.equal(0) + this.createAccount.callCount.should.equal(0) + this.createBillingInfo.callCount.should.equal(0) + this.setAddressAndCompanyBillingInfo.callCount.should.equal(0) + this.createSubscription.callCount.should.equal(0) + }) }) describe('paypal actions', function () { diff --git a/services/web/types/recurly/pricing/subscription.ts b/services/web/types/recurly/pricing/subscription.ts index e018daf085..744d08c3ea 100644 --- a/services/web/types/recurly/pricing/subscription.ts +++ b/services/web/types/recurly/pricing/subscription.ts @@ -48,13 +48,18 @@ interface Coupon { redemption_resource: string } +interface AddOn { + code: string + quantity: number +} + // Extending the default interface as it lacks the `items` prop export interface SubscriptionPricingInstanceCustom extends SubscriptionPricingInstance, SubscriptionPricingState { id: string items: { - addons: unknown[] + addons: AddOn[] address?: Address coupon?: Coupon currency: string