Cloud Code Functions

Stripe Integration using Cloud Functions

Introduction

In this guide, we are going to show you how to integrate a hosted backend in Back4App with Stripe API. The best architecture choice to build it on Back4App is using a very powerful feature called Cloud Functions. Once you finish the cloud function integration with Stripe you will be able to use this integration for all your front-end projects (Web, iOS, Android). This guide presents a complete Stripe integration using a web example.

Prerequisites

To complete this tutorial, you will need:

Goal

Integrate Stripe on a web project using Back4App Cloud Functions.

What is Stripe?

Stripe is a tech company operating in over 25 countries, which allows both individuals and businesses to accept payments over the Internet. Stripe focuses on providing the technical, fraud prevention, and banking infrastructure required to operate online payment systems.

This tutorial will walk you through the steps of creating functions and integrating Stripe API to your Parse Server into your web app.

More specifically, in this guide, we will create an environment in which a user can log in or sign up, register credit cards, and generate example purchases with them via Stripe Payments. Also, you will be guided on how to set up the whole process as well as test if the connection to the server and the Stripe API is working properly.

Step 1 - Create a Stripe Account

Go to Stripe and click on the sign up to create an account. There, you just need to provide your personal information and to which country your account belongs.

Next, verify your Stripe account (you will receive an email containing a verification link from Stripe). Click on that link, and then follow the steps to confirm your Stripe email address.

Step 2 - Setting up your database classes

After configuring the Stripe environment for Step 1, go to your Back4App app dashboard so you can set up your database. This step is not obligatory since Parse will automatically create the classes while the cloud functions try to create a new object, but we will go through them to explain which fields will be created and why.

There will be two classes that will hold your app Stripe related data: PaymentMethod and Payment:

Here is how the classes are laid out:

  • PaymentMethod
    • type (String): its value will always be “card”;
    • card (Object): will hold the complete Stripe data regarding the registered card;
    • stripeID (String): id referencing this PaymentMethod on the Stripe backend;
    • user (Pointer to Parse.User): direct reference to which User this PaymentMethod belongs.
  • Payment
    • data (Object): will hold the complete Stripe data regarding the payment;
    • user (Pointer to Parse.User): direct reference to which User this Payment belongs.

We will also add two new String value columns in your app default User class called setupSecret and customerId that will contain the Stripe ids that relate the User to its Stripe counterpart.

Step 3 - Implementing Cloud Code

Let’s configure the Cloud Code functions in the app, installing the Stripe module and deploying the Code.

If you want to better understand the Cloud Code enviroment, check this guide.

3.1 - Get your Stripe Key

Now, open your Stripe dashboard, navigate to the Developers page at the top and then select API Keys on the left menu. In that section, you will be able to see your Publishable key and your Secret key.

Stripe on Back4App

Write down these keys as you will need them later.

3.2 - Cloud Code files

On your computer, create the following files, that will be responsible to install the module and adding your Cloud Code functions to Back4App.

package.json

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

Add the code below to a new file and don’t forget to paste your Stripe secret key on the top.

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
const STRIPE_SECRET_KEY =
  "YOUR_STRIPE_SECRET_KEY";
const stripe = require("stripe")(STRIPE_SECRET_KEY);

// Stripe needs an unique customer id to create payments, so after
// signing up, this function should be called to do this operation
Parse.Cloud.define("createStripeCustomer", async (request) => {
  // Get Parse.User object
  const userQuery = new Parse.Query(Parse.User);
  userQuery.equalTo("objectId", request.params.userId);
  let user = await userQuery.first();

  const customer = await stripe.customers.create({ email: user.get("email") });
  // Creates an stripe setupIntent, that will enable the stripe lib to perform
  // a singel operation related to payments
  const intent = await stripe.setupIntents.create({
    customer: customer.id,
  });
  // Set and save the stripe ids to the Parse.User object
  user.set({
    customerId: customer.id,
    setupSecret: intent.client_secret,
  });
  return await user.save(null, { useMasterKey: true });
});

// Creates new payment method for a registered customer
Parse.Cloud.define("addNewPaymentMethod", async (request) => {
  // Get Parse.User object
  const userQuery = new Parse.Query(Parse.User);
  userQuery.equalTo("objectId", request.params.userId);
  let user = await userQuery.first();

  // Retrieve complete stripe payment method by its id
  const stripePaymentMethod = await stripe.paymentMethods.retrieve(
    request.params.paymentMethodId
  );

  // Create a new SetupIntent so the customer can add a new method next time.
  const intent = await stripe.setupIntents.create({
    customer: `${stripePaymentMethod.customer}`,
  });
  user.set("setupSecret", intent.client_secret);
  user = await user.save(null, { useMasterKey: true });

  // Creates a new Parse object in the PaymentMethod class
  let PaymentMethod = new Parse.Object("PaymentMethod");
  PaymentMethod.set({
    user: user,
    type: "card",
    stripeId: stripePaymentMethod.id,
    card: stripePaymentMethod.card,
  });
  PaymentMethod.save();
  return true;
});

