# Integration Examples

## Complete integration examples

### JavaScript/Node.js

Complete integration example using Express:

```javascript
const express = require('express');
const crypto = require('crypto');
const axios = require('axios');

const app = express();
const PORT = process.env.PORT || 3000;

// Joy API client setup
const joyApi = axios.create({
  baseURL: 'https://joy.avada.io/app/api/v1',
  headers: {
    'X-Joy-Loyalty-App-Key': process.env.JOY_APP_KEY,
    'X-Joy-Loyalty-Secret-Key': process.env.JOY_SECRET_KEY
  }
});

// HMAC verification middleware
function verifyWebhook(req, res, next) {
  const hmac = req.get('X-Joy-Loyalty-Hmac-Sha256');
  const calculatedHmac = crypto
    .createHmac('sha256', process.env.JOY_SECRET_KEY)
    .update(req.rawBody, 'utf8')
    .digest('base64');

  if (!crypto.timingSafeEqual(Buffer.from(calculatedHmac), Buffer.from(hmac))) {
    return res.status(401).send('Invalid signature');
  }
  
  next();
}

// Raw body parser for HMAC verification
app.use('/webhook', express.raw({type: 'application/json'}), (req, res, next) => {
  req.rawBody = req.body;
  req.body = JSON.parse(req.body);
  next();
});

// Webhook handlers
app.post('/webhook/points-earned', verifyWebhook, (req, res) => {
  const {customer, oldPoint, newPoint} = req.body;
  console.log(`Customer ${customer.email} earned ${newPoint - oldPoint} points`);
  
  // Your business logic here
  
  res.status(200).send('OK');
});

app.post('/webhook/tier-upgraded', verifyWebhook, (req, res) => {
  const {customer, oldTierName, newTierName} = req.body;
  console.log(`Customer ${customer.email} upgraded from ${oldTierName} to ${newTierName}`);
  
  // Your business logic here
  
  res.status(200).send('OK');
});

// API management functions
async function createWebhook(topic, url) {
  try {
    const response = await joyApi.post('/webhooks', {topic, url});
    return response.data;
  } catch (error) {
    console.error('Failed to create webhook:', error.response?.data || error.message);
    throw error;
  }
}

async function listWebhooks() {
  try {
    const response = await joyApi.get('/webhooks');
    return response.data.webhooks;
  } catch (error) {
    console.error('Failed to list webhooks:', error.response?.data || error.message);
    throw error;
  }
}

app.listen(PORT, () => {
  console.log(`Webhook server running on port ${PORT}`);
});
```

### Python

Complete integration example using Flask:

```python
import os
import hmac
import hashlib
import base64
import json
import requests
from flask import Flask, request

app = Flask(__name__)

class JoyWebhookClient:
    def __init__(self, app_key, secret_key):
        self.app_key = app_key
        self.secret_key = secret_key
        self.base_url = 'https://joy.avada.io/app/api/v1'
        self.session = requests.Session()
        self.session.headers.update({
            'Content-Type': 'application/json',
            'X-Joy-Loyalty-App-Key': app_key,
            'X-Joy-Loyalty-Secret-Key': secret_key
        })

    def verify_webhook(self, raw_body, hmac_header):
        calculated_hmac = base64.b64encode(
            hmac.new(
                self.secret_key.encode('utf-8'),
                raw_body,
                hashlib.sha256
            ).digest()
        ).decode()
        
        return hmac.compare_digest(calculated_hmac, hmac_header)

    def create_webhook(self, topic, url):
        response = self.session.post(f'{self.base_url}/webhooks', 
                                   json={'topic': topic, 'url': url})
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f'Failed to create webhook: {response.text}')

    def list_webhooks(self):
        response = self.session.get(f'{self.base_url}/webhooks')
        if response.status_code == 200:
            return response.json().get('webhooks', [])
        else:
            raise Exception(f'Failed to list webhooks: {response.text}')

# Initialize client
webhook_client = JoyWebhookClient(
    os.getenv('JOY_APP_KEY'),
    os.getenv('JOY_SECRET_KEY')
)

@app.route('/webhook/points-earned', methods=['POST'])
def handle_points_earned():
    # Verify HMAC
    hmac_header = request.headers.get('X-Joy-Loyalty-Hmac-Sha256')
    if not webhook_client.verify_webhook(request.data, hmac_header):
        return 'Invalid signature', 401
    
    # Process webhook
    payload = request.get_json()
    customer = payload.get('customer', {})
    old_point = payload.get('oldPoint', 0)
    new_point = payload.get('newPoint', 0)
    
    print(f"Customer {customer.get('email')} earned {new_point - old_point} points")
    
    # Your business logic here
    
    return 'OK', 200

@app.route('/webhook/tier-upgraded', methods=['POST'])
def handle_tier_upgraded():
    # Verify HMAC
    hmac_header = request.headers.get('X-Joy-Loyalty-Hmac-Sha256')
    if not webhook_client.verify_webhook(request.data, hmac_header):
        return 'Invalid signature', 401
    
    # Process webhook
    payload = request.get_json()
    customer = payload.get('customer', {})
    old_tier = payload.get('oldTierName')
    new_tier = payload.get('newTierName')
    
    print(f"Customer {customer.get('email')} upgraded from {old_tier} to {new_tier}")
    
    # Your business logic here
    
    return 'OK', 200

if __name__ == '__main__':
    app.run(debug=True, port=5000)
```

