392 lines
14 KiB
TypeScript
392 lines
14 KiB
TypeScript
import { Component, OnInit } from '@angular/core';
|
|
import { Router, ActivatedRoute, Params } from "@angular/router";
|
|
import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http";
|
|
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
|
import { PmtData } from "./pmtservice.model";
|
|
import { XeroInvoice } from "./xeroinvoice.model";
|
|
import { Owner } from '../owner.model';
|
|
// import { Item } from '../items/item.model'
|
|
import { Order } from '../order/order.model'
|
|
import { ConfigData } from '../configdata';
|
|
import { faCheck, faHourglass } from '@fortawesome/free-solid-svg-icons';
|
|
|
|
import { NotifierService } from '../notifier.service';
|
|
|
|
var QRCode = require('easyqrcodejs');
|
|
var URLSafeBase64 = require('urlsafe-base64');
|
|
var Buffer = require('buffer/').Buffer;
|
|
|
|
@Component({
|
|
selector: 'app-pmtservice',
|
|
templateUrl: './pmtservice.component.html',
|
|
styleUrls: ['./pmtservice.component.css']
|
|
})
|
|
|
|
export class PmtserviceComponent implements OnInit {
|
|
|
|
faCheck = faCheck;
|
|
faHourglass = faHourglass;
|
|
|
|
beUrl = ConfigData.Be_URL;
|
|
private reqHeaders: HttpHeaders = new HttpHeaders();
|
|
|
|
public pmtData : PmtData = {
|
|
ownerId :'',
|
|
invoice: '',
|
|
amount: 0,
|
|
currency: '',
|
|
shortcode: ''
|
|
};
|
|
|
|
public invData : XeroInvoice = {
|
|
inv_Type : '',
|
|
inv_Id : '',
|
|
inv_No : '',
|
|
inv_Contact : '',
|
|
inv_Currency : '',
|
|
inv_CurrencyRate : 0,
|
|
inv_Status : '',
|
|
inv_Total : 0,
|
|
inv_Date : new Date(),
|
|
inv_shortCode : '',
|
|
inv_ProcDate : new Date()
|
|
};
|
|
|
|
public owner: Owner = {
|
|
_id: '',
|
|
address: '',
|
|
name: '',
|
|
currency: 'usd',
|
|
tax: false,
|
|
taxValue: 0,
|
|
vat: false,
|
|
vatValue: 0,
|
|
first: '',
|
|
last: '',
|
|
email: '',
|
|
street: '',
|
|
city: '',
|
|
state: '',
|
|
postal: '',
|
|
phone: '',
|
|
paid: false,
|
|
website: '',
|
|
country: '',
|
|
zats: false,
|
|
invoices: false,
|
|
expiration: new Date(Date.now()).toISOString(),
|
|
payconf: false,
|
|
viewkey: '',
|
|
crmToken: ''
|
|
};
|
|
|
|
public order: Order = {
|
|
_id : '',
|
|
address: '',
|
|
session: '',
|
|
timestamp: '',
|
|
closed: false,
|
|
currency: '',
|
|
price: 0,
|
|
total: 0,
|
|
totalZec: 0,
|
|
paid: false,
|
|
externalInvoice: '',
|
|
shortCode: '',
|
|
lines: [
|
|
{
|
|
qty: 1,
|
|
name: '',
|
|
cost:0
|
|
}
|
|
]
|
|
};
|
|
|
|
private invData_raw : string = '';
|
|
private invData_buff : any = null;
|
|
|
|
public reportType = 1000;
|
|
public Status = 0;
|
|
|
|
codeString: string = '';
|
|
zcashUrl: SafeUrl = '';
|
|
zPrice: number = 1.0;
|
|
name: string = '';
|
|
error: boolean = false;
|
|
orderId : string = '';
|
|
|
|
constructor(private activatedRoute : ActivatedRoute,
|
|
private http : HttpClient,
|
|
private sanitizer: DomSanitizer,
|
|
private notifierService : NotifierService ) {}
|
|
|
|
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"];
|
|
// console.log(this.pmtData);
|
|
|
|
this.getInvoiceData( this.pmtData );
|
|
});
|
|
|
|
}
|
|
|
|
getInvoiceData( reqData : PmtData ) {
|
|
|
|
//
|
|
// 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 ) {
|
|
|
|
/*
|
|
// Call test Xero API
|
|
let url : string = "http://localhost:3000/xero/" + reqData.invoice;
|
|
this.http
|
|
.get<any>(url)
|
|
*/
|
|
console.log('>> find current zcash price');
|
|
this.getPrice(this.owner.currency);
|
|
|
|
console.log('get Invoice -> ' + reqData.invoice);
|
|
let invParams = new HttpParams();
|
|
invParams = invParams.append('address', this.owner.address);
|
|
invParams = invParams.append('inv', reqData.invoice);
|
|
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;
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
|
|
createOrder() {
|
|
this.reportType = 0;
|
|
// console.log('Starting order generation');
|
|
// console.log('>> find current zcash price');
|
|
|
|
this.order = {
|
|
_id: '',
|
|
address: this.owner.address,
|
|
session: 'Xero-' + this.owner._id,
|
|
currency: this.owner.currency,
|
|
timestamp: new Date(Date.now()).toISOString(),
|
|
closed: true,
|
|
totalZec: this.invData.inv_Total/this.zPrice,
|
|
price: this.zPrice,
|
|
total: this.invData.inv_Total,
|
|
paid: false,
|
|
externalInvoice: this.invData.inv_No,
|
|
shortCode: this.invData.inv_shortCode,
|
|
lines: [{qty: 1,
|
|
name: 'Invoice from ' + this.owner.name + '[' + this.invData.inv_No + ']',
|
|
cost: this.invData.inv_Total}]
|
|
};
|
|
|
|
let obs = this.http.post<{message: string, order: Order}>
|
|
(this.beUrl+'api/orderx',
|
|
{payload: this.order},
|
|
{ headers: this.reqHeaders }
|
|
);
|
|
obs.subscribe((orderData) => {
|
|
// console.log('Order created');
|
|
|
|
// console.log(orderData.order);
|
|
this.order = orderData.order
|
|
console.log('>> order -> ' + JSON.stringify(this.order));
|
|
this.orderId = String(this.order._id);
|
|
|
|
// console.log('Generating QRCode....')
|
|
|
|
this.codeString = `zcash:${this.order.address}?amount=${this.order.totalZec.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGo Order::'.concat(this.orderId)))}`;
|
|
|
|
var qrcode = new QRCode(document.getElementById("payment-qr"), {
|
|
text: this.codeString,
|
|
logo: "/assets/zcash.png",
|
|
width: 180,
|
|
height: 180,
|
|
logoWidth: 50,
|
|
logoHeight: 50,
|
|
correctLevel: QRCode.CorrectLevel.H
|
|
});
|
|
|
|
this.codeString = `zcash:${this.order.address}?amount=${this.order.totalZec.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGo Order::'.concat(this.orderId)))}`;
|
|
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("Copy functionality not supported","Close","error");
|
|
}
|
|
try {
|
|
navigator.clipboard.writeText(this.order.address);
|
|
} catch (err) {
|
|
this.notifierService
|
|
.showNotification("Error copying address","Close","error");
|
|
// console.error("Error", err);
|
|
}
|
|
}
|
|
copyAmount() {
|
|
if (!navigator.clipboard) {
|
|
// alert("Copy functionality not supported");
|
|
this.notifierService
|
|
.showNotification("Copy functionality not supported","Close","error");
|
|
}
|
|
try {
|
|
navigator.clipboard.writeText(this.order.totalZec.toString());
|
|
} catch (err) {
|
|
this.notifierService
|
|
.showNotification("Error while copying ammount","Close","error");
|
|
// console.error("Error", err);
|
|
}
|
|
}
|
|
|
|
copyMemo() {
|
|
if (!navigator.clipboard) {
|
|
// alert("Copy functionality not supported");
|
|
this.notifierService
|
|
.showNotification("Copy functionality not supported","Close","error");
|
|
}
|
|
try {
|
|
navigator.clipboard.writeText("ZGo Order::" + this.orderId);
|
|
} catch (err) {
|
|
this.notifierService
|
|
.showNotification("Error while copying Memo","Close","error");
|
|
// console.error("Error", err);
|
|
}
|
|
}
|
|
}
|