['openid email profile offline_access assets projects accounting.settings accounting.transactions accounting.contacts accounting.journals.read accounting.reports.read accounting.attachments'] ]; public $storage; public $config; public $apiInstance; public $xeroTenantId; public function __construct() { add_action( 'after_setup_theme', array($this,'boot_carbon' )); add_action( 'carbon_fields_register_fields', array($this, 'build_settings_page' )); add_action( 'carbon_fields_container_activated', array($this, 'field_activated')); add_action( 'parse_request', array($this, 'xero_callback')); add_shortcode( 'xero_org_name', array($this, 'xero_org_name')); add_shortcode( 'xero_org_contacts', array($this, 'xero_org_contacts')); add_shortcode( 'xero_org_invoices', array($this, 'xero_org_invoices')); add_action('init', array($this, "xero_init")); add_action('plugins_loaded', array($this, load_storage)); // $this->xero_init(); $this->storage = new StorageClass(); } public function xero_init() { $this->provider = new \League\OAuth2\Client\Provider\GenericProvider([ 'clientId' => '85B4A7B8AF35442CBB9943799B402FE1', 'clientSecret' => 'bNSYPDdBTGNMVF7kB56iOLhEmqQTlsitwH6cc4kQy83XW3iO', 'redirectUri' => 'https://procomhost.com/?xero_callback', 'urlAuthorize' => 'https://login.xero.com/identity/connect/authorize', 'urlAccessToken' => 'https://identity.xero.com/connect/token', 'urlResourceOwnerDetails' => 'https://api.xero.com/api.xro/2.0/Organisation' ]); } public function load_storage() { //$this->storage->read_value(); } public function boot_carbon() { \Carbon_Fields\Carbon_Fields::boot(); } function build_settings_page() { Container::make( 'theme_options', __( 'Xero Integration' ) ) ->set_page_parent( 'options-general.php' ) ->add_fields( array( Field::make( 'text', 'xero_oauth2state', 'Xero Oauth2 State' ) ->set_attribute( 'maxLength', 2048) ->set_attribute( 'readOnly', true) ->set_default_value($this->storage->getOauth2State()), Field::make( 'text', 'xero_token', 'Xero Token' ) ->set_attribute( 'maxLength', 2048) ->set_attribute( 'readOnly', true) ->set_default_value($this->storage->getSession()['token']), Field::make( 'text', 'xero_refresh_token', 'RefreshToken' ) ->set_attribute( 'readOnly', true) ->set_default_value( $this->storage->getSession()['refresh_token'] ), Field::make( 'text', 'xero_id_token', 'ID Token' ) ->set_attribute( 'readOnly', true) ->set_default_value( $this->storage->getSession()['id_token'] ), Field::make( 'text', 'xero_tenant_id', 'Tenant ID' ) ->set_attribute( 'readOnly', true) ->set_default_value( $this->storage->getSession()['tenant_id'] ), Field::make( 'text', 'xero_expires', 'Expires' ) ->set_attribute( 'readOnly', true) ->set_default_value( $this->storage->getSession()['expires'] ), Field::make( 'text', 'xero_expires_human', 'Expires' ) ->set_attribute( 'readOnly', true) ->set_default_value( $this->storage->getSession()['expires_human'] ), Field::make( 'html', 'crb_information_text' ) ->set_html( '

Connect/Reconnect

if the above field is empty, or the expire date looks suspicous, please reconnect to Xero

' ) ) ); $this->storage->read_value(); } function field_activated() { $this->storage->read_value(); $xeroTenantId = (string)$this->storage->getSession()['tenant_id']; if ( $xeroTenantId == "" ){ $this->startAuthorization(); }else{ $this->refresh_token(); } } public function startAuthorization() { // This returns the authorizeUrl with necessary parameters applied (e.g. state). $authorizationUrl = $this->provider->getAuthorizationUrl($this->options); // Save the state generated for you and store it to the session. // For security, on callback we compare the saved state with the one returned to ensure they match. $this->storage->setOauth2State($this->provider->getState()); // Redirect the user to the authorization URL. header('Location: ' . $authorizationUrl); exit(); } function xero_callback() { if( isset($_GET['xero_reauth']) ) { $this->startAuthorization(); return; } if( ! isset($_GET['xero_callback']) ) { return ; } // If we don't have an authorization code then get one if (!isset($_GET['code'])) { echo "Something went wrong, no authorization code found"; exit("Something went wrong, no authorization code found"); // Check given state against previously stored one to mitigate CSRF attack } elseif (empty($_GET['state']) || ($_GET['state'] !== $this->storage->getOauth2State() )) { echo "Invalid State"; $this->storage->setOauth2State(""); exit('Invalid state'); } else { try { // Try to get an access token using the authorization code grant. $accessToken = $this->provider->getAccessToken('authorization_code', [ 'code' => $_GET['code'] ]); $config = \XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken( (string)$accessToken->getToken() ); $identityInstance = new \XeroAPI\XeroPHP\Api\IdentityApi( new \GuzzleHttp\Client(), $config ); $result = $identityInstance->getConnections(); // Save my tokens, expiration tenant_id $this->storage->setToken( $accessToken->getToken(), $accessToken->getExpires(), $result[0]->getTenantId(), $accessToken->getRefreshToken(), $accessToken->getValues()["id_token"] ); // related to $this->build_settings_page $url = "/wp-admin/options-general.php?page=crb_carbon_fields_container_xero_integration.php"; header('Location: ' . $url); exit(); } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) { echo "Xero Callback failed"; exit(); } } } function refresh_token() { $this->storage->read_value(); $this->xeroTenantId = (string)$this->storage->getSession()['tenant_id']; if ($this->storage->getHasExpired()) { $provider = new \League\OAuth2\Client\Provider\GenericProvider([ 'clientId' => '85B4A7B8AF35442CBB9943799B402FE1', 'clientSecret' => 'bNSYPDdBTGNMVF7kB56iOLhEmqQTlsitwH6cc4kQy83XW3iO', 'redirectUri' => 'https://procomhost.com/test/xero-php-oauth2-starter/callback.php', 'urlAuthorize' => 'https://login.xero.com/identity/connect/authorize', 'urlAccessToken' => 'https://identity.xero.com/connect/token', 'urlResourceOwnerDetails' => 'https://api.xero.com/api.xro/2.0/Organisation' ]); try { $newAccessToken = $provider->getAccessToken('refresh_token', [ 'refresh_token' => $this->storage->getRefreshToken() ]); }catch (\Exception $e) { $this->startAuthorization(); return; } // Save my token, expiration and refresh token $this->storage->setToken( $newAccessToken->getToken(), $newAccessToken->getExpires(), $this->xeroTenantId, $newAccessToken->getRefreshToken(), $newAccessToken->getValues()["id_token"] ); } if ( $this->apiInstance == null ){ $this->config = \XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken( (string)$this->storage->getSession()['token'] ); $this->apiInstance = new \XeroAPI\XeroPHP\Api\AccountingApi( new \GuzzleHttp\Client(), $this->config ); } } public function xero_org_name() { ini_set('display_errors', 'On'); $this->refresh_token(); $apiResponse = $this->apiInstance->getOrganisations($this->xeroTenantId); $message = 'Organisation Name: ' . $apiResponse->getOrganisations()[0]->getName() . " "; return $message; } public function xero_org_contacts() { ini_set('display_errors', 'On'); $this->refresh_token(); $apiResponse = $this->apiInstance->getContacts($this->xeroTenantId); $contacts = $apiResponse->getContacts(); $message = " "; $message .= " "; $count = 1; foreach ( $contacts as $c) { $group = ""; foreach ( $c->getContactGroups() as $g) { $group .= $g->getName() . " - " . $g->getStatus() . "
"; } $message .= " " . " " . " " . " " . " " . " " . " " . ""; } $message .= "
# unique-id name Supplier Customer Group Status
" . $count ++ . " " . $c->getContactId() . " " . $c->getName() . " " . ( $c->getIsSupplier() ? "yes" : " - " ) . " " . ( $c->getIsCustomer() ? "yes" : " - " ) . " " . $group . " " . $c->getContactStatus() . "
"; return $message; } public function xero_org_invoices() { ini_set('display_errors', 'On'); $this->refresh_token(); $apiResponse = $this->apiInstance->getInvoices($this->xeroTenantId); $invoices = $apiResponse->getInvoices(); $message = " "; $message .= " "; $count = 1; foreach ( $invoices as $c) { $strDate = ""; $d = $c->getDate(); if ( $d != null) { $da = $c->getDateAsDate(); $strDate = $da->format("Y-m-d"); } else { $strDate = $d; } $message .= " " . " " . " " . " " . " " . " " . " " . ""; } $message .= "
# invoice id date contact amount Type Status
" . $count ++ . " " . $c->getInvoiceNumber() . " " . $strDate . " " . $c->getContact()->getName() . " " . $c->getTotal() . " " . $c->getType() . " " . $c->getStatus() . "
"; return $message; } } $b = new Xero();