Tez Payment Request API - payment-request-api

I'm trying to integrate Google-Tez payment in my site, But When I'm calling request.show() getting error msg as
"Payee isn't a valid merchant"
, When i call checkCanMakePayment() getting error msg as
"Cannot query payment request"
and I enclose my code below. My UPI ID is "hsbc". Can anyone help me to troubleshoot this issue? and I need to know is there any process like merchant has to register with Google Tez
function onBuyClicked() {
const creditCardPaymentMethod = {
supportedMethods: 'basic-card',
data: {
supportedNetworks: ['visa', 'mastercard'],
supportedTypes: ['credit', 'debit']
}
};
const supportedInstruments = [
{
supportedMethods: ['https://tez.google.com/pay'],
//supportedMethods:[creditCardPaymentMethod],
data: {
pa:'**********',
pn:'**********',
tr:'123456ABCDEFSD',
url:'***********',
mc:'*********',
tn:'Purchase in Merchant'
}
}
];
var details =
{
total:
{
label:'Total',
amount: {
currency:'INR',
value:'10.01' //sample amount
}
},
displayItems: [
{
label:'Original Amount',
amount: {
currency:'INR',
value:'10.01'
}
}
]
};
var request =null;
try {
request = new PaymentRequest(supportedInstruments, details);
console.log(request);
/*request.show()
.then(function(result){
alert("hai");
})
.catch(function(err){
alert('Payment Request Error: '+ err.message+' 74');
});*/
}catch (e) {
alert('Payment Request Error: '+ e.message+'77');
console.log('Payment Request Error: '+ e.message);
//return;
}
if (!request) {
alert('Web payments are not supported in this browser 77');
console.log('Web payments are not supported in this browser.');
// return;
} 
var canMakePaymentPromise = checkCanMakePayment(request);
canMakePaymentPromise
.then(function(result){
showPaymentUI(request,result)
})
.catch(function(err){
console.log('Error in calling checkCanMakePayment: ' + err);
});
}
const canMakePaymentCache = 'canMakePaymentCache';
function checkCanMakePayment(request){
// Checks canMakePayment cache, and use the cache result if it exists.
if(sessionStorage.hasOwnProperty(canMakePaymentCache)){
return Promise.resolve(JSON.parse(sessionStorage[canMakePaymentCache]));
}
// If canMakePayment() isn't available, default to assuming that the method is supported
var canMakePaymentPromise = request.canMakePayment();
if(request.canMakePayment){
canMakePaymentPromise = request.canMakePayment();
}
return canMakePaymentPromise
.then(function(result){
sessionStorage[canMakePaymentCache] = result;
return result;
})
.catch(function (err){
alert('Error calling canMakePayment: '+ err);
console.log('Error calling canMakePayment: '+ err);
});
}
function showPaymentUI(request, canMakePayment){
if(!canMakePayment){
handleNotReadyToPay();
return;
}
// Set payment timeout.
var paymentTimeout = window.setTimeout(function(){
window.clearTimeout(paymentTimeout);
request.abort()
.then(function(){
alert('Payment timed out after 20 mins 129');
console.log('Payment timed out after 20 mins');
}).catch(function(){
alert('Unable to abort,user is in process of paying 132');
console.log('Unable to abort,user is in process of paying');
});
}, 20 * 60 * 1000);
request.show()
.then(function(paymentResponse){
window.clearTimeout(paymentTimeout);
alert("Request Success");
console.log(paymentResponse);
processResponse(paymentResponse); // Handle response from browser
})
.catch(function (err){
alert(err +'142');
console.log(err);
});
}
function handleNotReadyToPay(){
alert("Tez is not ready to handle 149");
}
function processResponse(paymentResponse){
var paymentResponseString = paymentResponseToJsonString(paymentResponse);
console.log(paymentResponseString);
/* fetch('/buy',{
method: 'POST',
headers: new Headers({'Content-Type':'application/json'}),
body:paymentResponseString
})
.then(function(buyResult){
console.log('Buy Result'+buyResult);
})
.catch(function(err){
console.log('Unable to process payment. '+err);
});*/
}
onBuyClicked();

"Payee isn't a valid merchant" error comes when you use customer VPA in place of merchant VPA in the 'pa' field.
Resolution:
Use VPA which is issued for the merchant.

