'How do you carry a variable like userID through the Stripe Checkout process in Flask?

I have a simple flask site that is connected to a dial script in python. It will call the phone number you enter in on the home page and connect to your phone number along with some other things. How would I pass through the phone number the customer is trying to call through the Stripe Checkout process?

Currently I have the customer's homepage information shared in a database and it's passed through various routes via the URL ex site.com/subit/userID1234. The site works but I am not sure how to pass through these variables through the Stripe Checkout process.

I am trying to get from /stripe_purchase_page/ to /webhook/

    #STRIPE
@app.route('/stripe_purchase_page/<uniqueID>')
def stripePurchasePage(uniqueID):
    render_template('stripe_redirect_test.html')


stripe_keys = {
    "secret_key": os.environ["STRIPE_SECRET_KEY"],
    "publishable_key": os.environ["STRIPE_PUBLISHABLE_KEY"],
    "endpoint_secret": os.environ["STRIPE_ENDPOINT_SECRET"]
}


stripe.api_key = stripe_keys["secret_key"]

# @app.route("/")
# def index():
#     return render_template("index.html")


@app.route("/config")
def get_publishable_key():
    # customer = request.form['customer']
    # print(customer)
    stripe_config = {"publicKey": stripe_keys["publishable_key"]}
    return jsonify(stripe_config)


@app.route("/create-checkout-session")
def create_checkout_session():
    domain_url = "http://localhost:5000/"
    stripe.api_key = stripe_keys["secret_key"]

    try:
        # Create new Checkout Session for the order
        # Other optional params include:
        # [billing_address_collection] - to display billing address details on the page
        # [customer] - if you have an existing Stripe Customer ID
        # [payment_intent_data] - lets capture the payment later
        # [customer_email] - lets you prefill the email input in the form
        # For full details see https:#stripe.com/docs/api/checkout/sessions/create

        # ?session_id={CHECKOUT_SESSION_ID} means the redirect will have the session ID set as a query param
        checkout_session = stripe.checkout.Session.create(
            success_url=domain_url + "success?session_id={CHECKOUT_SESSION_ID}",
            cancel_url=domain_url + "cancelled",
            payment_method_types=["card"],
            mode="payment",
            line_items=[
                {
                    "name": "T-shirt",
                    "quantity": 1,
                    "currency": "usd",
                    "amount": "2000",
                }
            ]
        )
        return jsonify({"sessionId": checkout_session["id"]})
    except Exception as e:
        return jsonify(error=str(e)), 403


@app.route("/webhook", methods=['POST'])
def stripe_webhook():
    payload = request.get_data(as_text=True)
    sig_header = request.headers.get('Stripe-Signature')

    try:
        event = stripe.Webhook.construct_event(
            payload, sig_header, stripe_keys["endpoint_secret"]
        )

    except ValueError as e:
        # Invalid payload
        return 'Invalid payload', 400
    except stripe.error.SignatureVerificationError as e:
        # Invalid signature
        return 'Invalid signature', 400

    # Handle the checkout.session.completed event
    if event['type'] == 'checkout.session.completed':
        session = event['data']['object']

        # Fulfill the purchase...
        handle_checkout_session(session)

    return 'Success', 200


def handle_checkout_session(session):
    print("Payment was successful.")
    # run some custom code here with the Unique ID


Solution 1:[1]

Add your variables to the metadata as mentioned in another answer and then in your success route access the stripe session object and isolate them in the success route.

