Implement test connection to Xero
This commit is contained in:
parent
eb903b5ee3
commit
451bf6745c
10 changed files with 1521 additions and 96 deletions
1416
package-lock.json
generated
1416
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -34,10 +34,12 @@
|
||||||
"material-design-icons": "^3.0.1",
|
"material-design-icons": "^3.0.1",
|
||||||
"mongoose": "^6.0.13",
|
"mongoose": "^6.0.13",
|
||||||
"rxjs": "~6.6.0",
|
"rxjs": "~6.6.0",
|
||||||
|
"sha.js": "^2.4.11",
|
||||||
"stdrpc": "^1.3.0",
|
"stdrpc": "^1.3.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
"urlsafe-base64": "^1.0.0",
|
"urlsafe-base64": "^1.0.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
|
"xero-node": "^4.23.0",
|
||||||
"zone.js": "~0.11.4"
|
"zone.js": "~0.11.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -46,6 +48,7 @@
|
||||||
"@angular/compiler-cli": "^14.0.5",
|
"@angular/compiler-cli": "^14.0.5",
|
||||||
"@types/jasmine": "~3.8.0",
|
"@types/jasmine": "~3.8.0",
|
||||||
"@types/node": "^12.20.33",
|
"@types/node": "^12.20.33",
|
||||||
|
"@types/request": "^2.48.8",
|
||||||
"@types/urlsafe-base64": "^1.0.28",
|
"@types/urlsafe-base64": "^1.0.28",
|
||||||
"@types/uuid": "^8.3.1",
|
"@types/uuid": "^8.3.1",
|
||||||
"jasmine-core": "~3.8.0",
|
"jasmine-core": "~3.8.0",
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { ListOrdersComponent } from './listorders/listorders.component';
|
||||||
import { AuthGuardService } from './auth-guard.service';
|
import { AuthGuardService } from './auth-guard.service';
|
||||||
import { NodeResolverService } from './node-resolver.service';
|
import { NodeResolverService } from './node-resolver.service';
|
||||||
import { PmtserviceComponent } from './pmtservice/pmtservice.component';
|
import { PmtserviceComponent } from './pmtservice/pmtservice.component';
|
||||||
|
import { XeroRegComponent } from './xeroreg/xeroreg.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', component: LoginComponent, resolve: { response: NodeResolverService} },
|
{ path: '', component: LoginComponent, resolve: { response: NodeResolverService} },
|
||||||
|
@ -19,6 +20,7 @@ const routes: Routes = [
|
||||||
{ path: 'receipt/:orderId', component: ReceiptComponent},
|
{ path: 'receipt/:orderId', component: ReceiptComponent},
|
||||||
{ path: 'invoice/:orderId', component: InvoiceComponent},
|
{ path: 'invoice/:orderId', component: InvoiceComponent},
|
||||||
{ path: 'pmtservice', component: PmtserviceComponent},
|
{ path: 'pmtservice', component: PmtserviceComponent},
|
||||||
|
{ path: 'test', component: XeroRegComponent},
|
||||||
{ path: 'login', component: LoginComponent, resolve: { response: NodeResolverService}}
|
{ path: 'login', component: LoginComponent, resolve: { response: NodeResolverService}}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||||
import { MatStepperModule } from '@angular/material/stepper';
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
|
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
@ -46,6 +47,7 @@ import { PromptInvoiceComponent } from './prompt-invoice/prompt-invoice.componen
|
||||||
import { PromptReceiptComponent } from './prompt-receipt/prompt-receipt.component';
|
import { PromptReceiptComponent } from './prompt-receipt/prompt-receipt.component';
|
||||||
import { NotifierComponent } from './notifier/notifier.component';
|
import { NotifierComponent } from './notifier/notifier.component';
|
||||||
import { PmtserviceComponent } from './pmtservice/pmtservice.component';
|
import { PmtserviceComponent } from './pmtservice/pmtservice.component';
|
||||||
|
import { XeroRegComponent } from './xeroreg/xeroreg.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -73,7 +75,8 @@ import { PmtserviceComponent } from './pmtservice/pmtservice.component';
|
||||||
PromptInvoiceComponent,
|
PromptInvoiceComponent,
|
||||||
PromptReceiptComponent,
|
PromptReceiptComponent,
|
||||||
NotifierComponent,
|
NotifierComponent,
|
||||||
PmtserviceComponent
|
PmtserviceComponent,
|
||||||
|
XeroRegComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -96,6 +99,7 @@ import { PmtserviceComponent } from './pmtservice/pmtservice.component';
|
||||||
MatAutocompleteModule,
|
MatAutocompleteModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
|
MatTabsModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
FontAwesomeModule
|
FontAwesomeModule
|
||||||
],
|
],
|
||||||
|
|
|
@ -2,55 +2,64 @@
|
||||||
<div class="settings-title">Settings</div>
|
<div class="settings-title">Settings</div>
|
||||||
|
|
||||||
<div class="container" style="margin-top: 10px;">
|
<div class="container" style="margin-top: 10px;">
|
||||||
<mat-dialog-content [formGroup]="settingsForm">
|
<mat-tab-group mat-tab-align-tabs="start">
|
||||||
<mat-form-field class="settings-field" [style.width.%]="100">
|
<mat-tab label="Main">
|
||||||
<mat-label>Name</mat-label>
|
<mat-dialog-content [formGroup]="settingsForm">
|
||||||
<input matInput
|
<mat-form-field class="settings-field" [style.width.%]="100">
|
||||||
width="100%"
|
<mat-label>Name</mat-label>
|
||||||
placeholder="Name"
|
<input matInput
|
||||||
formControlName="name">
|
width="100%"
|
||||||
</mat-form-field>
|
placeholder="Name"
|
||||||
<mat-form-field [style.width.%]="100" >
|
formControlName="name">
|
||||||
<mat-label>Currency</mat-label>
|
</mat-form-field>
|
||||||
<mat-select formControlName="currency">
|
<mat-form-field [style.width.%]="100" >
|
||||||
<mat-option *ngFor="let coin of coins"
|
<mat-label>Currency</mat-label>
|
||||||
[value]="coin.symbol">
|
<mat-select formControlName="currency">
|
||||||
{{coin.label}}
|
<mat-option *ngFor="let coin of coins"
|
||||||
</mat-option>
|
[value]="coin.symbol">
|
||||||
</mat-select>
|
{{coin.label}}
|
||||||
</mat-form-field>
|
</mat-option>
|
||||||
<mat-slide-toggle formControlName="useZats"
|
</mat-select>
|
||||||
class="settings-toggle"
|
</mat-form-field>
|
||||||
(change)="onChange($event)">
|
<mat-slide-toggle formControlName="useZats"
|
||||||
Use zatoshis?
|
class="settings-toggle"
|
||||||
</mat-slide-toggle>
|
(change)="onChange($event)">
|
||||||
<pre></pre>
|
Use zatoshis?
|
||||||
<mat-slide-toggle formControlName="useVKey"
|
</mat-slide-toggle>
|
||||||
class="settings-toggle"
|
<pre></pre>
|
||||||
(change)="onChangeVKeyOn($event)">
|
<mat-slide-toggle formControlName="useVKey"
|
||||||
Confirm payments?
|
class="settings-toggle"
|
||||||
</mat-slide-toggle>
|
(change)="onChangeVKeyOn($event)">
|
||||||
<pre></pre>
|
Confirm payments?
|
||||||
<mat-form-field [style.width.%]="100">
|
</mat-slide-toggle>
|
||||||
<mat-label>Viewing key</mat-label>
|
<pre></pre>
|
||||||
<input matInput placeholder="Your wallet viewing key"
|
<mat-form-field [style.width.%]="100">
|
||||||
formControlName="vKey">
|
<mat-label>Viewing key</mat-label>
|
||||||
</mat-form-field>
|
<input matInput placeholder="Your wallet viewing key"
|
||||||
|
formControlName="vKey">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
</mat-dialog-content>
|
</mat-dialog-content>
|
||||||
|
|
||||||
<mat-dialog-actions style="display: flex;
|
<mat-dialog-actions style="display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 12px;">
|
margin-top: 12px;">
|
||||||
<button mat-raised-button
|
<button mat-raised-button
|
||||||
(click)="close()">
|
(click)="close()">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
<button mat-raised-button
|
<button mat-raised-button
|
||||||
color="primary"
|
color="primary"
|
||||||
(click)="save()">
|
(click)="save()">
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
</mat-dialog-actions>
|
</mat-dialog-actions>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab label="Advanced">
|
||||||
|
<a mat-raised-button color="primary" href="{{this.xeroLink}}">
|
||||||
|
Link to Xero
|
||||||
|
</a>
|
||||||
|
</mat-tab>
|
||||||
|
</mat-tab-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,6 +5,10 @@ import { UntypedFormBuilder, Validators, UntypedFormGroup, FormControl } from '@
|
||||||
import { User } from '../user.model';
|
import { User } from '../user.model';
|
||||||
import { Owner } from '../owner.model';
|
import { Owner } from '../owner.model';
|
||||||
|
|
||||||
|
var crypto = require('sha.js');
|
||||||
|
var URLSafeBase64 = require('urlsafe-base64');
|
||||||
|
var Buffer = require('buffer/').Buffer;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: 'app-settings',
|
||||||
templateUrl: './settings.component.html',
|
templateUrl: './settings.component.html',
|
||||||
|
@ -35,6 +39,8 @@ export class SettingsComponent implements OnInit {
|
||||||
symbol: 'aud'
|
symbol: 'aud'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
xeroLink: string = '';
|
||||||
|
localToken: string = '';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private fb: UntypedFormBuilder,
|
private fb: UntypedFormBuilder,
|
||||||
|
@ -56,6 +62,16 @@ export class SettingsComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
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){
|
||||||
|
return s.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
|
0
src/app/xeroreg/xeroreg.component.css
Normal file
0
src/app/xeroreg/xeroreg.component.css
Normal file
1
src/app/xeroreg/xeroreg.component.html
Normal file
1
src/app/xeroreg/xeroreg.component.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<p>test works!</p>
|
23
src/app/xeroreg/xeroreg.component.spec.ts
Normal file
23
src/app/xeroreg/xeroreg.component.spec.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TestComponent } from './test.component';
|
||||||
|
|
||||||
|
describe('TestComponent', () => {
|
||||||
|
let component: TestComponent;
|
||||||
|
let fixture: ComponentFixture<TestComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ TestComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(TestComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
43
src/app/xeroreg/xeroreg.component.ts
Normal file
43
src/app/xeroreg/xeroreg.component.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
|
||||||
|
import { UserService } from '../user.service';
|
||||||
|
import { Owner } from '../owner.model';
|
||||||
|
//import { XeroClient } from 'xero-node';
|
||||||
|
|
||||||
|
var Buffer = require('buffer/').Buffer;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-xeroreg',
|
||||||
|
templateUrl: './xeroreg.component.html',
|
||||||
|
styleUrls: ['./xeroreg.component.css']
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export class XeroRegComponent implements OnInit {
|
||||||
|
|
||||||
|
reqHeaders: HttpHeaders;
|
||||||
|
constructor(private http: HttpClient,
|
||||||
|
private activatedRoute: ActivatedRoute
|
||||||
|
) {
|
||||||
|
//const secret = 'J8Ft70Tk6theIFNYpuDRPvzuc271_dyjq7EJlzPFh8lpXXvV';
|
||||||
|
var auth = 'Basic ' + Buffer.from('CA4A8C8DA0AE462186B34DBD42074D2D:J8Ft70Tk6theIFNYpuDRPvzuc271_dyjq7EJlzPFh8lpXXvV').toString('base64');
|
||||||
|
this.reqHeaders = new HttpHeaders().set('Authorization', auth).append('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
|
//this.session = localStorage.getItem('s4z_token')!;
|
||||||
|
//this.ownerUpdate = userService.ownerUpdate;
|
||||||
|
//this.ownerUpdate.subscribe(ownerData => {
|
||||||
|
//this.owner = ownerData;
|
||||||
|
//});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.activatedRoute.queryParams.subscribe((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'})
|
||||||
|
.subscribe(responseData => {
|
||||||
|
console.log(responseData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue