如今,在大流行期间,大多数人更喜欢在线支付,不仅是因为它的无接触安全防范措施,而且还因为它快速、方便和可靠。很多移动应用程序都纳入了在线支付,如亚马逊、Uber等。
说到在线支付,很多应用开发者都在他们的React Native Android和iOS项目中使用Stripe,因为Stripe提供了一种将支付系统集成到这个框架中的简单方法。我们有两个选项可以将Stripe集成到React Native中。PaymentSheet,或者Elements。
PaymentSheet是一个由Stripe预先建立的结账面板,用户可以在其中输入卡的详细信息并进行支付。Elements则要复杂一些;你要更多地控制这个过程,所以你要放置卡片元素并负责进行支付。
在这篇文章中,我将讨论我对PaymentSheet的偏好,然后再深入到一个用React Native、Expo和PaymentSheet构建的捐赠应用实例的教程。
PaymentSheet与传统的Elements方法
以下是我认为PaymentSheet比Elements好的一些原因。
首先,Elements需要大量的配置。因为你负责支付,你需要管理支付表单。这可能很复杂,因为不同的国家有不同的卡配置;例如,印度的卡不需要邮政编码,而在美国则需要。您需要考虑所有这些条件,并在Elements中对其进行相应的管理。
然而,在PaymentSheet中,Stripe已经为你配置了这些东西中的大部分。因此,如果一个卡号需要一个邮政编码,就会自动提示用户添加一个邮政编码。另外,如果启用,PaymentSheet支持苹果支付和谷歌支付。
第二,Elements需要进行大量的错误处理。另一方面,PaymentSheet为你处理错误,并会提醒用户他们的支付方式出了什么问题,这意味着你对收款的担心减少了。
例如,如果卡的资金不足,Elements需要你读取错误信息并显示给用户。但当你使用PaymentSheet时,用户会被Stripe自动警告。你只需要处理付款后的流程。
最后,在使用Elements时,你可能会错过一些与支付处理有关的隐私或法律要求。例如,您可能在不知情的情况下存储了一些不应该存储的数据,如用户的付款细节。
不同的国家在数据隐私方面有不同的法律,要了解并遵守每一项法律可能会让人感到沮丧。PaymentSheet确保你不需要将任何数据保存在你的服务器上,因为支付所需的所有通信都是直接与Stripe进行的。这可以保护你不会意外地违反数据隐私法。
构建一个捐赠应用程序
今天我们将使用Expo和React Native与PaymentSheet建立一个捐赠应用程序,用于支付处理。我们还需要一个Node.js服务器来处理Stripe操作,例如启动支付,并在服务器上检测任何支付。
以下是你应该具备的条件,以便跟上我们今天要做的项目。
- 在你的机器上安装Node
- 一个代码编辑器--我更喜欢Visual Studio Code
- 一个Stripe账户
- 安装在您机器上的Stripe CLI
- 用于Visual Studio Code的Stripe扩展
- 对Node和React Native的工作知识
这里有GitHub仓库的链接,以防您被卡住并想参考代码。
让我们开始玩吧!创建一个你喜欢的文件夹(在我的例子中,我把它命名为expo-stripe ),作为我们的项目文件夹。
第一步是建立一个Node服务器,它将帮助我们启动支付。
创建一个Node.js服务器
在我们刚刚创建的expo-stripe 文件夹中,创建一个名为backend 的新文件夹。这就是我们的Node后端项目所在的地方。
使用下面的命令初始化一个Node项目,你将有一个package.json 文件准备好。
npm init -y
在backend 文件夹的终端中运行以下命令,以安装一些有助于我们的服务器的依赖性。
npm install express cors stripe dotenv
Express是用来用Node轻松制作REST API的。它支持使用中间件,有很多不同的功能;另外,它很容易使用。
cors 包与Express一起使用,以使与我们的服务器的通信更容易,并确保在向我们的服务器发送请求时不会抛出CORS错误。
stripe 包帮助我们与Stripe服务进行通信,例如我们的Stripe账户,以初始化支付,或检查支付状态。
最后,dotenv 包在我们的项目中设置了环境变量,这样我们就不必在代码中存储敏感数据,如Stripe的密匙。我们可以把它保存在一个单独的.env 文件中。
现在您可以在终端使用以下命令启动服务器。
nodemon index
如果您没有安装nodemon ,请使用下面的命令安装它。
npm install -g nodemon
获取我们的Stripe密匙
在我们实际处理Stripe操作之前,让我们从Stripe获得我们的秘钥。
打开您的Stripe仪表盘,并确保在侧边栏中查看测试数据被选中。然后,点击 "开发人员",再点击 "API密钥",就会看到您的API密钥。
记住要保持秘密密钥,不要与其他人分享,因为这将使他们能够访问您的Stripe账户。我们现在不需要可发布的密钥,但我们以后会在我们的React Native应用程序中使用它。
复制秘钥,回到你的backend 文件夹,创建一个新文件,命名为.env 。提到你的秘钥,格式如下所示。
STRIPE_SECRET_KEY=(secret key here)
初始化一个Express服务器并处理Stripe操作
在backend 文件夹中创建一个新文件,命名为index.js 。这将是存储服务器主要逻辑的文件。
首先,让我们创建一个基本的服务器模板。
require("dotenv").config();
const express = require("express");
const app = express();
const Stripe = require("stripe");
const stripe = Stripe(process.env.STRIPE_SECRET_KEY);
const cors = require("cors");
const PORT = process.env.PORT || 5000;
app.use(express.json());
app.use(cors());
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
在上面的代码中,我们初始化了dotenv ,它为我们初始化了环境变量。在我们的例子中,它是Stripe的密匙。
然后我们初始化了一个Express应用程序,这样我们就可以创建一个REST API,并初始化了stripe ,以便从环境变量中传入秘密密钥。我们还导入了 CORS,以便我们可以在 Express 中使用它。
接下来,我们创建了一个名为PORT 的变量。这将检查环境变量中是否提供了一个端口,如果没有,就在5000端口上运行。这通常与Heroku一起使用,因为Heroku使用它自己的端口。
我们还实现了app.use(express.json()); ,以便我们的服务器可以接受JSON数据作为请求的有效载荷。
创建一个PaymentIntent
让我们创建一个POST路由(/donate),因为我们将需要用户的一些数据,我们正在创建一个PaymentIntent。
app.post("/donate", async (req, res) => {
try {
// Getting data from client
let { amount, name } = req.body;
// Simple validation
if (!amount || !name)
return res.status(400).json({ message: "All fields are required" });
amount = parseInt(amount);
// Initiate payment
const paymentIntent = await stripe.paymentIntents.create({
amount: Math.round(amount * 100),
currency: "INR",
payment_method_types: ["card"],
metadata: { name },
});
// Extracting the client secret
const clientSecret = paymentIntent.client_secret;
// Sending the client secret as response
res.json({ message: "Payment initiated", clientSecret });
} catch (err) {
// Catch any error and send error 500 to client
console.error(err);
res.status(500).json({ message: "Internal Server Error" });
}
});
在上面的代码中,我们正在从我们的应用程序中获取amount 和name ,并对其进行验证。如果数据没有被发送,我们将返回一个400错误。
然后,我们将金额转换为整数,以防止向服务器发送字符串形式的数字。这是因为我们只能向Stripe传递整数值。
接下来,我们创建一个PaymentIntent并传入要支付的金额(最低面额)、货币(我住在印度,所以对我来说是印度卢比;使用您在Stripe账户中设置的货币)、支付方式和包含用户姓名的元数据。
当我们在Stripe仪表板上检查交易时,你可以在元数据部分看到用户的名字。如果你想在付款中包含一些信息,这真的很有帮助,以便你以后可以找到它。
然后,我们从PaymentIntent中提取客户秘密,这有助于我们React Native应用中的Stripe实例识别付款并进行确认。
最后,我们将这个客户秘密发回给我们的应用程序,它现在可以确认付款。
创建webhook
为了在本地测试Stripe webhooks,我们需要在Visual Studio代码中使用Stripe扩展来使事情变得更简单。记住,在进入本节之前,你应该已经安装了Stripe CLI!
从侧边栏打开Stripe扩展,你应该在顶部看到以下选项。

