# CDN Integration Guide: Shopify, Wix, WordPress

This guide explains how to integrate the ONE Payments Drop-in Element on platforms that don't use npm or bundlers, such as Shopify themes, Wix sites, and WordPress pages.

## Table of Contents

- [Overview](#overview)
- [When to Use This Guide](#when-to-use-this-guide)
- [Basic Usage Pattern](#basic-usage-pattern)
- [Shopify Theme Integration](#shopify-theme-integration)
- [Wix Integration](#wix-integration)
- [WordPress Integration](#wordpress-integration)
- [Security Considerations](#security-considerations)
- [Troubleshooting](#troubleshooting)

---

## Overview

The `@one-payments/web-components` package provides a browser-ready bundle that can be loaded via a simple `<script>` tag. This bundle:

- **Auto-registers** the `<one-payment>` custom element
- **Exposes** a global `window.OnePayments` API
- **Bundles all dependencies** (no additional scripts needed)
- **Works without npm, bundlers, or build steps**

### CDN URL

```html
<script src="https://cdn.jsdelivr.net/npm/@one-payments/web-components@1.1.27/dist/one-payment.browser.iife.js"></script>
```

Or using unpkg:

```html
<script src="https://unpkg.com/@one-payments/web-components@1.1.27/dist/one-payment.browser.iife.js"></script>
```

> **Tip**: Replace `1.1.26` with the version you want to use, or use `@latest` for the most recent version (not recommended for production).

---

## When to Use This Guide

**Use this CDN bundle if you are:**

- Building a Shopify theme (Online Store 2.0 or classic themes)
- Embedding payment on a Wix site
- Adding payment to WordPress pages
- Working on any static HTML site without a build system
- Integrating into a no-code/low-code platform

**Do NOT use this bundle if you are:**

- Building a React app → use `@one-payments/react` instead
- Building a Vue app → use `@one-payments/vue` instead
- Building an Angular app → use `@one-payments/angular` instead
- Using a bundler (Webpack, Vite, etc.) → use the ESM import

---

## Basic Usage Pattern

Every integration follows this pattern:

```html
<!-- 1. Load the script -->
<script src="https://cdn.jsdelivr.net/npm/@one-payments/web-components@1.1.27/dist/one-payment.browser.iife.js"></script>

<!-- 2. Add the element -->
<one-payment
  id="my-payment-element"
  amount="5000"
  currency="USD"
  order-id="order-123"
></one-payment>

<!-- 3. Initialize via JavaScript -->
<script>
  document.addEventListener('DOMContentLoaded', function () {
    var element = document.getElementById('my-payment-element');

    // Configuration (see Security section for production setup)
    element.config = {
      apiKey: 'pk_demo_...',
      environment: 'demo' // Use 'prod' for production
    };

    // Create adapters
    element.adapters = OnePayments.createWebAdapters();

    // Required customer info
    element.firstName = 'John';
    element.lastName = 'Doe';
    element.email = 'john@example.com';

    // Event handlers
    element.addEventListener('payment-success', function (event) {
      console.log('Payment successful!', event.detail.paymentIntentId);
      // Redirect to success page
    });

    element.addEventListener('payment-error', function (event) {
      console.error('Payment failed:', event.detail.error);
      // Show error message
    });
  });
</script>
```

---

## Shopify Theme Integration

### Step 1: Create a Liquid Snippet

Create a new file `snippets/one-payments-dropin.liquid`:

```liquid
{% comment %}
  ONE Payments Drop-in Element
  Usage: {% render 'one-payments-dropin' %}
{% endcomment %}

<!-- ONE Payments Drop-in Container -->
<div id="one-payments-container" style="max-width: 500px; margin: 0 auto;">
  <one-payment
    id="one-payments-element"
    amount="{{ cart.total_price }}"
    currency="{{ cart.currency.iso_code | default: shop.currency }}"
    order-id="{{ cart.token }}"
  ></one-payment>
</div>

<!-- Load ONE Payments Browser Bundle -->
<script src="https://cdn.jsdelivr.net/npm/@one-payments/web-components@1.1.27/dist/one-payment.browser.iife.js"></script>

<script>
  document.addEventListener('DOMContentLoaded', function () {
    var element = document.getElementById('one-payments-element');

    if (!element) {
      console.error('[ONE Payments] Element not found');
      return;
    }

    // IMPORTANT: In production, fetch config from your backend or App Proxy
    // Do NOT hard-code secret keys in theme files
    element.config = {
      apiKey: 'pk_demo_...',
      environment: 'demo'
    };

    element.adapters = OnePayments.createWebAdapters();

    // Customer information (use Shopify customer data if available)
    {% if customer %}
      element.firstName = {{ customer.first_name | json }};
      element.lastName = {{ customer.last_name | json }};
      element.email = {{ customer.email | json }};
    {% else %}
      // For guest checkout, you may need a form to collect this
      element.firstName = '';
      element.lastName = '';
      element.email = '';
    {% endif %}

    // Handle successful payment
    element.addEventListener('payment-success', function (event) {
      console.log('[ONE Payments] Success:', event.detail.paymentIntentId);

      // Store payment ID in cart attributes
      fetch('/cart/update.js', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          attributes: {
            'one_payment_id': event.detail.paymentIntentId
          }
        })
      }).then(function () {
        // Proceed to Shopify checkout
        window.location.href = '/checkout';
      });
    });

    // Handle payment error
    element.addEventListener('payment-error', function (event) {
      console.error('[ONE Payments] Error:', event.detail.error);
      alert('Payment failed: ' + event.detail.error);
    });
  });
</script>
```

### Step 2: Include in Your Template

Add this to your cart template (`templates/cart.liquid` or `sections/cart-template.liquid`):

```liquid
{% render 'one-payments-dropin' %}
```

### Shopify App Proxy (Recommended for Production)

For production, create an App Proxy endpoint to securely provide configuration:

```javascript
// Your app server endpoint: /apps/one-payments/config
app.post('/apps/one-payments/config', async (req, res) => {
  const { shop, order_id, amount } = req.body;

  // Validate the request
  // Return config WITHOUT exposing the secret key
  res.json({
    apiKey: process.env.ONE_PAYMENTS_API_KEY,
    secretKey: process.env.ONE_PAYMENTS_SECRET_KEY,
    environment: 'prod'
  });
});
```

Then in your Liquid snippet:

```javascript
fetch('/apps/one-payments/config', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    order_id: '{{ cart.token }}',
    amount: {{ cart.total_price }}
  })
})
.then(function (response) { return response.json(); })
.then(function (config) {
  element.config = config;
  element.adapters = OnePayments.createWebAdapters();
});
```

---

## Wix Integration

### HTML Embed Component

1. In Wix Editor, add an **HTML iframe** or **Custom Element** component
2. Paste the following code:

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      padding: 20px;
    }
    #payment-container {
      max-width: 500px;
      margin: 0 auto;
    }
  </style>
</head>
<body>
  <div id="payment-container">
    <one-payment id="wix-payment-element"></one-payment>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/@one-payments/web-components@1.1.27/dist/one-payment.browser.iife.js"></script>

  <script>
    (function () {
      var element = document.getElementById('wix-payment-element');

      if (!element) {
        console.error('[ONE Payments] Element not found');
        return;
      }

      // Get parameters from URL (passed by Wix Velo)
      var params = new URLSearchParams(window.location.search);

      // Configuration
      element.config = {
        apiKey: params.get('apiKey') || 'pk_demo_...',
        environment: params.get('env') || 'demo'
      };

      element.adapters = OnePayments.createWebAdapters();

      // Payment details
      element.amount = parseInt(params.get('amount')) || 5000;
      element.currency = params.get('currency') || 'USD';
      element.orderId = params.get('orderId') || 'wix-' + Date.now();

      // Customer info
      element.firstName = params.get('firstName') || '';
      element.lastName = params.get('lastName') || '';
      element.email = params.get('email') || '';

      // Communicate results back to Wix parent page
      element.addEventListener('payment-success', function (event) {
        window.parent.postMessage({
          type: 'ONE_PAYMENT_SUCCESS',
          data: event.detail
        }, '*');
      });

      element.addEventListener('payment-error', function (event) {
        window.parent.postMessage({
          type: 'ONE_PAYMENT_ERROR',
          data: event.detail
        }, '*');
      });
    })();
  </script>
</body>
</html>
```

### Wix Velo Code (Parent Page)

```javascript
// Page code in Wix Velo
import wixLocation from 'wix-location';

$w.onReady(function () {
  // Listen for messages from the payment iframe
  $w('#html1').onMessage((event) => {
    const { type, data } = event.data;

    if (type === 'ONE_PAYMENT_SUCCESS') {
      console.log('Payment successful:', data.paymentIntentId);
      wixLocation.to('/thank-you');
    }

    if (type === 'ONE_PAYMENT_ERROR') {
      console.error('Payment failed:', data.error);
      $w('#errorText').text = 'Payment failed: ' + data.error;
      $w('#errorText').show();
    }
  });
});
```

---

## WordPress Integration

### Custom HTML Block

1. In the WordPress block editor, add a **Custom HTML** block
2. Paste the following code:

```html
<div id="one-payments-wp-container" style="max-width: 500px; margin: 20px auto;">
  <h2 style="text-align: center; margin-bottom: 20px;">Complete Your Payment</h2>
  <one-payment
    id="wp-payment-element"
    amount="7500"
    currency="USD"
    order-id="wp-order-001"
  ></one-payment>
</div>

<script src="https://cdn.jsdelivr.net/npm/@one-payments/web-components@1.1.27/dist/one-payment.browser.iife.js"></script>

<script>
  (function () {
    // Wait for element to be available
    function initPayment() {
      var element = document.getElementById('wp-payment-element');

      if (!element) {
        console.error('[ONE Payments] Element not found');
        return;
      }

      // Configuration
      element.config = {
        apiKey: 'pk_demo_...',
        environment: 'demo'
      };

      element.adapters = OnePayments.createWebAdapters();

      // Customer info - in production, get from WooCommerce or form
      element.firstName = 'John';
      element.lastName = 'Doe';
      element.email = 'john@example.com';

      // Handle payment success
      element.addEventListener('payment-success', function (event) {
        console.log('[ONE Payments] Success:', event.detail.paymentIntentId);
        alert('Payment successful! ID: ' + event.detail.paymentIntentId);
        // Redirect to thank you page
        // window.location.href = '/thank-you/';
      });

      // Handle payment error
      element.addEventListener('payment-error', function (event) {
        console.error('[ONE Payments] Error:', event.detail.error);
        alert('Payment failed: ' + event.detail.error);
      });
    }

    // Initialize when DOM is ready
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', initPayment);
    } else {
      initPayment();
    }
  })();
</script>
```

### WooCommerce Integration

For WooCommerce, you would typically create a payment gateway plugin. The CDN bundle can be used in the checkout page template:

```php
// In your WooCommerce payment gateway class
public function payment_fields() {
    ?>
    <div id="one-payments-wc-container">
        <one-payment
            id="wc-payment-element"
            amount="<?php echo WC()->cart->get_total('edit') * 100; ?>"
            currency="<?php echo get_woocommerce_currency(); ?>"
            order-id="<?php echo WC()->session->get('order_awaiting_payment'); ?>"
        ></one-payment>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/@one-payments/web-components@1.1.27/dist/one-payment.browser.iife.js"></script>
    <?php
}
```

---

## Security Considerations

### Never Hard-Code Secret Keys

The `secretKey` should **NEVER** be hard-coded in client-side code (themes, embeds, etc.).

**Bad (insecure):**

```javascript
element.config = {
  apiKey: 'pk_live_abc123',
  secretKey: 'sk_live_xyz789', // EXPOSED TO ANYONE VIEWING SOURCE!
  environment: 'prod'
};
```

**Good (secure):**

```javascript
// Fetch config from your backend
fetch('/api/payment-config', {
  method: 'POST',
  body: JSON.stringify({ orderId: 'order-123' })
})
.then(response => response.json())
.then(config => {
  element.config = config;
  element.adapters = OnePayments.createWebAdapters();
});
```

### Backend Proxy Pattern

Your backend should:

1. Validate the request (check session, order ownership, etc.)
2. Return only the necessary config
3. Optionally create a payment intent server-side

---

## Troubleshooting

### Element Not Rendering

1. Check browser console for errors
2. Ensure the script loaded successfully
3. Verify `OnePayments` is available: `console.log(window.OnePayments)`
4. Check that all required properties are set

### "customElements is not defined"

This error means you're trying to use the bundle in a non-browser environment (Node.js, SSR). The bundle is designed for browser use only.

### Payment Not Initializing

Ensure all required properties are set:

- `config` (with `apiKey` and `environment`)
- `adapters` (use `OnePayments.createWebAdapters()`)
- `amount` (in smallest currency unit, e.g., cents)
- `currency` (ISO 4217 code)
- `orderId` (unique identifier)
- `firstName`, `lastName`, `email` (customer info)

### CSP (Content Security Policy) Issues

If you see CSP errors, ensure your platform allows:

- Scripts from `cdn.jsdelivr.net` or `unpkg.com`
- Inline scripts (or use nonce/hash)

---

## Support

- Documentation: [docs.one-payments.com](https://docs.one-payments.com)
- Issues: [GitHub Issues](https://github.com/one-payments/sdk/issues)
- Email: [support@one-payments.com](mailto:support@one-payments.com)
