# UPIDrop JavaScript SDK Integration Guide

The UPIDrop Universal JavaScript SDK (`upidrop.js`) provides a lightweight, zero-dependency, drop-in UPI payment checkout for any website, web application, or single-page app (React, Vue, Next.js, Svelte, Angular, or vanilla HTML).

---

## Key Features

- **Zero Aggregator Commission (0%):** Customer payments deposit directly into your bank UPI VPA.
- **Self-Contained & Lightweight:** Built-in offline QR code canvas generator (no third-party tracking or external image servers).
- **Intelligent Device Routing:**
  - **Mobile:** Shows 1-click UPI app launch buttons (Google Pay, PhonePe, Paytm, BHIM, CRED).
  - **Desktop:** Displays a dynamic payment QR code with real-time status polling.
- **SmartTrack Ready:** Automatically handles dynamic verification offsets and UTR reconciliation.

---

## 1. Quick Start (2 Lines of Code)

Add the script tag to your HTML `<head>` or before `</body>`:

```html
<!-- Include UPIDrop SDK -->
<script src="https://upidrop.roori.in/sdk/upidrop.js"></script>

<script>
  // 1. Initialize with your live Public Key
  UPIDrop.init({
    publicKey: 'pk_live_YOUR_PUBLIC_KEY'
  });

  // 2. Trigger checkout on button click
  function buyNow() {
    UPIDrop.checkout({
      amount: 499.00,
      description: 'E-Book: Master Web Dev',
      customerName: 'Aarav Sharma',
      customerEmail: 'aarav@example.com',
      onSuccess: function(response) {
        console.log('Payment Successful!', response);
        alert('Thank you! UTR Reference: ' + response.utr);
        window.location.href = '/thank-you?orderId=' + response.orderId;
      },
      onFailure: function(err) {
        console.error('Payment Failed:', err);
        alert('Payment failed: ' + err.message);
      },
      onClose: function() {
        console.log('Customer closed payment modal');
      }
    });
  }
</script>

<button onclick="buyNow()">Pay ₹499 with UPI</button>
```

---

## 2. Configuration Options (`UPIDrop.init`)

```javascript
UPIDrop.init({
  publicKey: 'pk_live_...',    // Required: Your merchant public key from UPIDrop dashboard
  baseUrl: 'https://upidrop.roori.in' // Optional: Custom API base URL (defaults to production)
});
```

---

## 3. Checkout Parameters (`UPIDrop.checkout`)

| Parameter | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `amount` | `Number` | **Yes** | The amount in INR (e.g., `499` or `199.50`). Minimum `1.00`. |
| `description` | `String` | No | Item description shown to the buyer in their UPI app (max 50 chars). |
| `customerName`| `String` | No | Buyer's full name. |
| `customerEmail`| `String`| No | Buyer's email address for notifications and receipts. |
| `onSuccess` | `Function` | No | Callback fired ONLY when payment is confirmed by UPIDrop SmartTrack on the server (`paid` or `late_success`). Never fires from client-only signals. |
| `onError` | `Function` | No | Callback fired if payment encounters an error or is rejected. |
| `onCancel` | `Function` | No | Callback fired if buyer closes the payment modal or cancels checkout. |
| `returnUrl` | `String` | No | Destination URL after payment (must be HTTPS and match your configured Checkout Domains). |
| `onFailure` | `Function` | No | Callback fired if order creation or payment fails. |
| `onClose` | `Function` | No | Callback fired when the customer dismisses the modal without paying. |

---

## 4. Alternative: Server-Side Order Creation (Recommended for Custom Backend)

If you prefer to generate orders on your server to keep amounts strictly tamper-proof:

### Step 1: Create Order on Your Backend (Node.js, Python, PHP, Go)
```javascript
// Node.js Backend Example
const response = await fetch('https://upidrop-pg.upidrop-payment-gateway.workers.dev/api/v1/orders', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': process.env.UPIDROP_PUBLIC_KEY
  },
  body: JSON.stringify({
    amount: 999.00,
    item_description: 'Annual Subscription',
    customer_name: 'Priya Patel',
    customer_email: 'priya@example.com'
  })
});

const order = await response.json();
// order contains: { orderId, amount, base_amount, paisa_offset, token, upiDeepLink, payUrl }
```

### Step 2: Open Checkout on Frontend
You can either redirect the customer directly to the hosted checkout page:
```javascript
window.location.href = order.payUrl; 
// e.g. https://upidrop.roori.in/pay.html?orderId=ORD_...&token=...
```

Or pass the `orderId` to the SDK:
```javascript
UPIDrop.checkout({
  orderId: order.orderId,
  token: order.token,
  amount: order.amount,
  onSuccess: (res) => window.location.reload()
});
```

---

## 5. Mobile vs Desktop Behavior

The SDK automatically adapts to the customer's device:

1. **On Mobile (Android / iOS):**
   - Renders 1-click app launcher buttons for installed UPI applications (`tez://` for Google Pay, `phonepe://` for PhonePe, `paytmmp://` for Paytm, and generic `upi://`).
   - Tapping any button launches the UPI app with the exact amount and merchant VPA pre-filled.
   - When the customer switches back to the browser, a prompt is displayed to enter the 12-digit UTR reference if auto-detection is pending.

2. **On Desktop (Mac / Windows / Linux):**
   - Generates an instant, high-contrast QR code on an HTML `<canvas>`.
   - Buyer scans with any UPI app camera on their phone.
   - Real-time polling queries order status every 3 seconds and automatically closes the modal upon confirmation.

---

## 6. Verifying Payments via Webhooks

Never rely solely on client-side callbacks for fulfilling digital goods or unlocking accounts. Configure a webhook in your UPIDrop Dashboard:

```javascript
// Express.js Webhook Handler
const crypto = require('crypto');

app.post('/api/webhook/upidrop', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-upidrop-signature'];
  const secretKey = process.env.UPIDROP_SECRET_KEY;

  // Verify HMAC-SHA256 signature
  const expectedSignature = crypto
    .createHmac('sha256', secretKey)
    .update(req.body)
    .digest('hex');

  if (signature !== expectedSignature) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body.toString());

  if (event.event === 'order.paid' || event.event === 'payment.confirmed') {
    const { order_id, amount, utr, customer_email } = event;
    console.log(`Payment confirmed for order ${order_id}, UTR: ${utr}`);
    
    // Fulfill order in your database
    markOrderAsPaid(order_id, utr);
  }

  res.status(200).json({ received: true });
});
```

---

## 7. Troubleshooting & FAQ

- **"UPIDrop: publicKey is required" error:** Ensure `UPIDrop.init({ publicKey: '...' })` is called before triggering `UPIDrop.checkout()`.
- **UPI QR says "Invalid VPA":** Ensure you configured an active bank UPI ID in your UPIDrop Dashboard Settings (`yourname@okhdfcbank`, `yourname@paytm`, etc.). Note that `@upi` is not a valid bank PSP handle.
- **CORS / Network Error:** Ensure you are loading the SDK over HTTPS (`https://upidrop.roori.in/sdk/upidrop.js`).