### PHP

Complete integration example:

```php
<?php
class JoyWebhookClient {
    private $appKey;
    private $secretKey;
    private $baseUrl = 'https://joy.avada.io/app/api/v1';

    public function __construct($appKey, $secretKey) {
        $this->appKey = $appKey;
        $this->secretKey = $secretKey;
    }

    public function verifyWebhook($rawBody, $hmacHeader) {
        $calculatedHmac = base64_encode(hash_hmac('sha256', $rawBody, $this->secretKey, true));
        return hash_equals($calculatedHmac, $hmacHeader);
    }

    public function createWebhook($topic, $url) {
        $data = json_encode(['topic' => $topic, 'url' => $url]);
        
        $context = stream_context_create([
            'http' => [
                'method' => 'POST',
                'header' => [
                    'Content-Type: application/json',
                    'X-Joy-Loyalty-App-Key: ' . $this->appKey,
                    'X-Joy-Loyalty-Secret-Key: ' . $this->secretKey
                ],
                'content' => $data
            ]
        ]);

        $response = file_get_contents($this->baseUrl . '/webhooks', false, $context);
        return json_decode($response, true);
    }

    public function listWebhooks() {
        $context = stream_context_create([
            'http' => [
                'method' => 'GET',
                'header' => [
                    'Content-Type: application/json',
                    'X-Joy-Loyalty-App-Key: ' . $this->appKey,
                    'X-Joy-Loyalty-Secret-Key: ' . $this->secretKey
                ]
            ]
        ]);

        $response = file_get_contents($this->baseUrl . '/webhooks', false, $context);
        $data = json_decode($response, true);
        return $data['webhooks'] ?? [];
    }
}

// Initialize client
$webhookClient = new JoyWebhookClient(
    $_ENV['JOY_APP_KEY'],
    $_ENV['JOY_SECRET_KEY']
);

// Handle webhook requests
$requestMethod = $_SERVER['REQUEST_METHOD'];
$requestPath = $_SERVER['REQUEST_URI'];

if ($requestMethod === 'POST' && strpos($requestPath, '/webhook/') === 0) {
    $rawBody = file_get_contents('php://input');
    $hmacHeader = $_SERVER['HTTP_X_JOY_LOYALTY_HMAC_SHA256'] ?? '';

    if (!$webhookClient->verifyWebhook($rawBody, $hmacHeader)) {
        http_response_code(401);
        exit('Invalid signature');
    }

    $payload = json_decode($rawBody, true);
    
    if (strpos($requestPath, '/webhook/points-earned') === 0) {
        $customer = $payload['customer'] ?? [];
        $oldPoint = $payload['oldPoint'] ?? 0;
        $newPoint = $payload['newPoint'] ?? 0;
        
        error_log("Customer {$customer['email']} earned " . ($newPoint - $oldPoint) . " points");
        
        // Your business logic here
        
    } elseif (strpos($requestPath, '/webhook/tier-upgraded') === 0) {
        $customer = $payload['customer'] ?? [];
        $oldTier = $payload['oldTierName'] ?? '';
        $newTier = $payload['newTierName'] ?? '';
        
        error_log("Customer {$customer['email']} upgraded from $oldTier to $newTier");
        
        // Your business logic here
    }

    http_response_code(200);
    echo 'OK';
}
?>
```
