PayPal Integration AI Prompt

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

Prompt

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

GOAL
- Integrate PayPal checkout on my website
- When customers complete payment, PayPal 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/paypal/webhook
- I have already configured my PayPal app in ExisOne with Webhook ID, Client ID, and Client 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 PayPal order/subscription using PayPal API
2. Customer completes payment on PayPal
3. PayPal sends webhook to ExisOne (PAYMENT.CAPTURE.COMPLETED or BILLING.SUBSCRIPTION.ACTIVATED)
4. ExisOne matches the webhook to my account using Webhook ID
5. ExisOne reads productId from custom_id or item sku
6. ExisOne generates license key and emails it to customer

REQUIREMENTS FOR ONE-TIME PAYMENTS

1) Server-Side: Create Order (Node.js)
   const paypal = require('@paypal/checkout-server-sdk');

   // Configure PayPal environment
   const environment = new paypal.core.SandboxEnvironment(
       'YOUR_CLIENT_ID',
       'YOUR_CLIENT_SECRET'
   );
   const client = new paypal.core.PayPalHttpClient(environment);

   app.post('/create-paypal-order', async (req, res) => {
       const request = new paypal.orders.OrdersCreateRequest();
       request.prefer("return=representation");
       request.requestBody({
           intent: 'CAPTURE',
           purchase_units: [{
               custom_id: '42',           // ExisOne Product ID - REQUIRED
               amount: {
                   currency_code: 'USD',
                   value: '29.99',
                   breakdown: {
                       item_total: { currency_code: 'USD', value: '29.99' }
                   }
               },
               items: [{
                   name: 'Pro License',
                   sku: '42',             // Alternative: Product ID in SKU
                   quantity: '1',         // Number of licenses to generate
                   unit_amount: { currency_code: 'USD', value: '29.99' }
               }]
           }]
       });

       const order = await client.execute(request);
       res.json({ id: order.result.id });
   });

   app.post('/capture-paypal-order', async (req, res) => {
       const { orderID } = req.body;
       const request = new paypal.orders.OrdersCaptureRequest(orderID);
       const capture = await client.execute(request);
       res.json({ status: capture.result.status });
   });

2) Client-Side: PayPal Buttons (JavaScript)
   <div id="paypal-button-container"></div>

   <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"></script>
   <script>
   paypal.Buttons({
       createOrder: async () => {
           const response = await fetch('/create-paypal-order', {
               method: 'POST',
               headers: { 'Content-Type': 'application/json' }
           });
           const order = await response.json();
           return order.id;
       },
       onApprove: async (data) => {
           const response = await fetch('/capture-paypal-order', {
               method: 'POST',
               headers: { 'Content-Type': 'application/json' },
               body: JSON.stringify({ orderID: data.orderID })
           });
           const result = await response.json();
           if (result.status === 'COMPLETED') {
               alert('Payment successful! Check your email for your license key.');
           }
       }
   }).render('#paypal-button-container');
   </script>

REQUIREMENTS FOR SUBSCRIPTIONS (recurring billing)

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

1) Create Subscription (Node.js)
   app.post('/create-subscription', async (req, res) => {
       const request = new paypal.subscriptions.SubscriptionsCreateRequest();
       request.requestBody({
           plan_id: 'P-XXXXXXXXXXXXXXXXXXXXXXXX',  // Your PayPal Plan ID
           custom_id: '42',                         // ExisOne Product ID - REQUIRED
           // Or for multiple licenses: '42:5' (productId:quantity)
           subscriber: {
               email_address: req.body.email
           },
           application_context: {
               return_url: 'https://yoursite.com/success',
               cancel_url: 'https://yoursite.com/cancel'
           }
       });

       const subscription = await client.execute(request);
       res.json({
           id: subscription.result.id,
           approvalUrl: subscription.result.links.find(l => l.rel === 'approve').href
       });
   });

PRODUCT ID PLACEMENT

One-Time Payments:
| Field      | Location                          | Description                        |
|------------|-----------------------------------|------------------------------------|
| custom_id  | purchase_units[0].custom_id       | Preferred - ExisOne Product ID     |
| sku        | purchase_units[0].items[0].sku    | Alternative - Product ID in SKU    |
| quantity   | purchase_units[0].items[0].quantity | Number of licenses to generate   |

Subscriptions:
| Field      | Format      | Description                              |
|------------|-------------|------------------------------------------|
| custom_id  | "42"        | ExisOne Product ID only (1 license)      |
| custom_id  | "42:5"      | Product ID with quantity (5 licenses)    |

PAYPAL WEBHOOK EVENTS
- PAYMENT.CAPTURE.COMPLETED - Triggers license for one-time payments
- BILLING.SUBSCRIPTION.ACTIVATED - Triggers license for new subscriptions
- PAYMENT.SALE.COMPLETED - Triggers license for subscription renewals

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

TESTING
1. Use Sandbox credentials during development
2. Use PayPal Sandbox test accounts for test purchases
3. Check ExisOne > PayPal Apps and Events to verify webhook received
4. Verify license appears in ExisOne > License Keys
5. Confirm customer received email with license key

GOING LIVE
1. Switch to Live credentials in PayPal Developer Dashboard
2. Create new webhook pointing to https://www.exisone.com/api/paypal/webhook
3. Add new PayPal app in ExisOne with Live credentials (check "Is Live")
4. Update website to use Live Client ID
5. Make a real test purchase (refund afterward)

DELIVERABLES
- Server-side code to create PayPal orders/subscriptions with productId in custom_id
- Client-side PayPal button integration
- Capture endpoint for completing payments
- Success/cancel page handling
- Ensure productId is always included in custom_id or item sku

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

Notes