Mewujudkan pasaran mungkin akan menjadi terlalu sukar, atau mustahil memandangkan tidak banyak pemproses pembayaran yang menawarkannya, jika mereka tidak menawarkannya maka anda berkemungkinan akan dibuang dari platform sebaik sahaja mereka mengetahuinya, dan walaupun tanpa itu adalah berisiko untuk mencipta pasaran di mana anda tidak mempunyai asas yang kukuh untuk mengendalikan pembayaran, bayaran balik dan pembayaran kepada penjual menggunakan platform.
Stripe Connect menangani isu ini, ia akan membolehkan kami mencipta pasaran asas di mana anda boleh mendaftar untuk menjadi penjual dan pelanggan boleh membeli item daripada penjual ini dengan mudah. Sebagai pemilik platform, anda juga boleh menetapkan yuran perkhidmatan anda, jadi apabila pengguna X membeli dari kedai Y maka kami akan mendapat potongan X% daripada urus niaga itu tetapi lebih lanjut mengenainya kemudian.
Untuk mengendalikan sambungan pangkalan data yang kami gunakan Prisma, pengesahan dikendalikan oleh remix-auth, untuk bahagian ini kami mengendalikan pihak penjual sahaja di pasaran.
// 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 }
Beginilah rupa fail schema.prisma kami, kami mempunyai model Penjual dan model Kedai yang berkaitan dengannya, medan "id" akan berfungsi sebagai subdomain jadi apabila kami sampai ke pihak pembeli, saya akan dapat layari di store.localhost.com dan beli produk daripada penjual di sana.
Dan kami juga akan menambah model Stripe, yang akan menyimpan data tentang akaun Connect penjual.
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? }
Sekarang kita boleh berurusan dengan onboarding pengguna, jadi mari kita tentukan pembolehubah lain dalam fail .env kami.
STRIPE_SK=your stripe secret key here
Anda boleh mendapatkan kunci rahsia Stripe dengan menjananya dalam halaman dev Stripe, adalah idea yang baik untuk mencipta kunci terhad yang pada masa ini hanya membenarkan penggunaan Stripe Connect.
Kemudian anda perlu mencipta fail baharu yang akan mengeksport klien Stripe supaya ia boleh digunakan oleh laluan kami
// app/libs/stripe.server.ts import Stripe from 'stripe'; export const stripe = new Stripe(process.env.STRIPE_SK)
Kami akan membuat laluan baharu yang akan berada di "/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> }
Kami akan menambah fungsi pemuat yang akan menghantar data mengenai status onboarding penjual
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 } }
Sekarang jika anda pergi ke /onboarding ia akan mengatakan bahawa anda tidak disambungkan, dan anda akan dapat menekan butang untuk mendaftar, di sinilah fungsi tindakan kami masuk
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) }
Apabila penjual menekan butang kami akan membuat akaun dengan e-mel yang mereka gunakan untuk mendaftar, kemudian kami akan membuat Pautan Akaun yang akan mengubah hala mereka ke halaman onboarding, jika penjual sudah mempunyai akaun Stripe yang dilampirkan tetapi tidak berada di dalam kapal, maka kami juga mengubah hala mereka ke pautan berpandukan.
Dari situ penjual akan masukkan e-mel/nombor telefonnya, dan proses onboarding akan bermula, Stripe biasanya akan meminta penjual lokasi perniagaan, butiran perniagaan, akaun bank dll...
Kini kami boleh mendengar webhooks untuk acara Stripe Connect, jadi apabila penjual telah berjaya masuk, kami akan menambahkan atribut tersebut pada rekod Penjual dalam pangkalan data.
Untuk ujian, anda hanya boleh memuat turun Stripe CLI dan dari situ anda boleh memajukan sebarang acara ke laluan baharu /api/pemberitahuan kami yang akan kami buat sekarang
// 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 }
Apabila anda menjalankan arahan itu, anda akan diberi tandatangan webhook, supaya kami boleh mengesahkan integriti setiap webhook yang dihantar kepada kami oleh Stripe, begitu juga jika anda membuat webhook pada portal pembangun di Stripe, anda akan mempunyai rahsia .
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? }
Kami juga akan menambah pembolehubah baharu dalam fail .env
STRIPE_SK=your stripe secret key here
Kini kami boleh menulis kod untuk mengendalikan acara ini yang dihantar kepada kami oleh Stripe
// app/libs/stripe.server.ts import Stripe from 'stripe'; export const stripe = new Stripe(process.env.STRIPE_SK)
Kami mengesahkan bahawa ia adalah Stripe yang menghantar permintaan, jika itu kemudian kami meneruskan, kini acara yang kami ingin lihat ialah akaun. dikemas kini, acara itu berkaitan dengan Akaun yang kami buat sebelum mengubah hala penjual.
Apabila penjual memulakan proses onboarding, menambah nombor telefonnya atau memasukkan e-mel, atau akhirnya menyelesaikan proses onboarding, kami akan mendapat acara 'account.updated' dan tatasusunan ini akan dihantar bersamanya
keperluan akaun.sedang_tetapnya
Apabila panjang tatasusunan 'currently_due' adalah pada sifar maka kami tahu pengguna sudah siap sepenuhnya, boleh menerima pembayaran dan oleh itu dari pihak kami, kami boleh mengemas kini pangkalan data dan membenarkan pengguna mencipta produk, tetapi sebelum kami melakukannya mari tambah logik ini dalam tindakan '/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> }
Setelah itu tersedia, kami boleh mencuba onboarding dan melihat sama ada ia berfungsi. Sebaik sahaja anda memasukkan alamat sebagai contoh, anda akan melihat mesej dalam konsol projek seperti
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 } }
Jadi itu bermakna badan itu disahkan dan kami berjaya menerima acara daripada Stripe, tetapi mari kita lihat jika onboarding akan berfungsi.
Apabila anda sampai ke langkah terakhir, ia mungkin akan mengatakan bahawa butiran akaun anda tidak lengkap, langkah terakhir ialah pengesahan ID, kerana ini adalah mod ujian, kami boleh mensimulasikannya
Baiklah jadi apabila kita telah melakukannya, kita akan kembali ke halaman sebelumnya dan kita boleh menekan hantar, tekan hantar dan kita akan masuk ke dalam konsol
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) }
Itu berkesan, sekarang Stripe akan mengembalikan kami ke halaman onboarding dan ia akan menunjukkan ID akaun kami yang bermakna kami telah berjaya onboard dan kami boleh mula membuat produk.
Baiklah, mari kita jadikan butang papan pemuka penjual itu berfungsi sebelum kita beralih kepada produk, buat laluan baharu yang akan berada di /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 }
Fungsi yang sangat asas, jadi sekarang apabila anda pergi ke /portal jika anda berada di atas kapal, anda akan dialihkan ke pautan sekali guna yang kami hasilkan untuk Akaun Stripe.
Dalam laluan onboarding, kami akan membalut div papan pemuka Penjual dengan Pautan.
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? }
Apabila kami melawati /portal atau menekan butang, kami akan dialihkan ke akaun Stripe's Portal for Connect, di sana pengguna boleh melihat analitisnya, pembayaran dll...
Ini menandakan berakhirnya bahagian pertama kami mencipta pasaran dengan Stripe Connect, bahagian kedua akan berurusan dengan produk, pembayaran dan pembayaran, bahagian tiga akan menjadi yang terakhir dan di sana kami akan berurusan dengan pelanggan yang berhadapan dengan bahagian projek .
Anda boleh melihat kod sumber projek di https://github.com/ddm50/stripe-connect-howto-seller
Atas ialah kandungan terperinci Mencipta pasaran dengan Stripe Connect: Proses onboard. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!