Skip to content

Feat: upgrade, downgrade, and cross-grade functionality for the Stripe payment gateway.#247

Merged
VeenaYemmiganur merged 18 commits intomasterfrom
stripe-up-downgrade
Feb 17, 2026
Merged

Feat: upgrade, downgrade, and cross-grade functionality for the Stripe payment gateway.#247
VeenaYemmiganur merged 18 commits intomasterfrom
stripe-up-downgrade

Conversation

@VeenaYemmiganur
Copy link
Contributor

@VeenaYemmiganur VeenaYemmiganur commented Feb 5, 2026

Description

Implementing the upgrade, downgrade, and cross-grade functionality for the Stripe payment gateway.
The prorated amount will be calculated based on the selected switch type

Fixes # (issue-reference)
https://github.com/quintype/page-builder/issues/4289

Summary by CodeRabbit

  • New Features

    • Enhanced checkout: added support for switching payment options mid-checkout with improved Stripe handling.
  • Chores

    • Bumped package version to 3.8.9-stripe-up-downgrade.9

@coderabbitai
Copy link

coderabbitai bot commented Feb 5, 2026

Walkthrough

Package version updated to "3.8.9-stripe-up-downgrade.9". initStripePayment in AccessTypeBase is now async and adds handling for options.intent === 'switch' to fetch switch payment options and invoke a switch-specific Stripe flow; non-switch flow unchanged.

Changes

Cohort / File(s) Summary
Version Update
package.json
Version changed from "3.8.8" to "3.8.9-stripe-up-downgrade.9".
Stripe Switch Intent Handling
src/components/access-type.js
initStripePayment signature updated to async. Adds conditional options.intent === 'switch': calls global.AccessType to get switch payment options, builds a payload including switch_type, subscription_plan_id, subscriptionId, success/cancel URLs, and calls switchPaymentOptions.stripe.proceed(payload). Preserves existing Stripe proceed flow for non-switch cases.

Sequence Diagram

sequenceDiagram
    participant Client
    participant AccessType
    participant GlobalAccessType as global.AccessType
    participant SwitchPaymentOptions
    participant Stripe

    Client->>AccessType: initStripePayment(options)
    alt intent === 'switch'
        AccessType->>GlobalAccessType: fetchSwitchPaymentOptions()
        GlobalAccessType-->>AccessType: switchPaymentOptions
        AccessType->>AccessType: build payload (switch_type, subscription_plan_id, subscriptionId, success/cancel URLs)
        AccessType->>SwitchPaymentOptions: switchPaymentOptions.stripe.proceed(payload)
        SwitchPaymentOptions->>Stripe: process switch payment
        Stripe-->>Client: payment result
    else non-switch
        AccessType->>SwitchPaymentOptions: paymentOptions.stripe.proceed(paymentObject)
        SwitchPaymentOptions->>Stripe: process standard payment
        Stripe-->>Client: payment result
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides basic information about the feature but is incomplete; it lacks required sections including type of change, testing details, and most checklist items from the template. Add missing sections: select appropriate type of change, describe how the feature was tested with reproducible steps, and complete the checklist items per the repository template.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature being added: upgrade, downgrade, and cross-grade functionality for Stripe payments, which aligns with the PR objectives and code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch stripe-up-downgrade

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/access-type.js (1)

402-406: ⚠️ Potential issue | 🟡 Minor

Use error semantics appropriate for async functions instead of returning false.

The function throws on some errors (line 420) but returns false on validation failure, creating inconsistent error handling. Async functions should reject or throw for errors rather than return falsy primitives, which makes error handling and debugging more difficult downstream.