checkout_session = stripe.checkout.Session.create(
        client_reference_id=token,
        success_url=domain_url + "success?session_id={CHECKOUT_SESSION_ID}",
        cancel_url=domain_url + "cancelled",
        payment_method_types=["card"],
        mode="payment",
        line_items=[
            {
                "name": "AICreated.Art - " + str(param) + " Credits",
                "quantity": 1,
                "currency": "usd",
                "amount": amt,
            }
        ],
        metadata={
             'user_id': 1234,
             'token': 'abcdf'
        }

And in your success route which is hit after the webhook:

@app.route("/success")
def success():
   sessions = stripe.checkout.Session.list()
   print(sessions.data[00]) # tree view
   data = {'username': sessions.data[00].metadata.user_id, 'token': sessions.data[00].metadata.token}
   return render_template('home/success.html', data=data, title="Home")

Solution 2:[2]

Use the metadata parameter, see the Session docs here. This parameter, docs here, is available on all Stripe updatable objects.

For example, passing a user_id value:

checkout_session = stripe.checkout.Session.create(
    success_url=domain_url + "success?session_id={CHECKOUT_SESSION_ID}",
    cancel_url=domain_url + "cancelled",
    payment_method_types=["card"],
    mode="payment",
    line_items=[
        {
            "name": "T-shirt",
            "quantity": 1,
            "currency": "usd",
            "amount": "2000",
        }
    ],
    metadata={
        'user_id': 1234
    }
)

Solution 3:[3]

?session_id={CHECKOUT_SESSION_ID}" will also be the Checkout's Session ID, so you'll be able to get that from the querystring on/at the success URL.

Solution 4:[4]

You can use sessions to pass variables through different routes. Then in the stripe checkout route you save that information in metadata, so you can use the data in stripe's webhook route like this:

from flask import session
stripe_keys = {
    "secret_key": os.environ["STRIPE_SECRET_KEY"],
    "publishable_key": os.environ["STRIPE_PUBLISHABLE_KEY"],
    "endpoint_secret": os.environ["STRIPE_ENDPOINT_SECRET"]
}


stripe.api_key = stripe_keys["secret_key"]

#STRIPE
@app.route('/stripe_purchase_page)
def stripePurchasePage():
    # add unique id to session
    session['unique_id'] = unique_id
    render_template('stripe_redirect_test.html')

@app.route("/config")
def get_publishable_key():
    # customer = request.form['customer']
    # print(customer)
    stripe_config = {"publicKey": stripe_keys["publishable_key"]}
    return jsonify(stripe_config)


@app.route("/create-checkout-session")
def create_checkout_session():
    domain_url = "http://localhost:5000/"
    stripe.api_key = stripe_keys["secret_key"]

    # Retrieve unique id from session and add to metadata 
    try:
        checkout_session = stripe.checkout.Session.create(
            success_url=domain_url + "success?session_id={CHECKOUT_SESSION_ID}",
            cancel_url=domain_url + "cancelled",
            payment_method_types=["card"],
            mode="payment",
            metadata={'unique_id': session['unique_id']},
            line_items=[
                {
                    "name": "T-shirt",
                    "quantity": 1,
                    "currency": "usd",
                    "amount": "2000",
                }
            ]
        )
        return jsonify({"sessionId": checkout_session["id"]})
    except Exception as e:
        return jsonify(error=str(e)), 403


@app.route("/webhook", methods=['POST'])
def stripe_webhook():
    payload = request.get_data(as_text=True)
    sig_header = request.headers.get('Stripe-Signature')

    try:
        event = stripe.Webhook.construct_event(
            payload, sig_header, stripe_keys["endpoint_secret"]
        )

    except ValueError as e:
        # Invalid payload
        return 'Invalid payload', 400
    except stripe.error.SignatureVerificationError as e:
        # Invalid signature
        return 'Invalid signature', 400

    # Handle the checkout.session.completed event
    if event['type'] == 'checkout.session.completed':
        session = event['data']['object']

        # Fulfill the purchase...
        handle_checkout_session(checkout_session)

    return 'Success', 200


def handle_checkout_session(checkout_session):
    print("Payment was successful.")

    # get data from metadata and do whatever you want with it
    unique_id = checkout_session['metadata'].get('unique_id')

    # run some custom code here with the Unique ID

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rob
Solution 2 pjcunningham
Solution 3 floatingLomas
Solution 4 Mohamed Diaby