Heim > Web-Frontend > js-Tutorial > Mit Stripe Connect einen Marktplatz erstellen: Der Onboard-Prozess

Mit Stripe Connect einen Marktplatz erstellen: Der Onboard-Prozess

Susan Sarandon
Freigeben: 2024-11-28 09:55:13
Original
366 Leute haben es durchsucht

Einführung

Die Schaffung eines Marktplatzes wäre wahrscheinlich zu schwierig oder unmöglich, wenn man bedenkt, dass ihn nicht viele Zahlungsabwickler anbieten. Wenn sie ihn nicht anbieten, würden Sie wahrscheinlich von der Plattform gebootet, sobald sie Wind davon bekommen, und selbst ohne das Es ist riskant, einen Marktplatz zu schaffen, auf dem man keine solide Grundlage für die Abwicklung von Zahlungen, Rückerstattungen und Auszahlungen an die Verkäufer hat, die die Plattform nutzen.

Stripe Connect behebt diese Probleme und ermöglicht uns die Schaffung eines einfachen Marktplatzes, auf dem Sie sich als Verkäufer anmelden können und auf dem Kunden problemlos Artikel von diesen Verkäufern kaufen können. Als Plattformbesitzer können Sie auch Ihre Servicegebühr festlegen. Wenn also Benutzer

Creating a marketplace with Stripe Connect: The onboard process

Einrichten des Projekts

Für die Verwaltung der Datenbankverbindung verwenden wir Prisma, die Authentifizierung wird von remix-auth übernommen, in diesem Teil kümmern wir uns ausschließlich um die Verkäuferseite des Marktplatzes.


// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Store {
  id         String   @id // This will be the store's subdomain
  name       String
  updated_at DateTime @default(now()) @updatedAt
  seller     Seller?
}

