initiatePayment( $user_id, $item_id, $quantity /*, $metadata_array */ ); // Example modification return $result; // Return whatever the gateway method returns (e.g., session ID, URL, WP_Error) } // If no active or supported gateway found return new \WP_Error( 'no_gateway', \__( 'No active or supported payment gateway configured.', 'quiztech' ) ); } /** * Handle incoming payment gateway webhooks. * This needs to be registered as a REST endpoint or admin-ajax handler. */ function quiztech_handle_payment_webhook() { // --- Implementation Required --- // Identify the gateway. This typically requires unique endpoints per gateway. // Example: Register '/webhook/stripe' and '/webhook/paypal'. The endpoint itself identifies the gateway. $gateway_slug = 'stripe'; // Placeholder: Determine dynamically based on the requested endpoint. if ( 'stripe' === $gateway_slug ) { $payload = @file_get_contents('php://input'); $signature = isset($_SERVER['HTTP_STRIPE_SIGNATURE']) ? $_SERVER['HTTP_STRIPE_SIGNATURE'] : ''; if ( empty($payload) || empty($signature) ) { \wp_send_json_error( 'Missing payload or signature for Stripe webhook.', 400 ); return; // Exit } $gateway = new StripeGateway(); $handled = $gateway->handleWebhook( $payload, $signature ); if ( $handled ) { // The handleWebhook method should call quiztech_process_successful_payment internally if needed. \wp_send_json_success( 'Webhook processed.', 200 ); } else { \wp_send_json_error( 'Stripe webhook verification or processing failed.', 400 ); } return; // Exit } // Handle other gateways or errors if no matching gateway found \wp_send_json_error( 'Invalid or unsupported webhook request.', 400 ); } // --- Implementation Required --- // Register the webhook handler(s) using WordPress REST API (recommended for webhooks). // Example (needs proper implementation, likely in a dedicated class or main plugin file): // add_action( 'rest_api_init', function () { // register_rest_route( 'quiztech/v1', '/webhook/stripe', array( // Use gateway-specific endpoint // 'methods' => 'POST', // 'callback' => 'quiztech_handle_payment_webhook', // 'permission_callback' => '__return_true' // IMPORTANT: Implement proper permission checks! // ) ); // } ); /** * Process a successful payment notification from a gateway webhook. * This function is typically called *by* the gateway-specific webhook handler. * * @param int $user_id The user ID who made the purchase. * @param int $credits_purchased The number of credits purchased. * @param string $transaction_id The gateway's transaction ID. * @param string $gateway_slug Slug of the gateway (e.g., 'stripe'). * @return bool True on success, false on failure. */ function quiztech_process_successful_payment( $user_id, $credits_purchased, $transaction_id, $gateway_slug ) { if ( ! $user_id || ! $credits_purchased > 0 || empty( $transaction_id ) || empty( $gateway_slug ) ) { // Log error: Invalid data received for payment processing. return false; } // --- Implementation Required --- // Add checks to prevent processing the same transaction ID multiple times. // This typically involves: // 1. Storing processed transaction IDs (e.g., in post meta on the user_evaluation, a dedicated log table, or user meta). // 2. Querying this storage before updating the balance. If the ID exists, return true (or log) without updating again. // 3. Saving the transaction ID after successfully updating the balance. // Update the user's credit balance $result = quiztech_update_user_credit_balance( $user_id, (int) $credits_purchased, \sprintf( '%s_purchase_%s', $gateway_slug, $transaction_id ) ); if ( false !== $result ) { // Optional: Log successful transaction details somewhere (custom table?) // Optional: Send purchase confirmation email to user // do_action('quiztech_credits_purchased', $user_id, $credits_purchased, $transaction_id, $gateway_slug); return true; } else { // Log error: Failed to update credit balance for user $user_id after successful payment $transaction_id. return false; } } ?>