0

I am doing some expermenting with the xero API, however i cant seem to get past the Connect to Xero returning an error

"Sorry, something went wrong Go back and try again. If the issue continues, check out our Status Page."

I have setup my App in the xero dev center

I have tried these 2 repos https://github.com/XeroAPI/xero-node-oauth2-app https://github.com/XeroAPI/node-oauth2-example

Both yeld the same result just an error page, no information in console/dev tools

Any help would be amazing as im completely stuck with this

Paladin
  • 3
  • 2

2 Answers2

0

So that looks like the error you get when either API keys and/or callback urls are not setup correctly.

Have you swapped in all your api keys & callback urls to the .env (environment) files?

Create a .env file in the root of your project & replace the 3 variables

Create an .env file in the root of your project using touch .env or edit the sample prefix off sample.env and change out with your /myapps credentials of the app you just made.

CLIENT_ID=...
CLIENT_SECRET=...
REDIRECT_URI=...
SerKnight
  • 2,502
  • 1
  • 16
  • 18
  • Thanks for the response Christopher, xero support got back to me and the only difference was a / at the end of the URL they must be exactly the same. however even after that the login works, i can auth a company but this app https://github.com/XeroAPI/xero-node-oauth2-app isnt getting or storing the token. as if you try and then complete an action it asks you to reauth – Paladin Feb 11 '20 at 23:10
  • Paladin - yes thats because it is a typescript app and when it recompiles - the session clears.. I will add an example soon so that you can persist the token - but we wanted to keep it as simple as possible and not keep any storage in the example app.. – SerKnight Feb 14 '20 at 19:11
  • If you console.log(accessToken) you can simply change the code to always pass in that json token instead of the session stored token.. Will shoot to get that strategy added next week. – SerKnight Feb 14 '20 at 19:12
0

Here is the library that is used successfully with ouath2.0 tokenization. The token is expired in 30 mints. After that, we need to refresh the token with old token objects.

First set up an app in developer.xero.com.

Add Company Name and Redirect URL while creating the app.

Setup environment configuration in your file.

X_CLIENT_ID=CD43E78278ED4BE68F35F155C3E708F7 X_CLIENT_SECRET=IuP5TrE70JoyYiezMRM2KwvcHFYoLy3qRbD3NFlOkYLN0Asy X_REDIRECT_URL=https://baseredirecturl.com/xero/default/redirect

Step-1: Here is the code for creating a token and refresh token.

public function actionConnectXero()
{
    $session = Yii::$app->session;
    $request = Yii::$app->request;

    if (empty($request->get('code'))) {

        // If we don't have an authorization code then get one
        $authUrl = $this->provider->getAuthorizationUrl([
            'scope' => 'offline_access openid email profile accounting.settings accounting.transactions accounting.contacts accounting.reports.read projects accounting.journals.read'
        ]);
        //offline_access openid email profile accounting.settings accounting.transactions accounting.contacts accounting.reports.read projects accounting.journals.read


        $session->set('oauth2state', $this->provider->getState());

        $this->redirect($authUrl);


    // Check given state against previously stored one to mitigate CSRF attack
    } elseif (empty($request->get('state')) || ($request->get('state') !== $session->get('oauth2state'))) {

        $session->remove('oauth2state');
        exit('Invalid state');

    } else {

        // Try to get an access token (using the authorization code grant)
        $token = $this->provider->getAccessToken('authorization_code', [
            'code' => $request->get('code')
        ]);

        $session->set('access_token', $token);

        //If you added the openid/profile scopes you can access the authorizing user's identity.
        $identity = $this->provider->getResourceOwner($token);
        echo "<pre>";
        print_r($identity);

        //Get the tenants that this user is authorized to access
        $tenants = $this->provider->getTenants($token);
        print_r($tenants);
        $session->set('tenantId', $tenants[0]->tenantId);
        exit;
    }
}

Step-2: Redirect to URL.

public function actionRedirectXero()
{
    $request = Yii::$app->request;
    $codeStr = explode("?", $request->getUrl());
    $token = $this->provider->getAccessToken('authorization_code', [
        'code' => $request->get('code')
    ]);

    $tenants = $this->provider->getTenants($token);

    $exits = XeroConfigs::find()->where(['created_by' => Yii::$app->user->identity->id])->one();

    $xeroConf = $exits ? XeroConfigs::findOne($exits->id) : new XeroConfigs();
    $xeroConf->access_token = $token;
    $xeroConf->refresh_token = $token->getRefreshToken();
    $xeroConf->expiry = $token->getExpires();
    $xeroConf->tenant_id = isset($tenants[0]) ? $tenants[0]->id : 0;
    $xeroConf->token_object = serialize($token);
    $xeroConf->created_by = Yii::$app->user->identity->id;
    $xeroConf->save();

    $this->redirect('/xero/default/get-xero-data?'.$codeStr[1]);
}

Step-3: Get data from xero. I just save and get contacts. for more examples, you can check the package documentation.

public function actionGetXeroData(){

    $configs = XeroConfigs::find()->where(['created_by' => Yii::$app->user->identity->id])->one();

    if($configs->expiry < time()){

        $newAccessToken = $this->provider->getAccessToken('refresh_token', [
            'grant_type' => 'refresh_token',
            'refresh_token' => $configs->refresh_token
        ]);

        $tenants = $this->provider->getTenants($newAccessToken);

        $xeroConf = XeroConfigs::findOne($configs->id);

        $xeroConf->access_token = $newAccessToken;
        $xeroConf->refresh_token = $newAccessToken->getRefreshToken();
        $xeroConf->expiry = $newAccessToken->getExpires();
        $xeroConf->tenant_id = isset($tenants[0]) ? $tenants[0]->id : 0;;
        $xeroConf->token_object = serialize($newAccessToken);;
        $xeroConf->updated_at = Carbon::now()->toDateTimeString();
        $xeroConf->created_by = Yii::$app->user->identity->id;
        $xeroConf->save();

        $configs = XeroConfigs::find()->where(['created_by' => Yii::$app->user->identity->id])->one();
    }

    $tokenObj = unserialize($configs->token_object);
    $tenants = $this->provider->getTenants($tokenObj);
    $xero = new \XeroPHP\Application($tokenObj, $tenants[0]->tenantId);
    $contact = new Contact($xero);

    $contact->setName('Hassan Raza')
        ->setAccountNumber('0245541574185741')
        ->setContactID('852986')
        ->setGUID('52552548-5585-8715-8888-871222554154')
        ->setBankAccountDetail('0245541574185741')
        ->setTaxNumber('55545352')
        ->setContactStatus('ACTIVE')
        ->setSkypeUserName('hassan_raza2010')
        ->setTrackingCategoryName('Manager')
        ->setFirstName('Hassan')
        ->setLastName('Raza')
        ->setEmailAddress('hassan@xero.com');

    $response = $contact->save();

    dd($response->getResponseBody());
Hassan Raza
  • 671
  • 10
  • 27