Monetizza il software open source con le funzioni Gatsby e Stripe
Pubblicato: 2022-03-10In questo articolo, spiegherò come ho utilizzato le funzioni Gatsby e l'API Stripe per abilitare contributi sicuri "Paga quello che vuoi" che aiutano a finanziare il mio progetto open source MDX Embed.
Nota : MDX Embed ti consente di incorporare facilmente contenuti multimediali di terze parti popolari come video di YouTube, Tweet, post di Instagram, lezioni di Egghead, Spotify, TikTok e molti altri direttamente nel tuo .mdx
, non è richiesta l'importazione.
Funzioni serverless di Gatsby
Le funzioni Gatsby aprono un mondo completamente nuovo per gli sviluppatori front-end in quanto forniscono un modo per scrivere e utilizzare codice lato server senza il fastidio di mantenere un server. Gli usi per le funzioni serverless vanno dall'iscrizione alla newsletter con ConvertKit, all'invio di un'e-mail tramite SendGrid, al salvataggio dei dati in un database come Fauna o, in questo caso, all'accettazione di pagamenti sicuri tramite Stripe: l'elenco è francamente infinito!
I servizi di terze parti come quelli sopra menzionati accetteranno solo le richieste inviate lato server. Ci sono una serie di ragioni per questo, ma l'utilizzo di chiavi sicure o private è in genere uno. L'uso di queste chiavi lato server significa che non sono esposte al client (browser) e non possono essere abusate, ed è qui che le funzioni serverless di Gatsby possono aiutare.
Gatsby fornisce lo stesso approccio logico alle funzioni serverless delle pagine. Ad esempio, le pagine del sito Web si trovano in src/pages
e le funzioni serverless si trovano in src/api
.
Naturalmente, c'è qualcosa in più, ma l'esperienza degli sviluppatori di Gatsby è sia logica che coerente, e io per primo lo adoro!
Stesse funzioni di origine
Nove volte su dieci, quando lavori con le funzioni serverless, le utilizzerai nel modo in cui avrebbero dovuto essere utilizzate, ad esempio, il tuo sito Web utilizza le proprie funzioni. Chiamo questo utilizzo Funzioni della stessa origine o SOF in breve. In questo scenario sia il front-end che l'API sono distribuiti alla stessa origine, ad esempio www.my-website.com e www.my-website.com/api, e la comunicazione tra i due è senza interruzioni e, ovviamente , velocissimo!
Ecco un diagramma per aiutare a illustrare come appare:
Funzioni cross-origine
Ci sono, tuttavia, almeno due scenari che ho incontrato in cui ho avuto bisogno di ciò che ho chiamato "Funzioni Cross-Origin" (o COF in breve). I due scenari in cui ho bisogno di COF sono i seguenti:
- Ho bisogno di funzionalità lato server ma il sito Web di origine non può eseguire funzioni serverless.
- La funzione serverless è utilizzata da più di un'origine.
Nota : l'uso di Gatsby non è l'unico modo per scrivere funzioni serverless, ma ne parleremo tra poco.
Ho sperimentato per la prima volta questo approccio nel novembre 2020 prima del rilascio di Gatsby Functions e ho utilizzato Netlify Functions per fornire comunicazioni da server a server con l'API di Twitter, il mio blog Gatsby e il portfolio commerciale. Puoi leggere questo approccio qui: Usa Netlify Functions e l'API di Twitter v2 come CMS per il tuo blog Gatsby.
Dopo il rilascio di Gatsby Functions nel giugno 2021, ho rifattorizzato quanto sopra per lavorare con Gatsby Functions ed ecco alcune informazioni in più su come ho fatto e perché: Utilizzo di Gatsby Functions come API astratta.
Ecco un diagramma per illustrare meglio l'approccio generale.
Nel diagramma precedente website-1.com
è costruito con Gatsby e avrebbe potuto usare le funzioni serverless (ma non lo fa) e website-2.com
è costruito usando qualcosa che non ha funzionalità di funzione serverless.
Nota : in entrambi i casi, entrambi devono utilizzare lo stesso servizio di terze parti, quindi ha senso astrarre questa funzionalità in un'API autonoma.
Anche l'API standalone di esempio ( my-api.com
) è un sito Gatsby e dispone di funzionalità Serverless Function, ma soprattutto consente a siti Web di altre origini di utilizzare le sue funzioni Serverless.
So cosa stai pensando: CORS! Bene, siediti stretto. Lo tratterò a breve.
Monetizzazione dell'incorporamento MDX
Questa era la situazione in cui mi trovavo con MDX Embed. Il sito Web della documentazione per questo progetto è stato creato utilizzando Storybook. Storybook non ha capacità serverless ma avevo davvero bisogno di una comunicazione da server a server. La mia soluzione? Ho creato un'API autonoma chiamata API Paulie.
API Paulie
L'API Paulie (come l'esempio dell'API standalone menzionata sopra) può accettare richieste da siti Web di origini diverse e può connettersi a diversi servizi di terze parti, uno dei quali è Stripe.
Per abilitare i pagamenti Stripe da MDX Embed, ho creato un endpoint api/make-stripe-payment
sull'API Paulie che può trasmettere le informazioni rilevanti da MDX Embed attraverso la propria funzione serverless e all'API Stripe per creare un "checkout". Puoi vedere il codice src qui.
Una volta che un checkout è stato creato con successo, l'API Stripe restituisce un URL. Questo URL viene ritrasferito a MDX Embed che apre una nuova finestra nel browser in cui i "clienti" possono inserire in modo sicuro i propri dettagli di pagamento su una pagina Web di Stripe... e boom! vieni pagato!
Ecco un diagramma che illustra meglio come funziona:
Questo approccio è lo stesso menzionato sopra, dove https://mdx-embed.com invia richieste a https://paulieapi.gatsbyjs.io che a sua volta si connette all'API Stripe utilizzando la comunicazione da server a server. Ma prima di andare troppo oltre, vale la pena spiegare perché non ho usato react-stripe-js
.
react-stripe-js
react-stripe-js
è un toolkit lato client (browser) che ti consente di creare checkout ed elementi Stripe nel tuo progetto React. Con react-stripe-js puoi impostare un metodo per accettare pagamenti in modo sicuro senza la necessità di comunicazioni lato server, ma... e c'è un ma. Volevo implementare i contributi "Paga quello che vuoi". Mi permetta di spiegare.
Ecco uno screenshot del "prodotto" MDX Embed che ho impostato nella dashboard di Stripe. Si noti che il prezzo è di $ 1,00.
Se avessi usato react-stripe-js per abilitare i pagamenti, a tutti i "clienti" verrebbe chiesto di pagare lo stesso importo. In questo caso, è solo $ 1,00 e non pagherà i conti, vero!
Per abilitare "Paga quello che vuoi" (ad esempio un importo nominale scelto da un "cliente"), devi approfondire un po' e utilizzare la comunicazione da server a server e inviare questo importo all'API Stripe utilizzando una richiesta HTTP personalizzata. È qui che utilizzo una funzione Gatsby e inserisco un valore dinamico che verrà quindi utilizzato per creare l'esperienza di "pagamento" e sovrascrivere il prezzo definito nella mia dashboard di Stripe.
Su MDX Embed, ho aggiunto un <input type="number" />
HTML che consente ai "clienti" di impostare un importo anziché pagare un importo predefinito, se solo tutti gli e-commerce fossero così!
Ecco un piccolo video che ho realizzato che mostra come MDX Embed, Paulie API e Stripe API funzionano tutti insieme:
Passando il valore di input da MDX Embed all'API Paulie che a sua volta si collega all'API Stripe sono in grado di creare un checkout "dinamico".
Nota : questo ora significa che i "clienti" possono decidere quanto vale il progetto per loro e impostare un importo adeguato per contribuire.
Vorrei citare a questo punto Benedicte Raae che per prima mi ha mostrato questo approccio durante il suo favoloso corso Summer Functions . Puoi saperne di più visitando i codici Queen Raae. ( Grazie Benedicte, sei il migliore! )
Parliamo di CORS
Per impostazione predefinita, le funzioni serverless di Gatsby non verranno bloccate da CORS poiché il front-end e l'API vengono distribuiti nella stessa origine. Quando si sviluppano funzioni cross-Origin, tuttavia, è necessario configurare la propria API in modo che accetti richieste da origini diverse da quella propria.
Ecco uno snippet di codice per mostrare come gestisco CORS nell'endpoint api/make-stripe-payment
:
// src/api/make-stripe-payment const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY) import Cors from 'cors' const allowedOrigins = [ 'https://www.mdx-embed.com', 'https://paulie.dev', ] const cors = Cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) { callback(null, true) } else { callback(new Error()) } }, }) const runCorsMiddleware = (req, res) => { return new Promise((resolve, reject) => { cors(req, res, (result) => { if (result instanceof Error) { return reject(result) } return resolve(result) }) }) } export default async function handler(req, res) { const { success_url, cancel_url, amount, product } = req.body try { await runCorsMiddleware(req, res) try { const session = await stripe.checkout.sessions.create({ success_url: success_url, cancel_url: cancel_url, payment_method_types: ['card'], line_items: [ { quantity: 1, price_data: { unit_amount: amount * 100, currency: 'usd', product: product, }, }, ], mode: 'payment', }) res.status(200).json({ message: ' Stripe checkout created ok', url: session.url }) } catch (error) { res.status(500).json({ message: ' Stripe checkout error' }) } } catch (error) { res.status(403).json({ message: ' Request blocked by CORS' }) } }
Nel frammento di codice sopra dovresti essere in grado di vedere che ho definito un array di allowedOrigins
, queste sono le uniche origini autorizzate a utilizzare questo endpoint. Le richieste provenienti da qualsiasi altra provenienza riceveranno un codice di stato 403
e un messaggio di Request blocked by CORS
.
Questa funzione accetta anche una serie di parametri del corpo, uno dei quali è l' amount
che il "cliente" ha deciso di pagare, questo è il valore dell'input HTML sul sito MDX Embed. Noterai anche il parametro del product
, questo è l'ID prodotto definito nella mia dashboard di Stripe e come l'API Stripe crea l'URL di "pagamento" corretto. Passare questo valore come parametro del corpo anziché codificarlo come hardcoded nella funzione mi consente di riutilizzare questo endpoint per altri prodotti Stripe.
Il succo vale la pena spremere?
Ho menzionato alcune cose lungo la strada per il motivo per cui ho deciso di intraprendere questa strada. Dopotutto, potrebbe sembrare un modo più complicato di utilizzare le funzioni serverless, ma ho le mie ragioni e penso che ne valga la pena. Ecco perché.
L'API Paulie è sia un'API Cross-Origin che un sito di documentazione. Naturalmente, se hai intenzione di scrivere un'API, deve essere documentata, giusto?
È qui che funziona a mio favore l'utilizzo di Gatsby per alimentare la mia API perché insieme alle funzionalità Serverless l'API di Paulie è anche un sito Web di Gatsby e poiché in realtà è un sito Web, posso riempirlo di contenuti e farlo sembrare carino, ma aspetta c'è di più …
Nota: Paulie API è anche un playground API interattivo!
Ogni funzione ha un collegamento Run in browser
. Questo ti porta ad una pagina del sito dove puoi interagire con la funzione. Serve sia come utile banco di prova mentre sto sviluppando la funzione, sia come un modo semplice per dimostrare come funziona la funzione, i documenti sono buoni, i documenti interattivi sono migliori!
Uso questa API anche per fornire funzionalità lato server simili per i miei altri siti Web. Dai un'occhiata alla pagina Informazioni in cui ho documentato quali dei miei siti utilizzano quali funzioni, ed ecco un diagramma per illustrare come tutto si combina attualmente.
Dovresti vedere dal diagramma sopra che https://paulie.dev utilizza anche l'endpoint Stripe. Ho utilizzato lo stesso approccio di MDX Embed per abilitare la funzionalità "Paga quello che vuoi". È una piccola cosa, ma poiché l'endpoint make-stripe-payment
è già scritto e funzionante, posso riutilizzarlo ed evitare di duplicare questa funzionalità.
Il sito Web https://paulie.dev ha anche le sue Gatsby Serverless Functions che utilizzo per pubblicare le reazioni degli utenti a Fauna e acquisire le iscrizioni alla newsletter. Questa funzionalità è unica per questo sito, quindi non l'ho ancora astratta. Tuttavia, se volessi iscrivermi alla newsletter su https://www.pauliescanlon.io, questo sarebbe il punto in cui migrerò la funzione sull'API Paulie.
Astrazione
Questo potrebbe sembrare un passo indietro per astrarre le tue funzioni serverless. Dopotutto, una delle cose più interessanti dell'andare senza server è che sia il codice front-end che il codice back-end sono attivi nello stesso posto. Come ho mostrato, ci sono momenti in cui l'astrazione ha un senso, per me comunque.
Traggo sicuramente dei vantaggi dall'utilizzo di questo approccio e prevedo di sviluppare ulteriormente la mia API per fornire più funzionalità a un certo numero dei miei siti Web, ma se fare soldi con l'open source è di tuo interesse e il tuo sito non è stato creato utilizzando Gatsby , questo approccio potrebbe essere la risposta che stavi cercando.
Vuoi iniziare con le funzioni di Gatsby? Dai un'occhiata ai documenti di Gatsby Functions per iniziare!
Ulteriori letture
Se sei interessato a saperne di più sulle funzioni serverless, ti consiglio:
- Il libro di Swizec Teller, "Manuale serverless per ingegneri di frontend"
- Corso di funzioni estive di Benedetto
- ...e, ovviamente, i documenti di Gatsby
FuncJam
Dal 17 agosto al 30 settembre, i Gatsby organizzano una competizione comunitaria con alcuni premi assolutamente mega da vincere. Se c'è ancora tempo, vai su FuncJam e unisciti. Inoltre, controlla la sezione Byte-size di questo post del blog; contiene video utili e collegamenti a una serie di funzioni di esempio.
Grazie per la lettura e se desideri discutere di qualcosa menzionato in questo articolo, lascia un commento qui sotto o trovami su Twitter.