#_sidharth
1 messages · Page 1 of 1 (latest)
Hi there!
Hi soma!
You can't add anything to the body of a webhook event.
The only option would be to use the metadata field to store additional information
ok please hear me out the scenario...
There are 3 plans. A customer chooses a plan and pays to the app using Stripe checkout(I have created 3 plans as 3 products in stripe dashboard). Now after the payment is success, i want to store the payment details like transac id , plan_id .
def process_payment(request: CheckoutRequest):
if not PlanRepository.get_plan_by_id(request.plan_id):
return {"message": "Invalid plan type"}
plan_details = PlanRepository.get_plan_by_id(request.plan_id)
plan_name = plan_details.name
# Check if the customer exists or not. If not, create a new customer
if request.customer_id:
customer = stripe.Customer.retrieve(request.customer_id)
else:
customer = stripe.Customer.create()
try:
session = stripe.checkout.Session.create(
success_url="", # need to add
cancel_url="", # need to add
mode="payment",
line_items=[{
"price": PlanUtils.plan_price_mapping()[PlanRepository.get_plan_by_id(request.plan_id).name],
"quantity": 1
}],
)
return {"sessionId": session["id"]}
except stripe.error.StripeError as e:
logger.error(str(e))
raise AppHTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=str(e)
)
above is fastapi code for the checkout
Below is the code which i have wrote inside the route which is mapped for the webhook
async def get_payment_stats(request: Request, plan_id: str, stripe_signature: str = Header(str)):
data = await request.body()
plan_details = PlanRepository.get_plan_by_id(plan_id)
try:
event = stripe.Webhook.construct_event(
payload=data,
sig_header=stripe_signature,
secret=config.webhook_secret
)
except ValueError as e:
logger.error(str(e))
raise AppHTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=str(e)
)
except stripe.error.SignatureVerificationError as e:
logger.error(str(e))
raise AppHTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=str(e)
)
event_type = event['type']
session = event['data']['object']
if event_type == 'checkout.session.expired':
logger.error(f"Payment failed. {session}")
return ErrorResponse(body="Payment failed. Please try again")
elif event_type == 'checkout.session.completed':
user_id = UserRepository.get_user_by_email(
session['object']['customer_details']['email']) # extract user id
logger.info(f"Payment Success {session['object']['customer_details']['email']}")
#STORE DETAILS HERE
return SuccessResponse(body="Payment successful")
else:
logger.info(f"{event_type}. {session}")
return event_type
according to u, which part would be best to write the logic for storing the payment details to my DB?
What do you mean by "payment details"? What exactly do you want to store?
But for this type of things, I would use the checkout.session.completed event to udpate your database.
And in the payload (plus some extra API call if needed) you can get all the info you need.
ok so let's say the payment_details be like transac_id , email, transac_time, etc which i would easily get from the response sent by stripe to my webhook. Only concern is to track that plan_id selected by the user
You can make an extra API call to retrieve the Checkout Session with expand: ["line_items"] https://stripe.com/docs/api/checkout/sessions/object?lang=node#checkout_session_object-line_items
This way you get access to the Product/Price the customer bought
If you are not familiar with expand, you can learn more about it here: https://stripe.com/docs/expand
ooh...now got it Soma..thanks a lot!
Happy to help 🙂