Files
html/api/stripe-live-bridge.php
2026-04-18 15:40:02 +02:00

150 lines
6.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Stripe Live Bridge v1.0 · 18 avril 2026
*
* Reads real Stripe credentials from /etc/weval/secrets.env
* Fetches MRR / ARR / customers / subscriptions from live Stripe account
* Returns v83-business-kpi compatible format
*
* GOLD: nouveau fichier, zero modif existant
* Source: Stripe API (live mode, acct_1RviYXCpdcPNJE6S)
*/
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('X-Stripe-Bridge: v1.0');
$t0 = microtime(true);
// ========== 1. Load secrets ==========
$secrets_file = '/etc/weval/secrets.env';
if (!is_readable($secrets_file)) {
http_response_code(500);
echo json_encode(['ok'=>false, 'error'=>'secrets_unreadable', 'source'=>$secrets_file]);
exit;
}
$secrets_raw = @file_get_contents($secrets_file);
preg_match('/STRIPE_SK_LIVE=([^\s\n]+)/', $secrets_raw, $mk);
$sk = $mk[1] ?? '';
preg_match('/STRIPE_ACCOUNT=([^\s\n]+)/', $secrets_raw, $ma);
$acct = $ma[1] ?? '';
if (empty($sk) || !str_starts_with($sk, 'sk_live_')) {
http_response_code(500);
echo json_encode(['ok'=>false, 'error'=>'invalid_key', 'livemode'=>false]);
exit;
}
// ========== 2. Helper: call Stripe API ==========
function stripe_get($sk, $path, $params = []) {
$url = 'https://api.stripe.com/v1/' . ltrim($path, '/');
if ($params) $url .= '?' . http_build_query($params);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => $sk . ':',
CURLOPT_TIMEOUT => 6,
CURLOPT_HTTPHEADER => ['Stripe-Version: 2024-12-18.acacia'],
]);
$r = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ['code' => $code, 'data' => json_decode($r, true)];
}
// ========== 3. Cache layer (60s TTL) ==========
$cache_file = '/tmp/stripe-live-cache.json';
$cache_ttl = 60;
if (is_readable($cache_file) && (time() - filemtime($cache_file)) < $cache_ttl) {
$cached = @json_decode(@file_get_contents($cache_file), true);
if ($cached && !isset($_GET['nocache'])) {
$cached['cached'] = true;
$cached['elapsed_ms'] = round((microtime(true) - $t0) * 1000, 1);
echo json_encode($cached, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
exit;
}
}
// ========== 4. Fetch live data ==========
$balance = stripe_get($sk, 'balance');
$customers = stripe_get($sk, 'customers', ['limit' => 100]);
$subs = stripe_get($sk, 'subscriptions', ['limit' => 100, 'status' => 'active']);
$invoices = stripe_get($sk, 'invoices', ['limit' => 20, 'status' => 'paid']);
// ========== 5. Compute KPIs ==========
$customer_list = $customers['data']['data'] ?? [];
$active_customer_count = count($customer_list);
$active_subs = $subs['data']['data'] ?? [];
$mrr_cents = 0;
$currency = 'eur';
foreach ($active_subs as $s) {
foreach (($s['items']['data'] ?? []) as $item) {
$unit = $item['price']['unit_amount'] ?? 0;
$interval = $item['price']['recurring']['interval'] ?? 'month';
$qty = $item['quantity'] ?? 1;
// Normalize to month
$monthly = ($interval === 'year') ? $unit / 12 : $unit;
$mrr_cents += $monthly * $qty;
$currency = $item['price']['currency'] ?? 'eur';
}
}
$mrr = round($mrr_cents / 100, 2);
$arr = round($mrr * 12, 2);
// Invoices total paid (revenue YTD)
$revenue_paid_cents = 0;
foreach (($invoices['data']['data'] ?? []) as $inv) {
if (($inv['status'] ?? '') === 'paid') {
$revenue_paid_cents += $inv['amount_paid'] ?? 0;
}
}
$revenue_paid = round($revenue_paid_cents / 100, 2);
// Balance
$bal = $balance['data']['available'][0] ?? [];
$balance_available = ($bal['amount'] ?? 0) / 100;
$balance_currency = $bal['currency'] ?? 'usd';
$livemode = $balance['data']['livemode'] ?? false;
// ========== 6. Build response (v83 compatible) ==========
$output = [
'ok' => true,
'source' => 'Stripe Live API',
'account' => $acct,
'livemode' => $livemode,
'currency' => strtoupper($currency),
'ts' => date('c'),
'cached' => false,
'kpis' => [
'mrr' => ['value' => $mrr, 'unit' => strtoupper($currency), 'target' => 50000, 'status' => $mrr >= 50000 ? 'ok' : ($mrr > 0 ? 'warn' : 'starting'), 'source' => 'Stripe subscriptions active'],
'arr' => ['value' => $arr, 'unit' => strtoupper($currency), 'target' => 600000, 'status' => $arr >= 600000 ? 'ok' : ($arr > 0 ? 'warn' : 'starting'), 'source' => 'MRR × 12'],
'active_customers' => ['value' => $active_customer_count, 'unit' => 'clients', 'target' => 20, 'status' => $active_customer_count >= 20 ? 'ok' : ($active_customer_count > 0 ? 'warn' : 'starting'), 'source' => 'Stripe customers'],
'active_subscriptions' => ['value' => count($active_subs), 'unit' => 'subs', 'target' => 20, 'status' => count($active_subs) >= 20 ? 'ok' : (count($active_subs) > 0 ? 'warn' : 'starting'), 'source' => 'Stripe subs active'],
'revenue_paid_recent' => ['value' => $revenue_paid, 'unit' => strtoupper($currency), 'target' => null, 'status' => 'info', 'source' => '20 last paid invoices'],
'balance_available' => ['value' => $balance_available, 'unit' => strtoupper($balance_currency), 'target' => null, 'status' => 'info', 'source' => 'Stripe balance'],
],
'customers_sample' => array_slice(array_map(function($c) {
return [
'id' => $c['id'] ?? '?',
'email' => $c['email'] ?? '?',
'name' => $c['name'] ?? '?',
'created' => date('Y-m-d', $c['created'] ?? 0),
];
}, $customer_list), 0, 10),
'badge' => [
'color' => $mrr > 0 ? '#10b981' : '#f59e0b',
'label' => $mrr > 0 ? sprintf('MRR %s%d', strtoupper($currency), $mrr) : 'Starting phase',
'phase' => $mrr >= 50000 ? 'scaling' : ($mrr > 0 ? 'validating' : 'launching'),
],
'honest_note' => $active_customer_count > 0 ?
sprintf('WEVAL Consulting SaaS · %d customer(s) · MRR %s%.2f · live Stripe data', $active_customer_count, strtoupper($currency), $mrr) :
'SaaS phase: no paying customer yet · integration ready · Stripe live connected',
'elapsed_ms' => round((microtime(true) - $t0) * 1000, 1),
];
// Cache result
@file_put_contents($cache_file, json_encode($output));
echo json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);