// Creates a new payment using a valid payment method
Parse.Cloud.define("createNewPayment", async (request) => {
  // Get Parse.User object
  const userQuery = new Parse.Query(Parse.User);
  userQuery.equalTo("objectId", request.params.userId);
  let user = await userQuery.first();

  const { amount, currency, payment_method } = request.params.paymentData;

  // Look up the Stripe customer id.
  const customer = user.get("customerId");

  // Create a charge using an unique idempotency key
  // to protect against double charges.
  const idempotencyKey = new Date().getTime();
  const payment = await stripe.paymentIntents.create(
    {
      amount,
      currency,
      customer,
      payment_method,
      off_session: false,
      confirm: true,
      confirmation_method: "manual",
    },
    { idempotencyKey }
  );
  // If the result is successful, write it back to the database.
  let Payment = new Parse.Object("Payment");
  Payment.set({
    user: user,
    data: payment,
  });
  await Payment.save();

  return true;
});

Step 4 - Upload functions to Cloud Code

Go to the Back4App website, log in and then find your app. After that, click on Dashboard link and you will end up on the page shown below. To deploy your Cloud Code, click on the + ADD button and find the main.js and package.json files that you created in the previous step, then click on the DEPLOY button.

Stripe on Back4App

You have just configured Cloud Code functions that you can use on any platform! Check the Deploy & call functions guide to learn how to call them. On the next step, you will work with a JavaScript project that calls them.

Step 5 - Integrating a JavaScript app with Cloud Code

Now you will see an example of a straightforward HTML page with JavaScript that has three main features: signing in or up a user on Parse, creating valid payment methods (credit cards), and creating new payments, charging these methods belonging to the user.

Go ahead and create a new directory in your computer and a new HTML file with the following code inside it:

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Back4App Stripe Payments</title>
    <link rel="stylesheet" href="app.css">
</head>

<body>
    <header class="header">
        <img class="header_logo"
            src="https://blog.back4app.com/wp-content/uploads/2019/05/back4app-white-logo-500px.png" alt="">
        <p class="header_text_bold">React on Back4App</p>
        <p class="header_text">Back4App Stripe Payments</p>
    </header>
    <section id="auth">
        <div class="container">
            <div class="form_wrapper">
                <form id="auth-signin-form">
                    <h2 class="form_heading">Sign In</h2>
                    <input class="form_input" type="email" name="email" placeholder="Email" required />
                    <input class="form_input" type="password" name="password" placeholder="Password" required />
                    <button class="form_button" type="submit">
                        Sign in
                    </button>
                    <a class="form_hint" id="signup-toggle" href="#">Don't have an account yet? Sign up instead.</a>
                </form>
                <form id="auth-signup-form" hidden>
                    <h2 class="form_heading">Sign Up</h2>
                    <input class="form_input" type="email" name="email" placeholder="Email" required />
                    <input class="form_input" type="password" name="password" placeholder="Password" required />
                    <button class="form_button" type="submit">
                        Sign up
                    </button>
                    <a class="form_hint" id="signin-toggle" href="#">Already have an account? Sign in instead.</a>
                </form>
            </div>
        </div>
    </section>
    <section id="content" style="display: none;">
        <div class="container">
            <div>
                <h2 class="form_heading">Add new payment method</h2>
                <p>
                    Use any of the
                    <a href="https://stripe.com/docs/testing#international-cards" target="_blank">Stripe test cards</a>
                    for this demo!
                </p>
                <form class="form" id="payment-method-form">
                    <input class="form_input" type="text" name="name" placeholder="Cardholder name" required />
                    <div class="card_element_wrapper">
                        <div id="card-element"></div>
                    </div>
                    <button class="form_button">Save Card</button>
                </form>
            </div>
            <div>
                <h2 class="form_heading">Create new payment</h2>
                <form class="form" id="payment-form">
                    <select class="form_input" name="payment-method" required>
                        <option disabled selected>Card (payment method):</option>
                    </select>
                    <div>
                        <input class="form_input" name="amount" type="number" min="1" max="99999999"
                            placeholder="Amount" required />
                        <select class="form_input" name="currency">
                            <option disabled selected>Currency:</option>
                            <option value="usd">USD</option>
                            <option value="brl">BRL</option>
                            <option value="eur">EUR</option>
                        </select>
                    </div>
                    <button class="form_button">Charge selected card</button>
                </form>
            </div>
            <div class="form">
                <h2 class="form_heading">Payments</h2>
                <ul id="payments-list"></ul>
            </div>
            <button type="button" id="signout">
                Sign out
            </button>
        </div>
    </section>
    <script type="text/javascript" src="https://npmcdn.com/parse/dist/parse.min.js"></script>
    <script type="text/javascript" src="https://js.stripe.com/v3/"></script>
    <script type="text/javascript" src="index.js"></script>
