Paypal Express Checkout Sandbox to test customer insufficient funds? - paypal-sandbox

I am implementing Paypal Checkout "https://developer.paypal.com/docs/checkout/quick-start/" on a SandBox account. How to test
if a customer has insufficient funds under sandbox?
Below code only checks if the user is authorized.
onAuthorize: function (data, actions) {
return actions.payment.execute()
.then(function () {
window.alert('Payment Complete!');
});
}
Thanks,

Related

Why is stripe creating the customer twice with firebase?

[RESOLVED] The issue is when I call the function subscribe() after le .then(() => when the account is created in firebase. I think the function is called more than one time.
I use Firebase and stripe to manage subscription payments (through the stripe subscription firebase extension) and have an issue when the user signs up and is added to stripe.
When the users signs up, an account is created in my Firebase app. Then he is redirected to a Stripe checkout session. In between he is added to the customers section of my stripe account (I don't manage that, it is done in the backend through the extension I believe).
Issue -> the customer is created twice in Stripe.
One of the duplicated customer in Stripe has the logs : "POST /v1/customers" and "POST /v1/checkout/session".
The other has only the log "POST /v1/customers".
They both have the same firebaseUID in the metadata section in Stripe. And only one user is created in Firebase.
This is my signUp function which is called through onclick() on a button :
if (agreeToTerms == true && name != '' && surname != '' && companyName != '' && companyActivity != '' ) {
auth.createUserWithEmailAndPassword(email, password).then(cred => {
return db.collection('collection-users').doc(cred.user.uid).set({
name: name,
surname: surname,
email: email,
companyName: companyName,
companyActivity: companyActivity
})
}).then(() => {
// User signed up, now redirected to stripe checkout session to subscribe
subscribe();
container_signup.querySelector(".error").innerHTML = '';
}).catch(err => {
container_signup.querySelector(".error").innerHTML = err.message;
});
} else {
container_signup.querySelector(".error").innerHTML = "Please add all the required informations."
}
And this is my subscribe function which is used to redirect the user to the stripe checkout session (called when the account has been created) :
async function subscribe() {
const docRef = await db
.collection('collection-users')
.doc(firebase.auth().currentUser.uid)
.collection('checkout_sessions')
.add({
price: 'price_id',
success_url: 'https://mywebsite.com',
cancel_url: 'https://mywebsite.com',
});
// Wait for the CheckoutSession to get attached by the extension
docRef.onSnapshot((snap) => {
const { error, url } = snap.data();
if (error) {
// Show an error to your customer and
// inspect your Cloud Function logs in the Firebase console.
alert(`An error occured: ${error.message}`);
}
if (url) {
// We have a Stripe Checkout URL, let's redirect.
window.location.assign(url);
}
});
}
What am I doing wrong?
Thank you very much for your help.
[EDIT] The firebase logs down below. What we can see is that the function .createCustomer creates the first customer while .createCheckoutSession creates not only the checkout session but also another customer (the duplicated one).
7:48:29.200 pm
ext-firestore-stripe-subscriptions-createCustomer
Function execution started
7:48:29.202 pm
info
gmp_mods ext-firestore-stripe-subscriptions-createCustomer
⚙️ Creating customer object for [t5LdbvNH5hSOFe7ECuzpHfWke1x2].
7:48:29.215 pm
outlined_flag
gmp_mods ext-firestore-stripe-subscriptions-createCheckoutSession
Function execution started
7:48:29.218 pm
info
gmp_mods ext-firestore-stripe-subscriptions-createCheckoutSession
⚙️ Creating checkout session for doc [UkCpB5Yqw8c9RR76wyp6].
7:48:29.464 pm
info
gmp_mods ext-firestore-stripe-subscriptions-createCheckoutSession
⚙️ Creating customer object for [t5LdbvNH5hSOFe7ECuzpHfWke1x2].
7:48:29.636 pm
info
gmp_mods ext-firestore-stripe-subscriptions-createCustomer
✅Created a new customer: https://dashboard.stripe.com/test/customers/cus_KMlAFc3l3oAgnd.
7:48:29.637 pm
outlined_flag
gmp_mods ext-firestore-stripe-subscriptions-createCustomer
Function execution took 437 ms, finished with status: 'ok'
7:48:29.925 pm
info
gmp_mods ext-firestore-stripe-subscriptions-createCheckoutSession
✅Created a new customer: https://dashboard.stripe.com/test/customers/cus_KMlAUuGRyge978.
7:48:30.679 pm
info
gmp_mods ext-firestore-stripe-subscriptions-createCheckoutSession
✅Checkout session created for doc [UkCpB5Yqw8c9RR76wyp6].
7:48:30.679 pm
outlined_flag
gmp_mods ext-firestore-stripe-subscriptions-createCheckoutSession
Function execution took 1464 ms, finished with status: 'ok'

User redirect and authentication with middleware of Nuxt

I'm trying to redirect a user to a login page if the user is not logged in when he tries to access certain pages with the following code.
// middlware/authenticated.js
import firebase from 'firebase'
export default function ({ store, redirect }) {
let user = firebase.auth().currentUser
store.state.user = user //this doesn't work
if (!user) {
console.log('redirect')
return redirect('/login')
}
}
However, the problem is with this code when I refresh a page I'm redirected to login page although without using the middleware, I can stay in the same page with logged in. For some reasons, which I don't know why, firebase can't work in middleware.
How should I modify this middleware or implement this function?
Thanks.
//middleware/authenticated.js
export default function ({
store,
redirect
}) {
if (!store.getters['index/isAuthenticated']) {
return redirect('/login')
}
}
//post.vue
async mounted () {
if (process.browser) {
let user;
if (!this.user) user = await auth(); // this auth is a plugin
await Promise.all([
this.user ? Promise.resolve() : this.$store.dispatch("setUser", { user: user || null })
]);
this.isLoaded = true;
}
},
//plugins/auth.js
import firebase from '~/plugins/firebase'
function auth () {
return new Promise((resolve, reject) => {
firebase.auth().onAuthStateChanged((user) => {
resolve(user || false)
})
})
}
export default auth
By default Firebase persists the users logged in status on successful authentication. This example uses the session, to store the user uid and cookies to store the users token and used in situations where the sessions has ended (example when browser is closed) and then a new session started but where the user is still authenticated according to Firebase. In cases like these the user will not need to sign in to view protected resources.
Your basic Middleware to protect it should look like this (if you have a Store Module called User)
export default function ({ store, redirect }) {
if (!store.getters['modules/user/isAuthenticated']) {
return redirect('/auth/signin')
}
}
In your main Store you use the ServerInit Function to get the User if there is one saved in the Cookies and load it into your User Store Module which will be used for verification in the Middleware.
Your User Store Module should look like this, and keep in mind that you remove the Cookie when you Log the User out so that he is fully logged out.
I used the things i mentioned above as the beginning of my Authentication and modified it a bit, which you can also do. Most of the credit goes to davidroyer who has set up this nice Github Repo which includes all needed files as a good example on how to accomplish your goal.

Impersonate user in Meteor

I've built impersonate method in my Meteor application in order to login as another user, based on following article: https://dweldon.silvrback.com/impersonating-a-user. I also have Intercom integration (chat widget and user tracking). I would like to be able to disable on client side that Intercom widget, in order to avoid any tracking from Intercom application, when I am logged as another user (impersonating). I was thinking about creating on user profile impersonate boolean property, and updating it to true, when I am triggering that impersonate method for any user. The problem is that, I have no idea how to set it to false when impersonate method is finished. According to article, you can stop impersonating when you refresh the browser manually. Could you please help me, and find the best approach?
We can solve this in two parts:
When we start impersonating a user, keep track of who is impersonating who. Let's do this by first extending the impersonate method in the tutorial:
Meteor.methods({
impersonate: function(userId) {
check(userId, String);
if (!Meteor.users.findOne(userId))
throw new Meteor.Error(404, 'User not found');
if (!Meteor.user().isAdmin)
throw new Meteor.Error(403, 'Permission denied');
Meteor.users.update(this.userId, { $set: { 'profile.impersonating': userId }});
this.setUserId(userId);
}
});
Next we need to listen for a new login (which should happen on a browser refresh)
Meteor.onLogin(() => {
Meteor.call('clearImpersonation', (err, result) => {
if (err) console.log('Error clearing impersonation: ',err);
});
});
Meteor.methods({
clearImpersonation(){
const user = Meteor.users.findOne(this.userId);
if (user && user.profile && user.profile.impersonating) Meteor.users.update(user._id,{ $unset: 'profile.impersonating' });
return;
}
});
Now in your UI you can disable Intercom by checking for the existence of Meteor.user().profile.impersonating

Payment Request API: What is the Payee Account?

I was looking at the Payment Request API which is apparently available on some browsers but I was wondering, where/how do you set the account to which the payments get sent? I see nowhere in the following code that specifies an account to which the payment will be sent upon success:
function onBuyClicked() {
if (!window.PaymentRequest) {
// PaymentRequest API is not available. Forwarding to
// legacy form based experience.
location.href = '/checkout';
return;
}
// Supported payment methods
var supportedInstruments = [{
supportedMethods: ['basic-card']
data: {
supportedNetworks: [
'visa', 'mastercard', 'amex', 'discover',
'diners', 'jcb', 'unionpay'
]
}
}];
// Checkout details
var details = {
displayItems: [{
label: 'Original donation amount',
amount: { currency: 'USD', value: '65.00' }
}, {
label: 'Friends and family discount',
amount: { currency: 'USD', value: '-10.00' }
}],
total: {
label: 'Total due',
amount: { currency: 'USD', value : '55.00' }
}
};
// 1. Create a `PaymentRequest` instance
var request = new PaymentRequest(supportedInstruments, details);
// 2. Show the native UI with `.show()`
request.show()
// 3. Process the payment
.then(result => {
// POST the payment information to the server
return fetch('/pay', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(result.toJSON())
}).then(response => {
// 4. Display payment results
if (response.status === 200) {
// Payment successful
return result.complete('success');
} else {
// Payment failure
return result.complete('fail');
}
}).catch(() => {
return result.complete('fail');
});
});
}
document.querySelector('#start').addEventListener('click', onBuyClicked);
Ref. https://developers.google.com/web/fundamentals/discovery-and-monetization/payment-request/deep-dive-into-payment-request
Ref. https://www.w3.org/TR/payment-request/
Long story short: you don't.
Payment Request API is not a replacement for payment processors. The browser itself has no means to process the funds transfer to your account - it can't even validate whether the provided payment method is valid (though Android Pay can do this).
Per Introducing the Payment Request API doc (emphasis mine):
...
The browser then presents the payments UI to the user, who selects a
payment method and authorizes the transaction. A payment method can be
as straightforward as a credit card that is already stored by the
browser, or as esoteric as third-party application written
specifically to deliver payments to the site (this functionality is
coming soon). After the user authorizes the transaction, all the
necessary payment details are sent directly back to the site. For
example, for a credit card payment, the site will get back a card
number, a cardholder name, an expiration date, and a CVC.
...
In other words, the Payment Request API is just an easier, safer way for you to collect the user's card number and other info necessary to process a payment. Once you receive this information, it's pretty much the same as if the user submitted it via a normal form. You still need a payment processor (or something similar) to actually create a transaction.

Meteor: Passing value to database after successful Paypal payment

I'd like to update the users database after a successful payment. Basically, converting $ to site credits. I've used https://github.com/tirtohadi/meteor-paypal-demo/, basically using his code implementing paypal to the web app. The only idea I have is when the site gets routed to the return page after payment. Code's here.
Router.map(function() {
this.route('/payment_return/:invoice_no/:amount/', {
where: 'server',
onBeforeAction: function() {
console.log("result");
result = paypal_return(this.params.invoice_no,this.params.amount,this.params.query.token,this.params.query.PayerID);
console.log(result);
if (result)
{
this.response.end("Payment captured successfully");
}
else
{
this.response.end("Error in processing payment");
}
}
});
});
I guess my question is, how do I securely update the db after a successful payment. Because I know client side update is dangerous (from what I've read anyway)

Resources