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
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
| Code | Message | Cause |
|---|---|---|
| 400 | Missing required parameter 'itemKey'. | itemKey not sent |
| 401 | Invalid or expired token. | Bad user token |
| 500 | Failed to create payment link. | Invalid itemKey or Stripe error |