$method, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 30, CURLOPT_FOLLOWLOCATION => false]); if ($body !== null) curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body, JSON_THROW_ON_ERROR)); $raw = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); if ($raw === false) throw new RuntimeException('Connection failed. Retry the same payment with its existing idempotency UUID.'); $response = json_decode($raw, true, 512, JSON_THROW_ON_ERROR); if ($status < 200 || $status >= 300) throw new RuntimeException(($response['code'] ?? 'request_failed').': '.($response['message'] ?? '').' Request ID: '.($response['request_id'] ?? '')); return $response['data']; } $bytes = random_bytes(16); $bytes[6] = chr((ord($bytes[6]) & 15) | 64); $bytes[8] = chr((ord($bytes[8]) & 63) | 128); $hex = bin2hex($bytes); $uuid = substr($hex,0,8).'-'.substr($hex,8,4).'-'.substr($hex,12,4).'-'.substr($hex,16,4).'-'.substr($hex,20); // Persist this UUID with the order before sending. Keep it for all retries of this payment. $payment = nuepay('POST', '/collections', ['amount'=>'500.00', 'currency'=>'UGX', 'phone'=>'0772000000', 'merchant_reference'=>'example-order'], $uuid); $result = nuepay('POST', '/sandbox/transactions/'.$payment['reference'].'/simulate', ['outcome'=>'success']); echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR).PHP_EOL;