> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mycashq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Card Tokenization

> Securely tokenize card data using Approvely

## Overview

Card tokenization converts sensitive card data into a secure token (nonce) that can be used to process payments. This approach ensures that card data never touches your servers, reducing your PCI compliance requirements.

## How Tokenization Works

<Steps>
  <Step title="Customer enters card details">
    Customer fills out the tokenization form with their card information
  </Step>

  <Step title="Approvely generates nonce">
    Card data is sent directly to Approvely's secure servers, which return a one-time nonce token
  </Step>

  <Step title="Use nonce for payment">
    Your server uses the nonce token to process the payment via the charge endpoint
  </Step>
</Steps>

<Info>
  The nonce token is single-use and expires after a short period. It must be used immediately to process a payment.
</Info>

## Getting Your Tokenization Token

<Steps>
  <Step title="Log in to Control Panel">
    Access the [Approvely Control Panel](https://sandbox.approvelygateway.com/control-panel/sources)
  </Step>

  <Step title="Get Tokenization Token">
    Copy your **Tokenization Token** (also called API Key) from the Sources page
  </Step>
</Steps>

## Setting Up Tokenization

### Option 1: Using Python Local Server (Quick Test)

For quick testing, you can use a local HTML page:

<Steps>
  <Step title="Create HTML file">
    Create a file named `approvely_tokenization.html` with the tokenization form (see example below)
  </Step>

  <Step title="Start local server">
    Open your command line in the folder with the HTML file and run:

    ```bash theme={null}
    python -m http.server
    ```

    Or for a specific port:

    ```bash theme={null}
    python -m http.server 8080
    ```
  </Step>

  <Step title="Open in browser">
    Navigate to `http://127.0.0.1:8000/approvely_tokenization.html` in your browser
  </Step>
</Steps>

### Option 2: Integrate into Your Application

Integrate the tokenization form directly into your application's checkout page.

## HTML Tokenization Form Example

This example uses Approvely's Hosted Tokenization, which provides a secure iframe for card data entry:

```html theme={null}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hosted Tokenization Sample</title>
    
    <!-- Sandbox Tokenization Script -->
    <script src="https://tokenization.sandbox.approvelygateway.com/tokenization/v0.2"></script>
    
    <!-- For Production, use: -->
    <!-- <script src="https://tokenization.approvelygateway.com/tokenization/v0.2"></script> -->
</head>
<body>
<form>
    <div>
        <div>
            <label>Name<br/><input id="name" name="name" value="John Doe"/></label>
        </div>

        <div>
            <label>Amount<br/><input id="amount" name="amount" value="5"/></label>
        </div>
    </div>

    <!-- Card form will be mounted here -->
    <div id="iframe-container"></div>

    <div id="error-message"></div>

    <div>Masked Card #: <span id="masked-card"></span></div>
    <div>Masked CVV2: <span id="masked-cvv2"></span></div>
    <div>Nonce: <span id="nonce"></span></div>

    <div>
        <button type="button" id="charge">Get Token</button>
    </div>
</form>

<script defer>
    const chargeButton = document.querySelector('#charge');
    const nameEl = document.querySelector('#name');
    const amountEl = document.querySelector('#amount');
    const iframeContainerEl = document.querySelector('#iframe-container');
    const errorMessageEl = document.querySelector('#error-message');
    const maskedCardEl = document.querySelector('#masked-card');
    const maskedCvv2El = document.querySelector('#masked-cvv2');
    const nonceEl = document.querySelector('#nonce');

    chargeButton.addEventListener('click', onChargeClick);

    // Replace with your tokenization key from Approvely Control Panel
    const publicSourceKey = 'YOUR_TOKENIZATION_KEY_HERE';
    const hostedTokenization = new window.HostedTokenization(publicSourceKey);

    // Create and mount the card form
    const cardForm = hostedTokenization.create('card-form')
        .mount('#iframe-container')
        .on('input', _onEvent)
        .on('change', _onEvent);

    function _onEvent(event) {
        _handleError(event.error);
        maskedCardEl.innerText = (event.result && event.result.maskedCard) || '';
        maskedCvv2El.innerText = (event.result && event.result.maskedCvv2) || '';
        console.log(event.result);
    }

    function _handleError(error) {
        if (error) {
            errorMessageEl.innerText = error.message || 'An error occurred';
            console.error(error);
        } else {
            errorMessageEl.innerText = '';
        }
    }

    async function onChargeClick(event) {
        event.preventDefault();
        
        try {
            const result = await cardForm.getNonceToken();
            const nonceToken = 'nonce-' + result.nonce;
            nonceEl.innerText = nonceToken || '';
            console.log('Nonce token:', nonceToken);
            
            // Send nonce to your server
            sendToServer(nonceToken, amountEl.value, nameEl.value);
        } catch (error) {
            _handleError(error);
        }
    }
    
    function sendToServer(nonce, amount, name) {
        // Send the nonce to your server to process the charge
        fetch('/api/process-payment', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                nonce: nonce,
                amount: amount,
                cardholder_name: name
            })
        })
        .then(response => response.json())
        .then(data => {
            console.log('Payment processed:', data);
            alert('Payment successful!');
        })
        .catch(error => {
            console.error('Payment error:', error);
            alert('Payment failed: ' + error.message);
        });
    }
</script>
</body>
</html>
```

<Warning>
  **Replace the tokenization key:** Change `YOUR_TOKENIZATION_KEY_HERE` to your actual tokenization key from the [Approvely Control Panel](https://sandbox.approvelygateway.com/control-panel/sources).
</Warning>

### How This Works

<Steps>
  <Step title="Load Tokenization Script">
    The Approvely tokenization script is loaded from their CDN
  </Step>

  <Step title="Initialize Hosted Tokenization">
    Create a `HostedTokenization` instance with your public source key
  </Step>

  <Step title="Mount Card Form">
    The card form is mounted as a secure iframe in the `#iframe-container` div
  </Step>

  <Step title="Customer Enters Card Data">
    Customer enters card details directly in the secure iframe (never touches your server)
  </Step>

  <Step title="Get Nonce Token">
    When user clicks "Get Token", call `cardForm.getNonceToken()` to get the nonce
  </Step>

  <Step title="Send to Server">
    Send the nonce token to your server to process the charge
  </Step>
</Steps>

### Key Features

* **Secure Iframe**: Card data is entered in Approvely's secure iframe, never touching your server
* **Real-time Validation**: Card number and CVV are validated as the user types
* **Masked Display**: Shows masked card number and CVV for user confirmation
* **Event Handling**: Listen to `input` and `change` events for real-time feedback

## Test Card Data

Use these test cards in the sandbox environment:

### Successful Transaction

| Field               | Value                                 |
| ------------------- | ------------------------------------- |
| **Card Number**     | `4111 1111 1111 1111`                 |
| **Cardholder Name** | Any name (e.g., "John Doe")           |
| **CVV**             | Any 3 digits (e.g., "123")            |
| **Expiry Date**     | Any valid future date (e.g., "10/28") |
| **Amount**          | Any amount (e.g., "5.00")             |

### Other Test Cards

<AccordionGroup>
  <Accordion title="Visa">
    **Card Number:** `4111 1111 1111 1111`

    **Result:** Successful transaction
  </Accordion>

  <Accordion title="Mastercard">
    **Card Number:** `5555 5555 5555 4444`

    **Result:** Successful transaction
  </Accordion>

  <Accordion title="American Express">
    **Card Number:** `3782 822463 10005`

    **CVV:** 4 digits (e.g., "1234")

    **Result:** Successful transaction
  </Accordion>

  <Accordion title="Declined Card">
    **Card Number:** `4000 0000 0000 0002`

    **Result:** Card declined
  </Accordion>
</AccordionGroup>

### CVV Numbers by Card Type

For testing purposes, use the following CVV numbers based on card type:

| Card Type      | CVV  |
| -------------- | ---- |
| **Visa**       | 999  |
| **Mastercard** | 998  |
| **Discover**   | 996  |
| **Amex**       | 9997 |
| **Diners**     | 996  |
| **JCB**        | 996  |

<Warning>
  **Testing Amount Limitation:** Most sales under $1.00 will return a decline. Use amounts of $1.00 or higher for successful test transactions.
</Warning>

## Nonce Token Format

After successful tokenization, you'll receive a nonce token in this format:

```
nonce-134avdynjq3ey1r8r7gq
```

**Example Response:**

```json theme={null}
{
  "nonce": "nonce-pft4uav4cker5g8bk3db",
  "card_type": "visa",
  "last_four": "1111",
  "expiry_month": "10",
  "expiry_year": "2028"
}
```

## Using the Nonce Token

Once you have the nonce token, immediately send it to your server to process the charge:

```javascript theme={null}
// Client-side: Send nonce to your server
async function processPayment(nonce, amount, cardholderName) {
  const response = await fetch('/api/process-payment', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      nonce: nonce,
      amount: amount,
      cardholder_name: cardholderName
    })
  });
  
  return await response.json();
}
```

```javascript theme={null}
// Server-side: Use nonce to charge
async function chargeCard(nonce, amount, expiryMonth, expiryYear, billingInfo) {
  const credentials = Buffer.from(`${apiKey}:${pin}`).toString('base64');
  
  const response = await fetch(
    'https://api.sandbox.approvelygateway.com/api/v2/transactions/charge',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Basic ${credentials}`
      },
      body: JSON.stringify({
        amount: amount,
        source: nonce,
        expiry_month: expiryMonth,
        expiry_year: expiryYear,
        billing_info: {
          first_name: billingInfo.first_name,
          last_name: billingInfo.last_name,
          street: billingInfo.street,
          street2: billingInfo.street2,
          city: billingInfo.city,
          state: billingInfo.state,
          zip: billingInfo.zip,
          country: billingInfo.country,
          phone: billingInfo.phone
        }
      })
    }
  );
  
  return await response.json();
}
```

## Security Best Practices

<CardGroup cols={2}>
  <Card title="Never Store Card Data" icon="ban">
    Never store raw card numbers, CVV, or full expiry dates on your servers
  </Card>

  <Card title="Use Nonce Immediately" icon="clock">
    Nonce tokens expire quickly. Use them immediately after generation
  </Card>

  <Card title="HTTPS Only" icon="lock">
    Always serve your tokenization form over HTTPS
  </Card>

  <Card title="Validate Client-Side" icon="check">
    Validate card data format before sending to tokenization
  </Card>
</CardGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Tokenization fails">
    **Possible causes:**

    * Invalid tokenization token
    * Incorrect card number format
    * Network connectivity issues

    **Solution:**

    * Verify your tokenization token is correct
    * Ensure card number contains only digits
    * Check browser console for error messages
  </Accordion>

  <Accordion title="Nonce expires before use">
    **Cause:** Delay between tokenization and charge request

    **Solution:**

    * Process the charge immediately after receiving the nonce
    * Don't store nonces for later use
    * If expired, re-tokenize the card
  </Accordion>

  <Accordion title="CORS errors">
    **Cause:** Tokenization script blocked by browser

    **Solution:**

    * Ensure you're using HTTPS
    * Verify the Approvely script URL is correct
    * Check browser console for specific CORS errors
  </Accordion>
</AccordionGroup>

## Next Steps

<Card title="Process Charges" icon="bolt" href="/payin/charge">
  Learn how to use the nonce token to process payments
</Card>
