Monétisez les logiciels open source avec les fonctions Gatsby et Stripe

Publié: 2022-03-10
Résumé rapide ↬ Les fonctions Gatsby offrent aux développeurs frontaux un moyen d'écrire et d'utiliser du code côté serveur sans avoir à gérer un serveur. Si gagner de l'argent avec l'open source vous intéresse et que votre site n'est pas construit à l'aide de Gatsby, cette approche pourrait bien être la réponse que vous recherchiez.

Dans cet article, j'expliquerai comment j'ai utilisé les fonctions Gatsby et l'API Stripe pour permettre des contributions sécurisées « Payez ce que vous voulez » qui aident à financer mon projet open source MDX Embed.

Remarque : MDX Embed vous permet d'intégrer facilement du contenu multimédia tiers populaire tel que des vidéos YouTube, des tweets, des publications Instagram, des leçons Egghead, Spotify, TikTok et bien d'autres directement dans votre .mdx - aucune importation requise.

Fonctions Gatsby sans serveur

Les fonctions Gatsby ouvrent un tout nouveau monde pour les développeurs front-end car elles permettent d'écrire et d'utiliser du code côté serveur sans avoir à gérer un serveur. Les utilisations des fonctions sans serveur vont des inscriptions à la newsletter avec ConvertKit, l'envoi d'un e-mail à l'aide de SendGrid, l'enregistrement de données dans une base de données comme Fauna ou, dans ce cas, l'acceptation de paiements sécurisés à l'aide de Stripe - la liste est franchement interminable !

Les services tiers comme ceux mentionnés ci-dessus n'accepteront que les demandes envoyées côté serveur. Il y a plusieurs raisons à cela, mais l'utilisation de clés sécurisées ou privées en est généralement une. L'utilisation de ces clés côté serveur signifie qu'elles ne sont pas exposées au client (navigateur) et ne peuvent pas être abusées, et c'est là que les fonctions sans serveur de Gatsby peuvent vous aider.

Gatsby fournit la même approche logique aux fonctions sans serveur qu'aux pages. Par exemple, les pages du site Web sont situées dans src/pages et les fonctions sans serveur sont situées dans src/api .

Naturellement, il y a un peu plus que cela, mais l'expérience de développeur de Gatsby est à la fois logique et cohérente, et pour ma part, j'adore ça !

Fonctions de même origine

Neuf fois sur dix, lorsque vous travaillez avec des fonctions sans serveur, vous les utilisez comme elles étaient censées être utilisées. Par exemple, votre site Web utilise ses propres fonctions. J'appelle cette utilisation Same Origin Functions ou SOF en abrégé. Dans ce scénario, le front-end et l'API sont déployés sur la même origine, par exemple www.my-website.com et www.my-website.com/api, et la communication entre les deux est à la fois transparente et, bien sûr , brûlant vite!

Voici un schéma pour aider à illustrer à quoi cela ressemble :

Diagramme de la même fonction d'origine
Un site Web Gatsby utilisant ses propres fonctions sans serveur. ( Grand aperçu )

Fonctions d'origine croisée

Il y a, cependant, au moins deux scénarios que j'ai rencontrés où j'ai eu besoin de ce que j'ai appelé "Fonctions d'origine croisée" (ou COF en abrégé). Les deux scénarios où j'ai eu besoin de COF sont les suivants :

  1. J'ai besoin de fonctionnalités côté serveur, mais le site Web d'origine ne peut pas exécuter les fonctions sans serveur.
  2. La fonction sans serveur est utilisée par plusieurs origines.

Remarque : Utiliser Gatsby n'est pas le seul moyen d'écrire des fonctions sans serveur, mais vous en saurez plus dans un instant.

J'ai expérimenté cette approche pour la première fois en novembre 2020 avant la sortie de Gatsby Functions et j'ai utilisé Netlify Functions pour fournir des communications de serveur à serveur avec l'API Twitter et mon blog Gatsby et mon portefeuille commercial. Vous pouvez en savoir plus sur cette approche ici : Utilisez les fonctions Netlify et l'API Twitter v2 comme CMS pour votre blog Gatsby.

Après la sortie de Gatsby Functions en juin 2021, j'ai refactorisé ce qui précède pour travailler avec Gatsby Functions et voici un peu plus d'informations sur la façon dont je m'y suis pris et pourquoi : Utiliser Gatsby Functions comme une API abstraite.

Voici un schéma pour mieux illustrer l'approche générale.

Diagramme de la fonction d'origine croisée
Deux sites Web utilisant les fonctions sans serveur d'une API Gatsby. ( Grand aperçu )

Dans le diagramme ci-dessus, website-1.com est construit avec Gatsby et aurait pu utiliser des fonctions sans serveur (mais ne le fait pas) et website-2.com est construit en utilisant quelque chose qui n'a pas de capacités de fonction sans serveur.

Remarque : Dans les deux cas, ils doivent tous deux utiliser le même service tiers, il est donc logique d'abstraire cette fonctionnalité dans une API autonome.

L'exemple d'API autonome ( my-api.com ) est également un site Gatsby et possède des capacités de fonction sans serveur, mais plus important encore, il permet aux sites Web d'autres origines d'utiliser ses fonctions sans serveur.