Suggested fix
   initStripePayment = async (options = {}) => {
     if (!options.selectedPlan) {
-      console.warn('Stripe pay needs a plan')
-      return false
+      const err = new Error('Stripe pay needs a plan')
+      console.warn(err.message)
+      throw err
     }
🤖 Fix all issues with AI agents
In `@src/components/access-type.js`:
- Around line 414-430: When handling intent === 'switch' (the awaitHelper call
to global.AccessType.getPaymentOptions and the switchPaymentOptions result), add
guards to ensure switchPaymentOptions and switchPaymentOptions.stripe exist and
that stripe.proceed is a function before calling it; if missing, throw a clear
error. Also validate options?.successUrl and options?.cancelUrl are non-empty
strings (or provide safe defaults) before building payload.urls and calling
stripe.proceed; if either URL is invalid, throw an error indicating which URL is
missing/invalid. Ensure these checks are applied around the existing
paymentObject/payload construction and the call to
switchPaymentOptions.stripe.proceed.

Comment on lines +414 to +430
if (intent === 'switch') {
const { error, data: switchPaymentOptions } = await awaitHelper(
global.AccessType.getPaymentOptions(null, null, "switch")
);

if (error) throw new Error("payment options fetch failed");
const payload = {
...paymentObject,
switch_type: switchType,
subscription_plan_id: options?.selectedPlan?.id,
subscriptionId: options?.selectedPlan?.subscriptionId,
urls : {
success_url: options?.successUrl,
cancel_url: options?.cancelUrl
}
};
return switchPaymentOptions.stripe.proceed(payload);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n src/components/access-type.js | sed -n '414,430p'

Repository: quintype/quintype-node-components

Length of output: 822


🏁 Script executed:

cat -n src/components/access-type.js | sed -n '380,435p'

Repository: quintype/quintype-node-components

Length of output: 2478


🏁 Script executed:

rg -n "awaitHelper" src/components/access-type.js -B 2 -A 2

Repository: quintype/quintype-node-components

Length of output: 3261


🏁 Script executed:

rg -n "export.*awaitHelper|function awaitHelper" src/utils -B 2 -A 10

Repository: quintype/quintype-node-components

Length of output: 126


🏁 Script executed:

rg -n "export.*awaitHelper|function awaitHelper" -B 2 -A 10

Repository: quintype/quintype-node-components

Length of output: 855


🏁 Script executed:

rg -n "initStripePayment" src/components/access-type.js -B 2 -A 5

Repository: quintype/quintype-node-components

Length of output: 3098


🏁 Script executed:

cat -n src/components/access-type.js | sed -n '387,400p'

Repository: quintype/quintype-node-components

Length of output: 709


🏁 Script executed:

rg -n "switchPaymentOptions\|switchPaymentOptions.stripe" src/components/access-type.js -B 2 -A 2

Repository: quintype/quintype-node-components

Length of output: 59


🏁 Script executed:

rg -n "\.stripe\." src/components/access-type.js -B 2 -A 2

Repository: quintype/quintype-node-components

Length of output: 350


Guard against missing Stripe provider and validate payment URLs before proceeding.

The switch case directly accesses switchPaymentOptions.stripe.proceed() without verifying that stripe exists, while the default case (lines 432-434) includes this guard. Additionally, successUrl and cancelUrl are constructed with optional chaining and may be undefined, which can break the Stripe flow. Both the provider and URLs must be validated before use.

Suggested fix
    if (intent === 'switch') {
      const { error, data: switchPaymentOptions } = await awaitHelper(
        global.AccessType.getPaymentOptions(null, null, "switch")
      );

      if (error) throw new Error("payment options fetch failed");
+     if (!switchPaymentOptions?.stripe) {
+       return Promise.reject({ message: 'Payment option is loading...' })
+     }
+     if (!options?.successUrl || !options?.cancelUrl) {
+       throw new Error('successUrl and cancelUrl are required for switch')
+     }
      const payload = {
        ...paymentObject,
        switch_type: switchType,
        subscription_plan_id: options?.selectedPlan?.id,
        subscriptionId: options?.selectedPlan?.subscriptionId,
        urls: {
-         success_url: options?.successUrl,
-         cancel_url: options?.cancelUrl
+         success_url: options.successUrl,
+         cancel_url: options.cancelUrl
        }
      };
      return switchPaymentOptions.stripe.proceed(payload);
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (intent === 'switch') {
const { error, data: switchPaymentOptions } = await awaitHelper(
global.AccessType.getPaymentOptions(null, null, "switch")
);
if (error) throw new Error("payment options fetch failed");
const payload = {
...paymentObject,
switch_type: switchType,
subscription_plan_id: options?.selectedPlan?.id,
subscriptionId: options?.selectedPlan?.subscriptionId,
urls : {
success_url: options?.successUrl,
cancel_url: options?.cancelUrl
}
};
return switchPaymentOptions.stripe.proceed(payload);
if (intent === 'switch') {
const { error, data: switchPaymentOptions } = await awaitHelper(
global.AccessType.getPaymentOptions(null, null, "switch")
);
if (error) throw new Error("payment options fetch failed");
if (!switchPaymentOptions?.stripe) {
return Promise.reject({ message: 'Payment option is loading...' })
}
if (!options?.successUrl || !options?.cancelUrl) {
throw new Error('successUrl and cancelUrl are required for switch')
}
const payload = {
...paymentObject,
switch_type: switchType,
subscription_plan_id: options?.selectedPlan?.id,
subscriptionId: options?.selectedPlan?.subscriptionId,
urls: {
success_url: options.successUrl,
cancel_url: options.cancelUrl
}
};
return switchPaymentOptions.stripe.proceed(payload);
}
🤖 Prompt for AI Agents
In `@src/components/access-type.js` around lines 414 - 430, When handling intent
=== 'switch' (the awaitHelper call to global.AccessType.getPaymentOptions and
the switchPaymentOptions result), add guards to ensure switchPaymentOptions and
switchPaymentOptions.stripe exist and that stripe.proceed is a function before
calling it; if missing, throw a clear error. Also validate options?.successUrl
and options?.cancelUrl are non-empty strings (or provide safe defaults) before
building payload.urls and calling stripe.proceed; if either URL is invalid,
throw an error indicating which URL is missing/invalid. Ensure these checks are
applied around the existing paymentObject/payload construction and the call to
switchPaymentOptions.stripe.proceed.

@VeenaYemmiganur VeenaYemmiganur merged commit a3bc7d3 into master Feb 17, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants