Files
api/services/nginx/app/classes/stripe_fake_http_client.php
T
Jeppe Bundgaard 7d450e285e Remove outdated edge gateway object classes, add new agent implementation
Transitioned from obsolete gateway object classes (`edge_gateway_shell_action_jobs_o`, `edge_gateway_shell_events_o`, `edge_gateway_shell_sessions_o`, `edge_gateway_update_jobs_o`) to the new agent implementation (`edge-gateway-agent/agent.php`).
2026-04-21 14:13:17 +02:00

269 lines
9.1 KiB
PHP

<?php
namespace classes;
use Stripe\HttpClient\ClientInterface;
class stripe_fake_http_client implements ClientInterface
{
private const DEFAULT_STATE = [
'next_customer' => 1,
'next_price' => 1,
'next_invoice' => 1,
'next_invoice_item' => 1,
'customers' => [],
'prices' => [],
'products' => [],
'invoice_items' => [],
'invoices' => [],
];
public static function resetStore(): void
{
self::writeStore(self::DEFAULT_STATE);
}
public static function setInvoiceState(string $invoiceId, array $attributes): void
{
$store = self::readStore();
$invoice = $store['invoices'][$invoiceId] ?? null;
if (!$invoice) {
return;
}
$store['invoices'][$invoiceId] = [
...$invoice,
...$attributes,
];
self::writeStore($store);
}
public function request($method, $absUrl, $headers, $params, $hasFile, $apiMode = 'v1')
{
$path = (string)parse_url((string)$absUrl, PHP_URL_PATH);
$store = self::readStore();
if ($method === 'post' && $path === '/v1/customers') {
$customerId = sprintf('cus_fake_%06d', (int)$store['next_customer']);
$store['next_customer']++;
$customer = [
'id' => $customerId,
'object' => 'customer',
'email' => (string)($params['email'] ?? ''),
];
$store['customers'][$customerId] = $customer;
self::writeStore($store);
return $this->jsonResponse($customer);
}
if ($method === 'get' && preg_match('#^/v1/customers/(?P<id>[^/]+)$#', $path, $matches)) {
$customer = $store['customers'][$matches['id']] ?? null;
if (!$customer) {
return $this->errorResponse(404, 'resource_missing', 'No such customer.');
}
return $this->jsonResponse($customer);
}
if ($method === 'get' && preg_match('#^/v1/products/(?P<id>[^/]+)$#', $path, $matches)) {
$product = $store['products'][$matches['id']] ?? null;
if (!$product) {
return $this->errorResponse(404, 'resource_missing', 'No such product.');
}
return $this->jsonResponse($product);
}
if ($method === 'post' && $path === '/v1/products') {
$productId = (string)($params['id'] ?? sprintf('prod_fake_%06d', count($store['products']) + 1));
$product = [
'id' => $productId,
'object' => 'product',
'name' => (string)($params['name'] ?? 'Fake Product'),
];
$store['products'][$productId] = $product;
self::writeStore($store);
return $this->jsonResponse($product);
}
if ($method === 'post' && $path === '/v1/prices') {
$priceId = sprintf('price_fake_%06d', (int)$store['next_price']);
$store['next_price']++;
$price = [
'id' => $priceId,
'object' => 'price',
'product' => (string)($params['product'] ?? ''),
'unit_amount' => (int)($params['unit_amount'] ?? 0),
'currency' => strtolower((string)($params['currency'] ?? 'dkk')),
];
$store['prices'][$priceId] = $price;
self::writeStore($store);
return $this->jsonResponse($price);
}
if ($method === 'post' && $path === '/v1/invoices') {
$invoiceId = sprintf('in_fake_%06d', (int)$store['next_invoice']);
$store['next_invoice']++;
$invoice = [
'id' => $invoiceId,
'object' => 'invoice',
'customer' => (string)($params['customer'] ?? ''),
'status' => 'draft',
'paid' => false,
'amount_due' => 0,
'amount_paid' => 0,
'collection_method' => (string)($params['collection_method'] ?? 'send_invoice'),
'hosted_invoice_url' => sprintf('https://stripe.test/invoices/%s', $invoiceId),
'metadata' => is_array($params['metadata'] ?? null) ? $params['metadata'] : [],
'lines' => [],
];
$store['invoices'][$invoiceId] = $invoice;
self::writeStore($store);
return $this->jsonResponse($invoice);
}
if ($method === 'post' && $path === '/v1/invoiceitems') {
$invoiceId = (string)($params['invoice'] ?? '');
$invoice = $store['invoices'][$invoiceId] ?? null;
if (!$invoice) {
return $this->errorResponse(404, 'resource_missing', 'No such invoice.');
}
$invoiceItemId = sprintf('ii_fake_%06d', (int)$store['next_invoice_item']);
$store['next_invoice_item']++;
$priceId = (string)($params['price'] ?? '');
$price = $store['prices'][$priceId] ?? ['unit_amount' => 0];
$invoiceItem = [
'id' => $invoiceItemId,
'object' => 'invoiceitem',
'invoice' => $invoiceId,
'customer' => (string)($params['customer'] ?? ''),
'price' => $priceId,
'amount' => (int)($price['unit_amount'] ?? 0),
];
$store['invoice_items'][$invoiceItemId] = $invoiceItem;
$store['invoices'][$invoiceId]['lines'][] = $invoiceItemId;
$store['invoices'][$invoiceId]['amount_due'] += (int)($price['unit_amount'] ?? 0);
self::writeStore($store);
return $this->jsonResponse($invoiceItem);
}
if ($method === 'post' && preg_match('#^/v1/invoices/(?P<id>[^/]+)/finalize$#', $path, $matches)) {
$invoiceId = $matches['id'];
$invoice = $store['invoices'][$invoiceId] ?? null;
if (!$invoice) {
return $this->errorResponse(404, 'resource_missing', 'No such invoice.');
}
$invoice['status'] = 'open';
$store['invoices'][$invoiceId] = $invoice;
self::writeStore($store);
return $this->jsonResponse($invoice);
}
if ($method === 'post' && preg_match('#^/v1/invoices/(?P<id>[^/]+)/void$#', $path, $matches)) {
$invoiceId = $matches['id'];
$invoice = $store['invoices'][$invoiceId] ?? null;
if (!$invoice) {
return $this->errorResponse(404, 'resource_missing', 'No such invoice.');
}
$invoice['status'] = 'void';
$invoice['paid'] = false;
$store['invoices'][$invoiceId] = $invoice;
self::writeStore($store);
return $this->jsonResponse($invoice);
}
if ($method === 'get' && preg_match('#^/v1/invoices/(?P<id>[^/]+)$#', $path, $matches)) {
$invoice = $store['invoices'][$matches['id']] ?? null;
if (!$invoice) {
return $this->errorResponse(404, 'resource_missing', 'No such invoice.');
}
return $this->jsonResponse($invoice);
}
return $this->errorResponse(404, 'resource_missing', 'Unsupported fake Stripe request: ' . $method . ' ' . $path);
}
private function jsonResponse(array $payload, int $status = 200): array
{
return [
json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
$status,
[
'Content-Type' => 'application/json',
'Request-Id' => 'req_fake_stripe',
],
];
}
private function errorResponse(int $status, string $code, string $message): array
{
return [
json_encode([
'error' => [
'type' => 'invalid_request_error',
'code' => $code,
'message' => $message,
],
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
$status,
[
'Content-Type' => 'application/json',
'Request-Id' => 'req_fake_stripe_error',
],
];
}
private static function readStore(): array
{
$path = self::storePath();
if (!is_file($path)) {
return self::DEFAULT_STATE;
}
$json = file_get_contents($path);
if ($json === false || trim($json) === '') {
return self::DEFAULT_STATE;
}
$decoded = json_decode($json, true);
if (!is_array($decoded)) {
return self::DEFAULT_STATE;
}
return [
...self::DEFAULT_STATE,
...$decoded,
];
}
private static function writeStore(array $store): void
{
file_put_contents(
self::storePath(),
json_encode($store, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
);
}
private static function storePath(): string
{
$path = trim((string)getenv('STRIPE_FAKE_STORE_PATH'));
if ($path !== '') {
return $path;
}
return sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'truckwash-stripe-fake-store.json';
}
}