</body>

</html>

In this file you will find two main sections, the first one being the authentication one, which will be rendered by default if the user is not logged in yet. After logging in, the payment section will be shown, containing all the forms responsible for creating data on Stripe and also communicating with the Cloud Code functions on Back4App.

We now need to create a JavaScript function containing the code that ties it all together, called index.js:

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
// Define and initialize Parse and Stripe libs
const PARSE_APP_ID = "YOUR_PARSE_ID";
const PARSE_JS_KEY = "YOUR_PARSE_JS_KEY";
Parse.initialize(PARSE_APP_ID, PARSE_JS_KEY);
Parse.serverURL = "https://parseapi.back4app.com/";

const STRIPE_PUBLISHABLE_KEY = "YOUR_STRIPE_PUBLISHABLE_KEY";
const stripe = Stripe(STRIPE_PUBLISHABLE_KEY);

// Holds the currentUser complete Parse object
let currentUser = null;
const setCompleteCurrentUser = async () => {
  // Called when user is already signed in, completing
  // the currentUser object with the full one
  currentUser = await new Parse.Query(Parse.User)
    .equalTo("objectId", Parse.User.current().id)
    .first();
  // Retrieve and render user cards and payments
  retrieveCurrentUserPaymentMethods();
  retrieveCurrentUserPayments();
};

const retrieveCurrentUserPaymentMethods = async () => {
  // Query and render user PaymentMethods
  const PMQuery = new Parse.Query("PaymentMethod");
  PMQuery.equalTo("user", Parse.User.current());
  paymentMethods = await PMQuery.find();
  renderPaymentMethodOptions(paymentMethods);
};

const retrieveCurrentUserPayments = async () => {
  // Query and render user Payments
  const paymentsQuery = new Parse.Query("Payment");
  paymentsQuery.equalTo("user", Parse.User.current());
  payments = await paymentsQuery.find();
  renderPayments(payments);
};

const renderPaymentMethodOptions = async (paymentMethods) => {
  for (let paymentMethod of paymentMethods) {
    const optionId = `card-${paymentMethod.get("stripeId")}`;
    let optionElement = document.getElementById(optionId);

    // Add a new option if one doesn't exist yet.
    if (!optionElement) {
      optionElement = document.createElement("option");
      optionElement.id = optionId;
      document
        .querySelector("select[name=payment-method]")
        .appendChild(optionElement);
    }

    optionElement.value = paymentMethod.get("stripeId");
    optionElement.text = `${paymentMethod.get("card").brand} •••• ${
      paymentMethod.get("card").last4
    } | Expires ${paymentMethod.get("card").exp_month}/${
      paymentMethod.get("card").exp_year
    }`;
  }
};

const renderPayments = (payments) => {
  for (let payment of payments) {
    let liElement = document.getElementById(`payment-${payment.id}`);
    if (!liElement) {
      liElement = document.createElement("li");
      liElement.id = `payment-${payment.id}`;
    }

    const paymentData = payment.get("data");
    let content = "";
    if (
      paymentData.status === "new" ||
      paymentData.status === "requires_confirmation"
    ) {
      content = `Creating Payment for ${formatAmount(
        paymentData.amount,
        paymentData.currency
      )}`;
    } else if (paymentData.status === "succeeded") {
      const card = paymentData.charges.data[0].payment_method_details.card;
      content = `Payment for ${formatAmount(
        paymentData.amount,
        paymentData.currency
      )} on ${card.brand} card •••• ${card.last4} ${paymentData.status}!`;
    } else {
      content = `Payment for ${formatAmount(
        paymentData.amount,
        paymentData.currency
      )} ${paymentData.status}`;
    }
    liElement.innerText = content;
    document.querySelector("#payments-list").appendChild(liElement);
  }
};

