def client(self): """ Get a ready-made xero.Xero object :return: xero.Xero instance """ return Xero(credentials=PublicCredentials(**self.token), user_agent=get_xero_consumer_key())
def test_rate_limit_exceeded(self, r_get): "If you exceed the rate limit, an exception is raised." # Response based off Xero documentation; not confirmed by reality. r_get.return_value = Mock( status_code=503, text= "oauth_problem=rate%20limit%20exceeded&oauth_problem_advice=please%20wait%20before%20retrying%20the%20xero%20api" ) credentials = Mock() xero = Xero(credentials) try: xero.contacts.all() self.fail("Should raise a XeroRateLimitExceeded.") except XeroRateLimitExceeded, e: # Error messages have been extracted self.assertEqual(e.message, 'please wait before retrying the xero api') self.assertEqual(e.problem, 'rate limit exceeded') # The response has also been stored self.assertEqual(e.response.status_code, 503) self.assertEqual( e.response.text, "oauth_problem=rate%20limit%20exceeded&oauth_problem_advice=please%20wait%20before%20retrying%20the%20xero%20api" )
def test_unauthorized_expired(self, r_get): "A session with an expired token raises an unauthorized exception" # Verified response from the live API r_get.return_value = Mock( status_code=401, text= "oauth_problem=token_expired&oauth_problem_advice=The%20access%20token%20has%20expired" ) credentials = Mock() xero = Xero(credentials) try: xero.contacts.all() self.fail("Should raise a XeroUnauthorized.") except XeroUnauthorized, e: # Error messages have been extracted self.assertEqual(e.message, 'The access token has expired') self.assertEqual(e.problem, 'token_expired') # The response has also been stored self.assertEqual(e.response.status_code, 401) self.assertEqual( e.response.text, 'oauth_problem=token_expired&oauth_problem_advice=The%20access%20token%20has%20expired' )
def test_unregistered_app(self, r_get): "An app without a signature raises a BadRequest exception, but with HTML payload" # Verified response from the live API head = dict() head['content-type'] = 'text/html; charset=utf-8' r_get.return_value = Mock( status_code=400, text= 'oauth_problem=signature_method_rejected&oauth_problem_advice=No%20certificates%20have%20been%20registered%20for%20the%20consumer', headers=head) credentials = Mock(base_url="") xero = Xero(credentials) try: xero.contacts.all() self.fail("Should raise a XeroUnauthorized.") except XeroBadRequest as e: # Error messages have been extracted self.assertEqual( str(e), 'No certificates have been registered for the consumer') self.assertEqual(e.problem, 'signature_method_rejected') # The response has also been stored self.assertEqual(e.response.status_code, 400) self.assertEqual( e.response.text, 'oauth_problem=signature_method_rejected&oauth_problem_advice=No%20certificates%20have%20been%20registered%20for%20the%20consumer' ) except Exception as e: self.fail("Should raise a XeroBadRequest, not %s" % e)
def generate_account_number(profile): if "PORTAL_XERO_CONSUMER_KEY" in os.environ: with open(xero_rsa) as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials( os.environ.get("PORTAL_XERO_CONSUMER_KEY", "/usr/src/data/xerkey.pem"), rsa_key, ) xero = Xero(credentials) contacts = xero.contacts.filter(includeArchived=True) for x in range(100, 999): account_number = profile.first_name[ 0] + profile.last_name[:2] + str(x) account_number = account_number.upper() if not any( d.get("AccountNumber", None) == account_number for d in contacts): profile.xero_account_number = account_number profile.save() print("Generated Xero Account: " + account_number) return profile.xero_account_number else: return False
def test_not_implemented(self, make_authed_request): "In case of an SSL failure, a Forbidden exception is raised" # Verified response from the live API make_authed_request.return_value = Mock( status_code=501, encoding='utf-8', data=mock_data.not_implemented_text) credentials = Mock(base_url="") xero = Xero(credentials) try: self.loop.run_until_complete(xero.organisations.save({})) self.fail("Should raise a XeroNotImplemented.") except XeroNotImplemented as e: # Error messages have been extracted self.assertEqual(str(e), 'The Api Method called is not implemented') # The response has also been stored self.assertEqual(e.response.status_code, 501) self.assertTrue(e.response.data.startswith, '<ApiException') except Exception as e: self.fail("Should raise a XeroNotImplemented, not %s" % e)
def test_not_found(self, r_get): "If you request an object that doesn't exist, a Not Found exception is raised" # Verified response from the live API r_get.return_value = Mock( status_code=404, text="The resource you're looking for cannot be found") credentials = Mock(base_url="") xero = Xero(credentials) try: xero.contacts.get(id='deadbeef') self.fail("Should raise a XeroNotFound.") except XeroNotFound as e: # Error messages have been extracted self.assertEqual( str(e), "The resource you're looking for cannot be found") # The response has also been stored self.assertEqual(e.response.status_code, 404) self.assertEqual( e.response.text, "The resource you're looking for cannot be found") except Exception as e: self.fail("Should raise a XeroNotFound, not %s" % e)
def test_rate_limit_exceeded_429(self, r_get): "If you exceed the rate limit, an exception is raised." # Response based off Xero documentation; not confirmed by reality. r_get.return_value = Mock( status_code=429, headers={"X-Rate-Limit-Problem": "day"}, text= "oauth_problem=rate%20limit%20exceeded&oauth_problem_advice=please%20wait%20before%20retrying%20the%20xero%20api", ) credentials = Mock(base_url="") xero = Xero(credentials) try: xero.contacts.all() self.fail("Should raise a XeroRateLimitExceeded.") except XeroRateLimitExceeded as e: # Error messages have been extracted self.assertEqual(str(e), "please wait before retrying the xero api") self.assertIn("rate limit exceeded", e.errors[0]) # The response has also been stored self.assertEqual(e.response.status_code, 429) self.assertEqual( e.response.text, "oauth_problem=rate%20limit%20exceeded&oauth_problem_advice=please%20wait%20before%20retrying%20the%20xero%20api", ) except Exception as e: self.fail("Should raise a XeroRateLimitExceeded, not %s" % e)
def test_bad_request_invalid_response(self, r_put): "If the error response from the backend is malformed (or truncated), raise a XeroExceptionUnknown" head = {"content-type": "text/xml; charset=utf-8"} # Same error as before, but the response got cut off prematurely bad_response = mock_data.bad_request_text[:1000] r_put.return_value = Mock(status_code=400, encoding="utf-8", text=bad_response, headers=head) credentials = Mock(base_url="") xero = Xero(credentials) with self.assertRaises(XeroExceptionUnknown, msg="Should raise a XeroExceptionUnknown"): xero.invoices.put({ "Type": "ACCREC", "LineAmountTypes": "Exclusive", "Date": date(2013, 4, 29), "DueDate": date(2013, 4, 29), "Reference": "Order # 123456", "Status": "PAID", "AmountPaid": "19.05", "TotalTax": "1.05", "AmountDue": "0.00", "Total": "19.05", "SubTotal": "18.00", })
def submit(request): data = cache.get('data', None) cred_state = cache.get('creds',None) if 'invoice' not in data: return redirect('Oauth:add') if 'invoice' in data and 'Contact' not in data['invoice']: return redirect('Oauth:add') if 'tenant_id' in cred_state: try: credentials = OAuth2Credentials(**cred_state) xero = Xero(credentials) print(xero) print("karunga") print(data['invoice']) d = data['invoice'] print(d) d = beautify(d) xero.invoices.put(d) cache.set('data', {}) return JsonResponse(d, safe=False) except: return HttpResponse("Wrong Values Entered Check Again") else: return redirect('Oauth:index')
def test_unauthorized_invalid(self, r_get): "A session with an invalid token raises an unauthorized exception" # Verified response from the live API r_get.return_value = Mock( status_code=401, text= "oauth_problem=signature_invalid&oauth_problem_advice=Failed%20to%20validate%20signature", ) credentials = Mock(base_url="") xero = Xero(credentials) try: xero.contacts.all() self.fail("Should raise a XeroUnauthorized.") except XeroUnauthorized as e: # Error messages have been extracted self.assertEqual(str(e), "Failed to validate signature") self.assertEqual(e.errors[0], "signature_invalid") # The response has also been stored self.assertEqual(e.response.status_code, 401) self.assertEqual( e.response.text, "oauth_problem=signature_invalid&oauth_problem_advice=Failed%20to%20validate%20signature", ) except Exception as e: self.fail("Should raise a XeroUnauthorized, not %s" % e)
def test_not_implemented(self, r_post): "In case of an SSL failure, a Forbidden exception is raised" # Verified response from the live API r_post.return_value = Mock( status_code=501, text= """<ApiException xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ErrorNumber>20</ErrorNumber> <Type>ApiMethodNotImplementedException</Type> <Message>The Api Method called is not implemented</Message> </ApiException>""") credentials = Mock() xero = Xero(credentials) try: xero.organisation.save({}) self.fail("Should raise a XeroNotImplemented.") except XeroNotImplemented, e: # Error messages have been extracted self.assertEqual(e.message, 'The Api Method called is not implemented') # The response has also been stored self.assertEqual(e.response.status_code, 501) self.assertTrue(e.response.text.startswith, '<ApiException')
def pyCreateInvoice(ContactID, cYear, cMonth, cDay, dYear, dMonth, dDay, vbLineItems): from xero import Xero from xero.auth import PrivateCredentials from ast import literal_eval import datetime with open(r"PATH TO YOUR PRIVATEKEY.PEM REGISTERED ON XERO") as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials("CONSUMER KEY HERE", rsa_key) xero = Xero(credentials) evalLineItems = literal_eval(vbLineItems) original = { 'Type': 'ACCREC', 'Contact': { 'ContactID': ContactID }, 'Date': datetime.date(cYear, cMonth, cDay), 'DueDate': datetime.date(dYear, dMonth, dDay), 'Status': 'DRAFT', 'LineAmountTypes': 'Exclusive', 'LineItems': evalLineItems, } pyInvoiceID = xero.invoices.put(original)[0]['InvoiceID'] pyInvoiceNumber = xero.invoices.get(pyInvoiceID)[0]['InvoiceNumber'] response = [pyInvoiceID, pyInvoiceNumber] return response
def XeroConnect(): #C:\Users\timbi\source\repos\JmanOps\JmanOps\app\static\app\xero with open(XERO_PRIVATE_KEY) as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials(XERO_CONSUMER_KEY, rsa_key) xero = Xero(credentials) return xero
def test_unauthorized_expired(self, make_authed_request): "A session with an expired token raises an unauthorized exception" # Verified response from the live API make_authed_request.return_value = Mock( status_code=401, data= "oauth_problem=token_expired&oauth_problem_advice=The%20access%20token%20has%20expired" ) credentials = Mock(base_url="") xero = Xero(credentials) try: self.loop.run_until_complete(xero.contacts.all()) self.fail("Should raise a XeroUnauthorized.") except XeroUnauthorized as e: # Error messages have been extracted self.assertEqual(str(e), 'The access token has expired') self.assertEqual(e.errors[0], 'token_expired') # The response has also been stored self.assertEqual(e.response.status_code, 401) self.assertEqual( e.response.data, 'oauth_problem=token_expired&oauth_problem_advice=The%20access%20token%20has%20expired' ) except Exception as e: self.fail("Should raise a XeroUnauthorized, not %s" % e)
def xero_post_contact(cleaned_data, contact_number): credentials = PrivateCredentials(settings.XERO_CREDENTIALS, settings.XERO_PRIVATE_KEY) xero = Xero(credentials) lookup_contact = xero.contacts.filter(ContactNumber=contact_number) if lookup_contact: return lookup_contact[0]['ContactID'] name = "%s (%s %s)" % (cleaned_data['organisation'], cleaned_data['name_first'], cleaned_data['name_last']) contact = { 'Addresses': [{ 'AddressType': 'POBOX', 'City': cleaned_data['city'], 'Country': cleaned_data['country'], 'PostalCode': cleaned_data['postcode'], 'Region': cleaned_data['region'], 'AddressLine1': cleaned_data['street_line_one'], 'AddressLine2': cleaned_data['street_line_two'], 'AddressLine3': cleaned_data['street_line_three'], }], 'EmailAddress': cleaned_data['email'], 'Name': name, 'ContactNumber': contact_number } results = xero.contacts.put(contact) contact = results[0] return contact['ContactID']
def test_internal_error(self, make_authed_request): "In case of an SSL failure, a Forbidden exception is raised" # This is unconfirmed; haven't been able to verify this response from API. make_authed_request.return_value = Mock( status_code=500, data= 'An unhandled error with the Xero API occurred. Contact the Xero API team if problems persist.' ) credentials = Mock(base_url="") xero = Xero(credentials) try: self.loop.run_until_complete(xero.contacts.all()) self.fail("Should raise a XeroInternalError.") except XeroInternalError as e: # Error messages have been extracted self.assertEqual( str(e), 'An unhandled error with the Xero API occurred. Contact the Xero API team if problems persist.' ) # The response has also been stored self.assertEqual(e.response.status_code, 500) self.assertEqual( e.response.data, 'An unhandled error with the Xero API occurred. Contact the Xero API team if problems persist.' ) except Exception as e: self.fail("Should raise a XeroInternalError, not %s" % e)
def generate_account_number(profile): if "XERO_CONSUMER_KEY" in os.environ and "XERO_RSA_FILE" in os.environ: with open(os.environ.get('XERO_RSA_FILE')) as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials(os.environ.get('XERO_CONSUMER_KEY'), rsa_key) xero = Xero(credentials) contacts = xero.contacts.filter(includeArchived=True) for x in range(100, 999): account_number = profile.first_name[ 0] + profile.last_name[:2] + str(x) account_number = account_number.upper() if not any( d.get('AccountNumber', None) == account_number for d in contacts): profile.xero_account_number = account_number profile.save() print("Generated Xero Account: " + account_number) return profile.xero_account_number else: return False
def test_rate_limit_exceeded(self, make_authed_request): "If you exceed the rate limit, an exception is raised." # Response based off Xero documentation; not confirmed by reality. make_authed_request.return_value = Mock( status_code=503, data= "oauth_problem=rate%20limit%20exceeded&oauth_problem_advice=please%20wait%20before%20retrying%20the%20xero%20api" ) credentials = Mock(base_url="") xero = Xero(credentials) try: self.loop.run_until_complete(xero.contacts.all()) self.fail("Should raise a XeroRateLimitExceeded.") except XeroRateLimitExceeded as e: # Error messages have been extracted self.assertEqual(str(e), 'please wait before retrying the xero api') self.assertEqual(e.errors[0], 'rate limit exceeded') # The response has also been stored self.assertEqual(e.response.status_code, 503) self.assertEqual( e.response.data, "oauth_problem=rate%20limit%20exceeded&oauth_problem_advice=please%20wait%20before%20retrying%20the%20xero%20api" ) except Exception as e: self.fail("Should raise a XeroRateLimitExceeded, not %s" % e)
def test_bad_request_invalid_response(self, r_put): "If the error response from the backend is malformed (or truncated), raise a XeroExceptionUnknown" head = {'content-type': 'text/xml; charset=utf-8'} # Same error as before, but the response got cut off prematurely bad_response = mock_data.bad_request_text[:1000] r_put.return_value = Mock(status_code=400, encoding='utf-8', text=bad_response, headers=head) credentials = Mock(base_url="") xero = Xero(credentials) with self.assertRaises(XeroExceptionUnknown, msg='Should raise a XeroExceptionUnknown'): xero.invoices.put({ 'Type': 'ACCREC', 'LineAmountTypes': 'Exclusive', 'Date': date(2013, 4, 29), 'DueDate': date(2013, 4, 29), 'Reference': 'Order # 123456', 'Status': 'PAID', 'AmountPaid': '19.05', 'TotalTax': '1.05', 'AmountDue': '0.00', 'Total': '19.05', 'SubTotal': '18.00', })
def test_not_available(self, r_get): "If Xero goes down for maintenance, an exception is raised" # Response based off Xero documentation; not confirmed by reality. r_get.return_value = Mock( status_code=503, text="The Xero API is currently offline for maintenance") credentials = Mock(base_url="") xero = Xero(credentials) try: xero.contacts.all() self.fail("Should raise a XeroNotAvailable.") except XeroNotAvailable as e: # Error messages have been extracted self.assertEqual( str(e), "The Xero API is currently offline for maintenance") # The response has also been stored self.assertEqual(e.response.status_code, 503) self.assertEqual( e.response.text, "The Xero API is currently offline for maintenance") except Exception as e: self.fail("Should raise a XeroNotAvailable, not %s" % e)
def getCredentials(self, Renew=False): # Path = '/home/deepav/Desktop/privatekey.pem' # ConsumerKey = 'VNUIOH588GCAH6JMJVQXSEVTICLEU5' Config = request.env["ir.config_parameter"] Path = Config.sudo().get_param('xero.pem.path') ConsumerKey = Config.sudo().get_param('xero.consumer.key', default='') if Path == '/': _logger.warning('Xero Credentials Not Found: Pem file path missing !!') return False if ConsumerKey == '/': _logger.warning('Xero Credentials Not Found: Consumer Key missing !!') return False if Renew or not self._credentials: rsa_key = '' with open(Path) as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials(ConsumerKey, rsa_key) self._credentials = credentials else: credentials = self._credentials xero = False try: xero = Xero(credentials) except: e = sys.exc_info()[1] _logger.warning('Xero Credentials: %s'%(str(e))) return xero
def get_xero_contact(user): """ Returns an object with the xero contact details or None if it doesn't exist. :return: """ if "PORTAL_XERO_CONSUMER_KEY" in os.environ: with open(xero_rsa) as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials( os.environ.get("PORTAL_XERO_CONSUMER_KEY"), rsa_key) xero = Xero(credentials) email = xero.contacts.filter(EmailAddress=user.profile.email) name = xero.contacts.filter(Name=user.profile.get_full_name()) if email: return email elif name: return name return None else: return "Invalid Xero API details."
def xero(): cred_state = caches['default'].get('xero_creds') credentials = OAuth2Credentials(**cred_state) if credentials.expired(): credentials.refresh() caches['default'].set('xero_creds', credentials.state) return Xero(credentials)
def test_internal_error(self, r_get): "In case of an SSL failure, a Forbidden exception is raised" # This is unconfirmed; haven't been able to verify this response from API. r_get.return_value = Mock( status_code=500, text= 'An unhandled error with the Xero API occurred. Contact the Xero API team if problems persist.' ) credentials = Mock() xero = Xero(credentials) try: xero.contacts.all() self.fail("Should raise a XeroInternalError.") except XeroInternalError, e: # Error messages have been extracted self.assertEqual( e.message, 'An unhandled error with the Xero API occurred. Contact the Xero API team if problems persist.' ) # The response has also been stored self.assertEqual(e.response.status_code, 500) self.assertEqual( e.response.text, 'An unhandled error with the Xero API occurred. Contact the Xero API team if problems persist.' )
def __init__(self): print XERO_PATH_CERTIFICATE with open(XERO_PATH_CERTIFICATE) as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials(XERO_CONSUMER_KEY, rsa_key) self.credentials = credentials self.xero = Xero(credentials)
def test_unauthorized_invalid(self, r_get): "A session with an invalid token raises an unauthorized exception" # Verified response from the live API r_get.return_value = Mock( status_code=401, text= 'oauth_problem=signature_invalid&oauth_problem_advice=Failed%20to%20validate%20signature' ) credentials = Mock() xero = Xero(credentials) try: xero.contacts.all() self.fail("Should raise a XeroUnauthorized.") except XeroUnauthorized, e: # Error messages have been extracted self.assertEqual(e.message, 'Failed to validate signature') self.assertEqual(e.problem, 'signature_invalid') # The response has also been stored self.assertEqual(e.response.status_code, 401) self.assertEqual( e.response.text, 'oauth_problem=signature_invalid&oauth_problem_advice=Failed%20to%20validate%20signature' )
def trial_balance_for_period(pk, period_offset): cm = CompanyMeta.objects.filter(company_id=pk).first() cm.save() company = AccountsUtils.get_company(pk) st = time.time() credentials = AccountingUtils.get_credentials_by_company(company) if not credentials: return if not cm.monthly_reporting_current_period: return if company.accounting_type.lower() == Company.QUICKBOOKS.lower(): period = cm.monthly_reporting_current_period - relativedelta( months=+period_offset, day=31) # print('##### Getting TRIAL BALANCE for period ', period) query = '?start_date=' + period.strftime( '%Y-%m-1') + '&end_date=' + period.strftime('%Y-%m-%d') # print('####### QBO TB QUERY ', query) # for query in query_list: trial_balance_response, status_code = Utils.get_trial_balance( credentials.accessToken, credentials.realmId, query) if status_code >= 400: bearer = Utils.get_bearer_token_from_refresh_token( credentials.refreshToken) new_credentials = AccountingUtils.updateAccountingSession( company, bearer.accessToken, bearer.refreshToken, credentials.realmId) trial_balance_response, status_code = Utils.get_trial_balance( new_credentials.accessToken, new_credentials.realmId, query) if status_code >= 400: return from .third_party.quickbooks import QuickBooks entries = QuickBooks.save_trial_balance(company, trial_balance_response) TrialBalance.objects.bulk_create(entries) if company.accounting_type.lower() == Company.XERO.lower(): period = cm.monthly_reporting_current_period - relativedelta( months=+period_offset, day=31) # params = {'fromDate': str(period.strftime('%Y-%m-01')), 'toDate': str(period.strftime('%Y-%m-%d'))} params = {'date': str(period.strftime('%Y-%m-%d'))} auth = Utils.get_xero_auth(pk) credentials = Utils.get_xero_credentials(pk, **auth) xero = Xero(credentials) trialbalance = xero.reports.get('TrialBalance', params=params) XeroAccountings.save_trial_balance(company, trialbalance[0]) # print('{:.2f}s Elapsed'.format(time.time() - st)) # print('Took {:.2f}s Total'.format(time.time() - st)) cm.trialbalance_last_refresh_date = datetime.datetime.now() cm.trialbalance_dl_complete = True cm.save() return
def ready(self): with open(settings.XERO_CONFIG['private_key_file']) as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials(settings.XERO_CONFIG['consumer_key'], rsa_key) self.xero = Xero(credentials) super().ready()
def __init__(self): with open('config.json') as config_file: self.config = json.load(config_file) with open('keys/privatekey.pem', 'r') as keyfile: rsa_key = keyfile.read() credentials = PrivateCredentials(self.config['consumer_key'], rsa_key) self.xero = xero = Xero(credentials)