Related

how to get callback return value in nestjs

I am going to use vonage for text service.
However, only node.js syntax exists, and the corresponding API is being used.
There is a phenomenon that the callback is executed later when trying to receive the values ​​returned from the callback to check for an error.
How can I solve this part? The code is below.
await vonage.message.sendSms(from, to, text, async (err, responseData) => {
if (err) {
console.log('1');
result.message = err;
} else {
if (responseData.messages[0]['status'] === '0') {
console.log('2');
} else {
console.log('3');
result.error = `Message failed with error: ${responseData.messages[0]['error-text']}`;
}
}
});
console.log(result);
return result;
When an error occurs as a result of executing the above code,
result{error:undefined}
3
Outputs are in order.
From what I can understand the issue is that you are passing a async callback. you could simply just give vonage.message.sendSms() a synchronous callback like so.
const result = {};
vonage.message.sendSms(from, to, text, (err, responseData) => {
if (err) {
console.log('1');
result.message = err;
} else {
if (responseData.messages[0]['status'] === '0') {
console.log('2');
} else {
console.log('3');
result.error = `Message failed with error: ${responseData.messages[0]['error-text']}`;
}
}
});
if you want to use async or promises I would suggest something like this
const sendSMS = (from, to, text) => new Promise( (resolve, reject) => {
vonage.message.sendSms(from, to, text, (err, responseData) => {
if (err) {
reject(err);
} else {
resolve(responseData);
}
});
});
// elsewhere
sendSMS(from, to, text)
.then(...)
.catch(...);

ldapjs handling client.search response