Je sais ce que vous pensez : CORS ! Eh bien, restez assis. Je couvrirai cela sous peu.

Plus après saut! Continuez à lire ci-dessous ↓

Monétiser MDX Embed

C'est la situation dans laquelle je me suis retrouvé avec MDX Embed. Le site Web de documentation de ce projet est construit à l'aide de Storybook. Storybook n'a pas de fonctionnalités sans serveur, mais j'avais vraiment besoin d'une communication de serveur à serveur. Ma soluce ? J'ai créé une API autonome appelée Paulie API.

API Paulie

L'API Paulie (comme l'exemple d'API autonome mentionné ci-dessus) peut accepter les demandes de sites Web d'origines différentes et peut se connecter à un certain nombre de services tiers différents, dont Stripe.

Pour activer les paiements Stripe à partir de MDX Embed, j'ai créé un point de terminaison api/make-stripe-payment sur l'API Paulie qui peut transmettre les informations pertinentes de MDX Embed via sa propre fonction sans serveur et à l'API Stripe pour créer une "paiement". Vous pouvez voir le code src ici.

Une fois qu'un paiement a été créé avec succès, l'API Stripe renvoie une URL. Cette URL est renvoyée à MDX Embed qui ouvre une nouvelle fenêtre dans le navigateur où les « clients » peuvent saisir en toute sécurité leurs informations de paiement sur une page Web Stripe… et boum ! Vous êtes payé!

Voici un diagramme qui illustre mieux comment cela fonctionne :

Schéma de MDX Embed utilisant l'API Paulie
MDX Embed se connectant à l'API Stripe via les fonctions sans serveur de l'API Paulie. ( Grand aperçu )

Cette approche est la même que celle mentionnée ci-dessus où https://mdx-embed.com envoie des requêtes à https://paulieapi.gatsbyjs.io qui à son tour se connecte à l'API Stripe en utilisant une communication de serveur à serveur. Mais avant d'aller trop loin, il vaut la peine d'expliquer pourquoi je n'ai pas utilisé react-stripe-js .

react-stripe-js

react-stripe-js est une boîte à outils côté client (navigateur) qui vous permet de créer des vérifications et des éléments Stripe dans votre projet React. Avec react-stripe-js, vous pouvez configurer une méthode pour accepter les paiements en toute sécurité sans avoir besoin de communication côté serveur, mais… et il y a un mais. Je voulais mettre en place des contributions "Pay what you want". Permettez-moi de vous expliquer.

Voici une capture d'écran du "produit" MDX Embed que j'ai configuré dans mon tableau de bord Stripe. Notez que le prix est de 1,00 $.

Capture d'écran du tableau de bord Stripe avec un prix de 1,00 $ pour le produit MDX Embed
Section produit du tableau de bord Stripe. ( Grand aperçu )

Si j'avais utilisé react-stripe-js pour activer les paiements, tous les "clients" seraient invités à payer le même montant. Dans ce cas, c'est seulement 1,00 $ et ça ne paiera pas les factures, n'est-ce pas !

Pour activer « Payez ce que vous voulez » (par exemple, un montant nominal choisi par un « client »), vous devez plonger un peu plus profondément et utiliser la communication de serveur à serveur et envoyer ce montant à l'API Stripe à l'aide d'une requête HTTP personnalisée. C'est là que j'utilise une fonction Gatsby et que je transmets une valeur dynamique qui sera ensuite utilisée pour créer l'expérience de "paiement" et écraser le prix défini dans mon tableau de bord Stripe.

Sur MDX Embed, j'ai ajouté un HTML <input type="number" /> qui permet aux "clients" de fixer un montant plutôt que de payer un montant prédéfini - si seulement tous les e-commerce étaient comme ça !

Voici une petite vidéo que j'ai réalisée et qui montre comment MDX Embed, l'API Paulie et l'API Stripe fonctionnent ensemble :

Comment MDX Embed, l'API Paulie et l'API Stripe fonctionnent ensemble pour permettre « Payez ce que vous voulez ».

En transmettant la valeur d'entrée de MDX Embed à l'API Paulie qui se connecte à son tour à l'API Stripe, je suis en mesure de créer une caisse «dynamique».

Remarque : Cela signifie désormais que les « clients » peuvent décider de ce que le projet vaut pour eux et fixer un montant approprié à contribuer.

J'aimerais mentionner à ce stade Benedicte Raae qui m'a montré cette approche pour la première fois lors de son fabuleux cours Summer Functions . Vous pouvez en savoir plus en visitant Queen Raae Codes. ( Merci Bénédicte, tu es la meilleure ! )

Parlons de CORS

Par défaut, les fonctions Gatsby Serverless ne seront pas bloquées par CORS puisque le front-end et l'API sont déployés sur la même origine. Cependant, lors du développement de Cross-Origin Functions, vous devrez configurer votre API afin qu'elle accepte les requêtes d'origines différentes de la sienne.

Voici un extrait de code pour montrer comment je gère CORS dans le point de terminaison 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' }) } }