// Checks if user is already signed in on Parse
if (Parse.User.current() !== null) {
  setCompleteCurrentUser();
  // Hide auth screen and show payment fields
  document.getElementById("auth").style.display = "none";
  document.getElementById("content").style.display = "block";
}

// Toggle signin and signup forms
document
  .querySelector("#signup-toggle")
  .addEventListener("click", async (_event) => {
    document.getElementById("auth-signin-form").style.display = "none";
    document.getElementById("auth-signup-form").style.display = "block";
    clearAuthFormFields();
  });
document
  .querySelector("#signin-toggle")
  .addEventListener("click", async (_event) => {
    document.getElementById("auth-signup-form").style.display = "none";
    document.getElementById("auth-signin-form").style.display = "block";
    clearAuthFormFields();
  });

// Clear auth form fields
const clearAuthFormFields = () => {
  document
    .querySelector("#auth")
    .querySelectorAll("input")
    .forEach((input) => (input.value = ""));
};

// Handle auth forms
document
  .querySelector("#auth-signin-form")
  .addEventListener("submit", async (event) => {
    event.preventDefault();
    toggleAllButtonsEnabled(false);
    const form = new FormData(event.target);
    const email = form.get("email");
    const password = form.get("password");

    // Try to signin on Parse
    try {
      let user = await Parse.User.logIn(email, password);
      if (user !== null) {
        currentUser = user;
        // Hide auth screen and show payment fields
        document.getElementById("auth").style.display = "none";
        document.getElementById("content").style.display = "block";
        clearAuthFormFields();
      }
    } catch (error) {
      alert(error);
    }
    toggleAllButtonsEnabled(true);
  });

document
  .querySelector("#auth-signup-form")
  .addEventListener("submit", async (event) => {
    event.preventDefault();
    toggleAllButtonsEnabled(false);
    const form = new FormData(event.target);
    const email = form.get("email");
    const password = form.get("password");

    // Try to signup on Parse
    try {
      let user = await Parse.User.signUp(email, password, { email: email });
      // Cloud code to create Stripe user and intent
      user = await Parse.Cloud.run("createStripeCustomer", { userId: user.id });
      if (user !== null) {
        currentUser = user;
        // Hide auth screen and show payment fields
        document.getElementById("auth").style.display = "none";
        document.getElementById("content").style.display = "block";
        clearAuthFormFields();
      }
    } catch (error) {
      alert(error);
    }
    toggleAllButtonsEnabled(true);
  });

// Signout from Parse
document.querySelector("#signout").addEventListener("click", async (_event) => {
  await Parse.User.logOut();
  currentUser = null;
  // Show auth screen and hide payment fields
  document.getElementById("auth").style.display = "block";
  document.getElementById("content").style.display = "none";
});

// Creates stripe card UI element
const elements = stripe.elements();
const cardElement = elements.create("card");
cardElement.mount("#card-element");

// Handle add new card form
document
  .querySelector("#payment-method-form")
  .addEventListener("submit", async (event) => {
    event.preventDefault();
    toggleAllButtonsEnabled(false);
    if (!event.target.reportValidity()) {
      return;
    }
    const form = new FormData(event.target);
    const cardholderName = form.get("name");

    const result = await stripe.confirmCardSetup(
      currentUser.get("setupSecret"),
      {
        payment_method: {
          card: cardElement,
          billing_details: {
            name: cardholderName,
          },
        },
      }
    );

    if (result.error) {
      alert(result.error.message);
      toggleAllButtonsEnabled(true);
      return null;
    }

    let setupIntent = result.setupIntent;

    // Cloud code to add new payment method
    let cloudCodeResult = await Parse.Cloud.run("addNewPaymentMethod", {
      userId: currentUser.id,
      paymentMethodId: setupIntent.payment_method,
    });

    toggleAllButtonsEnabled(true);
    alert("Success on creating a new payment method!");

    // Update payment method options
    retrieveCurrentUserPaymentMethods();
  });

// Handles new payment form
document
  .querySelector("#payment-form")
  .addEventListener("submit", async (event) => {
    event.preventDefault();
    toggleAllButtonsEnabled(false);
    const form = new FormData(event.target);
    const amount = Number(form.get("amount"));
    const currency = form.get("currency");
    // Gets selected card option id
    const paymentMethod = form.get("payment-method");
    const paymentData = {
      payment_method: paymentMethod,
      currency,
      amount: formatAmountForStripe(amount, currency),
      status: "new",
    };
    // Cloud code to create new payment
    let cloudCodeResult = await Parse.Cloud.run("createNewPayment", {
      userId: currentUser.id,
      paymentData: paymentData,
    });

    toggleAllButtonsEnabled(true);
    alert("Success on creating a new payment!");

    retrieveCurrentUserPayments();
  });