I have the below code which is binding to an LDAP server and I want to return the user that I have added "ab" within the "interviewees" group (code taken from ldapjs client api page). I can see I am getting back a response from the server with the expected EventEmitter object. I am expecting to see information about the user when calling logging console.log() on the searchEntry object. I appear to have no searchEntry objects. Is my DN for my user correct? I am currently unsure whether the issue is with my query and I am not getting any data back or whether I am failing to process the response correctly?
const client = ldap.createClient({ url: 'ldap://' + LDAP_SERVER + ':' + LDAP_PORT });
// Connect and bind to the Active Directory.
const connectToClient = async () => {
const secret = LDAP_SECRET_KEY;
return await new Promise((resolve, reject) => {
client.bind(LDAP_USER, secret, function (err, res) {
if (err) {
console.error(err);
reject('Failed to connect to LDAP server');
} else {
resolve('Connected to LDAP server');
}
});
});
};
onst searchADForUser = async () => {
return await new Promise((resolve, reject) => {
client.search('CN=ab,OU=interviewees,OU=Users,OU=interview,DC=interview,DC=workspace,DC=com', function (err, res) {
if (err) {
console.error(err);
reject('Error searching LDAP server');
} else {
res.on('searchEntry', function (entry) {
console.log('entry: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
});
resolve(res);
}
});
});
};
const handler = async (event) => {
try {
return responses.success(
await connectToClient().then(async function(event) {
console.log(event);
await searchADForUser().then(function(event) {
console.log(event);
}).catch(function(event) {
console.log(event);
})
}).catch(function(event) {
console.log(event);
})
);
} catch (err) {
console.error(err);
return responses.error(err);
} finally {
client.unbind();
}
};
The active directory structure is below
The central issue I was having was understanding how to process the returned EventEmitter object from the search function. I need to add to an array on each searchEntry event and then return that entry in my resolve callback function only once the end event had occurred. The code above was calling resolve immediately and hence no searchEntry events or the end event had been processed yet.
Code I am now using below:
function (err, res) {
if (err) {
console.error(err);
reject(new Error('Error retrieving users from Active Directory'));
} else {
const entries = [];
res.on('searchEntry', function (entry) {
entries.push(entry);
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
if (result.status !== 0) {
reject(new Error('Error code received from Active Directory'));
} else {
resolve(entries);
}
});
}
}

Store collection value to variable

I am having issues storing a value in mongodb to a variable to use within my webpage.
When the user fills out a form on my website, I am trying to figure out what the arrivalTrailer was when the user filled out the arrival form.
So far I have
function previousLoad(loadNumber, callback){
CheckCall.find({loadNumber: loadNumber}).sort({date: 'desc'}).limit(1), function(err, arrival){
if (err){
callback(err, null);
}
else {
callback(null, arrival[0]);
}
}};
previousLoad(loadNumber, function(err, arrival){
if (err){
console.log(err);
}
else{
arrivalTrailer = arrival;
console.log(arrival);
}
});
console.log(previousLoad.arrival);
console.log(arrivalTrailer);
Both output as undefined when I try to console.log the variables.
Thank you :D
Try this :
async function previousLoad(loadNumber) {
try {
let resp = await CheckCall.find({ loadNumber: loadNumber }).sort({ date: -1 }).limit(1)
return resp[0]
} catch (error) {
console.log('error ::', error)
throw new Error (error)
}
}
/** You can return response from previousLoad but to test it, Call it from here */
previousLoad(loadNumber).then(resp => { console.log('successfully found ::', resp)}).catch(err => { console.log('Error in DB Op ::', err)});

Multiple save operations in async.forEachOf

I have a loop through some payments in a mongo collection. All the payments with payoutdate == today() must be exported and written to an sepa file, so we can handle the payments by bank.
The payments doesn't have an invoicenumber while they are created and we generating one when the payment is processed (exported via the above function).
The problem is, that when we run the function with multiple payments to be exported, all the payments are getting the same invoice number. So it looks like, that the last save operation is not completed before the next payment is processed.
How can I archieve that every payment is getting an increasing number?
This is the loop function:
const fs = require('fs');
const async = require('async');
const DateDiff = require('date-diff');
const SEPA = require('sepa');
const shopService = require(path.join(__dirname, '..', 'services', 'shop.service'));
async.forEachOf(payments, function(payment, key, paymentDone){
var diff = new DateDiff(new Date(payment.payoutDate), new Date());
if(payment.payoutDate && payment.amount > 0 && payment.completed == false && payment.exported == false && diff.days() <= 0){
//payment has amount, is not completed and is not exported, create an SEPA transfer, and set the payment to completed
//but first create an invoicenumber
orderService.updateOrderPayment(payment.orderId, {generateInvoiceNumber: true}, function(err, result){
if(err){
console.log("error updating payment", err);
}
//reget the payment to avoid duplicated invoice numbers
orderService.getPayment(result.orderId, function(err, payment){
if(err){
console.log("error getting payment", err);
}
Shop.findOne({_id: payment.shopId}).exec(function(err, shop){
if(shop && shop.bankAccountNumber && shop.accountHolder && shop.bicCode){
//create transaction and add this to the file
}else{
var result = {
paymentID: payment._id,
orderId: payment.orderId,
status: payment.status,
message: "shop does not have an iban, accountholder or biccode",
shop: shop.nameSlug
}
resultArray.push(result);
console.log("shop does not have an iban, accountholder or biccode", shop.nameSlug);
paymentDone();
}
orderService.updateOrderPayment(payment.orderId, {status: 'completed'}, function(err, result){
orderService.updateOrderStatusById(payment.orderId, {status: 'Granted', date: new Date(), comment: null});
var result = {
paymentID: payment._id,
orderId: payment.orderId,
status: payment.status,
message: "payment exported",
}
resultArray.push(result);
counter++;
paymentDone();
})
})
})
})
}else{
var result = {
paymentID: payment._id,
orderId: payment.orderId,
status: payment.status,
message: "order already processed"
}
resultArray.push(result);
paymentDone();
}
}, function(){
if(resultArray.length == payments.length){
//console.log("Result", resultArray);
if(counter == 0){
res.status(200).json({"message":"No orders to export", resultArray});
}else{
res.set({"Content-Disposition":"attachment; filename=\"sepa.xml\""});
res.send(doc.toString());
}
}
})
The orderService contains the following functions (relevant to this question)
function updateOrderPayment(orderId, paymentStatus, callback){
console.log("updateOrderPayment");
if(!paymentStatus){
return callback("No payment details provided");
}else{
if(!paymentStatus.comment){
paymentStatus.comment = null;
}
}
getPayment(orderId, function(err, payment){
if(err)
return callback(err);
handlePayment(payment, paymentStatus, function(result){
result.save(function(err, result){
if(err){
return callback(err);
}
console.log("payment saved");
return callback(null, result);
})
})
})
}
function handlePayment(payment, paymentStatus, callback){
if(paymentStatus.status){
var status = {
status: paymentStatus.status,
comment: paymentStatus.comment,
date: Date.now()
}
payment.status.push(status);
}
if(paymentStatus.generateInvoiceNumber){
console.log("generateInvoiceNumber");
var invoiceNumber =0;
Payment.findOne({invoiceNumber: {$exists:true}}).sort({_id: -1}).exec(function(err, latestPaymentsWithNumber){
if(latestPaymentsWithNumber && latestPaymentsWithNumber.invoiceNumber){
invoiceNumber = latestPaymentsWithNumber.invoiceNumber.split("-")[1];
}
var date = new Date();
payment.invoiceNumber = date.getFullYear().toString() + date.getMonth().toString() + "-" + (parseInt(invoiceNumber)+1);
console.log("number", payment.invoiceNumber);
return callback(payment);
})
}
if(paymentStatus.status == 'returned' || paymentStatus.status == 'cancelled'){
payment.cancelled = true;
payment.amount = 0;
payment.payoutDate = null;
return callback(payment);
}
if(paymentStatus.status == 'completed'){
payment.completed = true;
payment.exported = true;
payment.payoutDate = null;
return callback(payment);
}
}
function getPayment(orderId, callback){
Payment.findOne({orderId: orderId}).exec(function(err, payment){
if(err){
return callback(err);
}
return callback(null, payment);
})
}
you have 2 choices:
1) implement callbacks to your save operation within scope
x.forEach(function(_x) {
_x.save(function(err) { });
});
2) break out your functions to async units or use an async library
function async(x, cb) {
x.operations(cb)
}
function series(x) {
if (x) {
async(x, function() { series(xs.pop()); });
} else // finished
}
series(xs.pop()); // xs is the array you're iterating
Thanks to both of the reply's! A combination was the solution.
I have changed the query to find the last invoiceNumber to
Payment.find({invoiceNumber: {$ne:null}}).sort({date: -1}).limit(1).exec(function(err, latestPaymentsWithNumber){
I use now async.eachSeries to iterate over payments:
async.eachSeries(payments, function(payment, paymentDone){
And I do a result.save in the first callback to asume I have the right data
result.save(function(err, payment){

Angular2 Stripe integration stripeResponseHandler cannot access this

I'm integrating Stripe payments with Angular2 (actually Ionic but the code is the same)
the call to Stripe.card.createToken is successful and returns a token
but in stripeResponseHandler which is an async callback, I cannot access any of the "this" variables. for example I cannot set this.amount = 10 and I cannot call this._http.post
how can I access the "this" variables ? I'm trying to http post the token and the amount to an API to make the payment
constructor(private _navController: NavController,
private _http: Http) { }
submitPayment() {
Stripe.setPublishableKey(this.key);
this.card = new Card();
this.card.number = this.cardNumber;
this.card.cvc = this.cardCVC;
this.card.exp_month = this.cardExpMonth;
this.card.exp_year = this.cardExpYear;
this.card.address_zip = this.cardAddressZip;
try {
Stripe.card.createToken(this.card, this.stripeResponseHandler);
}
catch (e) {
alert(e.message);
}
// Prevent the form from being submitted:
return false;
}
stripeResponseHandler(status, response) {
if (response.error) { // Problem!
alert(response.error);
} else { // Token was created!
// Get the token ID:
alert(response.id);
try {
this.amount = 10;
let payment = new Payment();
payment.token = response.id;
payment.amount = this.amount;
let body = JSON.stringify(payment);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
this._http.post(this.url, body, options)
.map(res => res.json())
.catch(this.handleError);
}
catch (e) {
alert(e.message);
}
}
}
handleError(error: Response) {
// may send the error to some remote logging infrastructure
// instead of just logging it to the console
console.error(error);
alert('error' + error.text + " " + error.statusText);
return Observable.throw(error.json().error || 'Server error');
}
If you just pass the function reference, then JavaScript doesn't keep the this reference. You have to take care of this explicitely:
Instead of
Stripe.card.createToken(this.card, this.stripeResponseHandler);
use
Stripe.card.createToken(this.card, (status, person) => this.stripeResponseHandler(status, person));
See also https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions
or
Stripe.card.createToken(this.card, this.stripeResponseHandler.bind(this));