Merge branch 'security1'

This commit is contained in:
Rene Vergara 2023-06-26 12:42:03 -05:00
commit e33e0a7f36
Signed by: pitmutt
GPG key ID: 65122AD495A7F5B2
15 changed files with 377 additions and 515 deletions

View file

@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Modified order service to query API using `token`. - Modified order service to query API using `token`.
- Modified receipt component to use the new `token`. - Modified receipt component to use the new `token`.
- Modified invoice component to use the new `token`. - Modified invoice component to use the new `token`.
- Modified payment service component to remove order-creation logic.
### Fixed ### Fixed

View file

@ -1,6 +1,6 @@
{ {
"name": "zgo", "name": "zgo",
"version": "2.2.0", "version": "2.3.0",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "ng serve", "start": "ng serve",

View file

@ -45,7 +45,7 @@
style="margin-top: 10px; style="margin-top: 10px;
margin-bottom: 20px;"> margin-bottom: 20px;">
<div >&copy; 2023 Vergara Technologies LLC</div> <div >&copy; 2023 Vergara Technologies LLC</div>
<div class="tiny">Version 2.2.0</div> <div class="tiny">Version 2.3.0</div>
<div class="tiny">{{ vE.mainPriceData }}</div> <div class="tiny">{{ vE.mainPriceData }}</div>
</div> </div>
<div></div> <div></div>

View file

@ -89,14 +89,14 @@
</tr> </tr>
</table> </table>
<div style="height: 15px;"></div> <div style="height: 15px;"></div>
<div width="100%" <div *ngIf="!order.paid" width="100%"
style="font-size: 14px; style="font-size: 14px;
font-weight: 700; font-weight: 700;
font-style: italic; font-style: italic;
text-align: center;"> text-align: center;">
{{ vE.invoiceScanQrcode }} {{ vE.invoiceScanQrcode }}
</div> </div>
<div style="text-align: center; <div *ngIf="!order.paid" style="text-align: center;
margin-top: 10px; margin-top: 10px;
line-height: 30px;"> line-height: 30px;">
<div style="font-family: 'Spartan'; <div style="font-family: 'Spartan';

View file

@ -22,6 +22,8 @@ export class LanguageService {
private loginURL = ConfigData.Be_URL + 'getloginlang'; private loginURL = ConfigData.Be_URL + 'getloginlang';
private mainURL = ConfigData.Be_URL + 'getmainlang'; private mainURL = ConfigData.Be_URL + 'getmainlang';
private scanURL = ConfigData.Be_URL + 'getscanlang'; private scanURL = ConfigData.Be_URL + 'getscanlang';
private invoiceURL = ConfigData.Be_URL + 'getinvoicelang';
private pmtservURL = ConfigData.Be_URL + 'getpmtservicelang';
public zgoLanguage: string = ''; public zgoLanguage: string = '';
@ -58,6 +60,10 @@ export class LanguageService {
return this.http.get<LanguageData>(this.mainURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params}); return this.http.get<LanguageData>(this.mainURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params});
} else if (viewName === 'scan') { } else if (viewName === 'scan') {
return this.http.get<LanguageData>(this.scanURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params}); return this.http.get<LanguageData>(this.scanURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params});
} else if (viewName === 'invoice') {
return this.http.get<LanguageData>(this.invoiceURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params});
} else if (viewName === 'pmtservice') {
return this.http.get<LanguageData>(this.pmtservURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params});
} else { } else {
return this.http.get<LanguageData>(this.baseURL + return this.http.get<LanguageData>(this.baseURL +
'/?lang=' + this.zgoLanguage + '/?lang=' + this.zgoLanguage +

View file

@ -214,7 +214,8 @@ export class OrderComponent implements OnInit{
dialogConfig.disableClose = true; dialogConfig.disableClose = true;
dialogConfig.autoFocus = true; dialogConfig.autoFocus = true;
dialogConfig.data = { dialogConfig.data = {
orderId: this.order._id orderId: this.order._id,
orderToken: this.order.token
}; };
//console.log ('order_id : ' + this.order._id); //console.log ('order_id : ' + this.order._id);

View file

@ -24,11 +24,11 @@
<div style="height: 50px;"> <div style="height: 50px;">
</div> </div>
<div style="font-weight: 700; <div style="font-weight: 700;
font-size: 25px; fonT-size: 25px;
text-align: center;"> text-align: center;">
{{ vE.pmtservicePmtsrvNot }}<br> {{ vE.pmtservicePmtsrvNot }}<br>
{{ vE.pmtserviceEnabledFor }}<br> {{ vE.pmtserviceEnabledFor }}<br>
{{ owner.name}} {{ shop }}
</div> </div>
<div style="height: 40px;"> <div style="height: 40px;">
</div> </div>
@ -131,7 +131,7 @@
</div> </div>
<div class="invoiceDetail" <div class="invoiceDetail"
*ngIf="reportType==0" *ngIf="reportType==0"
id="invoice"> >
<div class="invoiceHdrTxt1">{{ vE.pmtserviceHdrTxt1 }}</div> <div class="invoiceHdrTxt1">{{ vE.pmtserviceHdrTxt1 }}</div>
<div class="invoiceHdrTxt2">{{ vE.pmtserviceHdrTxt2 }}{{orderId}}</div> <div class="invoiceHdrTxt2">{{ vE.pmtserviceHdrTxt2 }}{{orderId}}</div>
<div class="invoiceHdrTxt3">{{ vE.pmtserviceHdrTxt3 }}{{order.timestamp | date}} <div class="invoiceHdrTxt3">{{ vE.pmtserviceHdrTxt3 }}{{order.timestamp | date}}
@ -206,7 +206,7 @@
</td> </td>
<td width="25%"> <td width="25%">
<div style="text-align: right;" <div style="text-align: right;"
id="payment-qr" id="invoice-qr"
*ngIf="!order.paid"></div> *ngIf="!order.paid"></div>
</td> </td>
</tr> </tr>

View file

@ -4,8 +4,6 @@ import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http";
import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { PmtData } from "./pmtservice.model"; import { PmtData } from "./pmtservice.model";
import { XeroInvoice } from "./xeroinvoice.model"; import { XeroInvoice } from "./xeroinvoice.model";
import { Owner } from '../owner.model';
// import { Item } from '../items/item.model'
import { Order } from '../order/order.model' import { Order } from '../order/order.model'
import { ConfigData } from '../configdata'; import { ConfigData } from '../configdata';
import { faCheck, faHourglass } from '@fortawesome/free-solid-svg-icons'; import { faCheck, faHourglass } from '@fortawesome/free-solid-svg-icons';
@ -19,481 +17,302 @@ var Buffer = require('buffer/').Buffer;
import { LanguageService } from '../language.service'; import { LanguageService } from '../language.service';
@Component({ @Component({
selector: 'app-pmtservice', selector: 'app-pmtservice',
templateUrl: './pmtservice.component.html', templateUrl: './pmtservice.component.html',
styleUrls: ['./pmtservice.component.css'] styleUrls: ['./pmtservice.component.css']
}) })
export class PmtserviceComponent implements OnInit { export class PmtserviceComponent implements OnInit {
faCheck = faCheck; faCheck = faCheck;
faHourglass = faHourglass; faHourglass = faHourglass;
beUrl = ConfigData.Be_URL; beUrl = ConfigData.Be_URL;
private reqHeaders: HttpHeaders = new HttpHeaders(); private reqHeaders: HttpHeaders = new HttpHeaders();
public pmtData : PmtData = { public shop: string = '';
ownerId :'', public pmtData : PmtData = {
invoice: '', ownerId :'',
amount: 0, invoice: '',
currency: '', amount: 0,
shortcode: '' currency: '',
}; shortcode: ''
};
public invData : XeroInvoice = { public invData : XeroInvoice = {
inv_Type : '', inv_Type : '',
inv_Id : '', inv_Id : '',
inv_No : '', inv_No : '',
inv_Contact : '', inv_Contact : '',
inv_Currency : '', inv_Currency : '',
inv_CurrencyRate : 0, inv_CurrencyRate : 0,
inv_Status : '', inv_Status : '',
inv_Total : 0, inv_Total : 0,
inv_Date : new Date(), inv_Date : new Date(),
inv_shortCode : '', inv_shortCode : '',
inv_ProcDate : new Date() inv_ProcDate : new Date()
}; };
public owner: Owner = {
_id: '',
address: '',
name: '',
currency: 'usd',
tax: false,
taxValue: 0,
vat: false,
vatValue: 0,
paid: false,
zats: false,
invoices: false,
expiration: new Date(Date.now()).toISOString(),
payconf: false,
crmToken: '',
viewkey: ''
};
public order: Order = { public order: Order = {
_id : '', _id : '',
address: '', address: '',
session: '', session: '',
timestamp: '', timestamp: '',
closed: false, closed: false,
currency: '', currency: '',
price: 0, price: 0,
total: 0, total: 0,
totalZec: 0, totalZec: 0,
paid: false, paid: false,
externalInvoice: '', externalInvoice: '',
shortCode: '', shortCode: '',
token: '', token: '',
lines: [ lines: [
{ {
qty: 1, qty: 1,
name: '', name: '',
cost:0 cost:0
} }
] ]
}; };
private invData_raw : string = ''; private invData_raw : string = '';
private invData_buff : any = null; private invData_buff : any = null;
public reportType = 1000; public reportType = 0;
public Status = 0; public Status = 0;
codeString: string = ''; codeString: string = 'ZGo - The Zcash Register';
zcashUrl: SafeUrl = ''; zcashUrl: SafeUrl = '';
zPrice: number = 1.0; zPrice: number = 1.0;
name: string = ''; name: string = '';
error: boolean = false; error: boolean = false;
orderId : string = ''; orderId : string = '';
// ------------------------------------- // -------------------------------------
// Language Support // Language Support
// //
vE = { vE = {
pmtserviceInvalidOwnerid : '', pmtserviceInvalidOwnerid : '',
pmtserviceNotservClose : '', pmtserviceNotservClose : '',
pmtserviceNotservError : '', pmtserviceNotservError : '',
pmtserviceCopyNotavail : '', pmtserviceCopyNotavail : '',
pmtserviceCopyaddressError : '', pmtserviceCopyaddressError : '',
pmtserviceCopyamountError : '', pmtserviceCopyamountError : '',
pmtserviceCopymemoError : '', pmtserviceCopymemoError : '',
pmtservicePaymentNotprocessed : '', pmtservicePaymentNotprocessed : '',
pmtservicePmtsrvNot : '', pmtservicePmtsrvNot : '',
pmtserviceEnabledFor : '', pmtserviceEnabledFor : '',
pmtserviceConnectoXero : '', pmtserviceConnectoXero : '',
pmtserviceServerFailed : '', pmtserviceServerFailed : '',
pmtserviceInvoiceNum : '', pmtserviceInvoiceNum : '',
pmtserviceInvoiceNotfound : '', pmtserviceInvoiceNotfound : '',
pmtserviceInvoiceInvalid : '', pmtserviceInvoiceInvalid : '',
pmtserviceInvoicePaid : '', pmtserviceInvoicePaid : '',
pmtserviceInvoiceCurrency : '', pmtserviceInvoiceCurrency : '',
pmtserviceCurrencyNotsup : '', pmtserviceCurrencyNotsup : '',
pmtserviceAmountDoesnot : '', pmtserviceAmountDoesnot : '',
pmtserviceMatchValue : '', pmtserviceMatchValue : '',
pmtserviceReportedByxero : '', pmtserviceReportedByxero : '',
pmtserviceHdrTxt1 : '', pmtserviceHdrTxt1 : '',
pmtserviceHdrTxt2 : '', pmtserviceHdrTxt2 : '',
pmtserviceHdrTxt3 : '', pmtserviceHdrTxt3 : '',
pmtserviceZecdataPrice : '', pmtserviceZecdataPrice : '',
pmtserviceZecdataTotal : '', pmtserviceZecdataTotal : '',
pmtserviceInvoiceItem : '', pmtserviceInvoiceItem : '',
pmtserviceInvoiceQty : '', pmtserviceInvoiceQty : '',
pmtserviceInvoicePrice : '', pmtserviceInvoicePrice : '',
pmtserviceInvoiceTotal : '', pmtserviceInvoiceTotal : '',
pmtservicePaymentConfirmed : '', pmtservicePaymentConfirmed : '',
pmtservicePaymentPending : '', pmtservicePaymentPending : '',
pmtserviceScanQrcode : '', pmtserviceScanQrcode : '',
pmtserviceCantScan : '', pmtserviceCantScan : '',
pmtserviceUseThis : '', pmtserviceUseThis : '',
pmtserviceWalletLink : '', pmtserviceWalletLink : '',
pmtserviceCopyAddress : '', pmtserviceCopyAddress : '',
pmtserviceCopyAmount : '', pmtserviceCopyAmount : '',
pmtserviceCopyMemo : '' pmtserviceCopyMemo : ''
} }
// //
constructor(private activatedRoute : ActivatedRoute, constructor(private activatedRoute : ActivatedRoute,
private http : HttpClient, private http : HttpClient,
private sanitizer: DomSanitizer, private sanitizer: DomSanitizer,
private notifierService : NotifierService, private notifierService : NotifierService,
private languageService : LanguageService ) {} private languageService : LanguageService ){
var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64');
this.reqHeaders = new HttpHeaders().set('Authorization', auth);
this.activatedRoute.queryParams.subscribe((params) => {
this.pmtData.ownerId = params["owner"];
this.pmtData.invoice = params["invoiceNo"];
this.pmtData.amount = +params["amount"];
this.pmtData.currency = params["currency"];
this.pmtData.shortcode = params["shortCode"];
this.getInvoiceData( this.pmtData );
});
this.chgUILanguage();
}
ngOnInit() { ngOnInit() {
var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64'); }
this.reqHeaders = new HttpHeaders().set('Authorization', auth);
this.activatedRoute.queryParams.subscribe((params) => {
this.pmtData.ownerId = params["owner"];
this.pmtData.invoice = params["invoiceNo"];
this.pmtData.amount = params["amount"];
this.pmtData.currency = params["currency"];
this.pmtData.shortcode = params["shortCode"];
this.getInvoiceData( this.pmtData );
});
this.chgUILanguage();
}
getInvoiceData( reqData : PmtData ) { getInvoiceData( reqData : PmtData ) {
//this.getXeroInvoiceData( reqData );
let obs = this.http.post<{reportType: number, order: Order, shop: string}>
(this.beUrl+'invdata',
{payload: reqData},
{headers: this.reqHeaders, observe: 'response' }
);
obs.subscribe((invoiceData) => {
if(invoiceData.status == 201) {
this.reportType = invoiceData.body!.reportType;
this.order = invoiceData.body!.order;
this.shop = invoiceData.body!.shop;
this.orderId = String(this.order._id);
// // console.log('Generating QRCode....')
// Verify owner id ( Status = 1 if not exists )
// ( Status = 2 if service not available for user )
//
// console.log('getOwner -> '+ reqData.ownerId);
// console.log('received amount -> ' + reqData.amount);
const ownParams = new HttpParams().append('id', reqData.ownerId);
let obs = this.http.get<{message:string, owner: any}>
( this.beUrl+'api/ownerid',
{ headers: this.reqHeaders,
params: ownParams,
observe: 'response'});
obs.subscribe((OwnerDataResponse) => {
//console.log('api/getowner', OwnerDataResponse.status);
if (OwnerDataResponse.status == 200) {
this.owner = OwnerDataResponse.body!.owner;
console.log('Owner => ' + this.owner.name );
//
// ==> remove "== false" for production enviroment
//
if ( this.owner.invoices ) {
// process data
console.log("Owner check passed!!!");
this.getXeroInvoiceData( reqData );
} else {
console.log("Owner check failed!!!")
this.reportType = 2;
};
} else {
if ( OwnerDataResponse.status == 204 ) {
console.log('Res.Status = ' + OwnerDataResponse.status)
console.log('Owner id not found!!!');
this.reportType = 1;
}
}});
}
getXeroInvoiceData( reqData : PmtData ) { this.codeString = `zcash:${this.order.address}?amount=${this.order.totalZec.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGo Order::'.concat(this.orderId).concat(' Invoice: ').concat(this.order.externalInvoice)))}`;
/* var qrcode = new QRCode(document.getElementById("invoice-qr"), {
// Call test Xero API text: this.codeString,
let url : string = "http://localhost:3000/xero/" + reqData.invoice; logo: "/assets/zcash.png",
this.http width: 180,
.get<any>(url) height: 180,
*/ logoWidth: 50,
console.log('>> find current zcash price'); logoHeight: 50,
this.getPrice(this.owner.currency); correctLevel: QRCode.CorrectLevel.H
});
console.log('get Invoice -> ' + reqData.invoice); this.zcashUrl = this.sanitizer.bypassSecurityTrustUrl(this.codeString);
let invParams = new HttpParams(); } else {
invParams = invParams.append('address', this.owner.address); this.reportType = invoiceData.body!.reportType;
invParams = invParams.append('inv', reqData.invoice); console.log('reportType ' + invoiceData.body!.reportType + ' code ' + invoiceData.status);
let inv = this.http.get<{message:string, invData: any}> }
( this.beUrl+'api/invdata', });
{ headers: this.reqHeaders, }
params: invParams,
observe: 'response'});
inv.subscribe( invDataResponse => {
// console.log('Response from ZGo-Xero');
// console.log(invDataResponse.status);
this.invData_buff = invDataResponse.body;
this.invData.inv_Type = this.invData_buff.invdata.inv_Type;
this.invData.inv_Id = this.invData_buff.invdata.inv_Id;
this.invData.inv_No = this.invData_buff.invdata.inv_No;
this.invData.inv_Contact = this.invData_buff.invdata.inv_Contact;
this.invData.inv_Currency = this.invData_buff.invdata.inv_Currency;
this.invData.inv_CurrencyRate = this.invData_buff.invdata.inv_CurrencyRate;
this.invData.inv_Total = this.invData_buff.invdata.inv_Total;
this.invData.inv_Status = this.invData_buff.invdata.inv_Status;
this.invData.inv_Date = this.invData_buff.invdata.inv_Date;
this.invData.inv_shortCode = reqData.shortcode;
/*
console.log('>>> inv_Type -> ' + this.invData.inv_Type);
console.log('>>> inv_Id -> ' + this.invData.inv_Id);
console.log('>>> inv_No -> ' + this.invData.inv_No);
console.log('>>> inv_Contact -> ' + this.invData.inv_Contact);
console.log('>>> inv_Currency-> ' + this.invData.inv_Currency);
console.log('>>> inv_CurrencyRate -> ' + this.invData.inv_CurrencyRate);
console.log('>>> inv_Total -> ' + this.invData.inv_Total);
console.log('>>> inv_Status-> ' + this.invData.inv_Status);
console.log('>>> inv_Date -> ' + this.invData.inv_Date);
*/
if ( this.invData.inv_Type == 'ACCREC' ) {
console.log('Invoice type is correct!!');
// Test if invoice is not already paid
if ( this.invData.inv_Status == 'AUTHORISED') {
console.log('invoice is payable');
// Test if Invoice's currency is supported
if ( this.invData.inv_Currency == reqData.currency ) {
console.log('Invoice currency supported');
// Test if requested amount is as reported by Xero
if ( this.invData.inv_Total == reqData.amount ) {
console.log('Invoice amount Ok - create Order');
// =====> Create order here
this.createOrder();
//
} else {
console.log('Invoice amount does not match')
this.reportType = 8;
}
} else {
console.log('Invoice currency not supported');
this.reportType = 7;
}
} else {
console.log('Invoice already paid');
this.reportType = 6;
}
} else {
console.log('Invoice type is invalid' );
this.reportType = 5;
}
},
error => {
console.log("Error while getting invData!!!");
console.log(error);
console.log(error.status);
if ( error.status == 500 ) {
// Assume that invoice was not found by haskell server
this.reportType = 4;
}
}); getIconStyle(order : Order) {
} if( order.paid )
return "font-size: 14px; color: #72cc50; margin-bottom: -2px;";
return "color: #FB4F14; margin-bottom: -2px; cursor: pointer;";
createOrder() { }
this.reportType = 0;
// console.log('Starting order generation');
// console.log('>> find current zcash price');
this.order = { copyAddress() {
_id: '', if (!navigator.clipboard) {
address: this.owner.address, // alert("Copy functionality not supported");
session: 'Xero-' + this.owner._id, this.notifierService
currency: this.owner.currency, .showNotification(this.vE.pmtserviceCopyNotavail,
timestamp: new Date(Date.now()).toISOString(), this.vE.pmtserviceNotservClose,
closed: true, "error",
totalZec: this.invData.inv_Total/this.zPrice, this.vE.pmtserviceNotservError);
price: this.zPrice, }
total: this.invData.inv_Total, try {
paid: false, navigator.clipboard.writeText(this.order.address);
externalInvoice: this.invData.inv_No, } catch (err) {
shortCode: this.invData.inv_shortCode, this.notifierService
token: '', .showNotification(this.vE.pmtserviceCopyaddressError,
lines: [{qty: 1, this.vE.pmtserviceNotservClose,
name: 'Invoice from ' + this.owner.name + '[' + this.invData.inv_No + ']', "error",
cost: this.invData.inv_Total}] this.vE.pmtserviceNotservError);
}; // console.error("Error", err);
}
}
let obs = this.http.post<{message: string, order: Order}> copyAmount() {
(this.beUrl+'api/orderx', if (!navigator.clipboard) {
{payload: this.order}, // alert("Copy functionality not supported");
{ headers: this.reqHeaders } this.notifierService
); .showNotification(this.vE.pmtserviceCopyNotavail,
obs.subscribe((orderData) => { this.vE.pmtserviceNotservClose,
// console.log('Order created'); "error",
this.vE.pmtserviceNotservError);
}
try {
navigator.clipboard.writeText(this.order.totalZec.toString());
} catch (err) {
this.notifierService
.showNotification(this.vE.pmtserviceCopyamountError,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
// console.error("Error", err);
}
}
// console.log(orderData.order); copyMemo() {
this.order = orderData.order if (!navigator.clipboard) {
console.log('>> order -> ' + JSON.stringify(this.order)); // alert("Copy functionality not supported");
this.orderId = String(this.order._id); this.notifierService
.showNotification(this.vE.pmtserviceCopyNotavail,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
}
try {
navigator.clipboard.writeText("ZGo Order::" + this.orderId + " Invoice: " + this.order.externalInvoice);
} catch (err) {
this.notifierService
.showNotification(this.vE.pmtserviceCopymemoError,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
// console.error("Error", err);
}
}
// console.log('Generating QRCode....') chgUILanguage(){
console.log('PMTSERVICE.chgUILanguage Called ');
this.languageService.getViewElements('pmtservice').subscribe(
response => {
console.log('Received >> ', response );
console.log('Language Code : ', response.language);
console.log('Component Name : ',response.component);
console.log('Language data : ',response.data);
this.codeString = `zcash:${this.order.address}?amount=${this.order.totalZec.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGo Order::'.concat(this.orderId).concat(' Invoice: ').concat(orderData.order.externalInvoice)))}`; this.vE.pmtserviceInvalidOwnerid = response.data.pmtservice_invalid_ownerid;
this.vE.pmtserviceNotservClose = response.data.pmtservice_notserv_close;
this.vE.pmtserviceNotservError = response.data.pmtservice_notserv_error;
this.vE.pmtserviceCopyNotavail = response.data.pmtservice_copy_notavail;
this.vE.pmtserviceCopyaddressError = response.data.pmtservice_copyaddress_error;
this.vE.pmtserviceCopyamountError = response.data.pmtservice_copyamount_error;
this.vE.pmtserviceCopymemoError = response.data.pmtservice_copymemo_error;
this.vE.pmtservicePaymentNotprocessed = response.data.pmtservice_payment_notprocessed;
this.vE.pmtservicePmtsrvNot = response.data.pmtservice_pmtsrv_not;
this.vE.pmtserviceEnabledFor = response.data.pmtservice_enabled_for;
this.vE.pmtserviceConnectoXero = response.data.pmtservice_connecto_xero;
this.vE.pmtserviceServerFailed = response.data.pmtservice_server_failed;
this.vE.pmtserviceInvoiceNum = response.data.pmtservice_invoice_num;
this.vE.pmtserviceInvoiceNotfound = response.data.pmtservice_invoice_notfound;
this.vE.pmtserviceInvoiceInvalid = response.data.pmtservice_invoice_invalid;
this.vE.pmtserviceInvoicePaid = response.data.pmtservice_invoice_paid;
this.vE.pmtserviceInvoiceCurrency = response.data.pmtservice_invoice_currency;
this.vE.pmtserviceCurrencyNotsup = response.data.pmtservice_currensy_notsup;
this.vE.pmtserviceAmountDoesnot = response.data.pmtservice_amount_doesnot;
this.vE.pmtserviceMatchValue = response.data.pmtservice_match_value;
this.vE.pmtserviceReportedByxero = response.data.pmtservice_reported_byxero;
this.vE.pmtserviceHdrTxt1 = response.data.pmtservice_hdr_txt1;
this.vE.pmtserviceHdrTxt2 = response.data.pmtservice_hdr_txt2;
this.vE.pmtserviceHdrTxt3 = response.data.pmtservice_hdr_txt3;
this.vE.pmtserviceZecdataPrice = response.data.pmtservice_zecdata_price;
this.vE.pmtserviceZecdataTotal = response.data.pmtservice_zecdata_total;
this.vE.pmtserviceInvoiceItem = response.data.pmtservice_invoice_item;
this.vE.pmtserviceInvoiceQty = response.data.pmtservice_invoice_qty;
this.vE.pmtserviceInvoicePrice = response.data.pmtservice_invoice_price;
this.vE.pmtserviceInvoiceTotal = response.data.pmtservice_invoice_total;
this.vE.pmtservicePaymentConfirmed = response.data.pmtservice_payment_confirmed;
this.vE.pmtservicePaymentPending = response.data.pmtservice_payment_pending;
this.vE.pmtserviceScanQrcode = response.data.pmtservice_scan_qrcode;
this.vE.pmtserviceCantScan = response.data.pmtservice_cant_scan;
this.vE.pmtserviceUseThis = response.data.pmtservice_use_this;
this.vE.pmtserviceWalletLink = response.data.pmtservice_wallet_link;
this.vE.pmtserviceCopyAddress = response.data.pmtservice_copy_address;
this.vE.pmtserviceCopyAmount = response.data.pmtservice_copy_amount;
this.vE.pmtserviceCopyMemo = response.data.pmtservice_copy_memo;
var qrcode = new QRCode(document.getElementById("payment-qr"), { },
text: this.codeString, error => { console.log('Error >> ',error); }
logo: "/assets/zcash.png", );
width: 180, }
height: 180,
logoWidth: 50,
logoHeight: 50,
correctLevel: QRCode.CorrectLevel.H
});
this.zcashUrl = this.sanitizer.bypassSecurityTrustUrl(this.codeString);
}, error => {
console.log(error.message);
});
}
getIconStyle(order : Order) {
if( order.paid )
return "font-size: 14px; color: #72cc50; margin-bottom: -2px;";
return "color: #FB4F14; margin-bottom: -2px; cursor: pointer;";
}
getPrice(currency: string){
//var currency = 'usd';
const params = new HttpParams().append('currency', currency);
let obs = this.http.get<{message: string, price: any}>(this.beUrl+'api/price', { headers:this.reqHeaders, params: params, observe: 'response'});
obs.subscribe((PriceData) => {
if (PriceData.status == 200) {
this.zPrice = PriceData.body!.price.price;
console.log("price", this.zPrice);
} else {
console.log('No price found for currency', currency);
this.zPrice = 1.0;
}
});
return obs;
}
copyAddress() {
if (!navigator.clipboard) {
// alert("Copy functionality not supported");
this.notifierService
.showNotification(this.vE.pmtserviceCopyNotavail,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
}
try {
navigator.clipboard.writeText(this.order.address);
} catch (err) {
this.notifierService
.showNotification(this.vE.pmtserviceCopyaddressError,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
// console.error("Error", err);
}
}
copyAmount() {
if (!navigator.clipboard) {
// alert("Copy functionality not supported");
this.notifierService
.showNotification(this.vE.pmtserviceCopyNotavail,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
}
try {
navigator.clipboard.writeText(this.order.totalZec.toString());
} catch (err) {
this.notifierService
.showNotification(this.vE.pmtserviceCopyamountError,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
// console.error("Error", err);
}
}
copyMemo() {
if (!navigator.clipboard) {
// alert("Copy functionality not supported");
this.notifierService
.showNotification(this.vE.pmtserviceCopyNotavail,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
}
try {
navigator.clipboard.writeText("ZGo Order::" + this.orderId + " Invoice: " + this.order.externalInvoice);
} catch (err) {
this.notifierService
.showNotification(this.vE.pmtserviceCopymemoError,
this.vE.pmtserviceNotservClose,
"error",
this.vE.pmtserviceNotservError);
// console.error("Error", err);
}
}
chgUILanguage(){
console.log('PMTSERVICE.chgUILanguage Called ');
this.languageService.getViewElements('pmtservice').subscribe(
response => {
console.log('Received >> ', response );
console.log('Language Code : ', response.language);
console.log('Component Name : ',response.component);
console.log('Language data : ',response.data);
this.vE.pmtserviceInvalidOwnerid = response.data.pmtservice_invalid_ownerid;
this.vE.pmtserviceNotservClose = response.data.pmtservice_notserv_close;
this.vE.pmtserviceNotservError = response.data.pmtservice_notserv_error;
this.vE.pmtserviceCopyNotavail = response.data.pmtservice_copy_notavail;
this.vE.pmtserviceCopyaddressError = response.data.pmtservice_copyaddress_error;
this.vE.pmtserviceCopyamountError = response.data.pmtservice_copyamount_error;
this.vE.pmtserviceCopymemoError = response.data.pmtservice_copymemo_error;
this.vE.pmtservicePaymentNotprocessed = response.data.pmtservice_payment_notprocessed;
this.vE.pmtservicePmtsrvNot = response.data.pmtservice_pmtsrv_not;
this.vE.pmtserviceEnabledFor = response.data.pmtservice_enabled_for;
this.vE.pmtserviceConnectoXero = response.data.pmtservice_connecto_xero;
this.vE.pmtserviceServerFailed = response.data.pmtservice_server_failed;
this.vE.pmtserviceInvoiceNum = response.data.pmtservice_invoice_num;
this.vE.pmtserviceInvoiceNotfound = response.data.pmtservice_invoice_notfound;
this.vE.pmtserviceInvoiceInvalid = response.data.pmtservice_invoice_invalid;
this.vE.pmtserviceInvoicePaid = response.data.pmtservice_invoice_paid;
this.vE.pmtserviceInvoiceCurrency = response.data.pmtservice_invoice_currency;
this.vE.pmtserviceCurrencyNotsup = response.data.pmtservice_currensy_notsup;
this.vE.pmtserviceAmountDoesnot = response.data.pmtservice_amount_doesnot;
this.vE.pmtserviceMatchValue = response.data.pmtservice_match_value;
this.vE.pmtserviceReportedByxero = response.data.pmtservice_reported_byxero;
this.vE.pmtserviceHdrTxt1 = response.data.pmtservice_hdr_txt1;
this.vE.pmtserviceHdrTxt2 = response.data.pmtservice_hdr_txt2;
this.vE.pmtserviceHdrTxt3 = response.data.pmtservice_hdr_txt3;
this.vE.pmtserviceZecdataPrice = response.data.pmtservice_zecdata_price;
this.vE.pmtserviceZecdataTotal = response.data.pmtservice_zecdata_total;
this.vE.pmtserviceInvoiceItem = response.data.pmtservice_invoice_item;
this.vE.pmtserviceInvoiceQty = response.data.pmtservice_invoice_qty;
this.vE.pmtserviceInvoicePrice = response.data.pmtservice_invoice_price;
this.vE.pmtserviceInvoiceTotal = response.data.pmtservice_invoice_total;
this.vE.pmtservicePaymentConfirmed = response.data.pmtservice_payment_confirmed;
this.vE.pmtservicePaymentPending = response.data.pmtservice_payment_pending;
this.vE.pmtserviceScanQrcode = response.data.pmtservice_scan_qrcode;
this.vE.pmtserviceCantScan = response.data.pmtservice_cant_scan;
this.vE.pmtserviceUseThis = response.data.pmtservice_use_this;
this.vE.pmtserviceWalletLink = response.data.pmtservice_wallet_link;
this.vE.pmtserviceCopyAddress = response.data.pmtservice_copy_address;
this.vE.pmtserviceCopyAmount = response.data.pmtservice_copy_amount;
this.vE.pmtserviceCopyMemo = response.data.pmtservice_copy_memo;
},
error => { console.log('Error >> ',error); }
);
}
} }

View file

@ -14,7 +14,8 @@ var Buffer = require('buffer/').Buffer;
}) })
export class ReceiptService { export class ReceiptService {
beUrl = ConfigData.Be_URL; beUrl = ConfigData.Be_URL;
private dataStore: {order: Order, owner: Owner } = { private dataStore: {order: Order, owner: Owner, name: string } = {
name: '',
owner: { owner: {
_id: '', _id: '',
name: '', name: '',
@ -58,34 +59,30 @@ export class ReceiptService {
public readonly orderUpdate: Observable<Order> = this._orderUpdated.asObservable(); public readonly orderUpdate: Observable<Order> = this._orderUpdated.asObservable();
public _nameUpdated: BehaviorSubject<string> = new BehaviorSubject(this.dataStore.owner.name); public _nameUpdated: BehaviorSubject<string> = new BehaviorSubject(this.dataStore.owner.name);
public readonly nameUpdate: Observable<string>= this._nameUpdated.asObservable(); public readonly nameUpdate: Observable<string>= this._nameUpdated.asObservable();
public readonly ownerUpdate; //public readonly ownerUpdate;
private reqHeaders: HttpHeaders; private reqHeaders: HttpHeaders;
private session: null|string;
private params: HttpParams; private params: HttpParams;
constructor( constructor(
private http: HttpClient, private http: HttpClient,
public userService: UserService public userService: UserService
) { ) {
this.session = localStorage.getItem('s4z_token'); //this.session = localStorage.getItem('s4z_token');
this.params = new HttpParams(); this.params = new HttpParams();
var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64'); var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64');
this.reqHeaders = new HttpHeaders().set('Authorization', auth); this.reqHeaders = new HttpHeaders().set('Authorization', auth);
this.ownerUpdate = userService.ownerUpdate; //this.ownerUpdate = userService.ownerUpdate;
} }
getOrderById(id:string, token: string) { getOrderById(id:string, token: string) {
let obs = this.http.get<{message: string, order: any}>(this.beUrl+'order/'+id, { headers:this.reqHeaders, params: this.params.append("token", token), observe: 'response'}); let obs = this.http.get<{message: string, order: any, shop: string}>(this.beUrl+'order/'+id, { headers:this.reqHeaders, params: this.params.append("token", token), observe: 'response'});
obs.subscribe((OrderDataResponse) => { obs.subscribe((OrderDataResponse) => {
if (OrderDataResponse.status == 200) { if (OrderDataResponse.status == 200) {
this.dataStore.order = OrderDataResponse.body!.order; this.dataStore.order = OrderDataResponse.body!.order;
this.dataStore.name = OrderDataResponse.body!.shop;
this._orderUpdated.next(Object.assign({}, this.dataStore).order); this._orderUpdated.next(Object.assign({}, this.dataStore).order);
this.userService.getOwner(); this._nameUpdated.next(Object.assign({}, this.dataStore).name);
this.ownerUpdate.subscribe((owner) => {
this.dataStore.owner = owner;
this._nameUpdated.next(Object.assign({}, this.dataStore).owner.name);
});
} else { } else {
this._orderUpdated.next(Object.assign({}, this.dataStore).order); this._orderUpdated.next(Object.assign({}, this.dataStore).order);
console.log('No order found'); console.log('No order found');

View file

@ -42,7 +42,7 @@
<mat-form-field class="full-width" <mat-form-field class="full-width"
appearance="fill"> appearance="fill">
<mat-label>{{ vE.settingsVkeyLbl }}</mat-label> <mat-label>{{ vE.settingsVkeyLbl }}</mat-label>
<textarea matInput placeholder="{{ vE.settingsVkeyPlaceholder }}" <textarea matInput [readonly]="vKaccess" placeholder="{{ vE.settingsVkeyPlaceholder }}"
formControlName="vKey"> formControlName="vKey">
</textarea> </textarea>
</mat-form-field> </mat-form-field>

View file

@ -29,7 +29,6 @@ export class SettingsComponent implements OnInit {
owner: Owner; owner: Owner;
useZats: boolean; useZats: boolean;
proVersion: boolean = false; proVersion: boolean = false;
useVKey: boolean = false;
linkMsg: string = ''; linkMsg: string = '';
xeroAccCod: string = ''; xeroAccCod: string = '';
saveAccOk: boolean = false; saveAccOk: boolean = false;
@ -117,6 +116,7 @@ export class SettingsComponent implements OnInit {
}; };
// //
languageRdy = new Subject<boolean>(); languageRdy = new Subject<boolean>();
vKaccess = true;
// ------------------------------------------------------------ // ------------------------------------------------------------
constructor( constructor(
@ -128,13 +128,11 @@ export class SettingsComponent implements OnInit {
private dialogRef: MatDialogRef<SettingsComponent>, private dialogRef: MatDialogRef<SettingsComponent>,
@Inject(MAT_DIALOG_DATA) public data: {o: Owner}) { @Inject(MAT_DIALOG_DATA) public data: {o: Owner}) {
this.useZats = data.o.zats; this.useZats = data.o.zats;
this.useVKey = data.o.payconf;
this.settingsForm = fb.group({ this.settingsForm = fb.group({
name: [data.o.name, Validators.required], name: [data.o.name, Validators.required],
currency: [data.o.currency, Validators.required], currency: [data.o.currency, Validators.required],
useZats: [data.o.zats, Validators.required], useZats: [data.o.zats, Validators.required],
useVKey: [data.o.payconf, Validators.required], useVKey: [data.o.payconf, Validators.required],
// proVersion: [data.invoices, Validators.required],
vKey: [data.o.viewkey] vKey: [data.o.viewkey]
}); });
this.accCodForm = fb.group ({ this.accCodForm = fb.group ({
@ -142,7 +140,8 @@ export class SettingsComponent implements OnInit {
}); });
if (data.o.payconf) { if (data.o.payconf) {
this.settingsForm.get('vKey')!.enable(); this.vKaccess = false;
//this.settingsForm.get('vKey')!.enable();
} }
this.owner = data.o; this.owner = data.o;
this.viewkey = data.o.viewkey; this.viewkey = data.o.viewkey;
@ -181,23 +180,24 @@ export class SettingsComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.settingsForm.get('vKey')!.disable(); //this.settingsForm.get('vKey')!.disable();
// //
this.chgUILanguage(); this.vKaccess = true;
//console.log('SETTINGS: Return from chgUILanguage()'); this.chgUILanguage();
// //console.log('SETTINGS: Return from chgUILanguage()');
this.languageRdy.subscribe ( //
data => { this.languageRdy.subscribe (
this.linkMsg = this.vE.settingsLink2Xero; data => {
this.pmtServiceURL + ''; this.linkMsg = this.vE.settingsLink2Xero;
if ( this.linked2Xero ) { this.pmtServiceURL + '';
this.linkMsg = this.vE.settingsRelink2Xero; //'Relink to Xero'; if ( this.linked2Xero ) {
this.pmtServiceURL = this.linkMsg = this.vE.settingsRelink2Xero; //'Relink to Xero';
'https://zgo.cash/pmtservice?owner=' + this.pmtServiceURL =
this.owner._id + 'https://zgo.cash/pmtservice?owner=' +
'&invoiceNo=[INVOICENUMBER]&currency=[CURRENCY]&amount=[AMOUNTDUE]&shortCode=[SHORTCODE]'; this.owner._id +
} '&invoiceNo=[INVOICENUMBER]&currency=[CURRENCY]&amount=[AMOUNTDUE]&shortCode=[SHORTCODE]';
}); }
});
} }
safeURL(s: string){ safeURL(s: string){
@ -206,7 +206,7 @@ export class SettingsComponent implements OnInit {
close() { close() {
this.dialogRef.close(); this.dialogRef.close(null);
} }
closeIntegration() { closeIntegration() {
@ -223,8 +223,8 @@ export class SettingsComponent implements OnInit {
this.owner.currency = this.settingsForm.value.currency; this.owner.currency = this.settingsForm.value.currency;
this.owner.zats = this.settingsForm.value.useZats; this.owner.zats = this.settingsForm.value.useZats;
this.owner.payconf = this.settingsForm.value.useVKey; this.owner.payconf = this.settingsForm.value.useVKey;
this.viewkey = this.settingsForm.value.vKey; this.owner.viewkey = this.settingsForm.value.vKey;
//this.owner.invoices = this.settingsForm.value.proVersion console.log('Settings component key: ' + this.owner.viewkey);
this.dialogRef.close(this.owner); this.dialogRef.close(this.owner);
} }
@ -237,15 +237,16 @@ export class SettingsComponent implements OnInit {
} }
onChangeVKeyOn(ob: MatSlideToggleChange) { onChangeVKeyOn(ob: MatSlideToggleChange) {
// console.log("Viewing key switch is " + // console.log("Viewing key switch is " +
// ( ob.checked ? "[ON]." : "[OFF]." ) ); // ( ob.checked ? "[ON]." : "[OFF]." ) );
this.useVKey = ob.checked; if ( ob.checked ) {
//this.settingsForm.get('vKey')!.enable();
if ( ob.checked ) this.vKaccess = false;
this.settingsForm.get('vKey')!.enable(); } else {
else //this.settingsForm.get('vKey')!.disable();
this.settingsForm.get('vKey')!.disable(); this.vKaccess = true;
}
} }

View file

@ -162,17 +162,54 @@ export class UserService{
} }
saveOwnerSettings(o: Owner) { saveOwnerSettings(o: Owner) {
let obs = this.http.post(this.beUrl + 'api/ownersettings', {payload: o}, {headers: this.reqHeaders, params: this.reqParams}); console.log('saveOwnerSettings: ' + o.viewkey);
if(o.viewkey.length > 20) {
this.saveOwnerViewingKey(o.viewkey).subscribe({
next: () => {
let obs = this.http.post(this.beUrl + 'api/ownersettings', {payload: o}, {headers: this.reqHeaders, params: this.reqParams});
obs.subscribe({
next: () => {
this.getOwner();
},
error: (error) => {
if ( error.status == 500 ){
this.notifierService.showNotification("Saving settings failed", "Close", "error")
}
}
});
}
});
} else {
let obs = this.http.post(this.beUrl + 'api/ownersettings', {payload: o}, {headers: this.reqHeaders, params: this.reqParams});
obs.subscribe({
next: () => {
this.getOwner();
},
error: (error) => {
if ( error.status == 500 ){
this.notifierService.showNotification("Saving settings failed", "Close", "error")
}
}
});
}
}
saveOwnerViewingKey(vk: string){
let obs = this.http.post(this.beUrl + 'api/ownervk', {payload: vk}, {headers: this.reqHeaders, params: this.reqParams});
obs.subscribe({ obs.subscribe({
next: () => { next: () => {
this.getOwner(); this.getOwner();
}, },
error: (error) => { error: (error) => {
if ( error.status == 500 ){ if (error.status == 400) {
this.notifierService.showNotification("Saving settings failed", "Close", "error") this.notifierService.showNotification('Invalid viewing key, changes not saved', 'Close', 'error');
} else if (error.status == 403) {
this.notifierService.showNotification('Viewing key does not match shop, changes not saved', 'Close', 'error');
} }
} }
}) });
return obs;
} }
getOwner() { getOwner() {

View file

@ -65,8 +65,8 @@ export class XeroService {
return obs; return obs;
} }
getXeroAccessToken(code: string, address: string){ getXeroAccessToken(code: string){
const params = this.reqParams.append('code', code).append('address', address); const params = this.reqParams.append('code', code);
let obs = this.http.get(this.beUrl + 'api/xerotoken' , {headers: this.reqHeaders, params: params, observe: 'response'}); let obs = this.http.get(this.beUrl + 'api/xerotoken' , {headers: this.reqHeaders, params: params, observe: 'response'});
return obs; return obs;
} }

View file

@ -77,7 +77,7 @@ export class XeroRegComponent implements OnInit {
this.activatedRoute.queryParams.subscribe((params) => { this.activatedRoute.queryParams.subscribe((params) => {
//console.log(params); //console.log(params);
if (params.state === this.owner.address.substring(0,6)) { if (params.state === this.owner.address.substring(0,6)) {
this.xeroService.getXeroAccessToken(params.code, this.owner.address).subscribe(tokenData => { this.xeroService.getXeroAccessToken(params.code).subscribe(tokenData => {
if (tokenData.status == 200) { if (tokenData.status == 200) {
//console.log(tokenData.body!); //console.log(tokenData.body!);
this.flag = true; this.flag = true;

View file

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Z-Go!</title> <title>ZGo - The Zcash Register</title>
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">