Console
Guide

Payments

Charge users with Stripe Checkout. Your app never handles card data — Vanelton Pay redirects to a hosted Stripe page and returns the result.

How it works

1
Create a product
Go to the Developer Console → your app → Products. Copy the itemKey.
2
Create a payment
Call POST /api/pay/create_payment.php. Receive a payment_url (Stripe Checkout link).
3
Redirect the user
Send the user to the Stripe Checkout page. Stripe redirects them to your success_url after payment.
4
Verify & release
Call check_payment to confirm payment_status === "paid", then call release_payment after delivering the item.

1. Create a one-time payment

const res = await fetch('https://vaneltonmedia.com/api/pay/create_payment.php', {
  method: 'POST',
  headers: {
    'Authorization': `${APP_ID}:${APP_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    token:       localStorage.getItem('vm_token'),
    itemKey:     'abc123def456',
    currency:    'brl',
    success_url: 'https://myapp.com/purchase/success',
    cancel_url:  'https://myapp.com/purchase/cancel'
  })
});
const { payment_url } = await res.json();
window.location.href = payment_url; // redirect to Stripe Checkout
const res = await fetch('https://vaneltonmedia.com/api/pay/create_payment.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    token: localStorage.getItem('vm_token'),
    itemKey: 'abc123def456',
    currency: 'brl',
    success_url: 'https://myapp.com/purchase/success',
    cancel_url:  'https://myapp.com/purchase/cancel'
  })
});
const data = await res.json();
window.location.href = data.payment_url;
$ch = curl_init('https://vaneltonmedia.com/api/pay/create_payment.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'token'       => $_SESSION['vm_token'],
        'itemKey'     => 'abc123def456',
        'currency'    => 'brl',
        'success_url' => 'https://myapp.com/purchase/success',
        'cancel_url'  => 'https://myapp.com/purchase/cancel',
    ]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

header('Location: ' . $result['payment_url']);
exit;
res = requests.post(
    'https://vaneltonmedia.com/api/pay/create_payment.php',
    headers={'Authorization': f'{APP_ID}:{APP_KEY}', 'Content-Type': 'application/json'},
    json={
        'token': token, 'itemKey': 'abc123def456', 'currency': 'brl',
        'success_url': 'https://myapp.com/purchase/success',
        'cancel_url':  'https://myapp.com/purchase/cancel',
    }
)
payment_url = res.json()['payment_url']
# redirect user to payment_url
APP_ID="com.myapp.game"
APP_KEY="MyAppKey1234567890ABCDE"
TOKEN="YOUR_SESSION_TOKEN"

curl -s -X POST "https://vaneltonmedia.com/api/pay/create_payment.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\",\"itemKey\":\"abc123def456\",\"currency\":\"brl\",\"success_url\":\"https://myapp.com/purchase/success\",\"cancel_url\":\"https://myapp.com/purchase/cancel\"}"
using System.Net.Http;
using System.Text;
using System.Text.Json;

const string APP_ID  = "com.myapp.game";
const string APP_KEY = "MyAppKey1234567890ABCDE";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"{APP_ID}:{APP_KEY}");

var payload = JsonSerializer.Serialize(new {
    token       = token,
    itemKey     = "abc123def456",
    currency    = "brl",
    success_url = "https://myapp.com/purchase/success",
    cancel_url  = "https://myapp.com/purchase/cancel",
});
using var res = await client.PostAsync(
    "https://vaneltonmedia.com/api/pay/create_payment.php",
    new StringContent(payload, Encoding.UTF8, "application/json"));

using var doc = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
var paymentUrl = doc.RootElement.GetProperty("payment_url").GetString();
// redirect user to paymentUrl
-- Requires: luarocks install luasocket luasec lua-cjson
local http  = require("socket.http")
local ltn12 = require("ltn12")
local json  = require("cjson")

local APP_ID  = "com.myapp.game"
local APP_KEY = "MyAppKey1234567890ABCDE"

local body   = json.encode({
    token       = token,
    itemKey     = "abc123def456",
    currency    = "brl",
    success_url = "https://myapp.com/purchase/success",
    cancel_url  = "https://myapp.com/purchase/cancel",
})
local chunks = {}
http.request {
    url    = "https://vaneltonmedia.com/api/pay/create_payment.php",
    method = "POST",
    headers = {
        ["Authorization"]  = APP_ID .. ":" .. APP_KEY,
        ["Content-Type"]   = "application/json",
        ["Content-Length"] = #body,
    },
    source = ltn12.source.string(body),
    sink   = ltn12.sink.table(chunks),
}
local result = json.decode(table.concat(chunks))
local payment_url = result.payment_url
-- redirect user to payment_url

Success response:

{
  "success": true,
  "message": "Payment link created successfully.",
  "payment_url": "https://checkout.stripe.com/pay/cs_live_..."
}

2. Verify payment

Call this on your success_url page after Stripe redirects the user back.

const res = await fetch('https://vaneltonmedia.com/api/pay/check_payment.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), itemKey: 'abc123def456' })
});
const { payment_found, payment_details } = await res.json();

if (payment_found && payment_details.payment_status === 'paid') {
  // Deliver the item
  unlockContent(payment_details.itemKey);
}
const res = await fetch('https://vaneltonmedia.com/api/pay/check_payment.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), itemKey: 'abc123def456' })
});
const { payment_found, payment_details } = await res.json();

if (payment_found && payment_details.payment_status === 'paid') {
  unlockContent(payment_details.itemKey);
}
$ch = curl_init('https://vaneltonmedia.com/api/pay/check_payment.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['token' => $_SESSION['vm_token'], 'itemKey' => 'abc123def456']),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

if ($result['payment_found'] && $result['payment_details']['payment_status'] === 'paid') {
    // Deliver item and release
    $paymentId = $result['payment_details']['payment_id'];
}
result = requests.post(
    'https://vaneltonmedia.com/api/pay/check_payment.php',
    headers={'Authorization': f'{APP_ID}:{APP_KEY}', 'Content-Type': 'application/json'},
    json={'token': token, 'itemKey': 'abc123def456'}
).json()

if result['payment_found'] and result['payment_details']['payment_status'] == 'paid':
    deliver_item(result['payment_details']['itemKey'])
curl -s -X POST "https://vaneltonmedia.com/api/pay/check_payment.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\",\"itemKey\":\"abc123def456\"}"
var payload = JsonSerializer.Serialize(new { token, itemKey = "abc123def456" });
using var res = await client.PostAsync(
    "https://vaneltonmedia.com/api/pay/check_payment.php",
    new StringContent(payload, Encoding.UTF8, "application/json"));

using var doc    = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
bool paymentFound = doc.RootElement.GetProperty("payment_found").GetBoolean();
if (paymentFound) {
    var details = doc.RootElement.GetProperty("payment_details");
    if (details.GetProperty("payment_status").GetString() == "paid") {
        // deliver item
        int paymentId = details.GetProperty("payment_id").GetInt32();
    }
}
local body   = json.encode({ token = token, itemKey = "abc123def456" })
local chunks = {}
http.request {
    url    = "https://vaneltonmedia.com/api/pay/check_payment.php",
    method = "POST",
    headers = {
        ["Authorization"]  = APP_ID .. ":" .. APP_KEY,
        ["Content-Type"]   = "application/json",
        ["Content-Length"] = #body,
    },
    source = ltn12.source.string(body),
    sink   = ltn12.sink.table(chunks),
}
local result = json.decode(table.concat(chunks))
if result.payment_found and result.payment_details.payment_status == "paid" then
    deliver_item(result.payment_details.itemKey)
end

3. Release payment

After you deliver the item, call release_payment to mark it as delivered (release_status = released). Pass the payment_id from check_payment.

await fetch('https://vaneltonmedia.com/api/pay/release_payment.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), payment_id: 101 })
});
await fetch('https://vaneltonmedia.com/api/pay/release_payment.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), payment_id: paymentId })
});
$ch = curl_init('https://vaneltonmedia.com/api/pay/release_payment.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['token' => $_SESSION['vm_token'], 'payment_id' => $paymentId]),
]);
curl_exec($ch); curl_close($ch);
requests.post(
    'https://vaneltonmedia.com/api/pay/release_payment.php',
    headers={'Authorization': f'{APP_ID}:{APP_KEY}', 'Content-Type': 'application/json'},
    json={'token': token, 'payment_id': payment_id}
)
curl -s -X POST "https://vaneltonmedia.com/api/pay/release_payment.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\",\"payment_id\":101}"
var payload = JsonSerializer.Serialize(new { token, payment_id = paymentId });
await client.PostAsync(
    "https://vaneltonmedia.com/api/pay/release_payment.php",
    new StringContent(payload, Encoding.UTF8, "application/json"));
local body   = json.encode({ token = token, payment_id = payment_id })
local chunks = {}
http.request {
    url    = "https://vaneltonmedia.com/api/pay/release_payment.php",
    method = "POST",
    headers = {
        ["Authorization"]  = APP_ID .. ":" .. APP_KEY,
        ["Content-Type"]   = "application/json",
        ["Content-Length"] = #body,
    },
    source = ltn12.source.string(body),
    sink   = ltn12.sink.table(chunks),
}

Subscriptions

For recurring plans, use create_subscription and check_subscription instead. The flow is identical — create → redirect → verify.

// Create subscription checkout
const res = await fetch('https://vaneltonmedia.com/api/pay/create_subscription.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), itemKey: 'plan-pro', currency: 'brl' })
});
const { subscription_url } = await res.json();
window.location.href = subscription_url;

// Check active subscription
const check = await fetch('https://vaneltonmedia.com/api/pay/check_subscription.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), itemKey: 'plan-pro' })
});
const { active, subscription } = await check.json();
if (active) console.log('Renews:', subscription.current_period_end);
// Create subscription checkout
const res = await fetch('https://vaneltonmedia.com/api/pay/create_subscription.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), itemKey: 'plan-pro', currency: 'brl' })
});
const { subscription_url } = await res.json();
window.location.href = subscription_url;

// Check active subscription
const check = await fetch('https://vaneltonmedia.com/api/pay/check_subscription.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), itemKey: 'plan-pro' })
});
const { active, subscription } = await check.json();
if (active) console.log('Renews:', subscription.current_period_end);
// Create subscription
$ch = curl_init('https://vaneltonmedia.com/api/pay/create_subscription.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['token' => $_SESSION['vm_token'], 'itemKey' => 'plan-pro', 'currency' => 'brl']),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
header('Location: ' . $result['subscription_url']); exit;
# Create subscription
res = requests.post(
    'https://vaneltonmedia.com/api/pay/create_subscription.php',
    headers={'Authorization': f'{APP_ID}:{APP_KEY}', 'Content-Type': 'application/json'},
    json={'token': token, 'itemKey': 'plan-pro', 'currency': 'brl'}
)
subscription_url = res.json()['subscription_url']

# Check active subscription
check = requests.post(
    'https://vaneltonmedia.com/api/pay/check_subscription.php',
    headers={'Authorization': f'{APP_ID}:{APP_KEY}', 'Content-Type': 'application/json'},
    json={'token': token, 'itemKey': 'plan-pro'}
).json()
if check['active']:
    print('Renews:', check['subscription']['current_period_end'])
# Create subscription checkout
curl -s -X POST "https://vaneltonmedia.com/api/pay/create_subscription.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\",\"itemKey\":\"plan-pro\",\"currency\":\"brl\"}"

# Check active subscription
curl -s -X POST "https://vaneltonmedia.com/api/pay/check_subscription.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\",\"itemKey\":\"plan-pro\"}"
// Create subscription checkout
var subPayload = JsonSerializer.Serialize(new { token, itemKey = "plan-pro", currency = "brl" });
using var subRes = await client.PostAsync(
    "https://vaneltonmedia.com/api/pay/create_subscription.php",
    new StringContent(subPayload, Encoding.UTF8, "application/json"));
using var subDoc = JsonDocument.Parse(await subRes.Content.ReadAsStringAsync());
var subscriptionUrl = subDoc.RootElement.GetProperty("subscription_url").GetString();

// Check active subscription
var chkPayload = JsonSerializer.Serialize(new { token, itemKey = "plan-pro" });
using var chkRes = await client.PostAsync(
    "https://vaneltonmedia.com/api/pay/check_subscription.php",
    new StringContent(chkPayload, Encoding.UTF8, "application/json"));
using var chkDoc = JsonDocument.Parse(await chkRes.Content.ReadAsStringAsync());
bool active = chkDoc.RootElement.GetProperty("active").GetBoolean();
-- Create subscription checkout
local function pay_post(endpoint, body_tbl)
    local body   = json.encode(body_tbl)
    local chunks = {}
    http.request {
        url    = "https://vaneltonmedia.com/api/pay/" .. endpoint,
        method = "POST",
        headers = {
            ["Authorization"]  = APP_ID .. ":" .. APP_KEY,
            ["Content-Type"]   = "application/json",
            ["Content-Length"] = #body,
        },
        source = ltn12.source.string(body),
        sink   = ltn12.sink.table(chunks),
    }
    return json.decode(table.concat(chunks))
end

local sub    = pay_post("create_subscription.php", { token = token, itemKey = "plan-pro", currency = "brl" })
local check  = pay_post("check_subscription.php",  { token = token, itemKey = "plan-pro" })
if check.active then
    print("Renews:", check.subscription.current_period_end)
end

Error reference

CodeMessageCause
400Missing required parameter 'itemKey'.itemKey not sent
401Invalid or expired token.Bad user token
500Failed to create payment link.Invalid itemKey or Stripe error