Automating access to a GitHub Repo using Stripe Webhooks and Astro Endpoints
Rishi Raj Jain
Posted on January 19, 2024
In this tutorial, I'll walk you through the steps of leveraging Astro Endpoints to verify Stripe Webhooks, and seamlessly grant access to a GitHub repository, all condensed into concise and developer-friendly code. I'll dissect the process into digestible steps, making it effortless for you to integrate these powerful features into your web projects.
Prerequisites
Before we dive into the process, make sure you have the following prerequisites in place:
An Astro project: Create your Astro project if you haven't already. You can set up a new project by
npm create astro@latest
Stripe Account: You will need a Stripe account to handle payment transactions. Sign up at stripe.com, and obtain your Stripe Secret Key and Webhook Signing Secret
Stripe Checkout Fields: When creating a checkout url, add a custom field named
GitHub Username
GitHub Repository: Create a GitHub repository where you want to grant access to users upon successful payment
GitHub Personal Access Token: Obtain a GitHub Personal Access Token that allows admin access to the repo
Installation
Once setup with prerequisites, install stripe
npm package via:
npm install stripe
Add Stripe environment variables
Add Stripe Secret Key as STRIPE_SECRET_KEY
& Webhook Signing Secret as STRIPE_WEBHOOK_SIG
as the environment variables in your environment (usually it is an .env file).
Create Webhook Handler Endpoint in your Astro project
// File: src/pages/api/stripe/webhook.ts
// Stripe API Reference
// https://stripe.com/docs/webhooks#webhook-endpoint-def
export async function POST({ request }: APIContext) {
try {
const STRIPE_SECRET_KEY = import.meta.env.STRIPE_SECRET_KEY
const STRIPE_WEBHOOK_SIG = import.meta.env.STRIPE_WEBHOOK_SIG
const GITHUB_PAT_TOKEN = import.meta.env.GITHUB_PAT_TOKEN
if (!STRIPE_SECRET_KEY || !STRIPE_WEBHOOK_SIG || !GITHUB_PAT_TOKEN) {
return new Response(null, {
status: 500,
})
}
const stripe = new Stripe(STRIPE_SECRET_KEY, { apiVersion: '2023-08-16' })
// Verify Stripe Signature to protect the endpoint
// Send GitHub Access to the repo once verified
} catch (e) {
return new Response(e.message || e.toString(), { status: 500 })
}
}
Verify Stripe Signature in your Astro Endpoint
To verify stripe signatures, you need to get access to the raw body. Use the rawBody
function to get that done for you 👇🏻
// File: src/pages/api/stripe/webhook.ts
// Process rawBody from the request Object
async function getRawBody(request: Request) {
let chunks = []
let done = false
const reader = request.body.getReader()
while (!done) {
const { value, done: isDone } = await reader.read()
if (value) {
chunks.push(value)
}
done = isDone
}
const bodyData = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0))
let offset = 0
for (const chunk of chunks) {
bodyData.set(chunk, offset)
offset += chunk.length
}
return Buffer.from(bodyData)
}
With that done, now verify the request using the rawBody
function as below using stripe's constructEvent
function 👇🏻
// File: src/pages/api/stripe/webhook.ts
export async function POST({ request }: APIContext) {
// Verify Stripe Signature to protect the endpoint
const rawBody = await getRawBody(request)
let event = JSON.parse(rawBody.toString())
const sig = request.headers.get('stripe-signature')
try {
event = stripe.webhooks.constructEvent(rawBody, sig, STRIPE_WEBHOOK_SIG)
} catch (err) {
console.log(err.message)
return new Response(`Webhook Error: ${err.message}`, {
status: 400,
})
}
// Send GitHub Access to the repo once verified
}
Add GitHub environment variable
Add GitHub Personal Access Token as GITHUB_PAT_TOKEN
as an environment variable in your environment (usually it is an .env file).
Send GitHub Access to the repo once verified
To send access to a GitHub repo, you need to make a PUT request using the GitHub API. Use the sendAccess
function to get that done for you 👇🏻
// File: src/pages/api/stripe/webhook.ts
// Send access to a github repo using custom field in Stripe checkout
async function sendAccess(paymentIntent) {
const username = paymentIntent['custom_fields'].find((i) => i.key === 'githubusername').text.value
await fetch(`https://api.github.com/repos/repo-owner/repo-name/collaborators/${username}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `token ${import.meta.env.GITHUB_PAT_TOKEN}`,
},
body: JSON.stringify({ permission: 'read' }),
})
}
With that done, now select the Stripe Events for which you need to automate the access. Right now, I'm demonstrating sending access when a Checkout Session is completed or a Payment is made successfully 👇🏻
// File: src/pages/api/stripe/webhook.ts
export async function POST({ request }: APIContext) {
// Send GitHub Access to the repo once verified
if (event.type === 'checkout.session.completed') {
return await sendAccess(event.data.object)
}
if (event.type === 'payment_intent.succeeded') {
return await sendAccess(event.data.object)
}
}
You're Done!
You've successfully set up verification of Stripe Webhooks and automated granting access to a GitHub repository using Astro Endpoints. This powerful combination of technologies allows you to create seamless payment and access management for your web projects.
Happy coding!
Posted on January 19, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
January 19, 2024