单击 "将事件转发到本地机器"。输入webhook URL为 [http://localhost:5000/stripe](http://localhost:5000/stripe);我们将在稍后处理该路由。如果提示您登录到Stripe并授权CLI,请这样做并重复这一过程。
如果你看一下终端,你会得到一个测试网络挂钩的密匙。在.env 文件中以下列格式复制并粘贴。
STRIPE_WEBHOOK_SECRET=(stripe webhook secret)
现在让我们创建一个路由来处理Stripe的webhook请求。首先,在我们之前做的JSON解析器之前添加以下一行(Stripe需要使用原始体)。
app.use("/stripe", express.raw({ type: "*/*" }));
现在我们可以着手处理路由了。
app.post("/stripe", async (req, res) => {
// Get the signature from the headers
const sig = req.headers["stripe-signature"];
let event;
try {
// Check if the event is sent from Stripe or a third party
// And parse the event
event = await stripe.webhooks.constructEvent(
req.body,
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
// Handle what happens if the event is not from Stripe
console.log(err);
return res.status(400).json({ message: err.message });
}
// Event when a payment is initiated
if (event.type === "payment_intent.created") {
console.log(`${event.data.object.metadata.name} initated payment!`);
}
// Event when a payment is succeeded
if (event.type === "payment_intent.succeeded") {
console.log(`${event.data.object.metadata.name} succeeded payment!`);
// fulfilment
}
res.json({ ok: true });
});
在这里,我们要从头文件中获取Stripe的签名,因为我们需要首先验证该请求是由Stripe还是一些假装是Stripe的第三方提出的。
我们将使用constructEvent ,根据我们存储在环境变量中的webhook秘密检查签名。如果请求来自第三方,则会抛出一个状态代码为400的错误。
现在,如果请求是来自Stripe本身,事件将被存储在event 。metadata 而现在我们可以使用之前制作的PaymentIntent的event.type 和用户的付款状态。如果你有任何付款后的动作,你可以在这里执行。
最后,我们添加一个响应,让Stripe知道我们已经收到了他们的请求。
现在我们的服务器已经设置好了,我们终于可以进入我们的Expo和React Native应用。
用Expo和React Native创建一个应用程序
回到你的项目文件夹(对我来说是expo-stripe )。如果你还没有安装Expo CLI,用下面的命令安装它。
npm install -g expo-cli
现在你可以用Expo创建React Native应用了。在终端中输入以下命令。
expo init rn-app
当提示有选项时,选择第一个选项,即一个带有管理的工作流的空白Expo应用。这将创建一个名为rn-app 的新文件夹,包含我们的React Native文件。
进入rn-app 文件夹,输入以下命令,在你的网络浏览器中启动开发工具。
npm start
这应该会自动启动你的浏览器,你应该看到这样的屏幕。

使用左侧边栏上的任何选项运行该应用程序。在我的例子中,我将使用一个iPhone模拟器。如果你在Windows机器上,你可能需要使用一个安卓模拟器或一个真正的物理设备。
运行后,你的模拟器应该启动,你应该看到该应用程序。

现在,让我们来安装Expo的Stripe软件包。Expo已经很容易将Stripe集成到React Native中,而不需要触及本地项目文件。
在终端键入以下命令来安装Stripe React Native包。
expo install @stripe/stripe-react-native
记住我们使用的是expo install ,而不是npm install ,因为Expo为我们处理了安装。
在React Native中配置Stripe
在配置Stripe之前,我强烈建议安装Visual Studio Code的ES7 Snippets扩展,因为它可以生成空白组件模板。
创建一个名为components 的新文件夹和一个名为Checkout.js 的新文件。开始输入rnfe ,选择片段,你将有一个组件准备好。保存该文件;我们将在稍后使用它。
转到App.js ,导入Checkout 组件和StripeProvider 。
import { StripeProvider } from "@stripe/stripe-react-native";
import Checkout from "./components/Checkout";
现在,你的JSX应该看起来像这样。
<View style={styles.container}>
<StatusBar style="dark" />
<StripeProvider publishableKey="(stripe publishable key here)">
<Checkout />
</StripeProvider>
</View>
记住要把您的Stripe可发布密钥放在Stripe仪表板上。我们将Checkout 组件包装在StripeProvider 内,这样我们就可以访问Stripe服务。
进入Checkout.js ,为name 和amount 创建状态。我们还将使用Stripe钩子来与Stripe通信。
const [name, setName] = useState("");
const [amount, setAmount] = useState("1");
const stripe = useStripe();
默认的名字将是空的,默认的金额将是INR。
现在,让我们创建一个基本的布局,并将这些状态与文本框进行映射。你的JSX应该看起来像这样。
<View>
<TextInput
placeholder="Name"
style={{ padding: 10, borderColor: "black", borderWidth: 1 }}
value={name}
onChangeText={(e) => setName(e)}
/>
<TextInput
placeholder="Amount"
keyboardType="numeric"
style={{ padding: 10, borderColor: "black", borderWidth: 1 }}
value={amount}
onChangeText={(e) => setAmount(e)}
/>
<Button title="Donate" onPress={donate} />
</View>
创建一个名为donate() 的函数,我们将在稍后进行处理。
const donate = async () => {};
生成的布局应该如下所示。

接下来,我们将处理donate 这个函数。
const donate = async () => {
try {
const finalAmount = parseInt(amount);
if (finalAmount < 1) return Alert.alert("You cannot donate below 1 INR");
const response = await fetch("http://localhost:5000/donate", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ amount: finalAmount, name }),
});
const data = await response.json();
if (!response.ok) {
return Alert.alert(data.message);
}
const initSheet = await stripe.initPaymentSheet({
paymentIntentClientSecret: data.clientSecret,
});
if (initSheet.error) {
console.error(initSheet.error);
return Alert.alert(initSheet.error.message);
}
const presentSheet = await stripe.presentPaymentSheet({
clientSecret: data.clientSecret,
});
if (presentSheet.error) {
console.error(presentSheet.error);
return Alert.alert(presentSheet.error.message);
}
Alert.alert("Donated successfully! Thank you for the donation.");
} catch (err) {
console.error(err);
Alert.alert("Payment failed!");
}
};
首先,我们要把数值从字符串转换为整数。然后,我们检查金额是否小于₹1 INR。如果是,应用程序就会抛出一个警报,交易就会停止。
接下来,我们向Node后端发出HTTP POST请求,以获得客户秘密。如果有任何错误,我们通过检查response.ok 来处理。
然后,我们使用initPaymentSheet() 函数初始化 PaymentSheet,并传入我们从后端得到的客户秘密。我们再次使用presentPaymentSheet() 来展示PaymentSheet,向它提供客户秘密,并检查是否有任何错误。如果我们发现任何错误,就会向用户发送一个警告。
如果没有错误,你应该得到一个 "捐赠成功 "的提示。当你点击捐赠按钮时,你会看到以下内容。

这是PaymentSheet,由Stripe制作。从这里开始,一切都由Stripe处理,你不需要担心错误的处理。
一旦支付成功,你可以在运行Node服务器的控制台中清楚地看到它与用户的名字。在生产环境中,你将需要从Stripe仪表板上手动创建一个webhook,并使用实时密钥而不是测试密钥。
接下来是什么?
恭喜你!你已经成功地集成了PaymentSheet。你已经成功地将PaymentSheet集成到你的Expo应用中。我希望你能尽可能多地使用这个功能。也许你可以尝试在使用PaymentSheet的同时使用Apple Pay和Google Pay,我认为这将是一个很好的锻炼机会
如果你面临任何挑战,你可以随时参考本文前面链接的Github资源库。
The postMastering Stripe PaymentSheet in React Native with Expoappeared first onLogRocket Blog.