Integration Examples

Copy-paste ready examples showing a full payment integration in your language.

Ruby

Setup

Add these gems to your Gemfile:

Gemfile
gem 'faraday'
gem 'sinatra' # or Rails, etc.

Create a Payment

Ruby
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:

Ruby
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:

Ruby
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

bash
npm install express

Create a Payment

JavaScript
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:

JavaScript
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

JavaScript
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

bash
pip install requests flask

Create a Payment

Python
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:

Python
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

Python
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
<?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
<?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
<?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);
}