Монетизируйте программное обеспечение с открытым исходным кодом с помощью Gatsby Functions и Stripe
Опубликовано: 2022-03-10В этой статье я объясню, как я использовал Gatsby Functions и Stripe API для обеспечения безопасных взносов «Плати сколько хочешь», которые помогают финансировать мой проект MDX Embed с открытым исходным кодом.
Примечание . MDX Embed позволяет легко встраивать популярный сторонний медиаконтент, такой как видео на YouTube, твиты, публикации в Instagram, уроки Egghead, Spotify, TikTok и многое другое, прямо в ваш .mdx
— импорт не требуется.
Бессерверные функции Gatsby
Функции Гэтсби открывают перед разработчиками интерфейсов совершенно новый мир, поскольку они позволяют писать и использовать код на стороне сервера без хлопот, связанных с обслуживанием сервера. Использование бессерверных функций варьируется от подписки на рассылку новостей с помощью ConvertKit, отправки электронной почты с помощью SendGrid, сохранения данных в базе данных, такой как Fauna, или, в этом случае, приема безопасных платежей с помощью Stripe — список, откровенно говоря, бесконечен!
Сторонние службы, подобные упомянутым выше, будут принимать только запросы, отправленные на стороне сервера. Для этого есть ряд причин, но обычно одной из них является использование защищенных или закрытых ключей. Использование этих ключей на стороне сервера означает, что они не доступны для клиента (браузера) и не могут быть использованы не по назначению, и именно здесь могут помочь бессерверные функции Gatsby.
Гэтсби предлагает тот же логический подход к бессерверным функциям, что и к страницам. Например, страницы веб-сайта находятся в src/pages
, а бессерверные функции — в src/api
.
Естественно, это еще не все, но опыт разработчиков Гэтсби логичен и последователен, и мне это очень нравится!
Функции того же происхождения
В девяти случаях из десяти при работе с бессерверными функциями вы будете использовать их так, как они должны были использоваться. Например, ваш веб-сайт использует собственные функции. Я называю это использование функциями того же происхождения или SOF для краткости. В этом сценарии и внешний интерфейс, и API развернуты в одном и том же источнике, например, www.my-website.com и www.my-website.com/api, и связь между ними беспрепятственна и, конечно же, , молниеносно!
Вот диаграмма, чтобы проиллюстрировать, как это выглядит:
Функции кросс-происхождения
Однако я столкнулся как минимум с двумя сценариями, в которых мне понадобилось то, что я называю «функциями кросс-происхождения» (или COF для краткости). Два сценария, в которых мне понадобились COF, следующие:
- Мне нужны возможности на стороне сервера, но исходный веб-сайт не может запускать бессерверные функции.
- Бессерверная функция используется более чем одним источником.
Примечание . Использование Gatsby — не единственный способ написания бессерверных функций, но об этом чуть позже.
Впервые я экспериментировал с этим подходом в ноябре 2020 года перед выпуском Gatsby Functions и использовал Netlify Functions для обеспечения связи между серверами с помощью API Twitter, моего блога Gatsby и коммерческого портфолио. Вы можете прочитать об этом подходе здесь: Используйте Netlify Functions и Twitter API v2 в качестве CMS для своего блога Gatsby.
После выпуска Gatsby Functions в июне 2021 года я реорганизовал вышеизложенное для работы с Gatsby Functions, и вот еще немного информации о том, как я это сделал и почему: Использование Gatsby Functions в качестве абстрактного API.
Вот диаграмма, чтобы лучше проиллюстрировать общий подход.
На приведенной выше диаграмме веб-сайт- website-1.com
создан с помощью Gatsby и мог бы использовать бессерверные функции (но не использует), а веб-сайт- website-2.com
построен с использованием чего-то, что не имеет возможностей бессерверных функций.
Примечание . В обоих случаях им обоим необходимо использовать одну и ту же стороннюю службу, поэтому имеет смысл выделить эту функциональность в отдельный API.
Пример автономного API ( my-api.com
) также является сайтом Gatsby и имеет возможности бессерверных функций, но, что более важно, он позволяет веб-сайтам из других источников использовать его бессерверные функции.
Я знаю, о чем вы думаете: CORS! Ну, сиди спокойно. Я расскажу об этом в ближайшее время.
Монетизация внедрения MDX
Это была ситуация, в которой я оказался с MDX Embed. Веб-сайт документации для этого проекта создан с использованием Storybook. У Storybook нет бессерверных возможностей, но мне действительно нужна была связь между серверами. Мое решение? Я создал автономный API под названием Paulie API.
Поли API
Paulie API (как и пример автономного API, упомянутого выше) может принимать запросы от веб-сайтов различного происхождения и может подключаться к ряду различных сторонних сервисов, одним из которых является Stripe.
Чтобы включить платежи Stripe из MDX Embed, я создал конечную точку api/make-stripe-payment
в Paulie API, которая может передавать соответствующую информацию из MDX Embed через свою собственную бессерверную функцию и в Stripe API для создания «кассы». Вы можете увидеть код src здесь.
После успешного создания проверки Stripe API возвращает URL-адрес. Этот URL-адрес передается обратно в MDX Embed, который открывает новое окно в браузере, где «клиенты» могут безопасно ввести свои платежные данные на веб-странице Stripe… и бум! Вам платят!
Вот диаграмма, которая лучше иллюстрирует, как это работает:
Этот подход аналогичен упомянутому выше, когда https://mdx-embed.com отправляет запросы на https://paulieapi.gatsbyjs.io, который, в свою очередь, подключается к Stripe API, используя связь между серверами. Но прежде чем мы зайдем слишком далеко, стоит объяснить, почему я не использовал react-stripe-js
.
react-stripe-js
react-stripe-js
— это набор инструментов на стороне клиента (браузера), который позволяет создавать проверки и элементы Stripe в вашем проекте React. С помощью react-stripe-js вы можете настроить метод безопасного приема платежей без необходимости связи на стороне сервера, но… и есть одно «но». Я хотел реализовать взносы «Плати сколько хочешь». Позвольте мне объяснить.
Вот скриншот «продукта» MDX Embed, который я настроил на панели управления Stripe. Обратите внимание, что цена составляет 1 доллар США.
Если бы я использовал react-stripe-js для осуществления платежей, всех «клиентов» попросили бы заплатить одинаковую сумму. В этом случае это всего лишь 1 доллар, и это не оплатит счета, не так ли!
Чтобы включить «Плати, сколько хочешь» (например, номинальную сумму, выбранную «клиентом»), вам нужно погрузиться немного глубже и использовать связь между серверами и отправить эту сумму в Stripe API с помощью пользовательского HTTP-запроса. Здесь я использую функцию Гэтсби и передаю динамическое значение, которое затем будет использоваться для создания опыта «оформления заказа» и перезаписи цены, определенной на моей панели инструментов Stripe.
В MDX Embed я добавил HTML-элемент <input type="number" />
, который позволяет «клиентам» устанавливать сумму, а не платить заранее определенную сумму — если бы только вся электронная коммерция была такой!
Вот небольшое видео, которое я сделал, которое показывает, как MDX Embed, Paulie API и Stripe API работают вместе:
Передавая входное значение из MDX Embed в Paulie API, который, в свою очередь, подключается к Stripe API, я могу создать «динамическую» кассу.
Примечание . Теперь это означает, что «клиенты» могут решить, сколько для них стоит проект, и установить соответствующую сумму вклада.
Здесь я хотел бы упомянуть Бенедикт Раае, которая впервые показала мне этот подход во время ее великолепного курса « Летние функции ». Вы можете узнать больше, посетив сайт Queen Raae Codes. ( Спасибо, Бенедикт, ты лучший! )
Поговорим о CORS
По умолчанию бессерверные функции Gatsby не будут заблокированы CORS, поскольку внешний интерфейс и API развернуты в одном и том же источнике. Однако при разработке функций кросс-происхождения вам потребуется настроить API так, чтобы он принимал запросы из источников, отличных от его собственного.
Вот фрагмент кода, показывающий, как я обрабатываю CORS в конечной точке api/make-stripe-payment
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' }) } }
В приведенном выше фрагменте кода вы должны увидеть, что я определил массив allowedOrigins
, это единственные источники, которым разрешено использовать эту конечную точку. Запросы из любого другого источника получат код состояния 403
и сообщение о том, что Request blocked by CORS
.
Эта функция также принимает ряд параметров тела, одним из которых является amount
, которую «клиент» решил заплатить, это значение из ввода HTML на сайте MDX Embed. Вы также заметите параметр product
, это идентификатор продукта, определенный в моей панели инструментов Stripe, и то, как Stripe API создает правильный URL-адрес «оформления заказа». Передача этого значения в качестве параметра тела, а не жесткое кодирование его в функции, позволяет мне повторно использовать эту конечную точку для других продуктов Stripe.
Стоит ли выжимать сок?
По пути я упомянул несколько вещей, почему я решил пойти по этому пути. В конце концов, это может показаться более сложным способом использования бессерверных функций, но у меня есть свои причины, и я думаю, что оно того стоит. Вот почему.
Paulie API — это одновременно и Cross-Origin API, и сайт документации. Естественно, если вы собираетесь писать API, его нужно документировать, верно?
Именно здесь использование Gatsby для поддержки моего API работает в мою пользу, потому что наряду с бессерверными возможностями Paulie API также является веб-сайтом Gatsby, и поскольку это на самом деле веб-сайт, я могу наполнить его контентом и сделать его красивым, но подождите, это еще не все. …
Примечание. Paulie API также является интерактивной площадкой API!
Каждая функция имеет ссылку « Run in browser
. Это приведет вас на страницу сайта, где вы можете взаимодействовать с функцией. Он служит как полезной площадкой для тестирования, пока я разрабатываю функцию, так и простым способом продемонстрировать, как функция работает, документы хороши, интерактивные документы лучше!
Я также использую этот API для обеспечения аналогичных функций на стороне сервера для других моих веб-сайтов. Взгляните на страницу «О нас», где я задокументировал, какие из моих сайтов используют какие функции, и вот диаграмма, иллюстрирующая, как все это в настоящее время объединяется.
На приведенной выше диаграмме видно, что https://paulie.dev также использует конечную точку Stripe. Я использовал тот же подход, что и в случае с MDX Embed, чтобы включить функцию «Плати сколько хочешь». Это мелочь, но поскольку конечная точка make-stripe-payment
уже написана и работает, я могу использовать ее повторно и не дублировать эту функциональность.
На веб-сайте https://paulie.dev также есть свои собственные бессерверные функции Gatsby, которые я использую, чтобы публиковать реакции пользователей на Fauna и регистрировать подписки на рассылку новостей. Эта функциональность уникальна для этого сайта, поэтому я еще не абстрагировался от нее. Однако, если бы я хотел подписаться на новостную рассылку на https://www.pauliescanlon.io, это был бы момент, когда я перенесу функцию на Paulie API.
Абстракция
Это может показаться шагом назад к абстрагированию бессерверных функций. В конце концов, одна из самых крутых вещей в переходе на бессерверную версию заключается в том, что ваш внешний и внутренний код находятся в одном месте. Как я показал, бывают случаи, когда абстрагирование имеет смысл — во всяком случае, для меня.
Я, безусловно, выиграю от использования этого подхода и планирую дальнейшее развитие моего API, чтобы предоставить больше функциональности ряду моих собственных веб-сайтов, но если вам интересно зарабатывать деньги с открытым исходным кодом, и ваш сайт не создан с использованием Gatsby , этот подход вполне может быть ответом, который вы искали.
Хотите начать работу с Gatsby Functions? Ознакомьтесь с документацией Gatsby Functions, чтобы приступить к работе!
Дальнейшее чтение
Если вам интересно узнать больше о бессерверных функциях, я бы порекомендовал:
- Книга Свизека Теллера «Serverless Handbook For Frontend Engineers»
- Курс Бенедикта «Летние функции»
- …и, конечно же, документы Гэтсби
FuncJam
С 17 августа по 30 сентября ребята из Гэтсби проводят общественное соревнование, в котором разыгрываются абсолютно мегапризы. Если еще есть время, загляните на FuncJam и присоединяйтесь. он содержит полезные видеоролики и ссылки на ряд примеров функций.
Спасибо за чтение, и если вы хотите обсудить что-либо, упомянутое в этой статье, оставьте комментарий ниже или найдите меня в Твиттере.