Stripe Integration Guide

Connect your Stripe account to ExisOne to automatically generate and email license keys when customers purchase on your website.

How it works: You integrate Stripe directly on your website using Stripe's API. When a customer pays, Stripe sends a webhook to ExisOne, which generates a license key and emails it to your customer automatically.

1. Get Your Stripe API Keys

  1. Log into Stripe Dashboard.
  2. Go to Developers > API keys.
  3. Copy your Publishable key (pk_test_... or pk_live_...).
  4. Copy your Secret key (sk_test_... or sk_live_...).

2. Configure Stripe Webhook

  1. In Stripe Dashboard, go to Developers > Webhooks.
  2. Click Add endpoint.
  3. Set the endpoint URL to: https://www.exisone.com/api/stripe/webhook
  4. Select these events to listen for:
    • checkout.session.completed - Primary event for payments
    • payment_intent.succeeded - Backup for one-time payments
    • invoice.paid - For subscription renewals
  5. Click Add endpoint, then copy the Signing secret (starts with whsec_).

3. Register Your Stripe App in ExisOne

  1. In ExisOne, go to Stripe Integration > Stripe Apps and Events.
  2. Click Add App and enter:
    • Publishable key - from step 1
    • Secret key - from step 1
    • Webhook signing secret - from step 2
  3. Set Is Live to match your keys (unchecked for test keys, checked for live keys).
  4. Check Active and Default.
  5. Save the app.

ExisOne uses the webhook signing secret to verify incoming webhooks are from your Stripe account.

App Status Indicators

After saving, the Stripe Apps table shows a Status column to help you verify your configuration:

StatusMeaningAction Required
Ready Secret key and webhook signing secret are both configured and can be decrypted None - your app is ready to process payments
Partial Secret key is configured, but webhook signing secret is missing Add your webhook signing secret (whsec_...) from Stripe
Not configured Secret key is missing or cannot be decrypted Enter your secret key (sk_test_... or sk_live_...). If you already entered it, ensure you have an active tenant encryption key.

4. Configure Your Product in ExisOne

For each product you sell, configure these settings on the Products page:

5. Find Your Product ID

You'll need your Product ID to include in Stripe checkout sessions. Find it on the Products page - it's displayed in the ID column.

Example: If your "Pro License" product shows ID 42, you'll use "productId": "42" in your Stripe metadata.

6. How the Payment Flow Works

Your Website                        Stripe                         ExisOne
      |                                 |                               |
      |-- Create checkout session ----->|                               |
      |   (using Stripe API directly)   |                               |
      |   metadata: { productId: "42" } |                               |
      |                                 |                               |
      |<---- Return checkout URL -------|                               |
      |                                 |                               |
      |   Customer completes payment    |                               |
      |                                 |                               |
      |                                 |-- Webhook ------------------ >|
      |                                 |                               |
      |                                 |   Verify signature (matches   |
      |                                 |   your stored webhook secret) |
      |                                 |                               |
      |                                 |   Extract productId from      |
      |                                 |   metadata                    |
      |                                 |                               |
      |                                 |   Generate license key        |
      |                                 |                               |
      |                                 |   Email key to customer       |
      |                                 |                               |

7. Integrate Stripe on Your Website

Use Stripe's API directly on your website. The key is to include your ExisOne productId in the checkout session metadata.

Server-Side (Node.js Example)
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',    // Your ExisOne Product ID - REQUIRED
            quantity: '1'       // Number of licenses to generate
        },
        customer_email: req.body.email,  // Optional: pre-fill customer email
        success_url: 'https://yoursite.com/success',
        cancel_url: 'https://yoursite.com/cancel',
    });

    res.json({ url: session.url });
});
Client-Side (JavaScript)
<button onclick="buyLicense()">Buy Pro License - $29.99</button>

<script>
async function buyLicense() {
    // Call your server to create checkout session
    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>
Important: The metadata.productId field is required. Without it, ExisOne cannot determine which product to generate a license for.
Required Metadata Fields (One-Time Payments)
FieldRequiredDescription
productIdYesYour ExisOne Product ID (from Products page)
quantityNoNumber of license keys to generate (default: 1)

7b. Subscription Licenses

For subscription-based licensing (e.g., annual renewals), ExisOne generates a new license key on each billing cycle - both on initial signup and every renewal.

Important: For subscription renewals to work, you must place the productId in the subscription metadata, not just the checkout session metadata. The subscription metadata persists and is read on each renewal.
Server-Side Subscription Example (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',    // Your 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 });
});
How Subscription Licensing Works
Initial Subscription                          Renewals (Annual)
        |                                            |
        |-- checkout.session.completed -->           |-- invoice.paid ----------------->
        |                                            |
        |   ExisOne reads productId from             |   ExisOne fetches subscription
        |   session metadata                         |   from Stripe, reads productId
        |                                            |   from subscription metadata
        |                                            |
        |   Generates license key                    |   Generates NEW license key
        |   Emails to customer                       |   Emails to customer
        |                                            |
