Implement Xero service

This commit is contained in:
Rene Vergara 2022-08-10 14:12:28 -05:00
parent 451bf6745c
commit 7ef0e16df5
Signed by: pitmutt
GPG key ID: 65122AD495A7F5B2
10 changed files with 152 additions and 33 deletions

View file

@ -34,6 +34,8 @@ export class InvoiceComponent implements OnInit {
total: 0, total: 0,
totalZec: 0, totalZec: 0,
paid: false, paid: false,
externalInvoice: '',
shortCode: '',
lines: [ lines: [
{ {
qty: 1, qty: 1,

View file

@ -41,6 +41,8 @@ export class OrderComponent implements OnInit{
total:0, total:0,
totalZec: 0, totalZec: 0,
paid: false, paid: false,
externalInvoice: '',
shortCode: '',
lines: [ lines: [
{ {
qty: 1, qty: 1,

View file

@ -11,5 +11,7 @@ export interface Order {
total: number, total: number,
totalZec: number, totalZec: number,
lines: LineItem[], lines: LineItem[],
paid: boolean paid: boolean,
externalInvoice: string,
shortCode: string
} }

View file

@ -62,6 +62,8 @@ export class OrderService {
total: 0, total: 0,
totalZec: 0, totalZec: 0,
paid: false, paid: false,
externalInvoice: '',
shortCode: '',
lines: [ lines: [
{ {
qty: 1, qty: 1,
@ -163,6 +165,8 @@ export class OrderService {
price: 0, price: 0,
total: 0, total: 0,
paid: false, paid: false,
externalInvoice: '',
shortCode: '',
lines: [lineItem] lines: [lineItem]
}; };
let obs = this.http.post<{message: string, order: Order}>(this.beUrl+'api/order', {payload: order}, { headers: this.reqHeaders }); let obs = this.http.post<{message: string, order: Order}>(this.beUrl+'api/order', {payload: order}, { headers: this.reqHeaders });
@ -190,6 +194,8 @@ export class OrderService {
totalZec: 0, totalZec: 0,
price: 0, price: 0,
paid: false, paid: false,
externalInvoice: '',
shortCode: '',
lines: [ lines: [
{ {
qty: 1, qty: 1,
@ -223,6 +229,8 @@ export class OrderService {
total: 0, total: 0,
totalZec: 0, totalZec: 0,
paid: false, paid: false,
externalInvoice: '',
shortCode: '',
lines: [ lines: [
{ {
qty: 1, qty: 1,

View file

@ -51,6 +51,8 @@ export class ReceiptService {
total: 0, total: 0,
totalZec: 0, totalZec: 0,
paid: false, paid: false,
externalInvoice: '',
shortCode: '',
lines: [ lines: [
{ {
qty: 1, qty: 1,

View file

@ -25,6 +25,8 @@ export class ReceiptComponent implements OnInit {
total: 0, total: 0,
totalZec: 0, totalZec: 0,
paid: false, paid: false,
externalInvoice: '',
shortCode: '',
lines: [ lines: [
{ {
qty: 1, qty: 1,

View file

@ -2,12 +2,9 @@ import { Inject, Component, OnInit, OnDestroy, ViewEncapsulation } from '@angula
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatSlideToggleChange } from '@angular/material/slide-toggle'; import { MatSlideToggleChange } from '@angular/material/slide-toggle';
import { UntypedFormBuilder, Validators, UntypedFormGroup, FormControl } from '@angular/forms'; import { UntypedFormBuilder, Validators, UntypedFormGroup, FormControl } from '@angular/forms';
import { User } from '../user.model'; import { Observable } from 'rxjs';
import { Owner } from '../owner.model'; import { Owner } from '../owner.model';
import { XeroService } from '../xero.service';
var crypto = require('sha.js');
var URLSafeBase64 = require('urlsafe-base64');
var Buffer = require('buffer/').Buffer;
@Component({ @Component({
selector: 'app-settings', selector: 'app-settings',
@ -41,9 +38,12 @@ export class SettingsComponent implements OnInit {
]; ];
xeroLink: string = ''; xeroLink: string = '';
localToken: string = ''; localToken: string = '';
clientId: string = '';
clientIdUpdate: Observable<string>;
constructor( constructor(
private fb: UntypedFormBuilder, private fb: UntypedFormBuilder,
public xeroService: XeroService,
private dialogRef: MatDialogRef<SettingsComponent>, private dialogRef: MatDialogRef<SettingsComponent>,
@Inject(MAT_DIALOG_DATA) public data: Owner) { @Inject(MAT_DIALOG_DATA) public data: Owner) {
this.useZats = data.zats; this.useZats = data.zats;
@ -59,15 +59,16 @@ export class SettingsComponent implements OnInit {
this.settingsForm.get('vKey')!.enable(); this.settingsForm.get('vKey')!.enable();
} }
this.owner = data; this.owner = data;
this.clientIdUpdate = xeroService.clientIdUpdate;
xeroService.getXeroConfig();
this.clientIdUpdate.subscribe(clientId => {
this.clientId = clientId;
this.xeroLink = `https://login.xero.com/identity/connect/authorize?response_type=code&client_id=${this.clientId}&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Ftest&scope=accounting.transactions offline_access&state=1234`
});
} }
ngOnInit() { ngOnInit() {
this.localToken = localStorage.getItem('s4z_token')!;
const hash = crypto('sha256').update(this.owner.address).digest('base64');
//const hash2 = URLSafeBase64.encode(crypto('sha256').update(this.localToken));
console.log(hash);
console.log(this.safeURL(hash));
this.xeroLink = `https://login.xero.com/identity/connect/authorize?response_type=code&client_id=CA4A8C8DA0AE462186B34DBD42074D2D&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Ftest&scope=accounting.transactions offline_access&state=1234`
} }
safeURL(s: string){ safeURL(s: string){

View file

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { XeroService } from './xero.service';
describe('XeroService', () => {
let service: XeroService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(XeroService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

73
src/app/xero.service.ts Normal file
View file

@ -0,0 +1,73 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { ConfigData } from './configdata';
var Buffer = require('buffer/').Buffer;
@Injectable({
providedIn: 'root'
})
export class XeroService {
beUrl = ConfigData.Be_URL;
clientId: string = '';
clientSecret: string = '';
xeroToken: any = {
accessToken: '',
refreshToken: '',
expiresIn: 0,
scope: '',
tokenType: ''
};
private _clientIdUpdated: BehaviorSubject<string> = new BehaviorSubject(this.clientId);
private _clientSecretUpdated: BehaviorSubject<string> = new BehaviorSubject(this.clientSecret);
private _tokenUpdated: BehaviorSubject<any> = new BehaviorSubject(this.xeroToken);
public readonly clientIdUpdate: Observable<string> = this._clientIdUpdated.asObservable();
public readonly clientSecretUpdate: Observable<string> = this._clientSecretUpdated.asObservable();
public readonly tokenUpdate: Observable<any> = this._tokenUpdated.asObservable();
private reqHeaders: HttpHeaders;
constructor(
private http: HttpClient
) {
var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64');
this.reqHeaders = new HttpHeaders().set('Authorization', auth);
this.getXeroConfig();
}
getXeroConfig(){
let obs = this.http.get<{message: string, xeroConfig: any}>(this.beUrl+'api/xero', { headers:this.reqHeaders, observe: 'response'});
obs.subscribe(xeroDataResponse => {
if (xeroDataResponse.status == 200) {
this.clientId = xeroDataResponse.body!.xeroConfig.clientId;
this.clientSecret = xeroDataResponse.body!.xeroConfig.clientSecret;
this._clientIdUpdated.next(Object.assign({}, this).clientId);
this._clientSecretUpdated.next(Object.assign({}, this).clientSecret);
} else {
console.log('No config in DB!');
}
});
return obs;
}
getXeroAccessToken(code: string){
this.getXeroConfig().subscribe(xeroDataResponse => {
console.log('XAT: '+this.clientId);
var xeroAuth = 'Basic ' + Buffer.from(`${this.clientId}:${this.clientSecret}`).toString('base64');
var xeroHeaders = new HttpHeaders().set('Authorization', xeroAuth).append('Content-Type', 'application/x-www-form-urlencoded');
let obs = this.http.post('https://identity.xero.com/connect/token', `grant_type=authorization_code&code=${code}&redirect_uri=http://localhost:4200/test` , {headers: xeroHeaders, observe: 'response'})
obs.subscribe(tokenData => {
if (tokenData.status == 200) {
console.log(tokenData.body!);
this.xeroToken = tokenData.body!;
this._tokenUpdated.next(Object.assign({}, this).xeroToken);
} else {
console.log('Error: '+tokenData.status);
}
});
});
}
}

View file

@ -3,7 +3,8 @@ import { ActivatedRoute } from '@angular/router';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { UserService } from '../user.service'; import { UserService } from '../user.service';
import { Owner } from '../owner.model'; import { Owner } from '../owner.model';
//import { XeroClient } from 'xero-node'; import { Observable } from 'rxjs';
import { XeroService } from '../xero.service';
var Buffer = require('buffer/').Buffer; var Buffer = require('buffer/').Buffer;
@ -16,28 +17,38 @@ var Buffer = require('buffer/').Buffer;
export class XeroRegComponent implements OnInit { export class XeroRegComponent implements OnInit {
reqHeaders: HttpHeaders; clientId: string = '';
constructor(private http: HttpClient, clientSecret: string = '';
private activatedRoute: ActivatedRoute xeroToken: any;
) { clientIdUpdate: Observable<string>;
//const secret = 'J8Ft70Tk6theIFNYpuDRPvzuc271_dyjq7EJlzPFh8lpXXvV'; clientSecretUpdate: Observable<string>;
var auth = 'Basic ' + Buffer.from('CA4A8C8DA0AE462186B34DBD42074D2D:J8Ft70Tk6theIFNYpuDRPvzuc271_dyjq7EJlzPFh8lpXXvV').toString('base64'); tokenUpdate: Observable<any>;
this.reqHeaders = new HttpHeaders().set('Authorization', auth).append('Content-Type', 'application/x-www-form-urlencoded');
//this.session = localStorage.getItem('s4z_token')!; constructor(
//this.ownerUpdate = userService.ownerUpdate; public xeroService: XeroService,
//this.ownerUpdate.subscribe(ownerData => { private activatedRoute: ActivatedRoute
//this.owner = ownerData; ) {
//}); this.tokenUpdate = xeroService.tokenUpdate;
this.clientIdUpdate = xeroService.clientIdUpdate;
xeroService.getXeroConfig();
this.clientIdUpdate.subscribe(clientId => {
this.clientId = clientId;
});
this.clientSecretUpdate = xeroService.clientSecretUpdate;
this.clientSecretUpdate.subscribe(clientSecret => {
this.clientSecret = clientSecret;
});
} }
ngOnInit(): void { ngOnInit(): void {
this.activatedRoute.queryParams.subscribe((params) => { this.activatedRoute.queryParams.subscribe((params) => {
console.log(params); console.log(params);
this.http.post('https://identity.xero.com/connect/token', `grant_type=authorization_code&code=${params.code}&redirect_uri=http://localhost:4200/test` , {headers: this.reqHeaders, observe: 'response'}) this.xeroService.getXeroAccessToken(params.code)
.subscribe(responseData => { this.tokenUpdate.subscribe(token => {
console.log(responseData); console.log(token);
this.xeroToken = token;
}); });
}); });
} }
} }