public function run($request) { $appType = $this->config()->appType; $oauthCallback = $this->config()->oauthCallback; $userAgent = $this->config()->userAgent; $consumerKey = $this->config()->consumerKey; $sharedSecret = $this->config()->sharedSecret; $privateKeyPath = BASE_PATH . $this->config()->privateKeyPath; $publicKeyPath = BASE_PATH . $this->config()->publicKeyPath; $signatures = array('consumer_key' => $consumerKey, 'shared_secret' => $sharedSecret, 'core_version' => '2.0', 'payroll_version' => '1.0'); if ($appType == "Private" || $appType == "Partner") { $signatures['rsa_private_key'] = $privateKeyPath; $signatures['rsa_public_key'] = $publicKeyPath; } $XeroOAuth = new XeroOAuth(array_merge(array('application_type' => $appType, 'oauth_callback' => $oauthCallback, 'user_agent' => $userAgent), $signatures)); $initialCheck = $XeroOAuth->diagnostics(); $checkErrors = count($initialCheck); if ($checkErrors > 0) { // you could handle any config errors here, or keep on truckin if you like to live dangerously foreach ($initialCheck as $check) { echo 'Error: ' . $check . PHP_EOL; } } else { Session::set('Xero', array('oauth_token' => $XeroOAuth->config['consumer_key'], 'oauth_token_secret' => $XeroOAuth->config['shared_secret'], 'oauth_session_handle' => '')); $oauthSession['oauth_token'] = Session::get('Xero.oauth_token'); $oauthSession['oauth_token_secret'] = Session::get('Xero.oauth_token_secret'); $oauthSession['oauth_session_handle'] = Session::get('Xero.oauth_session_handle'); if (isset($oauthSession['oauth_token'])) { $XeroOAuth->config['access_token'] = $oauthSession['oauth_token']; $XeroOAuth->config['access_token_secret'] = $oauthSession['oauth_token_secret']; $this->createInvoices($XeroOAuth); $this->createPayments($XeroOAuth); } } }
* consumer_secret: for partner applications, set to: s (cannot be blank) * rsa_private_key: application certificate private key - not needed for public applications * rsa_public_key: application certificate public cert - not needed for public applications */ include 'tests/testRunner.php'; $signatures = array('consumer_key' => 'YOURCONSUMERKEY', 'shared_secret' => 'YOURSECRET', 'core_version' => '2.0', 'payroll_version' => '1.0', 'file_version' => '1.0'); if (XRO_APP_TYPE == "Private" || XRO_APP_TYPE == "Partner") { $signatures['rsa_private_key'] = BASE_PATH . '/certs/privatekey.pem'; $signatures['rsa_public_key'] = BASE_PATH . '/certs/publickey.cer'; } if (XRO_APP_TYPE == "Partner") { $signatures['curl_ssl_cert'] = BASE_PATH . '/certs/entrust-cert-RQ3.pem'; $signatures['curl_ssl_password'] = '******'; $signatures['curl_ssl_key'] = BASE_PATH . '/certs/entrust-private-RQ3.pem'; } $XeroOAuth = new XeroOAuth(array_merge(array('application_type' => XRO_APP_TYPE, 'oauth_callback' => OAUTH_CALLBACK, 'user_agent' => $useragent), $signatures)); $initialCheck = $XeroOAuth->diagnostics(); $checkErrors = count($initialCheck); if ($checkErrors > 0) { // you could handle any config errors here, or keep on truckin if you like to live dangerously foreach ($initialCheck as $check) { echo 'Error: ' . $check . PHP_EOL; } } else { $here = XeroOAuth::php_self(); session_start(); $oauthSession = retrieveSession(); include 'tests/tests.php'; if (isset($_REQUEST['oauth_verifier'])) { $XeroOAuth->config['access_token'] = $_SESSION['oauth']['oauth_token']; $XeroOAuth->config['access_token_secret'] = $_SESSION['oauth']['oauth_token_secret'];
<?php require 'lib/XeroOAuth.php'; define('BASE_PATH', dirname(__FILE__)); define("XRO_APP_TYPE", "Private"); define("OAUTH_CALLBACK", "oob"); $useragent = "XeroOAuth-PHP Private App Test"; $signatures = array('consumer_key' => 'YOURCONSUMERKEY', 'shared_secret' => 'YOURSECRET', 'core_version' => '2.0', 'payroll_version' => '1.0'); if (XRO_APP_TYPE == "Private" || XRO_APP_TYPE == "Partner") { $signatures['rsa_private_key'] = BASE_PATH . '/certs/privatekey.pem'; $signatures['rsa_public_key'] = BASE_PATH . '/certs/publickey.cer'; } $XeroOAuth = new XeroOAuth(array_merge(array('application_type' => XRO_APP_TYPE, 'oauth_callback' => OAUTH_CALLBACK, 'user_agent' => $useragent), $signatures)); include 'tests/testRunner.php'; $initialCheck = $XeroOAuth->diagnostics(); $checkErrors = count($initialCheck); if ($checkErrors > 0) { // you could handle any config errors here, or keep on truckin if you like to live dangerously foreach ($initialCheck as $check) { echo 'Error: ' . $check . PHP_EOL; } } else { $session = persistSession(array('oauth_token' => $XeroOAuth->config['consumer_key'], 'oauth_token_secret' => $XeroOAuth->config['shared_secret'], 'oauth_session_handle' => '')); $oauthSession = retrieveSession(); if (isset($oauthSession['oauth_token'])) { $XeroOAuth->config['access_token'] = $oauthSession['oauth_token']; $XeroOAuth->config['access_token_secret'] = $oauthSession['oauth_token_secret']; include 'tests/tests.php'; } testLinks(); }
function isxwpe_add_xero_invoice_to_account() { // Function to add invoices to xero account global $wpdb; // This if statement start when user complete checkout if (isset($_REQUEST['wpsc_action']) && $_REQUEST['wpsc_action'] == 'submit_checkout') { $samp_array = array(); $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}" . "xero_auth"); // Collect auth credentials if (!empty($results)) { foreach ($results as $result) { if ($result->credential == 'application_key') { $application_key = $result->value; } if ($result->credential == 'secret_key') { $secret_key = $result->value; } if ($result->credential == 'redirect_url') { $redirect_url = $result->value; } if ($result->credential == 'oauth_token') { $oauth_token = $result->value; } if ($result->credential == 'oauth_verifier') { $oauth_verifier = $result->value; } if ($result->credential == 'oauth_token_secret') { $oauth_token_secret = $result->value; } } } $checkout_session_id = wpsc_get_customer_meta('checkout_session_id'); // Find transaction Id $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}" . "wpsc_purchase_logs", ARRAY_A); // Collect transaction details foreach ($results as $temp_results) { if ($temp_results['sessionid'] == $checkout_session_id) { $samp_array = $temp_results; } } if (!empty($samp_array)) { $purchase_id = $samp_array['id']; $total_price = $samp_array['totalprice']; $user_id = $samp_array['user_ID']; $user_email = ''; $name = ''; $user_details = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}" . "wpsc_submited_form_data WHERE `log_id` = {$purchase_id}", ARRAY_A); foreach ($user_details as $user_data) { if (is_email($user_data['value'])) { $user_email = $user_data['value']; } if (isset($user_data['form_id']) && $user_data['form_id'] == 2) { $name = $name . $user_data['value']; } if (isset($user_data['form_id']) && $user_data['form_id'] == 3) { $name = $name . ' ' . $user_data['value']; } } } $currency = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}" . "options WHERE `option_name` ='currency_type'"); $currency_id = $currency[0]->option_value; $currency_details = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}" . "wpsc_currency_list WHERE id = {$currency_id}"); $currency_code = $currency_details[0]->code; // Set currency code for xero same as currency on WPecommerse plugin $wpdb->get_results("SELECT * FROM {$wpdb->prefix}" . "wpsc_cart_contents WHERE purchaseid = {$purchase_id} "); // Select product details $purchased_items = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}" . "wpsc_cart_contents WHERE purchaseid = {$purchase_id} "); $wp_wpsc_purchase_logs = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}" . "wpsc_purchase_logs WHERE id = {$purchase_id} "); $wp_wpsc_purchase_log = $wp_wpsc_purchase_logs[0]; $line_items = ''; foreach ($purchased_items as $selected_items) { //print_r($purchased_items); $line_items .= '<LineItem> <Description>' . $selected_items->name . '</Description> <Quantity>' . $selected_items->quantity . '</Quantity> <TaxAmount>' . $selected_items->tax_charged . '</TaxAmount> <UnitAmount>' . $selected_items->price . '</UnitAmount> </LineItem>'; } require plugin_dir_path(__FILE__) . 'xero_library/lib/XeroOAuth.php'; define("XRO_APP_TYPE", "Public"); $useragent = "Xero-OAuth-PHP Public"; define("OAUTH_CALLBACK", $redirect_url); $signatures = array('consumer_key' => $application_key, 'shared_secret' => $secret_key, 'core_version' => '2.0', 'payroll_version' => '1.0', 'file_version' => '1.0', 'access_token' => $oauth_token, 'access_token_secret' => $oauth_token_secret); $target_directorys = wp_upload_dir(); $target_directory = $target_directorys['basedir']; if (XRO_APP_TYPE == "Private" || XRO_APP_TYPE == "Public") { $signatures['rsa_private_key'] = $target_directory . '/xero_invoice/private_keys/privatekey.pem'; $signatures['rsa_public_key'] = $target_directory . '/xero_invoice/private_keys/publickey.cer'; } $XeroOAuth = new XeroOAuth(array_merge(array('application_type' => XRO_APP_TYPE, 'oauth_callback' => OAUTH_CALLBACK, 'user_agent' => $useragent), $signatures)); $initialCheck = $XeroOAuth->diagnostics(); $today = date('Y-m-d'); include plugin_dir_path(__FILE__) . 'tests/testRunner.php'; $xml = "<Invoices>\n <Invoice>\n <Type>ACCREC</Type>\n\t\t\t\t\t\t<CurrencyCode>{$currency_code}</CurrencyCode>\n <Contact>\n <Name>{$name}</Name>\n\t\t\t\t\t\t <EmailAddress>{$user_email}</EmailAddress>\n </Contact>\n <Date>{$today}</Date>\n <LineAmountTypes>Exclusive</LineAmountTypes>\n <LineItems>\n {$line_items}\n </LineItems>\n </Invoice>\n </Invoices>"; //$myfile = fopen(WP_PLUGIN_DIR."/invoice-sync-for-xero-and-wpecommerce/XerSyncLog.txt", "w") or die("Unable to open file!"); $response = $XeroOAuth->request('POST', $XeroOAuth->url('Invoices', 'core'), array(), $xml); if ($XeroOAuth->response['code'] == 200) { // Add transaction details to DB id transaction is success $invoice = $XeroOAuth->parseResponse($XeroOAuth->response['response'], $XeroOAuth->response['format']); $invoice_id = $invoice->Invoices[0]->Invoice->InvoiceNumber; $wpdb->insert("{$wpdb->prefix}" . "xero_history", array('session_id' => $checkout_session_id, 'purchase_id' => $purchase_id, 'invoice_id' => $invoice_id, 'user_email' => $user_email), array('%d', '%d', '%s', '%s')); } else { //outputError($XeroOAuth); } } }
<?php require 'lib/XeroOAuth.php'; define('BASE_PATH', dirname(__FILE__)); define("XRO_APP_TYPE", "Private"); define("OAUTH_CALLBACK", "oob"); $useragent = "XeroOAuth-PHP Private App Test"; $signatures = array('consumer_key' => 'CNHHGAYDW7XZZNXXWDWKATZYDWDJXO', 'shared_secret' => 'CJW0KPOAIG0C7DDVIUXA3V8GWNIABV', 'core_version' => '2.0', 'payroll_version' => '1.0', 'file_version' => '1.0'); if (XRO_APP_TYPE == "Private" || XRO_APP_TYPE == "Partner") { $signatures['rsa_private_key'] = BASE_PATH . '/certs/privatekey.pem'; $signatures['rsa_public_key'] = BASE_PATH . '/certs/publickey.cer'; } $XeroOAuth = new XeroOAuth(array_merge(array('application_type' => XRO_APP_TYPE, 'oauth_callback' => OAUTH_CALLBACK, 'user_agent' => $useragent), $signatures)); include 'tests/testRunner.php'; $initialCheck = $XeroOAuth->diagnostics(); $checkErrors = count($initialCheck); if ($checkErrors > 0) { // you could handle any config errors here, or keep on truckin if you like to live dangerously foreach ($initialCheck as $check) { echo 'Error: ' . $check . PHP_EOL; } } else { $session = persistSession(array('oauth_token' => $XeroOAuth->config['consumer_key'], 'oauth_token_secret' => $XeroOAuth->config['shared_secret'], 'oauth_session_handle' => '')); $oauthSession = retrieveSession(); if (isset($oauthSession['oauth_token'])) { $XeroOAuth->config['access_token'] = $oauthSession['oauth_token']; $XeroOAuth->config['access_token_secret'] = $oauthSession['oauth_token_secret']; // include 'tests/xero_api.php'; if ($event_type == "invoice_generated") { $response = $XeroOAuth->request('POST', $XeroOAuth->url('Invoices', 'core'), array(), $xml); if ($XeroOAuth->response['code'] == 200) {
private function push_to_xero($id) { // Get data for sending customer details $customer = Customer::find($id); $contacts = $customer->customer_contacts; $contactsXML = '<ContactPersons>'; foreach ($contacts as $contact) { $contactsXML .= '<ContactPerson> <FirstName>' . $contact->first_name . '</FirstName> <LastName>' . $contact->last_name . '</LastName> <EmailAddress>' . $contact->email . '</EmailAddress> </ContactPerson>'; } $contactsXML .= '</ContactPersons>'; if (count($contacts) > 0) { $first_name = $contacts[0]->first_name; $last_name = $contacts[0]->last_name; $email = $contacts[0]->email; } else { $first_name = ''; $last_name = ''; $email = ''; } define('BASE_PATH', $_SERVER['DOCUMENT_ROOT']); define("XRO_APP_TYPE", "Private"); define("OAUTH_CALLBACK", 'http://printflow.local:8000/'); /* For Demo-Company define ( "OAUTH_CALLBACK", 'http://printflow.local:8000/' ); $useragent = "Demo-Printflow"; $signatures = array ( 'consumer_key' => 'NLOXKOEM8QUFCW9XCKWH7DQMARCWUW', 'shared_secret' => 'YEACQD0QQ2R5X1YCBFV6LZKMMLIYRT', // API versions 'core_version' => '2.0', 'payroll_version' => '1.0' ); */ $useragent = env('USER_AGENT'); $signatures = array('consumer_key' => env('XERO_KEY'), 'shared_secret' => env('XERO_SECRET'), 'core_version' => '2.0', 'payroll_version' => '1.0'); if (XRO_APP_TYPE == "Private" || XRO_APP_TYPE == "Partner") { $signatures['rsa_private_key'] = BASE_PATH . '/certs/privatekey.pem'; $signatures['rsa_public_key'] = BASE_PATH . '/certs/publickey.cer'; } $XeroOAuth = new \XeroOAuth(array_merge(array('application_type' => XRO_APP_TYPE, 'oauth_callback' => OAUTH_CALLBACK, 'user_agent' => $useragent), $signatures)); $initialCheck = $XeroOAuth->diagnostics(); $checkErrors = count($initialCheck); if ($checkErrors > 0) { // you could handle any config errors here, or keep on truckin if you like to live dangerously foreach ($initialCheck as $check) { echo 'Error: ' . $check . PHP_EOL; } } else { $session = $this->persistSession(array('oauth_token' => $XeroOAuth->config['consumer_key'], 'oauth_token_secret' => $XeroOAuth->config['shared_secret'], 'oauth_session_handle' => '')); $oauthSession = $this->retrieveSession(); if (isset($oauthSession['oauth_token'])) { $XeroOAuth->config['access_token'] = $oauthSession['oauth_token']; $XeroOAuth->config['access_token_secret'] = $oauthSession['oauth_token_secret']; if (isset($_REQUEST)) { if (!isset($_REQUEST['where'])) { $_REQUEST['where'] = ""; } } if (isset($_REQUEST['wipe'])) { session_destroy(); header("Location: {$here}"); // already got some credentials stored? } elseif (isset($_REQUEST['refresh'])) { $response = $XeroOAuth->refreshToken($oauthSession['oauth_token'], $oauthSession['oauth_session_handle']); if ($XeroOAuth->response['code'] == 200) { $session = $this->persistSession($response); $oauthSession = $this->retrieveSession(); } else { $this->outputError($XeroOAuth); if ($XeroOAuth->response['helper'] == "TokenExpired") { $XeroOAuth->refreshToken($oauthSession['oauth_token'], $oauthSession['session_handle']); } } } elseif (isset($oauthSession['oauth_token']) && isset($_REQUEST)) { $XeroOAuth->config['access_token'] = $oauthSession['oauth_token']; $XeroOAuth->config['access_token_secret'] = $oauthSession['oauth_token_secret']; $XeroOAuth->config['session_handle'] = $oauthSession['oauth_session_handle']; $xml = '<Contacts> <Contact> <Name>' . $customer->customer_name . '</Name> <FirstName>' . $first_name . '</FirstName> <LastName>' . $last_name . '</LastName> <EmailAddress>' . $email . '</EmailAddress> <Addresses> <Address> <AddressType>POBOX</AddressType> <AttentionTo>' . $customer->postal_attention . '</AttentionTo> <AddressLine1>' . $customer->customer_name . '</AddressLine1> <AddressLine2>' . $customer->postal_street . '</AddressLine2> <AddressLine3> </AddressLine3> <AddressLine4> </AddressLine4> <City>' . $customer->postal_city . '</City> <Region>' . $customer->postal_state . '</Region> <PostalCode>' . $customer->postal_postcode . '</PostalCode> <Country>' . $customer->postal_country . '</Country> </Address> <Address> <AddressType>STREET</AddressType> <AttentionTo>' . $customer->postal_attention . '</AttentionTo> <AddressLine1>' . $customer->customer_name . '</AddressLine1> <AddressLine2>' . $customer->postal_street . '</AddressLine2> <AddressLine3> </AddressLine3> <AddressLine4> </AddressLine4> <City>' . $customer->postal_city . '</City> <Region>' . $customer->postal_state . '</Region> <PostalCode>' . $customer->postal_postcode . '</PostalCode> <Country>' . $customer->postal_country . '</Country> </Address> </Addresses> <Phones> <Phone> <PhoneType>DEFAULT</PhoneType> <PhoneNumber>' . $customer->tel_number . '</PhoneNumber> <PhoneAreaCode>' . $customer->tel_area . '</PhoneAreaCode> <PhoneCountryCode>' . $customer->tel_country . '</PhoneCountryCode> </Phone> <Phone> <PhoneType>MOBILE</PhoneType> <PhoneNumber>' . $customer->mobile_number . '</PhoneNumber> <PhoneAreaCode>' . $customer->mobile_area . '</PhoneAreaCode> <PhoneCountryCode>' . $customer->mobile_country . '</PhoneCountryCode> </Phone> </Phones> <Website>' . $customer->web_address . '</Website> <IsCustomer>true</IsCustomer> ' . $contactsXML . ' </Contact> </Contacts>'; $response = $XeroOAuth->request('POST', $XeroOAuth->url('Contacts', 'core'), array(), $xml); if ($XeroOAuth->response['code'] == 200) { return 'OK'; } else { $this->outputError($XeroOAuth); return 'ERROR'; } } } } return 'ERROR'; }
public function send_invoice($id) { // Get data for sending invoice $quote_request = QuoteRequest::find($id); define('BASE_PATH', $_SERVER['DOCUMENT_ROOT']); define("XRO_APP_TYPE", "Private"); define("OAUTH_CALLBACK", 'http://printflow.local:8000/'); /* For Demo-Company define ( "OAUTH_CALLBACK", 'http://printflow.local:8000/' ); $useragent = "Demo-Printflow"; $signatures = array ( 'consumer_key' => 'PMNK76GMVNQLNK945E385MVIDCCMVQ', 'shared_secret' => 'VUQPJDKRZ1ZUPRSBBHUZ3J8DOQTQEL', // API versions 'core_version' => '2.0', 'payroll_version' => '1.0' ); */ $useragent = env('USER_AGENT'); $signatures = array('consumer_key' => env('XERO_KEY'), 'shared_secret' => env('XERO_SECRET'), 'core_version' => '2.0', 'payroll_version' => '1.0'); if (XRO_APP_TYPE == "Private" || XRO_APP_TYPE == "Partner") { $signatures['rsa_private_key'] = BASE_PATH . '/certs/privatekey.pem'; $signatures['rsa_public_key'] = BASE_PATH . '/certs/publickey.cer'; } $XeroOAuth = new \XeroOAuth(array_merge(array('application_type' => XRO_APP_TYPE, 'oauth_callback' => OAUTH_CALLBACK, 'user_agent' => $useragent), $signatures)); $initialCheck = $XeroOAuth->diagnostics(); $checkErrors = count($initialCheck); if ($checkErrors > 0) { // you could handle any config errors here, or keep on truckin if you like to live dangerously foreach ($initialCheck as $check) { echo 'Error: ' . $check . PHP_EOL; } } else { $session = $this->persistSession(array('oauth_token' => $XeroOAuth->config['consumer_key'], 'oauth_token_secret' => $XeroOAuth->config['shared_secret'], 'oauth_session_handle' => '')); $oauthSession = $this->retrieveSession(); if (isset($oauthSession['oauth_token'])) { $XeroOAuth->config['access_token'] = $oauthSession['oauth_token']; $XeroOAuth->config['access_token_secret'] = $oauthSession['oauth_token_secret']; if (isset($_REQUEST)) { if (!isset($_REQUEST['where'])) { $_REQUEST['where'] = ""; } } if (isset($_REQUEST['wipe'])) { session_destroy(); header("Location: {$here}"); // already got some credentials stored? } elseif (isset($_REQUEST['refresh'])) { $response = $XeroOAuth->refreshToken($oauthSession['oauth_token'], $oauthSession['oauth_session_handle']); if ($XeroOAuth->response['code'] == 200) { $session = $this->persistSession($response); $oauthSession = $this->retrieveSession(); } else { $this->outputError($XeroOAuth); if ($XeroOAuth->response['helper'] == "TokenExpired") { $XeroOAuth->refreshToken($oauthSession['oauth_token'], $oauthSession['session_handle']); } } } elseif (isset($oauthSession['oauth_token']) && isset($_REQUEST)) { $XeroOAuth->config['access_token'] = $oauthSession['oauth_token']; $XeroOAuth->config['access_token_secret'] = $oauthSession['oauth_token_secret']; $XeroOAuth->config['session_handle'] = $oauthSession['oauth_session_handle']; $xml = '<Invoices> <Invoice> <Type>ACCREC</Type> <Contact> <Name>' . htmlspecialchars($quote_request->customer->customer_name) . '</Name> </Contact> <Status>DRAFT</Status> <Date>' . Carbon::now()->format('Y-m-d') . '</Date> <DueDate>' . Carbon::now()->addWeeks(2)->format('Y-m-d') . '</DueDate> <Reference>' . htmlspecialchars($quote_request->ref) . '-' . $id . '</Reference> <LineAmountTypes>Exclusive</LineAmountTypes> <LineItems> <LineItem> <JobNo>' . $id . '</JobNo> <Title>' . htmlspecialchars($quote_request->title) . '</Title> <Description>' . htmlspecialchars($quote_request->title) . '</Description> <UnitAmount>' . $quote_request->job->job_item->price / $quote_request->job->job_item->quantity . '</UnitAmount> <GST>' . $quote_request->job->job_item->gst . '</GST> <AccountCode>230/</AccountCode> <TotalIncGST>' . $quote_request->job->job_item->total . '</TotalIncGST> <Quantity>' . $quote_request->job->job_item->quantity . '</Quantity> <PONumber>' . $id . '</PONumber> </LineItem>'; if (!empty($quote_request->summary)) { $xml .= '<LineItem> <Description>' . htmlspecialchars($quote_request->summary) . '</Description> </LineItem>'; } $xml .= '</LineItems> </Invoice> </Invoices>'; $response = $XeroOAuth->request('POST', $XeroOAuth->url('Invoices', 'core'), array(), $xml); if ($XeroOAuth->response['code'] == 200) { // Set status = 'completed' job $quote_request->status = 9; $quote_request->save(); return 'OK'; } else { $this->outputError($XeroOAuth); return 'ERROR'; } } } } return 'ERROR'; }