Create external_account for Stripe Connect payouts with Stripe.js (iOS) - ios

I am trying to connect actual bank accounts to the stripe accounts in Stripe Connect.
However, I am struggling with the actual implementation.
I use Custom Accounts, so I want to provide the user with the account creation logic through my iOS app.
In the Stripe API Reference it says that the recommended way to accomplish this is:
"Destination accounts are added via the external_accounts parameter when creating or updating Custom accounts. The value should be a bank account or debit card token returned from Stripe.js."
Creating the token is documented as follows (I am using NodeJS):
stripe.createToken('bank_account', {
country: 'US',
currency: 'usd',
routing_number: '110000000',
account_number: '000123456789',
account_holder_name: 'Jenny Rosen',
account_holder_type: 'individual',
}).then(function(result) {
// Handle result.error or result.token
});
Where to I link that token in the account creation process? See related code below:
app.post('/create_account', (req, res) => {
console.log('create account called');
var email = req.body.email;
var firstname = req.body.firstname;
var lastname = req.body.lastname;
stripe.accounts.create({
country: "CH",
type: "custom",
email: email,
business_name: "examplename",
legal_entity: {
first_name: "firstname",
last_name: "lastname",
dob: {
day: 1,
month: 1,
year: 1900
}
}
}).then((account) => {
res.status(200).send(account)
}).catch((err) => {
console.log(err, req.body)
res.status(500).end()
});
});
Is the token creation just a means of validating the account information client-side?
Would be glad if someone can elaborate on this with a simple step-by-step explanation, thank you in advance!

You'd pass the token in the external_account parameter:
var bankAccountToken = req.body.stripeToken;
stripe.accounts.create({
country: "CH",
type: "custom",
// ...
external_account: bankAccountToken,
}).then((account) => {
// ...

Related

How can I check if User exists when using Apple Sign In with React Native Firebase and Firestore?

I have implemented Apple Sign In to my React Native App using Firebase and the Sign In process is working fine.
I am adding the User details to a Database Collection named 'users' in Firestore.
When the user re-signs in the data which is added to the collection from their Profile gets overwritten.
How can I check if user exists so the collection document is only created once?
My code is as follows
appleSignIn: async () => {
try {
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: appleAuth.Operation.LOGIN,
requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
});
if(!appleAuthRequestResponse.identityToken) {
throw 'Apple Sign-In failed - no identify token returned';
}
const { identityToken, nonce } = appleAuthRequestResponse;
const appleCredential = auth.AppleAuthProvider.credential(identityToken, nonce);
await auth().signInWithCredential(appleCredential);
firestore().collection('users').doc(auth().currentUser.uid)
.set({
fname: appleAuthRequestResponse.fullName.givenName,
lname: appleAuthRequestResponse.fullName.familyName,
email: appleAuthRequestResponse.email,
createdAt: firestore.Timestamp.fromDate(new Date()),
userImg: null,
})
} catch (e) {
console.log(e);
}
},
You can check if is user exist in users collection.
...
await auth().signInWithCredential(appleCredential);
const existingUserDoc = await firestore().collection('users').doc(auth().currentUser.uid).get();
if (existingUserDoc && existingUserDoc.exists) {
// you can do something here. user details already created.
} else {
firestore().collection('users').doc(auth().currentUser.uid)
.set({
fname: appleAuthRequestResponse.fullName.givenName,
lname: appleAuthRequestResponse.fullName.familyName,
email: appleAuthRequestResponse.email,
createdAt: firestore.Timestamp.fromDate(new Date()),
userImg: null,
});
}
...
Or more simply way if user document exists you can pass firestore().collection('users').doc('uid').set({...}) execution.
...
await auth().signInWithCredential(appleCredential);
const existingUserDoc = await firestore().collection('users').doc(auth().currentUser.uid).get();
// ignore execution of setting user deatils.
if (!existingUserDoc && !existingUserDoc.exists) {
firestore().collection('users').doc(auth().currentUser.uid)
.set({
fname: appleAuthRequestResponse.fullName.givenName,
lname: appleAuthRequestResponse.fullName.familyName,
email: appleAuthRequestResponse.email,
createdAt: firestore.Timestamp.fromDate(new Date()),
userImg: null,
});
}
...

