Created
May 4, 2021 12:55
-
-
Save danrossi/35d605d8a8c3dbf0b8c6e4a46fedeb4b to your computer and use it in GitHub Desktop.
Stripe Checkout Webhook Lambda Function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Stripe Checkout Webhook Lambda Function | |
# Updates customer with missing name and address | |
# Sends custom SES email with product, price and any metadata field required | |
# Possible to send custom post payment invoice | |
# @author Daniel Rossi | |
import stripe | |
import boto3 | |
import json | |
import os | |
from botocore.exceptions import ClientError | |
AWS_REGION = os.environ['AWS_REGION'] | |
ses = boto3.client('ses', region_name=AWS_REGION) | |
SENDER = os.environ['SENDER'] | |
RECIPIENT = os.environ['RECIPIENT'] | |
def send_checkout_mail(templateData, name, email): | |
reply_to = "{0} <{1}>".format(name,email) | |
return ses.send_templated_email( | |
Source = SENDER, | |
Destination={ | |
'ToAddresses': [ | |
RECIPIENT, | |
] | |
}, | |
ReplyToAddresses=[reply_to], | |
Template="CheckoutNotify", | |
TemplateData=json.dumps(templateData) | |
) | |
def send_customer_mail(templateData, name, email): | |
to = "{0} <{1}>".format(name,email) | |
return ses.send_templated_email( | |
Source = SENDER, | |
Destination={ | |
'ToAddresses': [ | |
to, | |
] | |
}, | |
Template="ProcessingNotify", | |
TemplateData=json.dumps(templateData) | |
) | |
def send_mail(name, email, product, price_option, domains): | |
templateData = { | |
"product": product, | |
"price_option": price_option, | |
"domains": domains | |
} | |
send_checkout_mail(templateData, name, email) | |
send_customer_mail(templateData, name, email) | |
def lambda_handler(event, context): | |
requestHeaders = event.get("headers") | |
signature = requestHeaders['stripe-signature'] | |
try: | |
body = event.get("body") | |
if (isinstance(body, str)): | |
payload = json.loads(body) | |
else: | |
payload = body | |
if ("livemode" in payload and payload.get("livemode")): | |
stripe.api_key = os.environ['STRIPE_SECRET_KEY'] | |
publish_key = os.environ['STRIPE_PUBLISHABLE_KEY'] | |
endpoint_secret = os.environ['STRIPE_ENDPOINT_SECRET'] | |
stripe.api_key = os.environ['STRIPE_SECRET_KEY'] | |
else: | |
stripe.api_key = os.environ['STRIPE_TEST_SECRET_KEY'] | |
publish_key = os.environ['STRIPE_TEST_PUBLISHABLE_KEY'] | |
endpoint_secret = os.environ['STRIPE_TEST_ENDPOINT_SECRET'] | |
stripe.api_key = os.environ['STRIPE_TEST_SECRET_KEY'] | |
try: | |
webhook_event = stripe.Webhook.construct_event( | |
payload=event.get("body"), | |
sig_header=signature, | |
secret=endpoint_secret | |
) | |
except ValueError as e: | |
print(e) | |
return { | |
'statusCode': 400, | |
'body': json.dumps({ | |
'statusCode': 400, | |
'message': e.user_message | |
}) | |
} | |
except stripe.error.SignatureVerificationError as e: | |
print(e) | |
return { | |
'statusCode': 400, | |
'body': json.dumps({ | |
'statusCode': 400, | |
'message': e.user_message | |
}) | |
} | |
event_dict = webhook_event.to_dict() | |
session = event_dict['data']['object'] | |
if (event_dict["type"] == 'checkout.session.completed'): | |
#get name and address from payment intent | |
payment_intent = stripe.PaymentIntent.retrieve(session.payment_intent) | |
billing_details = payment_intent.charges.data[0].billing_details | |
#update customer with name and address | |
#TODO: Somehow send custom post paid invoice with produce and price. Somehow stop duplicated customers being added | |
customer = stripe.Customer.retrieve(session.customer) | |
if customer.name is None: | |
#print("Update customer") | |
stripe.Customer.modify(session.customer, | |
name=billing_details.name, | |
address=billing_details.address.to_dict() | |
) | |
#print("Payment Status") | |
#print(session.payment_status) | |
#get line items from session | |
items = stripe.checkout.Session.list_line_items(session.id, limit=1) | |
#only have one line item | |
item = items.data[0] | |
#get the product name not available in line items | |
product = stripe.Product.retrieve(item.price.product) | |
send_mail(billing_details.name, billing_details.email, product.name, item.description, session.metadata.domains) | |
except json.JSONDecodeError as e: | |
return { | |
'statusCode': 400, | |
'body': json.dumps({ | |
'statusCode': 400, | |
'message': e | |
}) | |
} | |
else: | |
return { | |
'statusCode': 200, | |
'body': json.dumps({ | |
'statusCode': 200, | |
'message': "Webhook Success" | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment