I have the exact same problem as described in the post Implementation of Paypal in single page application unfortunately nobody in this vast community seems to have an answer :( With lots of head banging I was able to implement a dirty hack as below and I know that this is not the right solution. Could any of the gurus kindly ponder over this question and answer/give feedback if my dirty hack is the right way or it can be better implemented. Below my dirty hack :( Many thanks in advance for your answers/comments.
I have a button to say pay with paypal and onClick I open a new window -> window.open("/paypalCreate", width = "20px", height = "20px");
and I capture this get request "/paypalCreate" in my node.js server and call create method which looks liek below
exports.create = function (req, res) {
//Payment object
var payment = {
//fill details from DB
};
//Passing the payment over to PayPal
paypal.payment.create(payment, function (error, payment) {
if (error) {
console.log(error);
} else {
if (payment.payer.payment_method === 'paypal') {
req.session.paymentId = payment.id;
var redirectUrl;
for (var i = 0; i < payment.links.length; i++) {
var link = payment.links[i];
if (link.method === 'REDIRECT') {
redirectUrl = link.href;
}
}
res.redirect(redirectUrl);
}
}
});
};
This redirects user to paypal and once user confirms or cancels payment, the redirect urls are called. And in the success redirect url I capture the payment details into the databse and render a html in this opened window with the confirmation.
exports.execute = function (req, res) {
var paymentId = req.session.paymentId;
var payerId = req.param('PayerID');
// 1. if this is executed, then that means the payment was successful, now store the paymentId, payerId and token into the database
// 2. At the close of the popup window open a confirmation for the reserved listing
var details = {"payer_id": payerId};
paypal.payment.execute(paymentId, details, function (error, payment) {
if (error) {
console.log(error);
} else {
//res.send("Hell yeah!");
res.render('paypalSuccess', {payerId: payerId, paymentId: paymentId});
}
});
};
Once the user closes the opened window in which paypal was being handled the orginal SPA window will be refreshed and thus getting the payment details from the DB and here you can handle the SPA in whatever way you want. I know that this is a dirty hack, but like you I couldnt find a better way. Please let me know if this works for you or if you have a found a better way to do tihs.
cheers, Chidan
Try this. It's what I use for my app.
var config = require("config3");
var paypal_api = require("paypal-rest-sdk");
paypal_api.configure(config.paypal);
var log = require("app/log");
function pay(creditCard, amount, description, callback) {
var paypalOptions = {
intent: "sale",
payer: {
payment_method: "credit_card",
funding_instruments: [{credit_card: creditCard}]
},
transactions: [{
amount: {
total: amount,
currency: "USD"
},
description: description
}]
};
if (config.paypal.enabled) {
paypal_api.payment.create(paypalOptions, function (error, response) {
log.debug({
err: error,
response: response || (error && error.response)
}, "paypal payment response");
callback(error, response);
});
} else {
setImmediate(function () {
callback(null, {"fakePaypal": "is fake"});
});
}
}
module.exports = pay;
Edit: The config3 module would look like this. The docs for this module can be found here
module.exports = {
paypal: {
client_id: "Secret API key",
client_secret: "Secret API key",
host: "api.sandbox.paypal.com",
enabled: true
},
mysql: {
host: 'localhost',
user: 'root',
password: '',
database: ''
},
redis: {
host: "localhost",
port: 6379
},
As far as redirection you don't need to send your user to Paypal. On success just show a transaction completed message / page. On failure show the error and let them fix it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With