Required Metadata Fields (Subscriptions)
FieldLocationRequiredDescription
productIdsubscription_data.metadataYesYour ExisOne Product ID - must be on the subscription for renewals
quantitysubscription_data.metadataNoNumber of license keys per billing cycle (default: 1)
Tip: Create your recurring price in Stripe Dashboard under Products > Add Product > Recurring. Set the billing period (monthly, yearly, etc.) and price. Copy the Price ID (price_xxx) to use in your code.

8. Test Your Integration

  1. Make sure you're using test mode keys (starting with pk_test_ and sk_test_).
  2. Trigger a checkout from your website.
  3. Complete payment using Stripe test card: 4242 4242 4242 4242 (any future expiry, any CVC).
  4. Check Stripe Apps and Events in ExisOne - you should see the webhook event with status "verified".
  5. Verify the license key appears under License Keys in the ExisOne dashboard.
  6. Confirm the customer received the license key email (if Auto Email is enabled).

You can also use ExisOne's built-in Test Purchase page to verify webhook connectivity before integrating with your website.

9. Notes

Troubleshooting

Status shows "Partial" (missing webhook signing secret)

This means your secret key is configured but the webhook signing secret is missing. To fix this:

  1. Go to Stripe Dashboard > Webhooks (use test or live mode as appropriate).
  2. If you don't have a webhook endpoint yet, click Add endpoint:
    • Set the URL to: https://www.exisone.com/api/stripe/webhook
    • Select events: checkout.session.completed, payment_intent.succeeded, invoice.paid
    • Click Add endpoint
  3. Click on your endpoint, then find Signing secret and click Reveal.
  4. Copy the value (starts with whsec_...).
  5. In ExisOne, go to Stripe Apps and Events, click Edit on your app.
  6. Paste the signing secret into the Webhook Signing Secret field and click Save.

The status should change from "Partial" to "Ready".

Status shows "Not configured" (missing secret key)

This means the secret key is missing or cannot be decrypted. To fix this:

  1. Go to Stripe Dashboard > API keys.
  2. Copy your Secret key (sk_test_... or sk_live_...).
  3. In ExisOne, go to Stripe Apps and Events, click Edit on your app.
  4. Paste the secret key into the Secret Key field and click Save.

If you still see "Not configured" after saving, you may need to generate a tenant encryption key first. Go to Settings > Tenant Keys and ensure you have an active key.

Subscription renewals not generating license keys

If initial subscription purchases generate keys but renewals don't, the issue is likely missing subscription metadata:

Signature verification fails ("no app matched signature")
Diagnostics

Verify that your saved secrets decrypt correctly for the right tenant:

GET /api/stripe/diagnostics
Authorization: ExisOneApi <your_token>

Both HasSecret and HasWebhookSigningSecret should be true for your app. If not, generate/activate a tenant key (Tenant Keys page), then re-save your secrets.

Event log

10. Setup Checklist

Before going live, verify all items are complete:

StepWhereStatus
Stripe API keys obtainedStripe Dashboard
Webhook endpoint created pointing to ExisOneStripe Dashboard > Webhooks
Stripe app registered with keys and webhook secretExisOne > Stripe Apps
Product created in ExisOneExisOne > Products
Product has Auto Email enabledExisOne > Products
Email template configuredExisOne > Products > Email Template
Website integration includes productId in metadataYour website code
Test purchase completed successfullyYour website (test mode)
Webhook received and verified in ExisOneExisOne > Stripe Events
License key generated and emailedExisOne > License Keys

11. Go Live

  1. In Stripe Dashboard, switch to live mode and create a new webhook endpoint pointing to https://www.exisone.com/api/stripe/webhook.
  2. In ExisOne, add a new Stripe app with your live keys (pk_live_..., sk_live_...) and the live webhook signing secret. Check Is Live and Active.
  3. Update your website to use your live Stripe secret key.
  4. Make a real purchase (you can refund it) to verify the complete flow works in production.