Monetarisieren Sie Open-Source-Software mit Gatsby-Funktionen und Stripe
Veröffentlicht: 2022-03-10In diesem Artikel werde ich erklären, wie ich Gatsby-Funktionen und die Stripe-API verwendet habe, um sichere „Pay what you want“-Beiträge zu ermöglichen, die zur Finanzierung meines Open-Source-Projekts MDX Embed beitragen.
Hinweis : Mit MDX Embed können Sie beliebte Medieninhalte von Drittanbietern wie YouTube-Videos, Tweets, Instagram-Posts, Egghead-Lektionen, Spotify, TikTok und viele mehr direkt in Ihre .mdx
– kein Import erforderlich.
Serverlose Gatsby-Funktionen
Gatsby-Funktionen eröffnen Front-End-Entwicklern eine völlig neue Welt, da sie eine Möglichkeit bieten, serverseitigen Code zu schreiben und zu verwenden, ohne sich um die Wartung eines Servers kümmern zu müssen. Die Verwendungsmöglichkeiten für serverlose Funktionen reichen von Newsletter-Anmeldungen mit ConvertKit, dem Senden einer E-Mail mit SendGrid, dem Speichern von Daten in einer Datenbank wie Fauna oder in diesem Fall dem Akzeptieren sicherer Zahlungen mit Stripe – die Liste ist offen gesagt endlos!
Dienste von Drittanbietern wie die oben genannten akzeptieren nur Anfragen, die serverseitig gesendet werden. Dafür gibt es eine Reihe von Gründen, aber die Verwendung sicherer oder privater Schlüssel ist in der Regel einer. Die serverseitige Verwendung dieser Schlüssel bedeutet, dass sie dem Client (Browser) nicht ausgesetzt sind und nicht missbraucht werden können, und hier können die serverlosen Funktionen von Gatsby helfen.
Gatsby bietet den gleichen logischen Ansatz für serverlose Funktionen wie für Seiten. Beispielsweise befinden sich Website-Seiten in src/pages
und Serverless Functions in src/api
.
Natürlich steckt noch etwas mehr dahinter, aber Gatsbys Entwicklererfahrung ist sowohl logisch als auch konsistent, und das liebe ich absolut!
Gleiche Ursprungsfunktionen
In neun von zehn Fällen, wenn Sie mit serverlosen Funktionen arbeiten, verwenden Sie sie so, wie sie verwendet werden sollten, z. B. verwendet Ihre Website ihre eigenen Funktionen. Ich nenne diese Verwendung Same Origin Functions oder kurz SOF's. In diesem Szenario werden sowohl das Front-End als auch die API auf demselben Ursprung bereitgestellt, z. B. www.my-website.com und www.my-website.com/api, und die Kommunikation zwischen den beiden ist nahtlos und natürlich , blitzschnell!
Hier ist ein Diagramm, um zu veranschaulichen, wie das aussieht:
Cross-Origin-Funktionen
Es gibt jedoch mindestens zwei Szenarien, denen ich begegnet bin, wo ich das benötigt habe, was ich „Cross-Origin Functions“ (oder kurz COFs) nenne. Die beiden Szenarien, in denen ich COFs benötigt habe, sind wie folgt:
- Ich benötige serverseitige Funktionen, aber die Ursprungswebsite kann keine serverlosen Funktionen ausführen.
- Die Serverless-Funktion wird von mehr als einem Ursprung verwendet.
Hinweis : Die Verwendung von Gatsby ist nicht die einzige Möglichkeit, serverlose Funktionen zu schreiben, aber dazu gleich mehr.
Ich habe mit diesem Ansatz erstmals im November 2020 vor der Veröffentlichung von Gatsby Functions experimentiert und Netlify Functions verwendet, um Server-zu-Server-Kommunikation mit der Twitter-API und meinem Gatsby-Blog und meinem kommerziellen Portfolio bereitzustellen. Sie können diesen Ansatz hier nachlesen: Verwenden Sie Netlify-Funktionen und die Twitter-API v2 als CMS für Ihren Gatsby-Blog.
Nach der Veröffentlichung von Gatsby Functions im Juni 2021 habe ich das obige umgestaltet, um mit Gatsby Functions zu arbeiten, und hier sind ein paar weitere Informationen darüber, wie ich vorgegangen bin und warum: Using Gatsby Functions as an abstracted API.
Hier ist ein Diagramm, um den allgemeinen Ansatz besser zu veranschaulichen.
Im obigen Diagramm wurde website-1.com
mit Gatsby erstellt und hätte serverlose Funktionen verwenden können (aber nicht) und website-2.com
wurde mit etwas erstellt, das keine serverlosen Funktionen hat.
Hinweis : In beiden Fällen müssen beide denselben Drittanbieterdienst verwenden, daher ist es sinnvoll, diese Funktionalität in einer eigenständigen API zu abstrahieren.
Die beispielhafte eigenständige API ( my-api.com
) ist ebenfalls eine Gatsby-Site und verfügt über serverlose Funktionen, aber was noch wichtiger ist, sie ermöglicht Websites anderer Herkunft, ihre serverlosen Funktionen zu verwenden.
Ich weiß, was du denkst: CORS! Nun, sitz fest. Ich werde das in Kürze behandeln.
Monetarisierung von MDX Embed
Das war die Situation, in der ich mich mit MDX Embed befand. Die Dokumentationswebsite für dieses Projekt wurde mit Storybook erstellt. Storybook hat keine serverlosen Fähigkeiten, aber ich brauchte wirklich eine Server-zu-Server-Kommunikation. Meine Lösung? Ich habe eine eigenständige API namens Paulie API erstellt.
Paulie-API
Die Paulie-API (wie die oben erwähnte beispielhafte eigenständige API) kann Anfragen von Websites unterschiedlicher Herkunft annehmen und eine Verbindung zu einer Reihe verschiedener Dienste von Drittanbietern herstellen, darunter Stripe.
Um Stripe-Zahlungen von MDX Embed zu ermöglichen, habe ich einen api/make-stripe-payment
Endpunkt auf der Paulie-API erstellt, der die relevanten Informationen von MDX Embed über seine eigene serverlose Funktion und an die Stripe-API weiterleiten kann, um eine „Kasse“ zu erstellen. Sie können den src-Code hier sehen.
Sobald ein Checkout erfolgreich erstellt wurde, gibt die Stripe-API eine URL zurück. Diese URL wird an MDX Embed zurückgegeben, das ein neues Fenster im Browser öffnet, in dem „Kunden“ ihre Zahlungsdetails sicher auf einer Stripe-Webseite eingeben können … und boom! Du wirst bezahlt!
Hier ist ein Diagramm, das besser veranschaulicht, wie das funktioniert:
Dieser Ansatz ist derselbe wie oben erwähnt, wo https://mdx-embed.com Anfragen an https://paulieapi.gatsbyjs.io sendet, die wiederum eine Verbindung zur Stripe-API über Server-zu-Server-Kommunikation herstellt. Aber bevor wir zu viel weiter gehen, lohnt es sich zu erklären, warum ich react-stripe-js
nicht verwendet habe.
react-stripe-js
react-stripe-js
ist ein clientseitiges (Browser-)Toolkit, mit dem Sie Stripe-Checkouts und -Elemente in Ihrem React-Projekt erstellen können. Mit React-Stripe-js können Sie eine Methode zum sicheren Akzeptieren von Zahlungen einrichten, ohne dass eine serverseitige Kommunikation erforderlich ist, aber… und es gibt ein Aber. Ich wollte „Pay what you want“-Beiträge umsetzen. Lassen Sie mich erklären.
Hier ist ein Screenshot des „Produkts“ MDX Embed, das ich in meinem Stripe-Dashboard eingerichtet habe. Beachten Sie, dass der Preis 1,00 $ beträgt.
Wenn ich React-Stripe-js verwendet hätte, um Zahlungen zu ermöglichen, würden alle „Kunden“ aufgefordert, den gleichen Betrag zu zahlen. In diesem Fall sind es nur $1,00 und das wird die Rechnungen nicht bezahlen, oder!
Um „Pay what you want“ (z. B. einen von einem „Kunden“ gewählten Nominalbetrag) zu aktivieren, müssen Sie etwas tiefer eintauchen und die Server-zu-Server-Kommunikation verwenden und diesen Betrag mithilfe einer benutzerdefinierten HTTP-Anforderung an die Stripe-API senden. Hier verwende ich eine Gatsby-Funktion und übergebe einen dynamischen Wert, der dann verwendet wird, um das „Checkout“-Erlebnis zu erstellen und den in meinem Stripe-Dashboard definierten Preis zu überschreiben.
Bei MDX Embed habe ich einen HTML- <input type="number" />
hinzugefügt, der es „Kunden“ ermöglicht, einen Betrag festzulegen, anstatt einen vordefinierten Betrag zu zahlen – wenn nur der gesamte E-Commerce so wäre!
Hier ist ein kleines Video, das ich gemacht habe und das zeigt, wie MDX Embed, die Paulie-API und die Stripe-API zusammenarbeiten:
Indem ich den Eingabewert von MDX Embed an die Paulie-API übergebe, die wiederum eine Verbindung zur Stripe-API herstellt, kann ich einen „dynamischen“ Checkout erstellen.
Hinweis : Dies bedeutet nun, dass „Kunden“ entscheiden können, was ihnen das Projekt wert ist, und einen angemessenen Beitragsbetrag festlegen können.
Ich möchte an dieser Stelle Benedicte Raae erwähnen, die mir diese Herangehensweise zum ersten Mal während ihres fabelhaften Summer Functions -Kurses gezeigt hat. Sie können mehr erfahren, indem Sie Queen Raae Codes besuchen. ( Danke Benedikt, du bist der Beste! )
Lassen Sie uns über CORS sprechen
Standardmäßig werden Gatsby Serverless Functions nicht von CORS blockiert, da das Front-End und die API am selben Ursprung bereitgestellt werden. Bei der Entwicklung von Cross-Origin-Funktionen müssen Sie Ihre API jedoch so konfigurieren, dass sie Anfragen von anderen Ursprüngen als dem eigenen akzeptiert.
Hier ist ein Code-Snippet, das zeigt, wie ich CORS im api/make-stripe-payment
Endpunkt handhabe:
// 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' }) } }
Im obigen Code-Snippet sollten Sie sehen können, dass ich ein Array von allowedOrigins
definiert habe, dies sind die einzigen Ursprünge, die diesen Endpunkt verwenden dürfen. Anfragen von anderen Quellen erhalten den Statuscode 403
und die Meldung Request blocked by CORS
.
Diese Funktion akzeptiert auch eine Reihe von Körperparametern, von denen einer der amount
ist, den der „Kunde“ zu zahlen entschieden hat, dies ist der Wert aus der HTML-Eingabe auf der MDX Embed-Site. Sie werden auch den product
bemerken, dies ist die in meinem Stripe-Dashboard definierte Produkt-ID und wie die Stripe-API die korrekte „Checkout“-URL erstellt. Indem ich diesen Wert als Body-Parameter übergebe, anstatt ihn in der Funktion fest zu codieren, kann ich diesen Endpunkt für andere Stripe-Produkte wiederverwenden.
Ist der Saft das Auspressen wert?
Ich habe ein paar Dinge auf dem Weg erwähnt, warum ich mich für diesen Weg entschieden habe. Schließlich mag es wie eine kompliziertere Art erscheinen, serverlose Funktionen zu verwenden, aber ich habe meine Gründe, und ich denke, es lohnt sich. Hier ist der Grund.
Die Paulie-API ist sowohl eine Cross-Origin-API als auch eine Dokumentationsseite. Wenn Sie eine API schreiben, muss diese natürlich dokumentiert werden, richtig?
Hier funktioniert es zu meinen Gunsten, Gatsby zum Betreiben meiner API zu verwenden, da die Paulie-API neben den serverlosen Funktionen auch eine Gatsby-Website ist, und da es sich tatsächlich um eine Website handelt, kann ich sie mit Inhalten füllen und hübsch aussehen lassen, aber warten Sie, es gibt noch mehr …
Hinweis: Paulie API ist auch ein interaktiver API-Spielplatz!
Jede Funktion hat einen Link zum Run in browser
. Dadurch gelangen Sie auf eine Seite der Website, auf der Sie mit der Funktion interagieren können. Es dient sowohl als nützliches Testgelände, während ich die Funktion entwickle, als auch als einfache Methode, um zu demonstrieren, wie die Funktion funktioniert. Dokumente sind gut, interaktive Dokumente sind besser!
Ich verwende diese API auch, um ähnliche serverseitige Funktionen für meine anderen Websites bereitzustellen. Werfen Sie einen Blick auf die About-Seite, auf der ich dokumentiert habe, welche meiner Sites welche Funktionen verwenden, und hier ist ein Diagramm, das veranschaulicht, wie alles derzeit zusammenhängt.
Sie sollten aus dem obigen Diagramm ersehen, dass https://paulie.dev auch den Stripe-Endpunkt verwendet. Ich habe denselben Ansatz wie bei MDX Embed verwendet, um die „Pay what you want“-Funktionalität zu aktivieren. Es ist eine kleine Sache, aber da der make-stripe-payment
Endpunkt bereits geschrieben ist und funktioniert, kann ich ihn wiederverwenden und vermeiden, diese Funktionalität zu duplizieren.
Die Website https://paulie.dev hat auch ihre eigenen Gatsby Serverless Functions, die ich verwende, um Benutzerreaktionen auf Fauna zu posten und Newsletter-Anmeldungen zu erfassen. Diese Funktionalität ist einzigartig auf dieser Website, daher habe ich sie noch nicht abstrahiert. Wenn ich jedoch Newsletter-Anmeldungen auf https://www.pauliescanlon.io wollte, wäre dies der Punkt, an dem ich die Funktion auf die Paulie-API migriere.
Abstraktion
Dies mag wie ein Rückschritt erscheinen, um Ihre serverlosen Funktionen zu abstrahieren. Schließlich ist eines der coolsten Dinge am Serverless, dass sowohl Ihr Front- als auch Ihr Back-End-Code am selben Ort live sind. Wie ich gezeigt habe, gibt es Zeiten, in denen das Abstrahieren sinnvoll ist – jedenfalls für mich.
Ich profitiere sicherlich von diesem Ansatz und plane, meine API weiterzuentwickeln, um mehr Funktionalität für eine Reihe meiner eigenen Websites bereitzustellen, aber wenn das Geldverdienen mit Open Source für Sie von Interesse ist und Ihre Website nicht mit Gatsby erstellt wurde , könnte dieser Ansatz genau die Antwort sein, nach der Sie gesucht haben.
Möchten Sie mit Gatsby Functions loslegen? Schauen Sie sich die Gatsby Functions-Dokumentation an, um loszulegen!
Weiterführende Lektüre
Wenn Sie mehr über serverlose Funktionen erfahren möchten, empfehle ich:
- Swizec Tellers Buch „Serverless Handbook For Frontend Engineers“
- Benedikts Summer Functions-Kurs
- … und natürlich die Gatsby-Dokumente
FuncJam
Vom 17. August bis 30. September veranstalten die Gatsby-Leute einen Community-Wettbewerb, bei dem einige absolut Mega-Preise zu gewinnen sind. Wenn du noch Zeit hast, dann schau bei FuncJam vorbei und mach mit. Schau dir auch den Byte-Size-Abschnitt dieses Blogposts an; Es enthält hilfreiche Videos und Links zu einer Reihe von Beispielfunktionen.
Vielen Dank fürs Lesen. Wenn Sie etwas in diesem Artikel Erwähntes diskutieren möchten, hinterlassen Sie unten einen Kommentar oder finden Sie mich auf Twitter.