How to use `checkout_session::CheckoutSession` vs `placeholders::CheckoutSession` for Event`
seenickcode opened this issue · 3 comments
Hi there, I'm a bit new to Rust and wanted to use this lib for receiving a Stripe webhook for event type checkout.session.completed
. My goal is to be able to get the SKU associated with a checkout_session
's line_items
field, yet accessing the Event
only provides the placeholders::CheckoutSession
type which doesn't expose what I need (it only exposes an ID).
Here's an example actix_web
handler I'm using to attempt to get this.
Line 34 is what I'm having trouble with:
use super::AppData;
use crate::DbPool;
use actix_session::Session;
use actix_web::{web, Error, HttpRequest};
use actix_web::{HttpResponse, Result};
use log::info;
use std::borrow::Borrow;
use stripe::{CheckoutSession, Event, EventObject, EventType, Webhook};
pub async fn stripe_webhook(
req: HttpRequest,
data: web::Data<AppData>,
pool: web::Data<DbPool>,
payload: web::Bytes,
) -> Result<HttpResponse, Error> {
// deserialize Stripe event
let payload_str = std::str::from_utf8(payload.borrow())?;
let sig = get_header_value(&req, "Stripe-Signature").unwrap_or_default();
let secret = data.stripe_webhook_secret.clone();
let event = Webhook::construct_event(payload_str, sig, &secret[..]).unwrap();
info!("got stripe event {:?}", event);
if let EventType::CheckoutSessionCompleted = event.event_type {
// TODO move to another method
// let sku = event.data.object::Sku;
if let EventObject::CheckoutSession(session) = event.data.object {
// using the 'session' of the event, get the first 'display item' sku
// ..and the customer email
let sku = session.id;
let items = session.line_items;
// fetch the user via customer email
// TODO fetch the course via sku (based on prod/non-prod flag)
// create a purchase using user ID, course slug, stripe email (using user email),
// transaction ID using the stripe session ID
}
}
// return a 201
Ok(HttpResponse::Created().finish())
}
fn get_header_value<'a>(req: &'a HttpRequest, key: &'a str) -> Option<&'a str> {
req.headers().get(key)?.to_str().ok()
}
Any help would be appreciated. Thanks.
Turns out I needed to enable the "checkout" feature flag, i.e. stripe-rust = { version = "0.12.3", default-features = false, features = ["checkout", "default-tls", "webhook-events"] }
Hi @seenickcode, I'm noobing out here but could you share your AppData
or an version of it?
Also was pool
ever used from the stripe_webhook
params?
This is could probably be added to /examples as how to parse webhook events. 🤷🏻♂️
Thank you 🙇🏻♂️
#[derive(Clone)]
pub struct AppData {
pub stripe_webhook_secret: String,
}
impl AppData {
pub fn new() -> Self {
Self {
stripe_webhook_secret: get_env(
"STRIPE_WEBHOOK_SECRET",
"redacted",
),
}
}
}
Yes I use pool in the handler because I need to access my database.