Xero API using CodeIgniter controller.php

49 Views Asked by At

I got this error

Array ( [Type] => [Title] => Forbidden [Status] => 403 [Detail] => AuthenticationUnsuccessful [Instance] => 114c05dd-3284-43bb-890f-223999170169 [Extensions] => Array ( ) )

is there some wrong in my code? or my App in Xero is not working? or it needs to be configured?

I want to pull the data of the Invoice in Xero API

<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Overdueinvoice extends MY_Controller
{
    private $client_id;
    private $client_secret;
    private $redirect_uri;
    private $authorization_endpoint;
    private $token_endpoint;
    private $scopes;
    private $state;
    private $xero_tenant_id;

    public function __construct()
    {
        parent::__construct();
        $this->load->helper('url');
        
        // Initialize your OAuth 2.0 credentials here
        $this->client_id = 'YOUR_CLIENT_ID';
        $this->client_secret = 'YOUR_CLIENT_SECRET';
        $this->redirect_uri = 'YOUR_REDIRECT_URI';
        $this->authorization_endpoint = 'https://login.xero.com/identity/connect/authorize';
        $this->token_endpoint = 'https://identity.xero.com/connect/token';
        $this->scopes = 'offline_access openid profile email accounting.transactions';
        $this->state = '123';
        $this->xero_tenant_id = 'YOUR_XERO_TENANT_ID';
    }

    public function index()
    {
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
        header("Access-Control-Allow-Headers: Content-Type, Authorization");

        if (isset($_GET['code'])) {
            $this->handleXeroAuthorization();
        } else {
            $this->redirectToXeroAuthorization();
        }
        $data["title"] = "Overdue Invoices | Tremendio Portal";
        $data["pagename"] = "Overdue Invoices";

        $this->load_page2("overdueinvoice", $data, "overdueinvoice_footer.php", "overdueinvoice_header.php");
    }

    private function handleXeroAuthorization()
    {
        // Xero OAuth 2.0 Credentials
        $client_id = $this->client_id;
        $client_secret = $this->client_secret;
        $redirect_uri = $this->redirect_uri;
        $authorization_endpoint = $this->authorization_endpoint;
        $token_endpoint = $this->token_endpoint;
        $scopes = $this->scopes;
        $state = $this->state;
        $xero_tenant_id = $this->xero_tenant_id; // Get the Xero tenant ID

        // Step 1: Handle the callback with the authorization code
        $authorization_code = $_GET['code'];

        // Step 2: Exchange the authorization code for an access token
        $token_request = array(
            'grant_type' => 'authorization_code',
            'code' => $authorization_code,
            'redirect_uri' => $redirect_uri,
        );

        $curl = curl_init($token_endpoint);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($token_request));
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Authorization: Basic ' . base64_encode($client_id . ':' . $client_secret),
        ));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

        $token_response = curl_exec($curl);
        curl_close($curl);

        // Step 3: Handle the access token and make API requests with it
        $token_data = json_decode($token_response, true);

        if (isset($token_data['access_token'])) {
            // Access token acquired, use it to make API requests, including the Xero tenant ID
            $access_token = $token_data['access_token'];

            // Store the access token and possibly the refresh token in your session
            $this->session->set_userdata('access_token', $access_token);
            $this->session->set_userdata('refresh_token', $token_data['refresh_token']);

            // Continue with your existing CodeIgniter code to fetch Xero data using the access token and tenant ID
            $api_url = 'https://api.xero.com/api.xro/2.0/Invoices?tenantId=' . $xero_tenant_id;

            $headers = array(
                'Authorization: Bearer ' . $access_token,
                'Content-Type: application/json',
            );

            $ch = curl_init($api_url);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            $response = curl_exec($ch);
            curl_close($ch);

            // Process and use the $response data as needed

            // You can return the data or do further processing here
            $data['xero_data'] = json_decode($response, true); // Assuming the response is JSON
        } else {
            // Handle the case where access token retrieval failed
            echo 'Access token retrieval failed';
        }

        $this->load->view('overdueinvoice', $data);
    }

    private function redirectToXeroAuthorization()
    {
        // Step 4: Redirect the user to Xero's authorization page with scopes and state
        // Use class-level properties, not local variables
        $client_id = $this->client_id;
        $client_secret = $this->client_secret;
        $redirect_uri = $this->redirect_uri;
        $authorization_endpoint = $this->authorization_endpoint;
        $token_endpoint = $this->token_endpoint;
        $scopes = $this->scopes;
        $state = $this->state;

        // The rest of your code remains the same
        $authorize_url = $this->authorization_endpoint . '?client_id=' . $client_id . '&redirect_uri=' . $redirect_uri . '&response_type=code&scope=' . $scopes . '&state=' . $state;
        header('Location: ' . $authorize_url);
        exit;
    }
}
1

There are 1 best solutions below

2
On

Using the instance id 114c05dd-3284-43bb-890f-223999170169 that you received in the response, I can see that the 403 error was thrown because the tenantID is missing from the request's header.