feat: support sign-in with subscription coupon (#5768)

This commit is contained in:
Joooye_34
2024-02-01 08:43:47 +00:00
parent fec2090de5
commit 338c3001b0
7 changed files with 56 additions and 31 deletions

View File

@@ -23,6 +23,7 @@ import type { AuthPanelProps } from './index';
import * as style from './style.css';
import { INTERNAL_BETA_URL, useAuth } from './use-auth';
import { Captcha, useCaptcha } from './use-captcha';
import { useSubscriptionSearch } from './use-subscription';
function validateEmail(email: string) {
return emailRegex.test(email);
@@ -37,6 +38,7 @@ export const SignIn: FC<AuthPanelProps> = ({
const t = useAFFiNEI18N();
const loginStatus = useCurrentLoginStatus();
const [verifyToken, challenge] = useCaptcha();
const subscriptionData = useSubscriptionSearch();
const {
isMutating: isSigningIn,
@@ -83,7 +85,8 @@ export const SignIn: FC<AuthPanelProps> = ({
if (verifyToken) {
if (user) {
// provider password sign-in if user has by default
if (user.hasPassword) {
// If with payment, onl support email sign in to avoid redirect to affine app
if (user.hasPassword && !subscriptionData) {
setAuthState('signInWithPassword');
} else {
const res = await signIn(email, verifyToken, challenge);
@@ -103,6 +106,7 @@ export const SignIn: FC<AuthPanelProps> = ({
}
}
}, [
subscriptionData,
challenge,
email,
setAuthEmail,

View File

@@ -3,10 +3,10 @@ import { Button } from '@affine/component/ui/button';
import { Loading } from '@affine/component/ui/loading';
import { AffineShapeIcon } from '@affine/core/components/page-list';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import type { SubscriptionRecurring } from '@affine/graphql';
import type { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
import {
changePasswordMutation,
checkoutMutation,
createCheckoutSessionMutation,
subscriptionQuery,
} from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
@@ -30,18 +30,25 @@ const usePaymentRedirect = () => {
}
const recurring = searchData.recurring as SubscriptionRecurring;
const plan = searchData.plan as SubscriptionPlan;
const coupon = searchData.coupon;
const idempotencyKey = useMemo(() => nanoid(), []);
const { trigger: checkoutSubscription } = useMutation({
mutation: checkoutMutation,
mutation: createCheckoutSessionMutation,
});
return useAsyncCallback(async () => {
const { checkout } = await checkoutSubscription({
recurring,
idempotencyKey,
const { createCheckoutSession: checkoutUrl } = await checkoutSubscription({
input: {
recurring,
plan,
coupon,
idempotencyKey,
successCallbackLink: null,
},
});
window.open(checkout, '_self', 'norefferer');
}, [recurring, idempotencyKey, checkoutSubscription]);
window.open(checkoutUrl, '_self', 'norefferer');
}, [recurring, plan, coupon, idempotencyKey, checkoutSubscription]);
};
const CenterLoading = () => {

View File

@@ -4,6 +4,7 @@ import { useSearchParams } from 'react-router-dom';
enum SubscriptionKey {
Recurring = 'subscription_recurring',
Plan = 'subscription_plan',
Coupon = 'coupon',
SignUp = 'sign_up', // A new user with subscription journey: signup > set password > pay in stripe > go to app
Token = 'token', // When signup, there should have a token to set password
}
@@ -22,11 +23,13 @@ export function useSubscriptionSearch() {
const recurring = searchParams.get(SubscriptionKey.Recurring);
const plan = searchParams.get(SubscriptionKey.Plan);
const coupon = searchParams.get(SubscriptionKey.Coupon);
const withSignUp = searchParams.get(SubscriptionKey.SignUp) === '1';
const passwordToken = searchParams.get(SubscriptionKey.Token);
return {
recurring,
plan,
coupon,
withSignUp,
passwordToken,
getRedirectUrl(signUp?: boolean) {
@@ -35,6 +38,10 @@ export function useSubscriptionSearch() {
[SubscriptionKey.Plan, plan ?? ''],
]);
if (coupon) {
paymentParams.set(SubscriptionKey.Coupon, coupon);
}
if (signUp) {
paymentParams.set(SubscriptionKey.SignUp, '1');
}

View File

@@ -6,7 +6,7 @@ import type {
SubscriptionMutator,
} from '@affine/core/hooks/use-subscription';
import {
checkoutMutation,
createCheckoutSessionMutation,
SubscriptionPlan,
SubscriptionRecurring,
SubscriptionStatus,
@@ -359,7 +359,7 @@ const Upgrade = ({
}) => {
const t = useAFFiNEI18N();
const { isMutating, trigger } = useMutation({
mutation: checkoutMutation,
mutation: createCheckoutSessionMutation,
});
const newTabRef = useRef<Window | null>(null);
@@ -383,13 +383,21 @@ const Upgrade = ({
newTabRef.current.focus();
} else {
await trigger(
{ recurring, idempotencyKey },
{
input: {
recurring,
idempotencyKey,
plan: SubscriptionPlan.Pro, // Only support prod plan now.
coupon: null,
successCallbackLink: null,
},
},
{
onSuccess: data => {
// FIXME: safari prevents from opening new tab by window api
// TODO(@xp): what if electron?
const newTab = window.open(
data.checkout,
data.createCheckoutSession,
'_blank',
'noopener noreferrer'
);