unexpected error when trying stripe with apple pay using ionic capacitor

i am using https://github.com/capacitor-community/stripe to integrate in my ionic-angular app with apple pay.
the payload and code looks like below
const Stripe = Plugins.Stripe as StripePlugin;
Stripe.setPublishableKey({ key: 'xxxx' }); //test key
const clientSecret: string = 'xxxx'; //test secret
pay(){
await Stripe.confirmPaymentIntent({
clientSecret,
applePayOptions: {
// options here
merchantId: 'merchant.xxx.xxx',
country: 'US',
currency: 'USD',
items: [
{
label: 'my desc',
amount: 1, // amount in dollars
}
]
},
})
}
this shows the apple pay sheeet nicely but when i double click to confirm the payment it thorws error that i can see in the xcode console as below
ERROR MESSAGE: {"message":"payment failed: There was an unexpected error -- try again in a few seconds","errorMessage":"There was an unexpected error -- try again in a few seconds"}
i have tried it on device and with live keys as well but no luck
The code below worked for me.
Note that it is 1 for $1 but stripe uses 100 for $1.
try {
const paymentIntent = await this.stripeService.createPaymentIntentOnServer(100);
const result = await StripePlg.confirmPaymentIntent(
{ clientSecret: paymentIntent.client_secret,
applePayOptions: {
merchantId: 'merchant.app.myapp',
items: [{ label: 'Bread sticks', amount: 1, },],
currency: 'NZD',
country: 'NZ',
},
});
// then call finalizeApplePayTransaction with the result to dismiss the UI modal
StripePlg.finalizeApplePayTransaction({ success: true });
} catch (err) {
console.log(err);
StripePlg.finalizeApplePayTransaction({ success: false })
}
// Server
// createPaymentIntentOnServer - this returns the client_secret
const paymentIntent = await stripe.paymentIntents.create({
amount: paymentAmount, // 100
currency: 'nzd',
payment_method_types: ['card'],
customer: customer.id, // I use a Stripe Customer here which I create first
expand: ['invoice']
});
Stripe allows only integer as amount (1 = 1cent) so 0.5$ would be 50, and 1$ is 100.
const Stripe = Plugins.Stripe as StripePlugin;
Stripe.setPublishableKey({ key: 'xxxx' }); //test key
const clientSecret: string = 'xxxx'; //test secret
pay(){
await Stripe.confirmPaymentIntent({
clientSecret,
applePayOptions: {
// options here
merchantId: 'merchant.xxx.xxx',
country: 'US',
currency: 'USD',
items: [
{
label: 'my desc',
amount: 50, // amount in cents
}
]
},
})
}

Apple Pay - "Payment Not Completed" - Using Stripe

I am using stripes "Payment Request Button" to implement Apple Pay for my website. On the stripe side of things all is well. The token is passed through correcty as I verified within Stripe logs.
https://stripe.com/docs/stripe-js/elements/payment-request-button
However, I get an error message: "Payment Not Completed" from Apple Pay every time I try to complete a test payment.
This has me stuck and I'm not sure how to debug or fix. Any ideas?
I get an undefined token
This is the error:
My set up:
FRONT END:
<script src="https://js.stripe.com/v3/"></script>
<div id="payment-request-button">
<!-- A Stripe Element will be inserted here. -->
</div>
<script>
var stripe = Stripe('pk_test_xxxxx');
var paymentRequest = stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'JobQuiz',
amount: 999,
},
requestPayerName: true,
requestPayerEmail: false,
});
var elements = stripe.elements();
var prButton = elements.create('paymentRequestButton', {
paymentRequest: paymentRequest,
});
// Check the availability of the Payment Request API first.
paymentRequest.canMakePayment().then(function(result) {
if (result) {
prButton.mount('#payment-request-button');
} else {
document.getElementById('payment-request-button').style.display = 'none';
}
});
paymentRequest.on('token', function(ev) {
// Send the token to your server to charge it!
fetch('/apple-pay', {
method: 'POST',
body: JSON.stringify({token: ev.token.id}),
headers: {'content-type': 'application/json'},
})
.then(function(response) {
if (response.ok) {
// Report to the browser that the payment was successful, prompting
// it to close the browser payment interface.
ev.complete('success');
} else {
// Report to the browser that the payment failed, prompting it to
// re-show the payment interface, or show an error message and close
// the payment interface.
ev.complete('fail');
}
});
});
</script>
Server side code in app.js
app.post('/apple-pay', function(req, res, next) {
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
var stripe = require("stripe")("sk_test_xxxxxx");
// Token is created using Checkout or Elements!
// Get the payment token ID submitted by the form:
const token = req.body.token; // Using Express
const charge = stripe.charges.create({
amount: 999,
currency: 'usd',
description: 'Example charge',
source: token,
}, function(err, charge){
if (err){
} else {
}
});
});
Finally solved this. It ended up being an issue with my bodyParser set up. This explains why token was being passed though empty. I had neglected to include app.use(bodyParser.json()); below...
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

