expo / stripe-expo Goto Github PK
View Code? Open in Web Editor NEWUse the Stripe HTTP API in Expo without the DOM, node, or native deps
License: MIT License
Use the Stripe HTTP API in Expo without the DOM, node, or native deps
License: MIT License
Hi,
I've been using this library for quite a while and never had an issue to create a credit card token with the method createToken(card). The card variable being an object following the documentation:
card: {
cvc: "123",
exp_month: "03",
exp_year: "2021",
number: "4000 0034 4000 0004"
}
Suddenly, I get the following error:
SyntaxError: Unexpected token o in JSON at position 1
Is this a bug?
Thank you.
My creditcard form works fine on iOS, however on Android it fails to fetch the token
Here's a snippet of the code
class ConfirmOrderScreen extends Component {
constructor(props, context) {
super(props, context);
this.receiveToken = this.receiveToken.bind(this);
this.processCreditCard = this.processCreditCard.bind(this);
this.stripe = stripe(STRIPE_CLIENT_KEY);
}
receiveToken(token) {
const order = Object.assign({}, this.props.order);
order.paymentToken = token;
this.props.confirm(order);
}
async processCreditCard(card) {
if (card.valid) {
const payment = {
card: {
number: card.values.number.replace(/\s/g, ''),
exp_month: card.values.expiry.slice(0, card.values.expiry.indexOf('/')),
exp_year: card.values.expiry.slice(card.values.expiry.indexOf('/') + 1),
cvc: card.values.cvc,
},
};
const token = await this.stripe.createToken(payment); //<--- Error on Android only: SyntaxError: Unexpected token o in JSON at position 1
this.receiveToken(token);
}
}
}
It appears to stem from the _parseJSON(token)
function, judging from the "Pause on caught exception" snapshot
I'm using the following versions
"expo": "^20.1.3",
"react": "^16.0.0-rc.3",
"react-native": "0.47",
"stripe-client": "^1.1.3",
"urijs": "^1.18.12"
i can generate token from this package, but it should also generate stripe element like stripe provide to enter card details, please help
I've tried following the docs but I always get this same error
./node_modules/next-stripe/client.js:1:0
Module not found: Can't resolve './dist/client'
Import trace for requested module:
./components/product.js
./pages/catalogue.js
Hello,
It seems to me that the premises under "Features" are false:
"Collect credit card information and convert it to a Stripe token in a single line of Javascript"
As far as I understand the library, it does not offer any tools to collect card information (checkout flow, UI elements or the like), but should instead read
"Convert credit card information to a Stripe token in a single line of Javascript"
We only want to install the testing utilities when actually working on the library, not when using it in someone's code as a library
Hi,
Thank you for all of the work on this. I've looked through some of the source code and the README, and am uncertain whether the token is generated on the client side.
It appears you are posting the payment details to the https://api.stripe.com/v1/tokens
endpoint (documented here, which might be advised against in the docs. They recommend using Checkout, Elements, or the native ios/android libraries, since the tokenization is done in the client.
Am I correct in my understanding, or is there only a risk if I were to send the payment information to my server before sending it to stripe? I tried digging into https://js.stripe.com/v3/, but am uncertain wether they create the token the same way.
Hi,
Thinking to switch my react-native apps to expo and the only blocking point I have today is about payment. According to the payment documentation from your website, I need to detach a project to implement it.
Is this library working without detaching the related expo project?
Also, if I need to detach a project, can I still use expo functionalities to publish my app to store and/or use push notifications for instance?
How can I be aware once expo support full implementation of Stripe payments?
Thanks and regards,
Is this package PCI compliant?
Pull request #20 fixes an important bug, but it is not being included when package.json reads:
"stripe-client": "^1.1.3"
Instead to get it one has to install the client using:
"stripe-client": "github:expo/stripe-expo#master"
I'm no expert in how to resolve this... perhaps tag a new release?
stripe-expo have any option for embed strip elements (card details,account info) view and validations ?
like rectjs we can use react-stripe-elements to embed stripe elements in our application directly.
Could this be extended to work for the Stripe Terminal SDK? Or is this strictly for the non-reader Stripe API?
Thanks,
Kevin
It seems that the .createToken() method is returning a different object than expected. Instead, it returns the entire response from the fetch to Stripe. The examples from the README.md access the 'id' attribute of the returned object, of which there is none.
I think that the solution is for the '_createTokenHelper()' function not to return the entire response from Stripe.
I'm going to make a quick pull-request to change it, but if this is actually the intended functionality of the 'createToken()' & '_createTokenHelper()' functions, don't mind me! 😊
Is this API just for creating credit card token?
It will be my first attempt to implement payments in the app, and I would like use stripe with expo.
Could you add a example of how to handle payment with this API?
Basically, the flow in the app will looks like.
user must register credit card to make a payment -> with the token saved in the client, user can make a payment -> user can remove credit card(remove the token).
I don't have a clear picture how it should be implemented.
Hi all! I’m in desperate need for help.
So I have a side project for an iOS app using Expo / React Native. And I'm having issues with setting up future payment methods using Stripe & Expo’s stripe library.
Our back-ender set up a graphql back-end, and provides me with all the variables I need. I’m trying to se up payment methods to charge clients later, but I’m having trouble having with the paymentIntentSheet not showing up after creating an intent and fetching the clientSecret, ephemeralKey and customerId from our back-end. Now i don’t know where the issue is.. Is it because of me using the wrong versions? Maybe incorrect installation? Are the variables I’m using right..?
I used the following documentation page(s) as a guide:
https://stripe.com/docs/payments/save-and-reuse?platform=react-native
https://github.com/stripe/stripe-react-native#expo
These are the version numbers of the libraries I’m using, relevant to this topic/issue:
"expo": "~41.0.1",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz",
"@stripe/stripe-react-native": "0.1.1"
These are the steps I took:
"plugins": [
[
"@stripe/stripe-react-native",
{
"merchantIdentifier": "",
"enableGooglePay": false
}
]
],
pk_live_51[.....]
On global level it’ll look like this:
<StripeProvider
publishableKey="pk_live_51[...]"
>
<AuthProvider>
<ApolloProvider client={client}>
<InnerApp />
</ApolloProvider>
</AuthProvider>
</StripeProvider>
mutation (
$createUserPaymentMethodSetupIntentInput: CreateUserPaymentMethodSetupIntentInput!
) {
createUserPaymentMethodSetupIntent(
input: $createUserPaymentMethodSetupIntentInput
) {
setupIntentId
clientSecret
customerId
ephemeralKeySecret
}
}
Then, I call the function that will eventually provide me with all the necessary variables:
createIntent({
variables: {
createUserPaymentMethodSetupIntentInput: {
userUid: userUid,
},
},
})
.then((res) => {
const clientSecret =
res.data.createUserPaymentMethodSetupIntent.clientSecret
const setupIntentId =
res.data.createUserPaymentMethodSetupIntent.setupIntentId
const ephemeralKeySecret =
res.data.createUserPaymentMethodSetupIntent.ephemeralKeySecret
const customerId =
res.data.createUserPaymentMethodSetupIntent.customerId
// IGNORE THIS FOR NOW
initializePaymentSheet(
clientSecret,
setupIntentId,
ephemeralKeySecret,
customerId
)
})
.catch((err) => console.log({ graphqlError: err }))
The function gives me the following response:
Object {
"data": Object {
"createUserPaymentMethodSetupIntent": Object {
"__typename": "CreatedUserPaymentMethodSetupIntent",
"clientSecret": "seti_1K[....]",
"customerId": "cus_[...]",
"ephemeralKeySecret": "ek_live_[...]",
"setupIntentId": "seti_[...]",
},
},
These functions are imported like this:
const { initPaymentSheet, presentPaymentSheet } = useStripe();
In step 3, you see that I call a function that then calls the initPaymentSheet after successfully fetching the values from the server.
initializePaymentSheet(
clientSecret,
setupIntentId,
ephemeralKeySecret,
customerId
)
The initializePaymentSheet looks like this:
const initializePaymentSheet = (
clientSecret,
setupIntentId,
ephemeralKeySecret,
customerId
) => {
initPaymentSheet({
customerId: customerId,
customerEphemeralKeySecret: ephemeralKeySecret,
setupIntentClientSecret: setupIntentId,
})
.then((res) => {
console.log(res)
setDisabledButton(false)
})
.catch((err) => console.log("error.."))
}
As you can see, I call the initPaymentSheet hook there, exactly like shown on the docs, and pass in the values i received from the back-end. However, after doing this i get the following error in the console:
Object {
"error": Object {
"code": "Failed",
"message": "You must provide the paymentIntentClientSecret",
},
}
This didn’t seem like a huge error, so I went ahead and changed the initPaymentSheet parameters by adding the paymentIntentClientSecret field and passed in the clientSecret value which wasn’t previously used:
initPaymentSheet({
customerId: customerId,
customerEphemeralKeySecret: ephemeralKeySecret,
setupIntentClientSecret: setupIntentId,
paymentIntentClientSecret: clientSecret
})
.then((res) => {
console.log(res)
setDisabledButton(false)
})
.catch((err) => console.log("little error.."))
After calling the function and seeing the error disappear, and the console.log shown above logs the following in the console:
Object {
"paymentOption": null,
}
I didn’t think too much of this, and thought it says null just because I have no previously set paymentOptions. I was just happy there were no more errors.
In the .then chain, you see that i enable a button that basically allows a user to call a function that would present a payment sheet where users can submit their paymentMethod. This button is disabled, because I think you should initialize the paymentSheet first before presenting it?
<WideButton
disabled={disabledButton}
text="Add New Payment Method"
clicked={openPaymentSheet}
/>
const openPaymentSheet = async () => {
setDisabledButton(true)
const { error, paymentOption } = await presentPaymentSheet()
if (error) {
console.log(error)
setDisabledButton(false)
Alert.alert(`Error code: ${error.code}`, error.message)
}
if (paymentOption) {
setDisabledButton(false)
Alert.alert(
"Success",
"Your payment method is successfully set up for future payments!"
)
console.log(paymentOption)
}
}
Now to quote the stripe docs:
When your customer taps the Set up button, call presentPaymentSheet() to open the sheet. After the customer completes setting up their payment method for future use, the sheet is dismissed and the promise resolves with an optional StripeError.
So, that's exactly what I did: Call the presentPaymentSheet, but then i get the following error:
Object {
"code": "Failed",
"message": "There was an unexpected error -- try again in a few seconds",
}
Now this is where I’m stuck, because it doesn’t provide me with any more information than given above. I’ve tried looking everywhere, and some resources tell me that I should update my stripe, some say i should add stripe to my plugins in app.json. I’ve done all of that and I can’t still figure it out.
Here is a video showing you the behavior in action:
https://user-images.githubusercontent.com/29804130/146274443-82c581ba-8913-4c87-ad2e-5b8719680fed.mov
Here is the code of the entire component:
// steps
// 1. call graphql query to set up intent, retrieve the clientsecret and setupintentid
// 2. call stripes initPaymentSheet's function and pass in useruid, clientsecret and setupintentid
// 3. when initpaymentsheet is ready, enable button for user to add payment information
// 4. Retrieve the payment information and call the createpaymentmethod mutation
// 5. disable button again, and refresh page
export default function PaymentMethods({ userUid }) {
const { initPaymentSheet, presentPaymentSheet } = useStripe()
const [disabledButton, setDisabledButton] = useState(false)
const [createIntent, { data, loading, error }] = useMutation(
ADD_PAYMENT_METHOD_INTENT
)
useEffect(() => {
createUserPaymentMethodIntent()
}, [])
const createUserPaymentMethodIntent = () => {
setDisabledButton(true)
createIntent({
variables: {
createUserPaymentMethodSetupIntentInput: {
userUid: userUid,
},
},
})
.then((res) => {
console.log(res)
const clientSecret =
res.data.createUserPaymentMethodSetupIntent.clientSecret
const setupIntentId =
res.data.createUserPaymentMethodSetupIntent.setupIntentId
const ephemeralKeySecret =
res.data.createUserPaymentMethodSetupIntent.ephemeralKeySecret
const customerId =
res.data.createUserPaymentMethodSetupIntent.customerId
initializePaymentSheet(
clientSecret,
setupIntentId,
ephemeralKeySecret,
customerId
)
})
.catch((err) => console.log({ graphqlError: err }))
}
const initializePaymentSheet = (
clientSecret,
setupIntentId,
ephemeralKeySecret,
customerId
) => {
initPaymentSheet({
customerId: customerId,
customerEphemeralKeySecret: ephemeralKeySecret,
setupIntentClientSecret: setupIntentId,
paymentIntentClientSecret: clientSecret,
})
.then((res) => {
console.log(res)
setDisabledButton(false)
})
.catch((err) => console.log("little error.."))
}
const openPaymentSheet = async () => {
setDisabledButton(true)
const { error } = await presentPaymentSheet()
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message)
} else {
Alert.alert(
"Success",
"Your payment method is successfully set up for future payments!"
)
}
}
return (
<ScrollView>
<PaymentMethodList userUid={userUid} />
<WideButton
disabled={disabledButton}
text="Add New Payment Method"
clicked={openPaymentSheet}
/>
</ScrollView>
)
}
someone plz help :(
I made the repo public, and enabled Travis at https://travis-ci.org/expo/stripe-expo. Once you open a PR with a .travis.yml
file, you should see builds appear there. It'd be awesome to get the tests you wrote running on every commit and PR!
Hi, I'm not sure if this is a "stipe-expo" issue but I suspect it might be because it relates to a token I'm trying to generate using this library. So forgive me if not ;)
I'm getting the error: Invalid token ID when creating a paymentIntent
through the official "stripe" node.js library on my back end.
I can process a simple payment where my platform charges a customer card token. This works fine:
stripe.paymentIntents
.create({
amount: 100,
confirm: true,
currency: "gbp",
description: "payment",
payment_method_types: ["card"],
payment_method_data: {
type: "card",
card: {
token: customerCard.id, // token generated on the client side (see below for code)
},
},
})
But now I want to move away from a 'simple' charge to a 'direct' charge flow using Stripe Connect, as per this guide: https://stripe.com/docs/connect/direct-charges
If I amend my code as per the guide so that I'm trying to generate the card token on the connect account (rather than my platform stripe account), and then create the paymentIntent to create the charge on the connect account:
stripe.paymentIntents
.create({
amount: 1000,
application_fee_amount: 100, // trying to take a fee now
confirm: true,
currency: "gbp",
description: "payment",
payment_method_types: ["card"],
payment_method_data: {
type: "card",
card: {
token: customerCard.id, // token generated using the connect account id (see below for code)
},
},
}, { stripeAccount: "{{ ACTUAL_CONNECT_ACCOUNT_ID_IS_HERE }}"}) // so that we're creating the charge on the connect account
The call fails (in my try catch) with "Error: Invalid token Id: tok_abc..."
Here's how I'm generating the token:
import createStripe from "stripe-client"; // https://github.com/expo/stripe-expo
...
// init a new instance of stripe client passing the ID of the connected account to create the token on that account
const stripeClient = createStripe(
"pk_test_5...gKi",
{ stripeAccount: "{ ACTUAL_CONNECT_ACCOUNT_ID_IS_HERE }" }
);
return stripeClient.createToken({ card });
I am getting what looks to be a valid token before passing it to the back end so I'm really stuck as to the reason the token is invalid.
Can someone please help?
Thanks!
Failed to minify the code from this file:
./node_modules/stripe-client/index.js:6
Read more here: http://bit.ly/2tRViJ9
Invalid API Key provided: pk_test_
This error seems to imply no test enviorment?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.