feat: handling subscription tier button link parameter (#7553)

## Summary

Discussion here:
https://comfy-organization.slack.com/archives/C0A0XANFJRE/p1764899027465379

Implement: Subscription tier query parameter for direct checkout flow

Example button link: `/cloud/subscribe?tier=standard`

`tier` could be `standard`, `creator` or `pro`
`cycle` could be `monthly` or `yearly`. it is optional, and `monthly` by
default.

<!-- One sentence describing what changed and why. -->

## Changes

- **What**: <!-- Core functionality added/modified -->
- Add a landing page called `CloudSubscriptionRedirectView.vue` to
handling the subscription tier button link parameter
  - Extract subscription handling logic from `PriceTable.vue`
 
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
  - Code change touched  `PriceTable.vue`
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->

## Review Focus
- link will redirect to login url, when cloud app not login
- after login, the cloud app will redirect to CloudSubscriptionRedirect
page
- wait for several seconds, the cloud app will be redirected to checkout
page

<!-- Critical design decisions or edge cases that need attention -->

<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->

## Screenshots (if applicable)

![Kapture 2025-12-16 at 18 43
28](https://github.com/user-attachments/assets/affbc18f-d45c-4953-b06a-fc797eba6804)


<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7553-feat-handling-subscription-tier-button-link-parameter-2cb6d73d365081ee9580e89090248300)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Yourz
2026-01-15 08:57:51 +08:00
committed by GitHub
parent 97b1a48a25
commit 3069c24f81
15 changed files with 536 additions and 71 deletions

View File

@@ -104,9 +104,9 @@ export const useFirebaseAuthActions = () => {
}, reportError)
const accessBillingPortal = wrapWithErrorHandlingAsync<
[targetTier?: BillingPortalTargetTier],
[targetTier?: BillingPortalTargetTier, openInNewTab?: boolean],
void
>(async (targetTier) => {
>(async (targetTier, openInNewTab = true) => {
const response = await authStore.accessBillingPortal(targetTier)
if (!response.billing_portal_url) {
throw new Error(
@@ -115,7 +115,11 @@ export const useFirebaseAuthActions = () => {
})
)
}
window.open(response.billing_portal_url, '_blank')
if (openInNewTab) {
window.open(response.billing_portal_url, '_blank')
} else {
globalThis.location.href = response.billing_portal_url
}
}, reportError)
const fetchBalance = wrapWithErrorHandlingAsync(async () => {