Stripe Integration AI Prompt

Copy/paste this prompt into your AI assistant (e.g., GitHub Copilot Chat, Cursor, ChatGPT) to integrate Stripe payments with ExisOne automatic license key generation.

Prompt

You're assisting me in integrating Stripe payments with ExisOne for automatic software license key generation.

GOAL
- Integrate Stripe Checkout on my website
- When customers complete payment, Stripe sends a webhook to ExisOne
- ExisOne automatically generates a license key and emails it to the customer
- Support both one-time payments and subscription-based licensing

CONTEXT
- ExisOne webhook URL: https://www.exisone.com/api/stripe/webhook
- I have already configured my Stripe app in ExisOne with Publishable key, Secret key, and Webhook signing secret
- I have an ExisOne Product ID (found on the Products page, e.g., "42")
- The product has "Auto Email" enabled in ExisOne to send license keys automatically

HOW IT WORKS
1. My website creates a Stripe Checkout session with productId in metadata
2. Customer completes payment on Stripe Checkout
3. Stripe sends webhook to ExisOne (checkout.session.completed or invoice.paid)
4. ExisOne verifies the webhook signature matches my stored signing secret
5. ExisOne reads productId from session/subscription metadata
6. ExisOne generates license key and emails it to customer

REQUIREMENTS FOR ONE-TIME PAYMENTS

1) Server-Side: Create Checkout Session (Node.js)
   const stripe = require('stripe')('sk_test_YOUR_SECRET_KEY');

   app.post('/create-checkout-session', async (req, res) => {
       const session = await stripe.checkout.sessions.create({
           mode: 'payment',
           line_items: [{
               price_data: {
                   currency: 'usd',
                   unit_amount: 2999,  // $29.99 in cents
                   product_data: {
                       name: 'Pro License',
                   },
               },
               quantity: 1,
           }],
           metadata: {
               productId: '42',    // ExisOne Product ID - REQUIRED
               quantity: '1'       // Number of licenses to generate
           },
           customer_email: req.body.email,  // Optional: pre-fill email
           success_url: 'https://yoursite.com/success',
           cancel_url: 'https://yoursite.com/cancel',
       });

       res.json({ url: session.url });
   });

2) Client-Side: Redirect to Checkout (JavaScript)
   <button onclick="buyLicense()">Buy Pro License - $29.99</button>

   <script>
   async function buyLicense() {
       const response = await fetch('/create-checkout-session', {
           method: 'POST',
           headers: { 'Content-Type': 'application/json' },
           body: JSON.stringify({ email: customerEmail })
       });

       const { url } = await response.json();
       window.location.href = url;  // Redirect to Stripe Checkout
   }
   </script>

REQUIREMENTS FOR SUBSCRIPTIONS (recurring billing)

For subscription-based licensing, ExisOne generates a NEW license key on each billing cycle.

IMPORTANT: Use subscription_data.metadata (not just metadata) for renewals to work.

1) Server-Side: Create Subscription Checkout (Node.js)
   const stripe = require('stripe')('sk_test_YOUR_SECRET_KEY');

   app.post('/create-subscription-checkout', async (req, res) => {
       const session = await stripe.checkout.sessions.create({
           mode: 'subscription',
           line_items: [{
               price: 'price_YOUR_RECURRING_PRICE_ID',  // Created in Stripe Dashboard
               quantity: 1,
           }],
           // IMPORTANT: Use subscription_data.metadata for renewals to work
           subscription_data: {
               metadata: {
                   productId: '42',    // ExisOne Product ID - REQUIRED
                   quantity: '1'       // Number of licenses per renewal
               }
           },
           customer_email: req.body.email,
           success_url: 'https://yoursite.com/success',
           cancel_url: 'https://yoursite.com/cancel',
       });

       res.json({ url: session.url });
   });

METADATA PLACEMENT

One-Time Payments:
| Field     | Location                    | Required | Description                     |
|-----------|-----------------------------|----------|--------------------------------|
| productId | metadata.productId          | Yes      | ExisOne Product ID              |
| quantity  | metadata.quantity           | No       | Number of licenses (default: 1) |

Subscriptions:
| Field     | Location                           | Required | Description                        |
|-----------|-----------------------------------|----------|-----------------------------------|
| productId | subscription_data.metadata.productId | Yes   | Must be on subscription for renewals |
| quantity  | subscription_data.metadata.quantity  | No    | Licenses per billing cycle         |

STRIPE WEBHOOK EVENTS
- checkout.session.completed - Primary event for completed payments
- payment_intent.succeeded - Backup for one-time payments
- invoice.paid - For subscription renewals

PYTHON EXAMPLE (Flask)
   import stripe
   from flask import Flask, request, jsonify

   stripe.api_key = 'sk_test_YOUR_SECRET_KEY'

   @app.route('/create-checkout-session', methods=['POST'])
   def create_checkout_session():
       session = stripe.checkout.Session.create(
           mode='payment',
           line_items=[{
               'price_data': {
                   'currency': 'usd',
                   'unit_amount': 2999,
                   'product_data': {'name': 'Pro License'},
               },
               'quantity': 1,
           }],
           metadata={
               'productId': '42',
               'quantity': '1'
           },
           success_url='https://yoursite.com/success',
           cancel_url='https://yoursite.com/cancel',
       )
       return jsonify({'url': session.url})

EMAIL TEMPLATE PLACEHOLDERS
- {{ActivationKey}} - The generated license key
- {{ProductName}} - Your product name
- {{CustomerEmail}} - Customer's email address
- {{PaymentProcessorCustomerName}} - Customer name from Stripe

TESTING
1. Use test mode keys (sk_test_..., pk_test_...)
2. Use Stripe test card: 4242 4242 4242 4242 (any future expiry, any CVC)
3. Check ExisOne > Stripe Apps and Events to verify webhook received with "verified" status
4. Verify license appears in ExisOne > License Keys
5. Confirm customer received email with license key

COMMON ISSUES

Subscription renewals not generating keys:
- Ensure productId is in subscription_data.metadata, not just metadata
- The subscription object must have the metadata, not just the checkout session
- Verify webhook is listening for invoice.paid events

Signature verification fails:
- Ensure webhook signing secret (whsec_...) matches the endpoint targeting ExisOne
- Test vs Live secrets must match your mode
- Re-enter the secret in ExisOne, avoid leading/trailing spaces

GOING LIVE
1. Create new webhook endpoint in Stripe Dashboard (live mode)
2. Point to: https://www.exisone.com/api/stripe/webhook
3. Copy the live webhook signing secret
4. Add new Stripe app in ExisOne with live keys (check "Is Live")
5. Update website to use live secret key
6. Make a real test purchase (refund afterward)

DELIVERABLES
- Server-side code to create Stripe Checkout sessions with productId in metadata
- For subscriptions, use subscription_data.metadata
- Client-side redirect to Stripe Checkout
- Success/cancel page handling
- Ensure productId is always included in the appropriate metadata location

Please produce idiomatic code for my stack (Node.js/Express/Python/Flask/Django/PHP/etc. as applicable), with proper error handling and no extraneous commentary.

Notes