Integration Examples
Complete integration examples
JavaScript/Node.js
Complete integration example using Express:
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:
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
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';
}
?>