Dans l'extrait de code ci-dessus, vous devriez pouvoir voir que j'ai défini un tableau de allowedOrigins , ce sont les seules origines autorisées à utiliser ce point de terminaison. Les demandes provenant de toute autre origine recevront un code d'état 403 et un message Request blocked by CORS .

Cette fonction accepte également un certain nombre de paramètres de corps, dont l'un est le amount que le "client" a décidé de payer, c'est la valeur de l'entrée HTML sur le site MDX Embed. Vous remarquerez également le paramètre product , il s'agit de l'identifiant du produit défini dans mon tableau de bord Stripe et comment l'API Stripe crée l'URL de « paiement » correcte. Passer cette valeur en tant que paramètre de corps plutôt que de la coder en dur dans la fonction me permet de réutiliser ce point de terminaison pour d'autres produits Stripe.

Le jus vaut-il la peine d'être pressé ?

J'ai mentionné quelques éléments en cours de route pour expliquer pourquoi j'ai décidé d'emprunter cette voie. Après tout, cela peut sembler être une façon plus compliquée d'utiliser les fonctions sans serveur, mais j'ai mes raisons et je pense que cela en vaut la peine. Voici pourquoi.

L'API Paulie est à la fois une API Cross-Origin et un site de documentation. Naturellement, si vous allez écrire une API, elle doit être documentée, n'est-ce pas ?

C'est là que cela fonctionne en ma faveur d'utiliser Gatsby pour alimenter mon API, car avec les capacités sans serveur, l'API Paulie est également un site Web Gatsby, et comme c'est en fait un site Web, je peux le remplir de contenu et le rendre joli, mais attendez, il y a plus …

Remarque : Paulie API est également un terrain de jeu API interactif !

Chaque fonction a un lien Run in browser . Cela vous amène à une page du site où vous pouvez interagir avec la fonction. Il sert à la fois de terrain d'essai utile pendant que je développe la fonction et de moyen simple de démontrer comment la fonction fonctionne, les docs sont bonnes, les docs interactives sont meilleures !

J'utilise également cette API pour fournir des fonctionnalités côté serveur similaires pour mes autres sites Web. Jetez un œil à la page À propos où j'ai documenté lequel de mes sites utilise quelles fonctions, et voici un diagramme pour illustrer comment tout cela s'articule actuellement.

Schéma des fonctions d'origine croisée de l'API Paulie
Capacités de la fonction d'origine croisée de l'API Paulie. ( Grand aperçu )

Vous devriez voir sur le diagramme ci-dessus que https://paulie.dev utilise également le point de terminaison Stripe. J'ai utilisé la même approche qu'avec MDX Embed pour activer la fonctionnalité « Payez ce que vous voulez ». C'est une petite chose, mais comme le point de terminaison make-stripe-payment est déjà écrit et fonctionne, je peux le réutiliser et éviter de dupliquer cette fonctionnalité.

Le site Web https://paulie.dev possède également ses propres fonctions sans serveur Gatsby que j'utilise pour publier les réactions des utilisateurs à Fauna et capturer les inscriptions à la newsletter. Cette fonctionnalité est unique à ce site, je n'ai donc pas encore résumé cela. Cependant, si je voulais des inscriptions à la newsletter sur https://www.pauliescanlon.io, ce serait le point où je migrerais la fonction vers l'API Paulie.

Capture d'écran de l'interface utilisateur "Pay what you want" de paulie.dev
la section « Payez ce que vous voulez » de paulie.dev. ( Grand aperçu )

Abstraction

Cela peut sembler un pas en arrière pour résumer vos fonctions sans serveur. Après tout, l'une des choses les plus intéressantes à propos du sans serveur est que votre code frontal et votre code principal sont en direct au même endroit. Comme je l'ai montré, il y a des moments où l'abstraction a du sens - pour moi en tout cas.

Je profite certainement de l'utilisation de cette approche et je prévois de développer davantage mon API pour fournir plus de fonctionnalités à un certain nombre de mes propres sites Web, mais si gagner de l'argent à partir de l'open source vous intéresse et que votre site n'est pas construit à l'aide de Gatsby , cette approche pourrait bien être la réponse que vous cherchiez.

Voulez-vous commencer avec les fonctions Gatsby ? Consultez la documentation sur les fonctions Gatsby pour commencer !

Lectures complémentaires

Si vous souhaitez en savoir plus sur les fonctions sans serveur, je vous recommande :

  • Livre de Swizec Teller, "Serverless Handbook For Frontend Engineers"
  • Cours d'été des fonctions de Benoît
  • …et, bien sûr, les docs Gatsby

FuncJam

Du 17 août au 30 septembre, les gens de Gatsby organisent un concours communautaire avec des prix absolument méga à gagner. S'il est encore temps, rendez-vous sur FuncJam et rejoignez-nous. Consultez également la section Taille en octets de cet article de blog ; il contient des vidéos utiles et des liens vers un certain nombre d'exemples de fonctions.

Merci d'avoir lu, et si vous souhaitez discuter de tout ce qui est mentionné dans cet article, laissez un commentaire ci-dessous ou retrouvez-moi sur Twitter.