Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- declare(strict_types=1);
- /**
- * Global Payments webhook endpoint.
- *
- * Responsibilities:
- * - Accepts POSTed JSON from Global Payments webhooks
- * - Logs request (headers + payload) into a daily logfile
- * - Extracts business fields from _embedded.itemsPaid[0].myMetadata.data
- * - Saves a row into payment_provider_payment_log per mapping provided
- * - Emails a debug dump
- * - Returns JSON flags + extracted data
- */
- $ignoreAuth = true;
- require_once dirname(__FILE__) . '/../config/globals.php';
- use iMedicWare\PaymentProvider\PaymentProviderHelper;
- use PHPMailer\PHPMailer\PHPMailer;
- use PHPMailer\PHPMailer\Exception;
- /**
- * Safely get header array in environments without getallheaders().
- */
- if (!function_exists('getallheaders')) {
- function getallheaders(): array {
- $headers = [];
- foreach ($_SERVER as $name => $value) {
- if (strncmp($name, 'HTTP_', 5) === 0) {
- $key = str_replace('_', '-', ucwords(strtolower(substr($name, 5)), '_'));
- $headers[$key] = $value;
- } elseif ($name === 'CONTENT_TYPE') {
- $headers['Content-Type'] = $value;
- } elseif ($name === 'CONTENT_LENGTH') {
- $headers['Content-Length'] = $value;
- }
- }
- return $headers;
- }
- }
- /**
- * Render scalar for logs. (No PHP 8 "mixed" type-hint here for PHP 7.3 compatibility.)
- */
- function scalarToString($value): string
- {
- if ($value === null) return 'null';
- if ($value === true) return 'true';
- if ($value === false) return 'false';
- if (is_int($value) || is_float($value)) return (string)$value;
- return (string)$value;
- }
- /**
- * Extracts nested meta data from webhook payload.
- *
- * Returns array with keys:
- * patientId, orderId, operatorId, scheduleId, facilityId, encounterId
- */
- function extractMetaFromPayload(array $decoded): array
- {
- $itemsPaid = isset($decoded['_embedded']['itemsPaid']) ? $decoded['_embedded']['itemsPaid'] : null;
- $meta = null;
- if (is_array($itemsPaid) && isset($itemsPaid[0]) && is_array($itemsPaid[0])) {
- if (isset($itemsPaid[0]['myMetadata']['data']) && is_array($itemsPaid[0]['myMetadata']['data'])) {
- $meta = $itemsPaid[0]['myMetadata']['data'];
- } elseif (isset($itemsPaid[0]['my_metadata']['data']) && is_array($itemsPaid[0]['my_metadata']['data'])) {
- $meta = $itemsPaid[0]['my_metadata']['data'];
- }
- }
- return [
- 'patientId' => $meta['patientId'] ?? null,
- 'orderId' => $meta['orderId'] ?? null,
- 'operatorId' => $meta['operatorId'] ?? null,
- 'scheduleId' => $meta['scheduleId'] ?? null,
- 'facilityId' => $meta['facilityId'] ?? null,
- 'encounterId' => $meta['encounterId'] ?? null,
- ];
- }
- /**
- * Convert an ISO 8601 datetime string (e.g., "2025-08-11T21:54:26.422Z")
- * into MySQL DATETIME ("Y-m-d H:i:s") in UTC.
- */
- function isoToMysqlDateTime(?string $iso): ?string
- {
- if (!$iso) return null;
- $ts = strtotime($iso);
- if ($ts === false) return null;
- return gmdate('Y-m-d H:i:s', $ts);
- }
- // -------------------------------
- // Flags / state
- // -------------------------------
- $received = false;
- $logged = false;
- $emailSent = false;
- $emailError = '';
- $dbSaved = false;
- $dbError = '';
- $extracted = [
- 'patientId' => null,
- 'orderId' => null,
- 'operatorId' => null,
- 'scheduleId' => null,
- 'facilityId' => null,
- 'encounterId' => null,
- ];
- // -------------------------------
- // Main
- // -------------------------------
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- $received = true;
- // 1) Raw body and JSON decode
- $rawPayload = file_get_contents('php://input');
- $decoded = json_decode($rawPayload, true);
- $payloadForLog = (json_last_error() === JSON_ERROR_NONE) ? print_r($decoded, true) : $rawPayload;
- // 2) Extract business fields if JSON
- if (is_array($decoded)) {
- $extracted = extractMetaFromPayload($decoded);
- }
- // 3) Read headers
- $headers = getallheaders();
- // 4) Log file path
- $logFile = __DIR__ . '/webhook_test_' . date('Y-m-d') . '.log';
- // 5) Build log entry
- $logEntry = "==== Webhook Received at " . date('Y-m-d H:i:s') . " ====" . PHP_EOL;
- $logEntry .= "Remote IP: " . ($_SERVER['REMOTE_ADDR'] ?? 'n/a') . PHP_EOL;
- $logEntry .= "Headers:" . PHP_EOL . print_r($headers, true);
- $logEntry .= "Payload:" . PHP_EOL . $payloadForLog . PHP_EOL;
- // 5a) Also log extracted + key mapped fields we will save
- $logEntry .= "Extracted (from _embedded.itemsPaid[0].myMetadata.data):" . PHP_EOL;
- foreach ($extracted as $k => $v) {
- $logEntry .= " {$k}: " . scalarToString($v) . PHP_EOL;
- }
- // 5b) Prepare DB mapping values per your specification
- $prettyAmount = is_array($decoded) ? ($decoded['prettyAmount'] ?? null) : null;
- $referenceId = is_array($decoded) ? ($decoded['referenceId'] ?? null) : null;
- $originalTransactionId = is_array($decoded) ? ($decoded['id'] ?? null) : null;
- $paymentType = is_array($decoded) ? ($decoded['paymentType'] ?? null) : null;
- $capturedDate = is_array($decoded) ? ($decoded['capturedDate'] ?? null) : null;
- $timestampMySQL = isoToMysqlDateTime($capturedDate);
- $clientId = is_array($decoded) ? ($decoded['_embedded']['customer']['id'] ?? null) : null;
- $cardBrand = is_array($decoded) ? ($decoded['cardBrand'] ?? null) : null;
- $cardLast4 = is_array($decoded) ? ($decoded['cardLast4'] ?? null) : null;
- $paymentProvider = PaymentProviderHelper::GLOBAL_PAYMENTS;
- // Action and section per request
- $action = 'Purchase';
- $sectionType = 'servicecharge';
- $actionContext = 'Webhook';
- // $actionContext = 'SAIL';
- // 6) Append mapping preview to log
- $logEntry .= "DB Mapping Preview:" . PHP_EOL;
- $logEntry .= " patientId: " . scalarToString($extracted['patientId']) . PHP_EOL;
- $logEntry .= " operator_id (authId): " . scalarToString($extracted['operatorId']) . PHP_EOL;
- $logEntry .= " scheduleID: " . scalarToString($extracted['scheduleId']) . PHP_EOL;
- $logEntry .= " facility_id: " . scalarToString($extracted['facilityId']) . PHP_EOL;
- $logEntry .= " encounterId: " . scalarToString($extracted['encounterId']) . PHP_EOL;
- $logEntry .= " amount (prettyAmount): " . scalarToString($prettyAmount) . PHP_EOL;
- $logEntry .= " action: " . $action . PHP_EOL;
- $logEntry .= " transactionId: " . scalarToString($referenceId) . PHP_EOL;
- $logEntry .= " originalTransactionId: " . scalarToString($originalTransactionId) . PHP_EOL;
- $logEntry .= " payMethod (paymentType): " . scalarToString($paymentType) . PHP_EOL;
- $logEntry .= " timestamp (capturedDate->MySQL): " . scalarToString($timestampMySQL) . PHP_EOL;
- $logEntry .= " clientId (_embedded.customer.id): " . scalarToString($clientId) . PHP_EOL;
- $logEntry .= " section_type: " . $sectionType . PHP_EOL;
- $logEntry .= " account_type (cardBrand): " . scalarToString($cardBrand) . PHP_EOL;
- $logEntry .= " account_number (cardLast4): " . scalarToString($cardLast4) . PHP_EOL;
- $logEntry .= " actionContext: " . $actionContext . PHP_EOL;
- $logEntry .= " payment_provider: " . scalarToString($paymentProvider) . PHP_EOL . PHP_EOL;
- // 7) Write log
- $bytes = file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
- if ($bytes !== false) {
- $logged = true;
- }
- // 8) Insert into DB (payment_provider_payment_log)
- try {
- $plog_req_qry = "INSERT INTO payment_provider_payment_log SET
- patientId = ?,
- operator_id = ?,
- scheduleID = ?,
- facility_id = ?,
- encounterId = ?,
- amount = ?,
- action = ?,
- transactionId = ?,
- originalTransactionId = ?,
- payMethod = ?,
- transaction_date = '" . date('Y-m-d H:i:s') . "',
- timestamp = ?,
- serviceDate = '" . date('Y-m-d') . "',
- clientId = ?,
- section_type = ?,
- account_type = ?,
- account_number = ?,
- actionContext = ?,
- payment_provider = ?";
- $params = [
- $extracted['patientId'], // patientId
- $extracted['operatorId'], // operator_id (authId)
- $extracted['scheduleId'], // scheduleID
- $extracted['facilityId'], // facility_id (loggedInFacility)
- $extracted['encounterId'], // encounterId
- $prettyAmount, // amount
- $action, // action
- $referenceId, // transactionId
- $originalTransactionId, // originalTransactionId
- $paymentType, // payMethod
- $timestampMySQL ?: date('Y-m-d H:i:s'),// timestamp (fallback to now if missing)
- $clientId, // clientId
- $sectionType, // section_type
- $cardBrand, // account_type
- $cardLast4, // account_number
- $actionContext, // actionContext
- $paymentProvider // payment_provider
- ];
- $dbRes = imwQuery($plog_req_qry, $params);
- if ($dbRes === false) {
- if (function_exists('imw_error')) {
- $dbError = 'DB insert failed: ' . imw_error();
- } else {
- $dbError = 'DB insert failed: unknown error';
- }
- } else {
- $dbSaved = true;
- }
- } catch (Throwable $t) {
- $dbError = 'Exception during DB insert: ' . $t->getMessage();
- file_put_contents(
- $logFile,
- "==== DB Error at " . date('Y-m-d H:i:s') . " ====\n{$dbError}\n\n",
- FILE_APPEND | LOCK_EX
- );
- }
- // 9) Send debug email with everything
- try {
- $mail = new PHPMailer(true);
- $mail->isSMTP();
- $mail->Host = 'smtp.office365.com';
- $mail->SMTPAuth = true;
- $mail->Password = 'G)147559698280ah';
- $mail->SMTPSecure = 'tls';
- $mail->Port = 587;
- $mail->Subject = 'Webhook Debug: ' . date('Y-m-d H:i:s');
- $bodyText = "Webhook received at " . date('Y-m-d H:i:s') . "\n\n";
- $bodyText .= "Remote IP: " . ($_SERVER['REMOTE_ADDR'] ?? 'n/a') . "\n\n";
- $bodyText .= "Headers:\n" . print_r($headers, true) . "\n";
- $bodyText .= "Payload:\n" . $payloadForLog . "\n";
- $bodyText .= "Extracted:\n" . print_r($extracted, true) . "\n";
- $bodyText .= "DB Saved: " . ($dbSaved ? 'true' : 'false') . "\n";
- if (!$dbSaved && $dbError) {
- $bodyText .= "DB Error: " . $dbError . "\n";
- }
- $mail->Body = nl2br(htmlspecialchars($bodyText));
- $mail->AltBody = $bodyText;
- $mail->send();
- $emailSent = true;
- } catch (Exception $e) {
- $emailError = $e->getMessage();
- file_put_contents(
- $logFile,
- "==== Email Error at " . date('Y-m-d H:i:s') . " ====\n{$emailError}\n\n",
- FILE_APPEND | LOCK_EX
- );
- }
- }
- // JSON response
- http_response_code(200);
- header('Content-Type: application/json');
- $response = [
- 'status' => 'success',
- 'received' => $received,
- 'logged' => $logged,
- 'emailSent' => $emailSent,
- 'dbSaved' => $dbSaved,
- 'extracted' => $extracted,
- ];
- if ($received && !$logged) { $response['logError'] = 'Failed to write log file'; }
- if ($received && !$emailSent) { $response['emailError'] = $emailError; }
- if ($received && !$dbSaved) { $response['dbError'] = $dbError; }
- echo json_encode($response);
Advertisement
Add Comment
Please, Sign In to add comment