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`).
269 lines
9.1 KiB
PHP
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';
|
|
}
|
|
}
|