model Seller {
  id           Int      @id @default(autoincrement())
  email        String
  password     String
  store        Store    @relation(fields: [store_id], references: [id])
  date_created DateTime @default(now())
  date_updated DateTime @updatedAt
  store_id     String   @unique
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
So sieht unsere schema.prisma-Datei aus. Wir haben ein Verkäufermodell und ein damit verbundenes Store-Modell. Das Feld „id“ dient als Subdomain. Wenn wir also auf der Käuferseite sind, kann ich das tun Besuchen Sie store.localhost.com und kaufen Sie die Produkte beim dortigen Verkäufer.

Außerdem werden wir ein Stripe-Modell hinzufügen, das Daten über das Connect-Konto des Verkäufers speichert.

model Stripe {
  account_id String @id
  is_onboarded Boolean @default(false)
  user Users @relation(fields: [user_id], references: [discord_id])
  user_id String @unique
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
}

model Seller {
  id           Int      @id @default(autoincrement())
  email        String
  password     String
  store        Store    @relation(fields: [store_id], references: [id])
  date_created DateTime @default(now())
  date_updated DateTime @updatedAt
  store_id     String   @unique
  stripe       Stripe?
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Jetzt können wir uns um das Onboarding des Benutzers kümmern, also definieren wir eine weitere Variable in unserer .env-Datei.


STRIPE_SK=your stripe secret key here
Nach dem Login kopieren
Nach dem Login kopieren
Sie können den geheimen Stripe-Schlüssel erhalten, indem Sie ihn auf der Entwicklungsseite von Stripe generieren. Es empfiehlt sich, einen eingeschränkten Schlüssel zu erstellen, der vorerst nur die Verwendung von Stripe Connect zulässt.

Dann müssen Sie eine neue Datei erstellen, die den Stripe-Client exportiert, damit er von unseren Routen verwendet werden kann


// app/libs/stripe.server.ts
import Stripe from 'stripe';
export const stripe = new Stripe(process.env.STRIPE_SK)
Nach dem Login kopieren
Nach dem Login kopieren
Wir erstellen eine neue Route, die sich unter „/onboarding“ befindet


// app/routes/onboarding.tsx

export default function Onboarding() {
    const {stripe} = useLoaderData();

    return <div className={'text-center pt-[6%]'}>
    <h1 className={'text-xl'}>Account onboarded: {stripe?.is_onboarded ? stripe?.account_id : '? Not connected'}</h1>
        <div className={'flex items-center  text-white text-sm  mt-5 justify-center gap-3'}>
            {!stripe ? <>
                <Form method={'post'}>
                    <button type={'submit'} className={'bg-blue-600 hover:cursor-pointer  rounded-[6px] px-4 py-1.5'}>Setup your seller
                        account
                    </button>

                </Form>
            </> : <>
                <div className={'bg-blue-600 rounded-[6px] px-4 py-1.5'}>Seller dashboard</div>

            </>}
        </div>
    </div>
}
Nach dem Login kopieren
Nach dem Login kopieren
Wir werden eine Loader-Funktion hinzufügen, die die Daten zum Onboarding-Status des Verkäufers weitergibt


export async function loader({request}: LoaderFunctionArgs) {
    const user = await authenticator.isAuthenticated(request, {
        failureRedirect: '/login'
    })

    const seller = await prisma.seller.findFirst({
        where: {
            id: user.id
        }, include: {
            stripe: true
        }
    })

    return {
        stripe: seller?.stripe
    }
}
Nach dem Login kopieren
Nach dem Login kopieren
Wenn Sie nun zu /onboarding gehen, wird Ihnen angezeigt, dass Sie nicht verbunden sind, und Sie können sich per Knopfdruck anmelden. Hier kommt unsere Aktionsfunktion ins Spiel


export async function action({request}: ActionFunctionArgs) {
    const authenticated = await authenticator.isAuthenticated(request, {
        failureRedirect: '/login'
    })
    const seller = await prisma.seller.findFirst({
        where: {
            id: authenticated.id
        }, include: {
            stripe: true
        }
    })
    if (seller && seller.stripe?.is_onboarded) {
        return json({
            message: 'User is onboarded already',
            error: true
        }, {
            status: 400
        })
    }
    const account = seller?.stripe?.account_id ? {
        id: seller.stripe?.account_id
    } : await stripe.accounts.create({
        email: seller?.email,
        controller: {
            fees: {
                payer: 'application',
            },
            losses: {
                payments: 'application',
            },
            stripe_dashboard: {
                type: 'express',
            },
        },
    });
    if (!seller?.stripe?.account_id) {
        await prisma.seller.update({
            where: {
                id: authenticated.id
            },
            data: {
                stripe: {
                    create: {
                        account_id: account.id
                    }
                }
            }, include: {
                stripe: true
            }
        })
    }
    const accountLink = await stripe.accountLinks.create({
        account: account.id,
        refresh_url: 'http://localhost:5173/onboarding',
        return_url: 'http://localhost:5173/onboarding',
        type: 'account_onboarding',
        collection_options: {
            fields: 'eventually_due',
        },
    });
    console.debug(`[ACCOUNT ID = ${account.id}] CREATED ACCOUNT ONBOARDING LINK, REDIRECTING...`)

    return redirect(accountLink.url)
}
Nach dem Login kopieren
Nach dem Login kopieren
Wenn der Verkäufer auf die Schaltfläche klickt, erstellen wir ein Konto mit der E-Mail-Adresse, mit der er sich angemeldet hat. Anschließend erstellen wir einen Kontolink, der ihn zu einer Onboarding-Seite weiterleitet, sofern der Verkäufer bereits über ein Stripe-Konto verfügt nicht an Bord sind, leiten wir sie ebenfalls auf den Onboarding-Link weiter.

Creating a marketplace with Stripe Connect: The onboard process

Von dort aus gibt der Verkäufer seine E-Mail-/Telefonnummer ein und der Onboarding-Prozess beginnt. Stripe fragt den Verkäufer normalerweise nach dem Standort des Unternehmens, Geschäftsdaten, Bankkonten usw.

Jetzt können wir Webhooks für Stripe Connect-Ereignisse abhören. Wenn sich ein Verkäufer erfolgreich angemeldet hat, fügen wir diese Attribute dem Datensatz des Verkäufers in der Datenbank hinzu.

Zum Testen können Sie einfach Stripe CLI herunterladen und von dort aus alle Ereignisse an unsere neue Route /api/notifications weiterleiten, die wir jetzt erstellen werden

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Store {
  id         String   @id // This will be the store's subdomain
  name       String
  updated_at DateTime @default(now()) @updatedAt
  seller     Seller?
}

model Seller {
  id           Int      @id @default(autoincrement())
  email        String
  password     String
  store        Store    @relation(fields: [store_id], references: [id])
  date_created DateTime @default(now())
  date_updated DateTime @updatedAt
  store_id     String   @unique
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wenn Sie diesen Befehl ausführen, erhalten Sie eine Webhook-Signatur, damit wir die Integrität jedes von Stripe an uns gesendeten Webhooks überprüfen können. Wenn Sie im Entwicklerportal auf Stripe einen Webhook erstellen, verfügen Sie ebenfalls über ein Geheimnis .

model Stripe {
  account_id String @id
  is_onboarded Boolean @default(false)
  user Users @relation(fields: [user_id], references: [discord_id])
  user_id String @unique
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
}

model Seller {
  id           Int      @id @default(autoincrement())
  email        String
  password     String
  store        Store    @relation(fields: [store_id], references: [id])
  date_created DateTime @default(now())
  date_updated DateTime @updatedAt
  store_id     String   @unique
  stripe       Stripe?
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir werden auch eine neue Variable in der .env-Datei hinzufügen

STRIPE_SK=your stripe secret key here
Nach dem Login kopieren
Nach dem Login kopieren

Jetzt können wir den Code schreiben, um diese Ereignisse zu verarbeiten, die uns von Stripe gesendet werden

// app/libs/stripe.server.ts
import Stripe from 'stripe';
export const stripe = new Stripe(process.env.STRIPE_SK)
Nach dem Login kopieren
Nach dem Login kopieren

Wir überprüfen, ob Stripe die Anfrage sendet. Ist dies der Fall, fahren wir fort. Das Ereignis, nach dem wir Ausschau halten möchten, ist „account.updated“. Dieses Ereignis hängt mit dem Konto zusammen, das wir vor der Weiterleitung des Verkäufers erstellt haben.

Wenn ein Verkäufer den Onboarding-Prozess startet, seine Telefonnummer hinzufügt oder die E-Mail-Adresse eingibt oder schließlich den Onboarding-Prozess abschließt, erhalten wir das Ereignis „account.updated“ und mit ihm wird dieses Array gesendet

account.requirements.currently_due

Wenn die Länge des Arrays „currently_due“ bei Null liegt, wissen wir, dass der Benutzer vollständig eingebunden ist und Zahlungen akzeptieren kann. Daher können wir von unserer Seite aus die Datenbank aktualisieren und dem Benutzer erlauben, Produkte zu erstellen, aber bevor wir das tun, fügen wir etwas hinzu diese Logik in der Aktion „/api/notifications“

// app/routes/onboarding.tsx

export default function Onboarding() {
    const {stripe} = useLoaderData();

    return <div className={'text-center pt-[6%]'}>
    <h1 className={'text-xl'}>Account onboarded: {stripe?.is_onboarded ? stripe?.account_id : '? Not connected'}</h1>
        <div className={'flex items-center  text-white text-sm  mt-5 justify-center gap-3'}>
            {!stripe ? <>
                <Form method={'post'}>
                    <button type={'submit'} className={'bg-blue-600 hover:cursor-pointer  rounded-[6px] px-4 py-1.5'}>Setup your seller
                        account
                    </button>

                </Form>
            </> : <>
                <div className={'bg-blue-600 rounded-[6px] px-4 py-1.5'}>Seller dashboard</div>

            </>}
        </div>
    </div>
}
Nach dem Login kopieren
Nach dem Login kopieren

Sobald das eingerichtet ist, können wir das Onboarding ausprobieren und sehen, ob es funktioniert. Sobald Sie beispielsweise die Adresse eingeben, sehen Sie in der Konsole des Projekts eine Meldung wie

export async function loader({request}: LoaderFunctionArgs) {
    const user = await authenticator.isAuthenticated(request, {
        failureRedirect: '/login'
    })

    const seller = await prisma.seller.findFirst({
        where: {
            id: user.id
        }, include: {
            stripe: true
        }
    })

    return {
        stripe: seller?.stripe
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

Das bedeutet also, dass der Körper validiert ist und wir erfolgreich Ereignisse von Stripe empfangen, aber mal sehen, ob das Onboarding funktioniert.

Sobald Sie zum letzten Schritt gelangen, wird Ihnen wahrscheinlich angezeigt, dass Ihre Kontodaten unvollständig sind. Der letzte Schritt ist die ID-Verifizierung, da es sich um einen Testmodus handelt, den wir simulieren können

Creating a marketplace with Stripe Connect: The onboard process

Okay, sobald wir das erledigt haben, kehren wir zur vorherigen Seite zurück und können auf „Senden“ klicken. Drücken Sie auf „Senden“ und wir gelangen zur Konsole

export async function action({request}: ActionFunctionArgs) {
    const authenticated = await authenticator.isAuthenticated(request, {
        failureRedirect: '/login'
    })
    const seller = await prisma.seller.findFirst({
        where: {
            id: authenticated.id
        }, include: {
            stripe: true
        }
    })
    if (seller && seller.stripe?.is_onboarded) {
        return json({
            message: 'User is onboarded already',
            error: true
        }, {
            status: 400
        })
    }
    const account = seller?.stripe?.account_id ? {
        id: seller.stripe?.account_id
    } : await stripe.accounts.create({
        email: seller?.email,
        controller: {
            fees: {
                payer: 'application',
            },
            losses: {
                payments: 'application',
            },
            stripe_dashboard: {
                type: 'express',
            },
        },
    });
    if (!seller?.stripe?.account_id) {
        await prisma.seller.update({
            where: {
                id: authenticated.id
            },
            data: {
                stripe: {
                    create: {
                        account_id: account.id
                    }
                }
            }, include: {
                stripe: true
            }
        })
    }
    const accountLink = await stripe.accountLinks.create({
        account: account.id,
        refresh_url: 'http://localhost:5173/onboarding',
        return_url: 'http://localhost:5173/onboarding',
        type: 'account_onboarding',
        collection_options: {
            fields: 'eventually_due',
        },
    });
    console.debug(`[ACCOUNT ID = ${account.id}] CREATED ACCOUNT ONBOARDING LINK, REDIRECTING...`)

    return redirect(accountLink.url)
}
Nach dem Login kopieren
Nach dem Login kopieren

Das funktioniert, jetzt bringt uns Stripe zur Onboarding-Seite zurück und zeigt uns unsere Konto-ID an, was bedeutet, dass wir das Onboarding erfolgreich abgeschlossen haben und mit der Erstellung von Produkten beginnen können.

Creating a marketplace with Stripe Connect: The onboard process

Okay, lasst uns einfach die Schaltfläche des Verkäufer-Dashboards funktionsfähig machen, bevor wir zu den Produkten übergehen, und eine neue Route erstellen, die sich unter /portal befindet

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Store {
  id         String   @id // This will be the store's subdomain
  name       String
  updated_at DateTime @default(now()) @updatedAt
  seller     Seller?
}

model Seller {
  id           Int      @id @default(autoincrement())
  email        String
  password     String
  store        Store    @relation(fields: [store_id], references: [id])
  date_created DateTime @default(now())
  date_updated DateTime @updatedAt
  store_id     String   @unique
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Sehr einfache Funktion. Wenn Sie also nach dem Onboarding zu /portal gehen, werden Sie zu dem einmaligen Link weitergeleitet, den wir für das Stripe-Konto generieren.

In der Onboarding-Route sorgen wir dafür, dass das Verkäufer-Dashboard-Div mit einem Link umschlossen wird.

model Stripe {
  account_id String @id
  is_onboarded Boolean @default(false)
  user Users @relation(fields: [user_id], references: [discord_id])
  user_id String @unique
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
}

model Seller {
  id           Int      @id @default(autoincrement())
  email        String
  password     String
  store        Store    @relation(fields: [store_id], references: [id])
  date_created DateTime @default(now())
  date_updated DateTime @updatedAt
  store_id     String   @unique
  stripe       Stripe?
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wenn wir /portal besuchen oder auf die Schaltfläche klicken, werden wir zum Stripe-Portal für Connect-Konten weitergeleitet, wo der Benutzer seine Analysen, Auszahlungen usw. sehen kann...

Creating a marketplace with Stripe Connect: The onboard process

Dies markiert das Ende von Teil eins unserer Entwicklung eines Marktplatzes mit Stripe Connect, Teil zwei wird sich mit Produkten, Zahlungen und Auszahlungen befassen, Teil drei wird der letzte sein und dort werden wir uns mit der kundenorientierten Seite des Projekts befassen .

Sie können den Quellcode des Projekts unter https://github.com/ddm50/stripe-connect-howto-seller sehen

Das obige ist der detaillierte Inhalt vonMit Stripe Connect einen Marktplatz erstellen: Der Onboard-Prozess. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage