إجراءات ما بعد التثبيت والإعداد
تحدد إجراءات ما بعد التثبيت ما يحدث مباشرة بعد أن يثبت المستخدم تطبيق Stripe الخاص بك. تجربة ما بعد التثبيت المصممة جيدًا ترشد المستخدمين خلال الإعداد وتزيد معدلات التفعيل.
أنواع إجراءات ما بعد التثبيت
يدعم Stripe أربعة أنواع من إجراءات ما بعد التثبيت، يتم تكوين كل منها في manifest التطبيق:
1. رابط إلى التطبيق (افتراضي)
يفتح التطبيق في viewport الـ drawer الافتراضي. هذا هو السلوك الافتراضي إذا لم يتم تحديد post_install_action:
{ "post_install_action": { "type": "default" }}يرى المستخدم viewport drawer.default للتطبيق في الشريط الجانبي للوحة التحكم.
2. رابط إلى الإعداد
يفتح عرض الإعداد المخصص للتطبيق، مما يوفر تجربة إعداد مركزة:
{ "post_install_action": { "type": "onboarding" }}يتطلب هذا viewport onboarding مُعلن في الـ manifest:
{ "ui_extension": { "views": [ { "viewport": "stripe.dashboard.onboarding", "component": "OnboardingView" } ] }, "post_install_action": { "type": "onboarding" }}3. رابط إلى الإعدادات
يفتح عرض إعدادات التطبيق، مفيد عندما يتطلب التطبيق مفاتيح API أو تكوين قبل الاستخدام:
{ "post_install_action": { "type": "settings" }}يتطلب هذا viewport settings:
{ "ui_extension": { "views": [ { "viewport": "stripe.dashboard.settings", "component": "SettingsView" } ] }, "post_install_action": { "type": "settings" }}4. رابط إلى URL خارجي
يعيد توجيه المستخدم إلى URL خارجي للإعداد. استخدم هذا عندما يكون تدفق الإعداد خارج لوحة تحكم Stripe:
{ "post_install_action": { "type": "external", "url": "https://app.tajo.io/stripe/setup" }}Caution
يجب أن تستخدم عناوين URL الخارجية HTTPS ويجب إدراجها في allowed_redirect_uris. سيتحقق فريق مراجعة Stripe من أن URL الخارجي يوفر تجربة إعداد وظيفية.
أفضل ممارسات الإعداد
اجعله سهلاً
قلل عدد الخطوات المطلوبة للبدء:
- ملء المعلومات مسبقًا المتاحة من سياق حساب Stripe
- استخدم إعدادات افتراضية معقولة لخيارات التكوين
- اسمح بالتخطي للخطوات الاختيارية مع مسار واضح لإكمالها لاحقًا
- أظهر التقدم بمؤشرات خطوات لتدفقات متعددة الخطوات
اجعله قابلاً للتخصيص
دع المستخدمين يكوّنون التكامل حسب احتياجاتهم:
- خيارات تعيين البيانات, دع المستخدمين يختارون حقول Stripe التي تتم مزامنتها مع Brevo
- تردد المزامنة, قدم خيارات مزامنة في الوقت الفعلي أو كل ساعة أو يوميًا
- مزامنة انتقائية, دع المستخدمين يختارون العملاء أو المنتجات التي ستتم مزامنتها
- تفضيلات الإشعارات, تكوين التنبيهات لأخطاء المزامنة أو الأحداث المهمة
اجعله ذا صلة
أظهر القيمة فورًا:
- معاينة البيانات المتزامنة قبل تمكين التكامل
- أظهر ما سيحدث عندما يكمل المستخدم الإعداد
- وفر خيار مزامنة تجريبية للتحقق من عمل الاتصال
- اعرض مقاييس النجاح بعد اكتمال المزامنة الأولية
مكون OnboardingView
يُعرض مكون OnboardingView في نافذة مركزة عندما يثبت المستخدم التطبيق:
import { Box, Button, Inline, Icon, Banner, TextField, Select, Divider,} from '@stripe/ui-extension-sdk/ui';import type { ExtensionContextValue } from '@stripe/ui-extension-sdk/context';import { useState } from 'react';
const OnboardingView = ({ environment, userContext }: ExtensionContextValue) => { const [step, setStep] = useState(1); const [brevoApiKey, setBrevoApiKey] = useState(''); const [syncMode, setSyncMode] = useState('realtime'); const [isConnecting, setIsConnecting] = useState(false); const [error, setError] = useState<string | null>(null);
const totalSteps = 3;
const handleConnect = async () => { setIsConnecting(true); setError(null);
try { // Store the API key securely await storeBrevoApiKey(brevoApiKey);
// Verify the connection const result = await verifyBrevoConnection(brevoApiKey);
if (result.success) { setStep(2); } else { setError('Unable to connect to Brevo. Please check your API key.'); } } catch (err) { setError('Connection failed. Please try again.'); } finally { setIsConnecting(false); } };
return ( <Box css={{ padding: 'large' }}> {/* Progress indicator */} <Inline css={{ marginBottom: 'large' }}> Step {step} of {totalSteps} </Inline>
{error && ( <Banner type="critical" title="Connection Error"> {error} </Banner> )}
{step === 1 && ( <Box> <Inline css={{ fontWeight: 'bold', fontSize: 'large' }}> Connect Your Brevo Account </Inline> <Inline css={{ marginTop: 'small', color: 'secondary' }}> Enter your Brevo API key to start syncing customer data. </Inline>
<TextField label="Brevo API Key" placeholder="xkeysib-..." value={brevoApiKey} onChange={(e) => setBrevoApiKey(e.target.value)} css={{ marginTop: 'medium' }} />
<Inline css={{ marginTop: 'xsmall', color: 'secondary', fontSize: 'small' }}> Find your API key in Brevo under Settings > SMTP & API > API Keys </Inline>
<Button type="primary" onPress={handleConnect} disabled={!brevoApiKey || isConnecting} css={{ marginTop: 'medium' }} > {isConnecting ? 'Connecting...' : 'Connect Brevo'} </Button> </Box> )}
{step === 2 && ( <Box> <Inline css={{ fontWeight: 'bold', fontSize: 'large' }}> Configure Sync Settings </Inline>
<Select label="Sync Mode" value={syncMode} onChange={(value) => setSyncMode(value)} css={{ marginTop: 'medium' }} > <option value="realtime">Real-time (recommended)</option> <option value="hourly">Every hour</option> <option value="daily">Once per day</option> </Select>
<Divider css={{ marginY: 'medium' }} />
<Button type="primary" onPress={() => setStep(3)}> Continue </Button> <Button type="secondary" onPress={() => setStep(1)}> Back </Button> </Box> )}
{step === 3 && ( <Box> <Banner type="default" title="Ready to Sync"> Your Brevo account is connected. Tajo will begin syncing customer data automatically. </Banner>
<Box css={{ marginTop: 'medium' }}> <Inline css={{ fontWeight: 'bold' }}>What happens next:</Inline> <ul> <li>Existing Stripe customers will sync to Brevo contacts</li> <li>New customers and events will sync in real-time</li> <li>View sync status on any customer's detail page</li> </ul> </Box>
<Button type="primary" onPress={() => {/* Navigate to dashboard */}}> Go to Dashboard </Button> </Box> )} </Box> );};
export default OnboardingView;تدفق تسجيل الدخول باستخدام SignInView
إذا كان تطبيقك يتطلب من المستخدمين تسجيل الدخول إلى حساب خارجي (مثل Tajo)، استخدم عرض تسجيل دخول مخصص:
import { Box, Button, Inline, TextField, Banner, Link,} from '@stripe/ui-extension-sdk/ui';import { useState } from 'react';
const SignInView = ({ onSignInComplete }) => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState<string | null>(null);
const handleSignIn = async () => { setIsLoading(true); setError(null);
try { const response = await fetch('https://api.tajo.io/v1/auth/stripe-app', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), });
if (!response.ok) { throw new Error('Invalid credentials'); }
const { token } = await response.json();
// Store the auth token securely in Stripe's Secret Store await storeAuthToken(token);
onSignInComplete(); } catch (err) { setError('Sign-in failed. Please check your credentials and try again.'); } finally { setIsLoading(false); } };
return ( <Box css={{ padding: 'large' }}> <Inline css={{ fontWeight: 'bold', fontSize: 'large' }}> Sign in to Tajo </Inline> <Inline css={{ marginTop: 'small', color: 'secondary' }}> Connect your Tajo account to enable Brevo sync. </Inline>
{error && ( <Banner type="critical" title="Sign-in Failed"> {error} </Banner> )}
<TextField label="Email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} css={{ marginTop: 'medium' }} />
<TextField label="Password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} css={{ marginTop: 'small' }} />
<Button type="primary" onPress={handleSignIn} disabled={!email || !password || isLoading} css={{ marginTop: 'medium' }} > {isLoading ? 'Signing in...' : 'Sign In'} </Button>
<Link href="https://app.tajo.io/signup" external css={{ marginTop: 'small' }}> Don't have a Tajo account? Sign up </Link> </Box> );};إطلاق الرابط العميق مع معاملات الاستعلام
يمكنك إطلاق خطوات إعداد محددة أو ملء البيانات مسبقًا باستخدام معاملات الاستعلام في الروابط العميقة:
import type { ExtensionContextValue } from '@stripe/ui-extension-sdk/context';
const OnboardingView = ({ environment }: ExtensionContextValue) => { // Access query parameters from the deep link const { queryParams } = environment;
// Pre-fill step from query parameter const initialStep = queryParams?.step ? parseInt(queryParams.step) : 1;
// Pre-fill API key from query parameter (e.g., from Tajo dashboard) const prefilledApiKey = queryParams?.brevo_key || '';
// Source tracking for analytics const installSource = queryParams?.source || 'marketplace';
const [step, setStep] = useState(initialStep); const [brevoApiKey, setBrevoApiKey] = useState(prefilledApiKey);
// ... rest of onboarding logic};إنشاء روابط عميقة تملأ بيانات الإعداد مسبقًا:
// From your Tajo dashboard, generate a link that pre-fills the Brevo API keyconst onboardingLink = [ 'https://dashboard.stripe.com/live/acct_xxxxx/dashboard', '?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.onboarding', '&apps[com.tajo.brevo-integration][queryParams][step]=1', '&apps[com.tajo.brevo-integration][queryParams][source]=tajo_dashboard',].join('');التعامل مع المستخدمين العائدين
عندما يفتح مستخدم تطبيقك بعد إكمال الإعداد، اكتشف حالته واعرض العرض المناسب:
const MainView = ({ environment, userContext }: ExtensionContextValue) => { const [authState, setAuthState] = useState<'loading' | 'signed-out' | 'onboarding' | 'ready'>('loading');
useEffect(() => { checkUserState().then((state) => { setAuthState(state); }); }, []);
switch (authState) { case 'loading': return <Spinner label="Loading..." />; case 'signed-out': return <SignInView onSignInComplete={() => setAuthState('onboarding')} />; case 'onboarding': return <OnboardingView onComplete={() => setAuthState('ready')} />; case 'ready': return <DashboardView />; }};Tip
خزّن حالة إكمال الإعداد في Stripe Secret Store حتى تتمكن من اكتشاف المستخدمين العائدين دون استدعاء API خارجي.