ホームページ > ウェブフロントエンド > jsチュートリアル > Stripe Connect を使用したマーケットプレイスの作成: オンボードプロセス

Stripe Connect を使用したマーケットプレイスの作成: オンボードプロセス

Susan Sarandon
リリース: 2024-11-28 09:55:13
オリジナル
308 人が閲覧しました

導入

マーケットプレイスを提供している決済処理業者が多くないことを考えると、マーケットプレイスを作成するのはおそらく難しすぎるか不可能でしょう。もしマーケットプレイスが提供しなければ、その情報を知った瞬間にプラットフォームから強制終了される可能性が高く、それがなかったとしてもプラットフォームを使用して販売者への支払い、返金、支払いを処理するための強固な基盤がないマーケットプレイスを作成するのは危険です。

Stripe Connect はこれらの問題に対処し、販売者としてサインアップできる基本的なマーケットプレイスを作成し、顧客がこれらの販売者から商品を簡単に購入できるようにします。プラットフォーム所有者はサービス手数料を設定することもできるため、ユーザー X がストア Y から購入すると、その取引の X% が取り扱われますが、それについては後ほど説明します。

Creating a marketplace with Stripe Connect: The onboard process

プロジェクトのセットアップ

データベース接続の処理には Prisma を使用し、認証は remix-auth によって処理されます。この部分については、マーケットプレイスの販売者側のみを処理します。

// 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
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

これは schema.prisma ファイルの外観です。販売者モデルとそれに関連する店舗モデルがあります。「id」フィールドはサブドメインとして機能するため、購入者の側に到達すると、次のことが可能になります。 store.localhost.com にアクセスし、そこの販売者から製品を購入します。
また、販売者の Connect アカウントに関するデータを保存する Stripe モデルも追加します。

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?
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

これでユーザーのオンボーディングを処理できるようになったので、.env ファイルに別の変数を定義しましょう。

STRIPE_SK=your stripe secret key here
ログイン後にコピー
ログイン後にコピー

Stripe の開発ページで生成することで Stripe 秘密キーを取得できます。現時点では Stripe Connect の使用のみを許可する制限付きキーを作成することをお勧めします。

次に、Stripe クライアントをエクスポートしてルートで使用できるようにする新しいファイルを作成する必要があります

// app/libs/stripe.server.ts
import Stripe from 'stripe';
export const stripe = new Stripe(process.env.STRIPE_SK)
ログイン後にコピー
ログイン後にコピー

「/onboarding」に新しいルートを作成します

// 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>
}
ログイン後にコピー
ログイン後にコピー

販売者のオンボーディングステータスに関するデータを渡すローダー関数を追加します

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
    }
}
ログイン後にコピー
ログイン後にコピー

ここで、/onboarding にアクセスすると、接続されていないことが表示され、ボタンを押してサインアップできるようになります。ここでアクション関数が登場します。

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)
}
ログイン後にコピー
ログイン後にコピー

販売者がボタンを押すと、登録に使用したメールアドレスでアカウントが作成され、販売者が既に Stripe アカウントを関連付けている場合は、オンボーディング ページにリダイレクトするアカウント リンクが作成されます。がオンボーディングされていない場合は、オンボーディング リンクにリダイレクトします。

Creating a marketplace with Stripe Connect: The onboard process

そこから販売者はメール/電話番号を入力し、オンボーディングプロセスが始まります。通常、Stripe は販売者にビジネスの場所、ビジネスの詳細、銀行口座などを尋ねます...

Stripe Connect イベントの Webhook をリッスンできるようになりました。そのため、販売者が正常にオンボーディングしたら、それらの属性をデータベース内の販売者のレコードに追加します。

テストの場合は、Stripe CLI をダウンロードするだけで、そこからイベントをこれから作成する新しいルート /api/notifications に転送できます

// 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
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

そのコマンドを実行すると、Webhook 署名が与えられます。これにより、Stripe から送信された各 Webhook の整合性を検証できるようになります。Stripe の開発者ポータルで Webhook を作成した場合も同様に、シークレットが得られます。 .

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?
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

.env ファイルに新しい変数も追加します

STRIPE_SK=your stripe secret key here
ログイン後にコピー
ログイン後にコピー

これで、Stripe から送信されるこれらのイベントを処理するコードを作成できます

// app/libs/stripe.server.ts
import Stripe from 'stripe';
export const stripe = new Stripe(process.env.STRIPE_SK)
ログイン後にコピー
ログイン後にコピー

Stripe がリクエストを送信していることを確認します。Stripe である場合は次に進みます。注目したいイベントは account.updated です。そのイベントは、販売者をリダイレクトする前に作成したアカウントに関連しています。

販売者がオンボーディング プロセスを開始したり、電話番号を追加したり、電子メールを入力したり、最終的にオンボーディング プロセスを完了すると、「account.updated」イベントが取得され、この配列が一緒に送信されます

アカウント.requirements.currently_due

'currently_due' 配列の長さが 0 の場合、ユーザーが完全にオンボーディングされ、支払いを受け入れることができることがわかります。そのため、データベースを更新してユーザーが商品を作成できるようにすることができますが、その前に以下を追加しましょう「/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>
}
ログイン後にコピー
ログイン後にコピー

それが整ったら、オンボーディングを試して、それが機能するかどうかを確認できます。たとえばアドレスを入力するとすぐに、プロジェクトのコンソールに
のようなメッセージが表示されます。

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
    }
}
ログイン後にコピー
ログイン後にコピー

これは、本文が検証され、Stripe からイベントを正常に受信していることを意味しますが、オンボーディングが機能するかどうかを見てみましょう。

最後のステップに到達すると、おそらくアカウントの詳細が不完全であることが表示されます。最後のステップは ID 確認です。これはテストモードなので、それをシミュレートできます

Creating a marketplace with Stripe Connect: The onboard process

それが完了したら、前のページに戻り、送信を押し、送信を押して、コンソールに入ります

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)
}
ログイン後にコピー
ログイン後にコピー

これでうまくいきました。Stripe はオンボーディング ページに戻り、アカウント ID が表示されます。これはオンボーディングが成功し、製品の作成を開始できることを意味します。

Creating a marketplace with Stripe Connect: The onboard process

それでは、商品に進む前に販売者ダッシュボード ボタンを機能させて、/portal に新しいルートを作成しましょう

// 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
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

非常に基本的な機能なので、オンボーディングしている場合に /portal にアクセスすると、Stripe アカウント用に生成された 1 回限りのリンクにリダイレクトされます。

オンボーディング ルートで、販売者ダッシュボード div をリンクでラップします。

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?
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

/portal にアクセスするかボタンを押すと、Stripe の Connect アカウント用ポータルにリダイレクトされ、ユーザーはそこで分析や支払いなどを確認できます...

Creating a marketplace with Stripe Connect: The onboard process

これで、Stripe Connect を使用してマーケットプレイスを作成するパート 1 が終了します。パート 2 は製品、支払い、支払いを扱います。パート 3 が最後で、そこでプロジェクトの顧客側の側面を扱います。 .

プロジェクトのソース コードは、https://github.com/ddm50/ Stripe-connect-howto-seller でご覧いただけます

以上がStripe Connect を使用したマーケットプレイスの作成: オンボードプロセスの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート