Integration Examples
Copy-paste ready examples showing a full payment integration in your language.
Ruby
Setup
Add these gems to your Gemfile:
gem 'faraday'
gem 'sinatra' # or Rails, etc.
Create a Payment
require 'faraday'
require 'json'
API_KEY = ENV.fetch('MOZART_PAY_API_KEY')
BASE_URL = 'https://api.mozartpay.io/api/v1'
conn = Faraday.new(url: BASE_URL) do |f|
f.request :json
f.response :json
f.headers['Authorization'] = "Bearer #{API_KEY}"
end
response = conn.post('payments', {
gateway: 'stripe',
amount_cents: 2500,
currency: 'GBP',
success_url: 'https://yoursite.com/success',
failure_url: 'https://yoursite.com/failure',
metadata: { order_id: 'ORD-123' }
})
if response.status == 201
data = response.body
puts "Payment created: #{data['payment_id']}"
puts "Redirect customer to: #{data['redirect_url']}"
else
puts "Error: #{response.body['message']}"
end
Handle the Redirect
After the customer completes payment, they are redirected to your success_url or failure_url. Check the payment status via the API:
get '/success' do
payment = conn.get("payments/#{params[:payment_id]}").body
if payment['status'] == 'completed'
"Payment successful!"
else
"Payment is #{payment['status']}. Please wait for confirmation."
end
end
Verify Webhook Signatures
When you receive a webhook, verify the signature before processing:
require 'openssl'
WEBHOOK_SECRET = ENV.fetch('MOZART_PAY_WEBHOOK_SECRET')
post '/webhooks/mozart-pay' do
payload = request.body.read
signature_header = request.env['HTTP_X_MOZART_SIGNATURE']
unless valid_signature?(payload, signature_header)
halt 401, 'Invalid signature'
end
event = JSON.parse(payload)
case event['event']
when 'payment.completed'
# Fulfil the order
when 'payment.failed'
# Notify the customer
when 'refund.completed'
# Update your records
end
status 200
end
def valid_signature?(payload, header)
return false unless header
parts = header.split(',').to_h { |p| p.split('=', 2) }
timestamp = parts['t']
received = parts['v1']
expected = OpenSSL::HMAC.hexdigest('SHA256', WEBHOOK_SECRET, "#{timestamp}.#{payload}")
ActiveSupport::SecurityUtils.secure_compare(expected, received)
end
Node.js
Setup
npm install express
Create a Payment
const API_KEY = process.env.MOZART_PAY_API_KEY;
const BASE_URL = "https://api.mozartpay.io/api/v1";
async function createPayment(orderData) {
const response = await fetch(`${BASE_URL}/payments`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
gateway: "stripe",
amount_cents: orderData.totalCents,
currency: "GBP",
success_url: "https://yoursite.com/success",
failure_url: "https://yoursite.com/failure",
metadata: { order_id: orderData.id },
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
return response.json();
}
// Usage
const payment = await createPayment({ id: "ORD-123", totalCents: 2500 });
console.log(`Redirect customer to: ${payment.redirect_url}`);
Handle the Redirect
After the customer completes payment, they are redirected to your success_url or failure_url. Check the payment status via the API:
import express from "express";
const app = express();
app.get("/success", async (req, res) => {
const response = await fetch(`${BASE_URL}/payments/${req.query.payment_id}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const payment = await response.json();
if (payment.status === "completed") {
res.send("Payment successful!");
} else {
res.send(`Payment is ${payment.status}. Please wait for confirmation.`);
}
});
Verify Webhook Signatures
import crypto from "node:crypto";
const WEBHOOK_SECRET = process.env.MOZART_PAY_WEBHOOK_SECRET;
function validSignature(payload, header) {
if (!header) return false;
const parts = Object.fromEntries(
header.split(",").map((p) => p.split("=", 2))
);
const timestamp = parts.t;
const received = parts.v1;
const expected = crypto
.createHmac("sha256", WEBHOOK_SECRET)
.update(`${timestamp}.${payload}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(received, "hex")
);
}
app.post("/webhooks/mozart-pay", express.raw({ type: "application/json" }), (req, res) => {
const payload = req.body.toString();
const signature = req.headers["x-mozart-signature"];
if (!validSignature(payload, signature)) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(payload);
switch (event.event) {
case "payment.completed":
// Fulfil the order
break;
case "payment.failed":
// Notify the customer
break;
case "refund.completed":
// Update your records
break;
}
res.sendStatus(200);
});
Python
Setup
pip install requests flask
Create a Payment
import os
import requests
API_KEY = os.environ["MOZART_PAY_API_KEY"]
BASE_URL = "https://api.mozartpay.io/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def create_payment(order_id, amount_cents):
response = requests.post(
f"{BASE_URL}/payments",
headers=HEADERS,
json={
"gateway": "stripe",
"amount_cents": amount_cents,
"currency": "GBP",
"success_url": "https://yoursite.com/success",
"failure_url": "https://yoursite.com/failure",
"metadata": {"order_id": order_id},
},
)
response.raise_for_status()
return response.json()
# Usage
payment = create_payment("ORD-123", 2500)
print(f"Redirect customer to: {payment['redirect_url']}")
Handle the Redirect
After the customer completes payment, they are redirected to your success_url or failure_url. Check the payment status via the API:
from flask import Flask, request
app = Flask(__name__)
@app.route("/success")
def success():
payment_id = request.args["payment_id"]
response = requests.get(f"{BASE_URL}/payments/{payment_id}", headers=HEADERS)
payment = response.json()
if payment["status"] == "completed":
return "Payment successful!"
return f"Payment is {payment['status']}. Please wait for confirmation."
Verify Webhook Signatures
import hashlib
import hmac
import os
WEBHOOK_SECRET = os.environ["MOZART_PAY_WEBHOOK_SECRET"]
def valid_signature(payload: bytes, header: str) -> bool:
if not header:
return False
parts = dict(p.split("=", 1) for p in header.split(","))
timestamp = parts["t"]
received = parts["v1"]
expected = hmac.new(
WEBHOOK_SECRET.encode(),
f"{timestamp}.{payload.decode()}".encode(),
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, received)
@app.route("/webhooks/mozart-pay", methods=["POST"])
def webhook():
payload = request.get_data()
signature = request.headers.get("X-Mozart-Signature")
if not valid_signature(payload, signature):
return "Invalid signature", 401
event = request.get_json()
match event["event"]:
case "payment.completed":
pass # Fulfil the order
case "payment.failed":
pass # Notify the customer
case "refund.completed":
pass # Update your records
return "", 200
PHP
Setup
No extra packages required. PHP ships with curl and hash_hmac.
Create a Payment
<?php
$apiKey = getenv('MOZART_PAY_API_KEY');
$baseUrl = 'https://api.mozartpay.io/api/v1';
function createPayment(string $orderId, int $amountCents): array
{
global $apiKey, $baseUrl;
$ch = curl_init("$baseUrl/payments");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $apiKey",
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'gateway' => 'stripe',
'amount_cents' => $amountCents,
'currency' => 'GBP',
'success_url' => 'https://yoursite.com/success',
'failure_url' => 'https://yoursite.com/failure',
'metadata' => ['order_id' => $orderId],
]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($status !== 201) {
throw new RuntimeException("API error: {$data['message']}");
}
return $data;
}
// Usage
$payment = createPayment('ORD-123', 2500);
echo "Redirect customer to: {$payment['redirect_url']}\n";
Handle the Redirect
After the customer completes payment, they are redirected to your success_url or failure_url. Check the payment status via the API:
<?php
// success.php
$paymentId = $_GET['payment_id'];
$ch = curl_init("$baseUrl/payments/$paymentId");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer $apiKey"],
]);
$response = curl_exec($ch);
curl_close($ch);
$payment = json_decode($response, true);
if ($payment['status'] === 'completed') {
echo 'Payment successful!';
} else {
echo "Payment is {$payment['status']}. Please wait for confirmation.";
}
Verify Webhook Signatures
<?php
// webhook.php
$webhookSecret = getenv('MOZART_PAY_WEBHOOK_SECRET');
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_MOZART_SIGNATURE'] ?? '';
if (!validSignature($payload, $signature, $webhookSecret)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($payload, true);
switch ($event['event']) {
case 'payment.completed':
// Fulfil the order
break;
case 'payment.failed':
// Notify the customer
break;
case 'refund.completed':
// Update your records
break;
}
http_response_code(200);
function validSignature(string $payload, string $header, string $secret): bool
{
if (empty($header)) {
return false;
}
$parts = [];
foreach (explode(',', $header) as $part) {
[$key, $value] = explode('=', $part, 2);
$parts[$key] = $value;
}
$timestamp = $parts['t'];
$received = $parts['v1'];
$expected = hash_hmac('sha256', "$timestamp.$payload", $secret);
return hash_equals($expected, $received);
}