// Helper functions
const toggleAllButtonsEnabled = (enabledValue) => {
  document
    .querySelectorAll("button")
    .forEach((button) => (button.disabled = !enabledValue));
};

const formatAmount = (amount, currency) => {
  amount = zeroDecimalCurrency(amount, currency)
    ? amount
    : (amount / 100).toFixed(2);
  return new Intl.NumberFormat("en-US", {
    style: "currency",
    currency,
  }).format(amount);
};

// Format amount for Stripe
const formatAmountForStripe = (amount, currency) => {
  return zeroDecimalCurrency(amount, currency)
    ? amount
    : Math.round(amount * 100);
};

// Check if we have a zero decimal currency
// https://stripe.com/docs/currencies#zero-decimal
const zeroDecimalCurrency = (amount, currency) => {
  let numberFormat = new Intl.NumberFormat(["en-US"], {
    style: "currency",
    currency: currency,
    currencyDisplay: "symbol",
  });
  const parts = numberFormat.formatToParts(amount);
  let zeroDecimalCurrency = true;
  for (let part of parts) {
    if (part.type === "decimal") {
      zeroDecimalCurrency = false;
    }
  }
  return zeroDecimalCurrency;
};

Make sure to add your Stripe publishable key and also your Parse app ID and JS key to the top of the file. These are some of the key elements to check out and understand in this script:

  • Check the usage of the Parse.User.current method when loading the script for the first time to render the correct part of the page;
  • The form submit action listeners that will perform actions on Parse, like signing in or up and calling the Cloud Code functions to create the Stripe related objects and save on your Back4App database;
  • The “retrieve” and “return” methods that make queries on Parse to retrieve the current user’s Payment and PaymentMethod objects.

Before testing the app, add the following stylesheet in a CSS file called app.css inside the same directory:

app.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* Back4App Guide */

*,
*:before,
*:after {
  margin: 0;
  padding: 0;
  box-sizing: inherit;
}

html {
  font-family: sans-serif;
  box-sizing: border-box;
  outline: none;
  overflow: auto;
}

body {
  margin: 0;
  background-color: #fff;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0;
}

p {
  margin: 0;
}

.container {
  width: 100%;
  max-width: 600px;
  margin: auto;
  padding: 20px 0;
}

.wrapper {
  width: '90%';
  align-self: 'center';
}

.header {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 25px 0;
  background-color: #208AEC;
}

.header_logo {
  height: 55px;
  margin-bottom: 20px;
  object-fit: contain;
}

.header_text_bold {
  margin-bottom: 3px;
  color: rgba(255, 255, 255, 0.9);
  font-size: 16px;
  font-weight: bold;
}

.header_text {
  color: rgba(255, 255, 255, 0.9);
  font-size: 15px;
}

.flex_row {
  display: flex;
}

.flex_between {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.form_wrapper {
  margin-top: 20px;
  margin-bottom: 10px;
}

.form_heading {
  margin-bottom: 10px;
}

.form {
  padding-bottom: 25px;
  margin: 25px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}

.form_input {
  display: block;
  width: 100%;
  height: 46px;
  padding: 0 15px;
  background-color: #e6e6e6;
  border: 1px solid #ccc;
  border-radius: 999px;
  margin-bottom: 20px;
  font-size: 16px;
}

.form_button {
  display: block;
  width: 100%;
  height: 42px;
  padding: 0 15px;
  background-color: #208AEC;
  border: 1px solid #208AEC;
  border-radius: 999px;
  color: #fff;
  font-size: 16px;
  cursor: pointer;
}

.form_hint {
  display: block;
  margin-top: 20px;
  color: rgba(0, 0, 0, 0.5);
  font-size: 16px;
  text-align: center;
  text-decoration-color: rgba(0, 0, 0, 0.4);
}

.card_element_wrapper {
  padding: 13px 15px;
  margin-bottom: 20px;
  background-color: #e6e6e6;
  border: 1px solid #ccc;
  border-radius: 999px;
}

Test the app using any kind of local HTTP server, like the http-server node package. After signing up, your app should look like this:

Stripe on Back4App

Conclusion

With the guide described above, you got to use Stripe with a Cloud Code function in Back4App as well as integrate payments to a simple JavaScript app!

In case you face any trouble while integrating Stripe or a function doesn’t work, please contact our team via chat!