Passport Facebook strategy returns undefined values

I am using the passport-facebook plugin in a NextJS app and my test script defines the strategy as below:
// Configure Passport
// ---------------------------------------------------------------
passport.use(new LocalStrategy(User.authenticate()));
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: process.env.FACEBOOK_APP_CALLBACK,
},
function (accessToken, refreshToken, profile, done) {
console.log(profile);
}
));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// ---------------------------------------------------------------
My authentication routes are:
// Facebook
router.get('/auth/facebook', passport.authenticate('facebook'));
router.get('/facebook/callback',
passport.authenticate('facebook', {
successRedirect: '/success',
failureRedirect: '/failure',
}),
);
All I'm trying to do with this for now, is to display all the values returned by Facebook upon a successful authentication. The authentication works as expected but Facebook seems to be returning undefined for most keys in the profile object:
{ id: '1234567812345677',
username: undefined,
displayName: 'John Doe',
name:
{ familyName: undefined,
givenName: undefined,
middleName: undefined },
gender: undefined,
profileUrl: undefined,
provider: 'facebook',
_raw: '{"name":"John Doe","id":"1234567812345677"}',
_json: { name: 'John Doe', id: '1234567812345677' } }
All I get is the displayName and id; everything else is undefined. What's going wrong? A very similar question was asked here before but none of the answers (no accepted answer) offered address the problem.
I have no experience in this area, but from looking at the readme of facebook-passport, it sounds like you need to use the profileFields in your FacebookStrategy. :
The Facebook profile contains a lot of information about a user. By
default, not all the fields in a profile are returned. The fields
needed by an application can be indicated by setting the profileFields
option.
new FacebookStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/callback",
profileFields: ['id', 'displayName', 'photos', 'email']
}), ...)
Refer to the User section of the Graph API Reference for the complete
set of available fields.

OAuth 2.0 Scope for Google Apps users' names with google-api-nodejs-client

I'm trying to use Google's 'google-api-nodejs-client' package (https://github.com/google/google-api-nodejs-client) to handle OAuth 2.0 authentication.
I've modified the example in examples/oauth2.js to console.log the entire profile object.
What scope can I use to correctly extract users' 'givenName' and 'familyName' if they're authenticating using a Google Apps account? Using the following scope:
scope: [
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.profile.emails.read'
]
returns the following response once authenticated:
{ kind: 'plus#person',
etag: '"LONG STRING"',
emails: [ { value: 'example#example.example', type: 'account' } ],
objectType: 'person',
id: '123456',
displayName: '',
name: { familyName: '', givenName: '' },
image:
{ url: 'https://lh3.googleusercontent.com/ etc etc',
isDefault: false },
isPlusUser: false,
language: 'en_GB',
circledByCount: 0,
verified: false,
domain: 'example.example' }
I tried fooling around with the API on the API Explorer (https://developers.google.com/apis-explorer/#p/plus/v1/plus.people.get?userId=me) and only needed the 'https://www.googleapis.com/auth/plus.login' scope to get my familyName and givenName.
Perhaps the user that you are requesting the data from does not have a given and family name set?

Resources