---
title: 如何在Back4App中集成Stripe API和云函数
slug: docs-ch/cloud-code-functions/integrations/stripe
description: 在本指南中了解如何在Back4App中使用云函数集成Stripe API，实现支付功能。
image: https://www.back4app.com/images/logo-social.png
createdAt: 2024-02-28T14:23:44.608Z
---

# 使用云函数进行Stripe集成

## 介绍

在本指南中，我们将向您展示如何将Back4App中的托管后端与Stripe API集成。在Back4App上构建它的最佳架构选择是使用一个非常强大的功能，称为 [云函数](https://www.back4app.com/docs/get-started/cloud-functions). 一旦您完成了与Stripe的云函数集成，您将能够在所有前端项目（Web、iOS、Android）中使用此集成。本指南提供了一个完整的Stripe集成示例。

## 先决条件

:::hint{type="info"}
要完成本教程，您需要：




- 在Back4App上创建的应用程序。
- 遵循 [创建新应用教程](https://www.back4app.com/docs/get-started/new-parse-app) 以了解如何在Back4App上创建应用程序。
- 在 [Stripe](https://stripe.com/br) 上创建的账户。
:::

## 目标

在Web项目中使用Back4App云函数集成Stripe。

## 什么是Stripe？

[Stripe](https://stripe.com/) 是一家在25个国家运营的科技公司，允许个人和企业通过互联网接受支付。Stripe专注于提供在线支付系统所需的技术、欺诈预防和银行基础设施。

本教程将引导您完成创建函数并将Stripe API集成到您的Parse Server中的Web应用程序的步骤。

更具体地说，在本指南中，我们将创建一个环境，用户可以在其中登录或注册，注册信用卡，并通过Stripe Payments生成示例购买。此外，您将被指导如何设置整个过程以及测试与服务器和Stripe API的连接是否正常工作。

## 1 - 创建一个Stripe账户

访问Stripe并点击注册以 [创建一个账户](https://dashboard.stripe.com/register)。在那里，您只需提供您的个人信息以及您的账户所属国家。

接下来，验证您的Stripe账户（您将收到一封包含Stripe验证链接的电子邮件）。点击该链接，然后按照步骤确认您的Stripe电子邮件地址。

## 2 - 设置您的数据库类

在为步骤1配置Stripe环境后，前往您的Back4App应用仪表板，以便设置您的数据库。此步骤不是强制性的，因为当云函数尝试创建新对象时，Parse会自动创建类，但我们将逐步讲解将创建哪些字段以及原因。

将有两个类来保存您的应用程序与Stripe相关的数据： <font color="#2166ae">`PaymentMethod`</font> 和 <font color="#2166ae">`Payment`</font>:

以下是课程的布局方式：

- <font color="#2166ae">`支付方式`</font>
  - <font color="#2166ae">`类型`</font>（字符串）：其值将始终为“card”；
  - <font color="#2166ae">`卡片`</font>（对象）：将保存有关注册卡的完整Stripe数据；
  - <font color="#2166ae">`stripeID`</font>（字符串）：引用此支付方式在Stripe后端的ID；
  - <font color="#2166ae">`用户`</font>（指向Parse.User的指针）：直接引用此支付方式所属的用户。
- <font color="#2166ae">`支付`</font>
  - <font color="#2166ae">`数据`</font>（对象）：将保存有关支付的完整Stripe数据；
  - <font color="#2166ae">`用户`</font>（指向Parse.User的指针）：直接引用此支付所属的用户。

我们还将在您的应用程序默认 <font color="#2166ae">`用户`</font> 类中添加两个新的 <font color="#2166ae">`字符串`</font> 值列，分别称为 <font color="#2166ae">`setupSecret`</font> 和 <font color="#2166ae">`customerId`</font>，将包含与 <font color="#2166ae">`用户`</font> 相关的Stripe ID。

## 3 - 实现云代码

让我们在应用中配置 [云代码函数](https://docs.parseplatform.org/cloudcode/guide/#cloud-functions)，安装Stripe模块并部署代码。

:::hint{type="info"}
**如果你想更好地理解云代码环境，请查看 [这份指南](https://www.back4app.com/docs/get-started/cloud-functions).**&#x20;
:::

### 3.1 - 获取你的Stripe密钥

现在，打开你的Stripe仪表板，导航到顶部的 <font color="#2166ae">`开发者`</font> 页面，然后在左侧菜单中选择 <font color="#2166ae">`API密钥`</font>。在该部分，你将能够看到你的 <font color="#2166ae">`可发布密钥`</font> 和你的 <font color="#2166ae">`秘密密钥`</font>。

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/XdeM4pK8gQagvIiLc0vd6_image.png)

请记下这些密钥，因为您稍后会需要它们。

### 3.2 - 云代码文件

在您的计算机上，创建以下文件，这些文件将负责安装模块并将您的云代码函数添加到 Back4App。

```json
1   {
2     "dependencies": {
3       "stripe": "*"
4     }
5   }
```

将以下代码添加到新文件中，并不要忘记在顶部粘贴您的 Stripe 秘密密钥。

:::CodeblockTabs
main.js

```javascript
1   const STRIPE_SECRET_KEY =
2     "YOUR_STRIPE_SECRET_KEY";
3   const stripe = require("stripe")(STRIPE_SECRET_KEY);
4
5   // Stripe needs an unique customer id to create payments, so after
6   // signing up, this function should be called to do this operation
7   Parse.Cloud.define("createStripeCustomer", async (request) => {
8     // Get Parse.User object
9     const userQuery = new Parse.Query(Parse.User);
10    userQuery.equalTo("objectId", request.params.userId);
11    let user = await userQuery.first();
12  
13    const customer = await stripe.customers.create({ email: user.get("email") });
14    // Creates an stripe setupIntent, that will enable the stripe lib to perform
15    // a singel operation related to payments
16    const intent = await stripe.setupIntents.create({
17      customer: customer.id,
18    });
19    // Set and save the stripe ids to the Parse.User object
20    user.set({
21      customerId: customer.id,
22      setupSecret: intent.client_secret,
23    });
24    return await user.save(null, { useMasterKey: true });
25  });
26
27  // Creates new payment method for a registered customer
28  Parse.Cloud.define("addNewPaymentMethod", async (request) => {
29    // Get Parse.User object
30    const userQuery = new Parse.Query(Parse.User);
31    userQuery.equalTo("objectId", request.params.userId);
32    let user = await userQuery.first();
33
34    // Retrieve complete stripe payment method by its id
35    const stripePaymentMethod = await stripe.paymentMethods.retrieve(
36      request.params.paymentMethodId
37    );
38
39    // Create a new SetupIntent so the customer can add a new method next time.
40      const intent = await stripe.setupIntents.create({
41      customer: `${stripePaymentMethod.customer}`,
42    });
43    user.set("setupSecret", intent.client_secret);
44    user = await user.save(null, { useMasterKey: true });
45
46    // Creates a new Parse object in the PaymentMethod class
47    let PaymentMethod = new Parse.Object("PaymentMethod");
48    PaymentMethod.set({
49      user: user,
50      type: "card",
51      stripeId: stripePaymentMethod.id,
52      card: stripePaymentMethod.card,
53    });
54    PaymentMethod.save();
55    return true;
56  });
57
58  // Creates a new payment using a valid payment method
59  Parse.Cloud.define("createNewPayment", async (request) => {
60    // Get Parse.User object
61    const userQuery = new Parse.Query(Parse.User);
62    userQuery.equalTo("objectId", request.params.userId);
63    let user = await userQuery.first();
64
65    const { amount, currency, payment_method } = request.params.paymentData;
66
67    // Look up the Stripe customer id.
68    const customer = user.get("customerId");
69
70    // Create a charge using an unique idempotency key
71    // to protect against double charges.
72    const idempotencyKey = new Date().getTime();
73    const payment = await stripe.paymentIntents.create(
74      {
75        amount,
76        currency,
77        customer,
78        payment_method,
79        off_session: false,
80        confirm: true,
81        confirmation_method: "manual",
82      },
83      { idempotencyKey }
84    );
85    // If the result is successful, write it back to the database.
86    let Payment = new Parse.Object("Payment");
87    Payment.set({
88      user: user,
89      data: payment,
90    });
91    await Payment.save();
92
93    return true;
94  });

```
:::

## 4 - 将函数上传到云代码

访问 Back4App 网站，登录后找到您的应用。之后，点击 <font color="#2166ae">`仪表板`</font> 链接，您将进入如下所示的页面。要部署您的云代码，请点击 <font color="#2166ae">`+ 添加`</font> 按钮，找到您在上一步中创建的 <font color="#2166ae">`main.js`</font> 和 <font color="#2166ae">`package.json`</font> 文件，然后点击 <font color="#2166ae">`部署`</font> 按钮。

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/6TdryEG35btnknL02_lCa_image.png)

:::hint{type="info"}
您刚刚配置了可以在任何平台上使用的云代码函数！查看 [部署和调用函数](https://www.back4app.com/docs/get-started/cloud-functions) 指南以了解如何调用它们。在下一步中，您将处理一个调用它们的 JavaScript 项目。
:::

## 5 - 将 JavaScript 应用与云代码集成

现在您将看到一个简单的 HTML 页面示例，包含 JavaScript，具有三个主要功能：在 Parse 上登录或注册用户，创建有效的支付方式（信用卡），以及创建新的支付，向这些属于用户的方式收费。

继续在您的计算机上创建一个新目录，并在其中创建一个新的 HTML 文件，文件内容如下：

:::CodeblockTabs
index.html

```html
1   <!DOCTYPE html>
2   <html lang="en">
3
4   <head>
5       <meta charset="UTF-8" />
6       <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7       <title>Back4App Stripe Payments</title>
8       <link rel="stylesheet" href="app.css">
9   </head>
10
11  <body>
12      <header class="header">
13          <img class="header_logo"
14              src="https://blog.back4app.com/wp-content/uploads/2019/05/back4app-white-logo-500px.png" alt="">
15          <p class="header_text_bold">React on Back4App</p>
16          <p class="header_text">Back4App Stripe Payments</p>
17      </header>
18      <section id="auth">
19          <div class="container">
20              <div class="form_wrapper">
21                  <form id="auth-signin-form">
22                      <h2 class="form_heading">Sign In</h2>
23                      <input class="form_input" type="email" name="email" placeholder="Email" required />
24                      <input class="form_input" type="password" name="password" placeholder="Password" required />
25                      <button class="form_button" type="submit">
26                          Sign in
27                      </button>
28                      <a class="form_hint" id="signup-toggle" href="#">Don't have an account yet? Sign up instead.</a>
29                  </form>
30                  <form id="auth-signup-form" hidden>
31                      <h2 class="form_heading">Sign Up</h2>
32                      <input class="form_input" type="email" name="email" placeholder="Email" required />
33                      <input class="form_input" type="password" name="password" placeholder="Password" required />
34                      <button class="form_button" type="submit">
35                          Sign up
36                      </button>
37                      <a class="form_hint" id="signin-toggle" href="#">Already have an account? Sign in instead.</a>
38                  </form>
39              </div>
40          </div>
41      </section>
42      <section id="content" style="display: none;">
43          <div class="container">
44              <div>
45                  <h2 class="form_heading">Add new payment method</h2>
46                  <p>
47                      Use any of the
48                      <a href="https://stripe.com/docs/testing#international-cards" target="_blank">Stripe test cards</a>
49                      for this demo!
50                  </p>
51                  <form class="form" id="payment-method-form">
52                      <input class="form_input" type="text" name="name" placeholder="Cardholder name" required />
53                      <div class="card_element_wrapper">
54                          <div id="card-element"></div>
55                      </div>
56                      <button class="form_button">Save Card</button>
57                  </form>
58              </div>
59              <div>
60                  <h2 class="form_heading">Create new payment</h2>
61                  <form class="form" id="payment-form">
62                      <select class="form_input" name="payment-method" required>
63                          <option disabled selected>Card (payment method):</option>
64                      </select>
65                      <div>
66                          <input class="form_input" name="amount" type="number" min="1" max="99999999"
67                              placeholder="Amount" required />
68                          <select class="form_input" name="currency">
69                              <option disabled selected>Currency:</option>
70                              <option value="usd">USD</option>
71                              <option value="brl">BRL</option>
72                              <option value="eur">EUR</option>
73                          </select>
74                      </div>
75                      <button class="form_button">Charge selected card</button>
76                  </form>
77              </div>
78              <div class="form">
79                  <h2 class="form_heading">Payments</h2>
80                  <ul id="payments-list"></ul>
81              </div>
82              <button type="button" id="signout">
83                  Sign out
84              </button>
85          </div>
86      </section>
87      <script type="text/javascript" src="https://npmcdn.com/parse/dist/parse.min.js"></script>
88      <script type="text/javascript" src="https://js.stripe.com/v3/"></script>
89      <script type="text/javascript" src="index.js"></script>
90  </body>
91
92  </html>
```
:::

在此文件中，您将找到两个主要部分，第一个是身份验证部分，如果用户尚未登录，将默认呈现该部分。登录后，将显示支付部分，其中包含负责在Stripe上创建数据的所有表单，并与Back4App上的Cloud Code函数进行通信。

我们现在需要创建一个包含将所有内容结合在一起的代码的JavaScript函数，称为 <font color="#2166ae">`index.js`</font>:

:::CodeblockTabs
index.js

```javascript
1   // Define and initialize Parse and Stripe libs
2   const PARSE_APP_ID = "YOUR_PARSE_ID";
3   const PARSE_JS_KEY = "YOUR_PARSE_JS_KEY";
4   Parse.initialize(PARSE_APP_ID, PARSE_JS_KEY);
5   Parse.serverURL = "https://parseapi.back4app.com/";
6
7   const STRIPE_PUBLISHABLE_KEY = "YOUR_STRIPE_PUBLISHABLE_KEY";
8   const stripe = Stripe(STRIPE_PUBLISHABLE_KEY);
9
10  // Holds the currentUser complete Parse object
11  let currentUser = null;
12  const setCompleteCurrentUser = async () => {
13    // Called when user is already signed in, completing
14    // the currentUser object with the full one
15    currentUser = await new Parse.Query(Parse.User)
16      .equalTo("objectId", Parse.User.current().id)
17      .first();
18    // Retrieve and render user cards and payments
19    retrieveCurrentUserPaymentMethods();
20    retrieveCurrentUserPayments();
21  };
22
23  const retrieveCurrentUserPaymentMethods = async () => {
24    // Query and render user PaymentMethods
25    const PMQuery = new Parse.Query("PaymentMethod");
26    PMQuery.equalTo("user", Parse.User.current());
27    paymentMethods = await PMQuery.find();
28    renderPaymentMethodOptions(paymentMethods);
29  };
30
31  const retrieveCurrentUserPayments = async () => {
32    // Query and render user Payments
33    const paymentsQuery = new Parse.Query("Payment");
34    paymentsQuery.equalTo("user", Parse.User.current());
35    payments = await paymentsQuery.find();
36    renderPayments(payments);
37  };
38  
39  const renderPaymentMethodOptions = async (paymentMethods) => {
40    for (let paymentMethod of paymentMethods) {
41      const optionId = `card-${paymentMethod.get("stripeId")}`;
42      let optionElement = document.getElementById(optionId);
43  
44      // Add a new option if one doesn't exist yet.
45      if (!optionElement) {
46        optionElement = document.createElement("option");
47        optionElement.id = optionId;
48        document
49          .querySelector("select[name=payment-method]")
50          .appendChild(optionElement);
51      }
52 
53      optionElement.value = paymentMethod.get("stripeId");
54      optionElement.text = `${paymentMethod.get("card").brand} •••• ${
55        paymentMethod.get("card").last4
56      } | Expires ${paymentMethod.get("card").exp_month}/${
57        paymentMethod.get("card").exp_year
58      }`;
59    }
60  };
61
62  const renderPayments = (payments) => {
63    for (let payment of payments) {
64      let liElement = document.getElementById(`payment-${payment.id}`);
65      if (!liElement) {
66        liElement = document.createElement("li");
67        liElement.id = `payment-${payment.id}`;
68      }
69
70      const paymentData = payment.get("data");
71      let content = "";
72      if (
73        paymentData.status === "new" ||
74        paymentData.status === "requires_confirmation"
75      ) {
76        content = `Creating Payment for ${formatAmount(
77          paymentData.amount,
78          paymentData.currency
79        )}`;
80      } else if (paymentData.status === "succeeded") {
81        const card = paymentData.charges.data[0].payment_method_details.card;
82        content = `Payment for ${formatAmount(
83          paymentData.amount,
84          paymentData.currency
85        )} on ${card.brand} card •••• ${card.last4} ${paymentData.status}!`;
86      } else {
87        content = `Payment for ${formatAmount(
88          paymentData.amount,
89          paymentData.currency
90        )} ${paymentData.status}`;
91      }
92      liElement.innerText = content;
93      document.querySelector("#payments-list").appendChild(liElement);
94    }
95  };
96
97  // Checks if user is already signed in on Parse
98  if (Parse.User.current() !== null) {
99    setCompleteCurrentUser();
100   // Hide auth screen and show payment fields
101   document.getElementById("auth").style.display = "none";
102   document.getElementById("content").style.display = "block";
103 }
104
105 // Toggle signin and signup forms
106 document
107   .querySelector("#signup-toggle")
108   .addEventListener("click", async (_event) => {
109     document.getElementById("auth-signin-form").style.display = "none";
110     document.getElementById("auth-signup-form").style.display = "block";
111     clearAuthFormFields();
112   });
113 document
114   .querySelector("#signin-toggle")
115   .addEventListener("click", async (_event) => {
116     document.getElementById("auth-signup-form").style.display = "none";
117     document.getElementById("auth-signin-form").style.display = "block";
118     clearAuthFormFields();
119   });
120 
121  // Clear auth form fields
122 const clearAuthFormFields = () => {
123   document
124     .querySelector("#auth")
125     .querySelectorAll("input")
126     .forEach((input) => (input.value = ""));
127 };
128 
129 // Handle auth forms
130 document
131   .querySelector("#auth-signin-form")
132   .addEventListener("submit", async (event) => {
133     event.preventDefault();
134     toggleAllButtonsEnabled(false);
135     const form = new FormData(event.target);
136     const email = form.get("email");
137     const password = form.get("password");
138
139    // Try to signin on Parse
140     try {
141       let user = await Parse.User.logIn(email, password);
142       if (user !== null) {
143         currentUser = user;
144         // Hide auth screen and show payment fields
145         document.getElementById("auth").style.display = "none";
146         document.getElementById("content").style.display = "block";
147         clearAuthFormFields();
148       }
149     } catch (error) {
150       alert(error);
151     }
152     toggleAllButtonsEnabled(true);
153   });
154 
155 document
156   .querySelector("#auth-signup-form")
157   .addEventListener("submit", async (event) => {
158     event.preventDefault();
159     toggleAllButtonsEnabled(false);
160     const form = new FormData(event.target);
161     const email = form.get("email");
162     const password = form.get("password");
163
164     // Try to signup on Parse
165     try {
166       let user = await Parse.User.signUp(email, password, { email: email });
167       // Cloud code to create Stripe user and intent
168       user = await Parse.Cloud.run("createStripeCustomer", { userId: user.id });
169       if (user !== null) {
170         currentUser = user;
171         // Hide auth screen and show payment fields
172         document.getElementById("auth").style.display = "none";
173         document.getElementById("content").style.display = "block";
174         clearAuthFormFields();
175       }
176     } catch (error) {
177       alert(error);
178     }
179     toggleAllButtonsEnabled(true);
180   });
181 
182 // Signout from Parse
183 document.querySelector("#signout").addEventListener("click", async (_event) => {
184   await Parse.User.logOut();
185   currentUser = null;
186   // Show auth screen and hide payment fields
187   document.getElementById("auth").style.display = "block";
188   document.getElementById("content").style.display = "none";
189 });
190
191 // Creates stripe card UI element
192 const elements = stripe.elements();
193 const cardElement = elements.create("card");
194 cardElement.mount("#card-element");
195
196 // Handle add new card form
197 document
198   .querySelector("#payment-method-form")
199   .addEventListener("submit", async (event) => {
200    event.preventDefault();
201     toggleAllButtonsEnabled(false);
202     if (!event.target.reportValidity()) {
203       return;
204     }
205    const form = new FormData(event.target);
206     const cardholderName = form.get("name");
207 
208     const result = await stripe.confirmCardSetup(
209       currentUser.get("setupSecret"),
210       {
211         payment_method: {
212           card: cardElement,
213           billing_details: {
214             name: cardholderName,
215           },
216         },
217       }
218     );
219 
220     if (result.error) {
221       alert(result.error.message);
222       toggleAllButtonsEnabled(true);
223       return null;
224     }
225
226     let setupIntent = result.setupIntent;
227 
228     // Cloud code to add new payment method
229     let cloudCodeResult = await Parse.Cloud.run("addNewPaymentMethod", {
230       userId: currentUser.id,
231       paymentMethodId: setupIntent.payment_method,
232     });
233 
234     toggleAllButtonsEnabled(true);
235     alert("Success on creating a new payment method!");
236
237     // Update payment method options
238     retrieveCurrentUserPaymentMethods();
239   });
240 
241 // Handles new payment form
242 document
243   .querySelector("#payment-form")
244   .addEventListener("submit", async (event) => {
245     event.preventDefault();
246     toggleAllButtonsEnabled(false);
247     const form = new FormData(event.target);
248     const amount = Number(form.get("amount"));
249     const currency = form.get("currency");
250     // Gets selected card option id
251     const paymentMethod = form.get("payment-method");
252     const paymentData = {
253       payment_method: paymentMethod,
254       currency,
255       amount: formatAmountForStripe(amount, currency),
256       status: "new",
257     };
258     // Cloud code to create new payment
259     let cloudCodeResult = await Parse.Cloud.run("createNewPayment", {
260       userId: currentUser.id,
261       paymentData: paymentData,
262     });
263 
264     toggleAllButtonsEnabled(true);
265     alert("Success on creating a new payment!");
266 
267     retrieveCurrentUserPayments();
268   });
269  
270 // Helper functions
271 const toggleAllButtonsEnabled = (enabledValue) => {
272   document
273     .querySelectorAll("button")
274     .forEach((button) => (button.disabled = !enabledValue));
275 };
276
277 const formatAmount = (amount, currency) => {
278   amount = zeroDecimalCurrency(amount, currency)
279     ? amount
280     : (amount / 100).toFixed(2);
281   return new Intl.NumberFormat("en-US", {
282     style: "currency",
283     currency,
284   }).format(amount);
285 };
286
287 // Format amount for Stripe
288 const formatAmountForStripe = (amount, currency) => {
289   return zeroDecimalCurrency(amount, currency)
290     ? amount
291     : Math.round(amount * 100);
292 };
293
294 // Check if we have a zero decimal currency
295 // https://stripe.com/docs/currencies#zero-decimal
296 const zeroDecimalCurrency = (amount, currency) => {
297   let numberFormat = new Intl.NumberFormat(["en-US"], {
298     style: "currency",
299     currency: currency,
300     currencyDisplay: "symbol",
301   });
302   const parts = numberFormat.formatToParts(amount);
303   let zeroDecimalCurrency = true;
304   for (let part of parts) {
305     if (part.type === "decimal") {
306       zeroDecimalCurrency = false;
307     }
308   }
309   return zeroDecimalCurrency;
310 };
```
:::

确保将您的 Stripe 可发布密钥以及您的 Parse 应用 ID 和 JS 密钥添加到文件顶部。这些是检查和理解此脚本的一些关键元素：

- 检查在首次加载脚本时使用 <font color="#2166ae">`Parse.User.current`</font> 方法以呈现页面的正确部分；
- 表单提交操作监听器将在 Parse 上执行操作，例如登录或注册，并调用云代码函数以创建与 Stripe 相关的对象并保存在您的 Back4App 数据库中；
- 用于在 Parse 上查询以检索当前用户的 “retrieve” 和 “return” 方法的 <font color="#2166ae">`Payment`</font> 和 <font color="#2166ae">`PaymentMethod`</font> 对象。

在测试应用之前，请在名为 <font color="#2166ae">`app.css`</font> 的 CSS 文件中添加以下样式表，放在同一目录下：

```css
1   /* Back4App Guide */
2 
3   *,
4   *:before,
5   *:after {
6     margin: 0;
7     padding: 0;
8     box-sizing: inherit;
9   }
10
11  html {
12    font-family: sans-serif;
13    box-sizing: border-box;
14    outline: none;
15    overflow: auto;
16  }
17
18  body {
19    margin: 0;
20    background-color: #fff;
21  }
22  
23  h1,
24  h2,
25  h3,
26  h4,
27  h5,
28  h6 {
29    margin: 0;
30  }
31
32  p {
33    margin: 0;
34  }
35
36  .container {
37    width: 100%;
38    max-width: 600px;
39    margin: auto;
40    padding: 20px 0;
41  }
42  
43  .wrapper {
44   width: '90%';
45    align-self: 'center';
46  }
47
48  .header {
49    display: flex;
50    flex-direction: column;
51    align-items: center;
52    padding: 25px 0;
53    background-color: #208AEC;
54  }
55
56  .header_logo {
57    height: 55px;
58    margin-bottom: 20px;
59    object-fit: contain;
60  }
61  
62  .header_text_bold {
63    margin-bottom: 3px;
64    color: rgba(255, 255, 255, 0.9);
65    font-size: 16px;
66    font-weight: bold;
67  }
68  
69  .header_text {
70    color: rgba(255, 255, 255, 0.9);
71    font-size: 15px;
72  }
73
74  .flex_row {
75    display: flex;
76  }
77  
78  .flex_between {
79    display: flex;
80    align-items: center;
81    justify-content: space-between;
82  }
83
84  .form_wrapper {
85    margin-top: 20px;
86    margin-bottom: 10px;
87  }
88
89  .form_heading {
90    margin-bottom: 10px;
91  }
92
93  .form {
94    padding-bottom: 25px;
95    margin: 25px 0;
96    border-bottom: 1px solid rgba(0, 0, 0, 0.12);
97  }
98
99  .form_input {
100   display: block;
101   width: 100%;
102   height: 46px;
103   padding: 0 15px;
104   background-color: #e6e6e6;
105   border: 1px solid #ccc;
106   border-radius: 999px;
107   margin-bottom: 20px;
108   font-size: 16px;
109 }
110
111 .form_button {
112   display: block;
113   width: 100%;
114   height: 42px;
115   padding: 0 15px;
116   background-color: #208AEC;
117   border: 1px solid #208AEC;
118   border-radius: 999px;
119   color: #fff;
120   font-size: 16px;
121   cursor: pointer;
122 }
123
124  .form_hint {
125   display: block;
126   margin-top: 20px;
127   color: rgba(0, 0, 0, 0.5);
128   font-size: 16px;
129   text-align: center;
130   text-decoration-color: rgba(0, 0, 0, 0.4);
131 }
132
133 .card_element_wrapper {
134   padding: 13px 15px;
135   margin-bottom: 20px;
136   background-color: #e6e6e6;
137   border: 1px solid #ccc;
138   border-radius: 999px;
139 }
```

使用任何类型的本地 HTTP 服务器测试应用程序，例如 [http-server node 包](https://github.com/http-party/http-server). 注册后，您的应用程序应该看起来像这样:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/zmw8j8fXi-Ghyk53M-7KG_image.png" size="80" width="800" height="673" position="center" showCaption="false"}

## 结论

通过上述指南，您可以在 Back4App 中使用 Stripe 和 Cloud Code 函数，并将支付集成到一个简单的 JavaScript 应用程序中！

如果在集成 Stripe 或某个功能无法正常工作时遇到任何问题，请通过聊天与我们的团队联系！
