使用PayPal按钮组件轻松集成电商支付系统

本文详细介绍了如何使用PayPal标准结账按钮组件在电商网站中集成支付功能,包含基础集成和自定义集成的完整代码示例,涵盖前后端开发、沙箱测试等关键技术环节。

使用PayPal按钮组件轻松集成电商支付系统

接受在线支付已成为从个体创业者到大型跨国公司的普遍需求。PayPal标准结账允许将PayPal支付按钮组件无缝集成到电商应用中,赋予您接受在线支付的能力。本指南将展示如何将标准结账功能添加到使用HTML和NodeJS构建的简单购物应用中。

指南概述

  • 第一部分:先决条件
  • 第二部分a:基础集成 - 代码设置
  • 第二部分b:基础集成 - 结账流程
  • 第三部分a:自定义集成 - 代码设置
  • 第三部分b:自定义集成 - 结账流程
  • 第四部分:结论
  • 第五部分:其他PayPal支付集成

第一部分:先决条件

要完成此集成,您需要以下信息:

  • PayPal REST应用的API凭据(客户端ID和密钥):从开发者仪表板粘贴这些信息。由于我们在开发环境中工作,请确保沙箱切换开关已打开。

获取测试API凭据

  • 个人沙箱账户的用户名和密码:您需要这些信息来完成结账流程。

导航至测试工具下的沙箱账户

获取个人沙箱账户登录详情

您可以从PayPal开发者GitHub仓库获取我们完成的结账集成演示代码。

第二部分a:基础集成 - 代码设置

导航至PayPal的集成结账文档。该文档向您展示如何设置开发环境:安装npm、验证package.json文件以及设置.env文件。

接下来,您将设置后端服务器和前端代码。文档展示了三个文件的内容:server.js(用于后端服务器)、app.js(用于客户端逻辑)和checkout.html(用于用户界面)。

复制后端代码

复制前端代码

获取这些代码片段并将它们粘贴到您的IDE(集成开发环境)中。我强烈建议您首先实现基础集成,并确保在添加自定义电商代码之前能够成功完成标准结账流程。我发现这种方法可以减少潜在错误和相关挫折。😅

在checkout.html文件中,将软件开发工具包(SDK)脚本标签中的"test"替换为您的客户端ID。

1
<script src="https://www.paypal.com/sdk/js?client-id=CLIENT_ID&currency=USD"></script>

在app.js文件中,请注意响应体中的"cart"对象是硬编码的,包含一个产品的SKU和数量信息。出于重要的安全原因,我们不从前端传递任何交易或价格金额。相反,我们使用SKU/ID和数量信息在数据存储中查找产品,并使用这些产品详细信息在后端计算购物车总价。

1
2
3
4
5
6
7
8
body: JSON.stringify({
  cart: [
    {
      id: "YOUR_PRODUCT_ID",
      quantity: "YOUR_PRODUCT_QUANTITY",
    },
  ],
})

在server.js文件中,请注意交易数量(“100.00”)是硬编码到createOrder调用中的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
const createOrder = async (cart) => {
  console.log(
    "shopping cart information passed from the frontend createOrder() callback:",
    cart,
  );
  const accessToken = await generateAccessToken();
  const url = `${base}/v2/checkout/orders`;
  const payload = {
    intent: "CAPTURE",
    purchase_units: [
      {
        amount: {
          currency_code: "USD",
          value: "100.00",
        },
      },
    ],
  };
  // ... 更多代码 ...
}

第二部分b:基础集成 - 结账流程

启动服务器;在命令行中运行"node server/server.js"或package.json文件中定义的任何快捷方式。您应该看到前端显示PayPal按钮组件。

PayPal按钮组件 - 基础集成

点击第一个PayPal按钮,显示结账模态框。请注意,模态框中的URL显示我们处于沙箱环境中。使用您的个人沙箱账户登录(如果尚未登录)。

结账模态框开始结账流程

然后您将看到交易金额(此时应为100.00美元)和几种支付选项。

交易金额硬编码为100美元

使用PayPal余额选项完成交易。浏览器中应出现确认消息;其位置取决于您在应用程序中放置id为"result-message"的元素的位置。

1
<p id="result-message"></p>

完成结账流程后的状态消息

第三部分a:自定义集成 - 代码设置

现在,让我们添加自定义电商代码!

在checkout.html文件中,我添加了在LiftOff商店销售的三款产品的代码。我使用TailwindCSS对代码进行了样式设计:

  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
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>PayPal JS SDK Standard Integration Demo</title>
    <script src="https://cdn.tailwindcss.com"></script>
  </head>
  <body class="p-6">
    <h1 class="text-center text-4xl font-medium">LiftOff Shop</h1>
    <main class="products flex flex-wrap justify-center">
      <div
        class="product text-center m-3 p-3 border border-slate-400 rounded-md"
      >
        <img src="https://picsum.photos/id/21/200" class="rounded-md" />
        <h2 class="text-xl my-2">Galaxy Shoes</h2>
        <p class="text-green-600 font-medium text-lg mb-2">$100</p>
        <div class="mb-3">
          <label class="text-lg" for="quantity1">Quantity:</label>
          <select class="text-lg" id="quantity1">
            <option value="0">0</option>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
          </select>
        </div>
        <button
          class="product-btn py-1 px-3 rounded-md bg-indigo-200 hover:bg-indigo-300"
          data-product-id="hdqgapq9"
          data-quantity-id="quantity1"
        >
          Add to Cart
        </button>
      </div>
      <div
        class="product text-center m-3 p-3 border border-slate-400 rounded-md"
      >
        <img src="https://picsum.photos/id/104/200" class="rounded-md" />
        <h2 class="text-xl my-2">Spaceship Earrings</h2>
        <p class="text-green-600 font-medium text-lg mb-2">$40</p>
        <div class="mb-3">
          <label class="text-lg" for="quantity2">Quantity:</label>
          <select class="text-lg" id="quantity2">
            <option value="0">0</option>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
          </select>
        </div>
        <button
          class="product-btn py-1 px-3 rounded-md bg-indigo-200 hover:bg-indigo-300"
          data-product-id="rnfjwsy0"
          data-quantity-id="quantity2"
        >
          Add to Cart
        </button>
      </div>
      <div
        class="product text-center m-3 p-3 border border-slate-400 rounded-md"
      >
        <img src="https://picsum.photos/id/342/200" class="rounded-md" />
        <h2 class="text-xl my-2">Martian Tote</h2>
        <p class="text-green-600 font-medium text-lg mb-2">$75</p>
        <div class="mb-3">
          <label class="text-lg" for="quantity3">Quantity:</label>
          <select class="text-lg" id="quantity3">
            <option value="0">0</option>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
          </select>
        </div>
        <button
          class="product-btn py-1 px-3 rounded-md bg-indigo-200 hover:bg-indigo-300"
          data-product-id="zytkddw5"
          data-quantity-id="quantity3"
        >
          Add to Cart
        </button>
      </div>
    </main>
    <p id="result-message" class="mx-auto text-center text-red-600 w-1/2"></p>
    <section class="mt-8 mx-auto flex flex-wrap w-1/2">
      <div class="mb-3 w-1/2 text-center" id="cart">
        <h2 class="text-xl font-medium">Cart</h2>
        <ul id="cart-items"></ul>
        <p>TOTAL $<span id="cart-total">0</span></p>
        <button
          id="clear-cart"
          class="py-1 px-3 mt-3 rounded-md bg-gray-200 hover:bg-gray-300"
        >
          Clear Cart
        </button>
      </div>
      <div class="text-center" id="paypal-button-container"></div>
    </section>
    <script src="https://www.paypal.com/sdk/js?client-id=AYCd0wKOWs9itZ23_2XEZUhZpbZdHT_c1qcMCjqTnb6fxFE7tQBnUQGSPh3_PVQkgoBamFV1KgPUI9B4&currency=USD"></script>
    <script type="module" src="app.js"></script>
  </body>
</html>

带有PayPal按钮组件的电商应用

在app.js文件中,我添加了实现添加到购物车、计算购物车总额和清空购物车功能的代码。为了计算购物车总额,我从products.js文件导入了产品信息,该文件充当我的临时数据存储。我还将响应体中的cart对象更新为cartItems数组(而不是之前的硬编码产品)。

 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
import { PRODUCTS } from "./products.js";

const cartItems = [];
let cartTotal = 0;

function addToCart(productId, quantityId) {
  const quantitySelect = document.getElementById(quantityId);
  const selectedQuantity = parseInt(quantitySelect.value, 10);
  if (selectedQuantity > 0) {
    cartItems.push({
      id: productId,
      quantity: selectedQuantity,
    });
    cartTotal = calculateCartTotal(cartItems);
    updateCart(cartItems);
  }
}

function calculateCartTotal(cartItems) {
  let total = 0;
  cartItems.forEach((item) => {
    total += item.quantity * PRODUCTS[item.id].price;
  });
  return total;
}

function updateCart(cartItems) {
  const cartItemsList = document.getElementById("cart-items");
  const cartTotalElement = document.getElementById("cart-total");
  cartItemsList.innerHTML = "";
  cartTotalElement.textContent = cartTotal;
  cartItems.forEach((item) => {
    const li = document.createElement("li");
    li.textContent = `${PRODUCTS[item.id].name}: ${item.quantity}`;
    cartItemsList.appendChild(li);
  });
}

window.paypal
  .Buttons({
    async createOrder() {
      try {
        const response = await fetch("/api/orders", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          // 使用"body"参数可选地传递额外的订单信息
          // 如产品ID和数量
          body: JSON.stringify({
            cart: cartItems,
          }),
        });
        // ... 更多代码 ...
        // ... 更多代码 ...
      })
      .render("#paypal-button-container");

// 向用户显示结果的示例函数。可以使用您网站的UI库代替。
function resultMessage(message) {
  const container = document.querySelector("#result-message");
  container.innerHTML = message;
}

// 事件监听器
const productBtns = document.querySelectorAll(".product-btn");
productBtns.forEach((btn) => {
  btn.addEventListener("click", (e) => {
    const productId = e.target.dataset.productId;
    const quantityId = e.target.dataset.quantityId;
    addToCart(productId, quantityId);
  });
});

// 清空购物车
document.getElementById("clear-cart").addEventListener("click", () => {
  // 清空购物车项目,不重新分配数组
  cartItems.length = 0;
  cartTotal = 0;
  updateCart(cartItems);
});

在server.js文件中,我从products.js导入了产品,并添加了一个使用购物车内容计算交易金额的函数。在createOrder调用中,我将硬编码的交易值替换为计算的购物车值。

 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
import express from "express";
import fetch from "node-fetch";
import "dotenv/config";
import path from "path";
import { PRODUCTS } from "../client/products.js";
// ... 更多代码 ...
// ... 更多代码 ...

function calculateTotalPrice(cart) {
  let totalPrice = 0;
  for (let i = 0; i < cart.length; i++) {
    totalPrice += PRODUCTS[cart[i].id].price * cart[i].quantity;
  }
  return totalPrice.toString();
}

/**
 * 创建订单以开始交易。
 * @see https://developer.paypal.com/docs/api/orders/v2/#orders_create
 */
const createOrder = async (cart) => {
  // 使用从前端传递的购物车信息计算购买单元详细信息
  console.log(
    "shopping cart information passed from the frontend createOrder() callback:",
    cart
  );
  const accessToken = await generateAccessToken();
  const url = `${base}/v2/checkout/orders`;
  const payload = {
    intent: "CAPTURE",
    purchase_units: [
      {
        amount: {
          currency_code: "USD",
          value: calculateTotalPrice(cart),
        },
      },
    ],
  };
  // ... 更多代码 ...
};
// ... 更多代码 ...

第三部分b:自定义集成 - 结账流程

重新启动服务器并向购物车添加一些产品;我选择了每种商品各一个,总计215美元。

购物车总额显示购物车项目总金额

点击金色的PayPal按钮激活结账(如有必要,使用您的个人沙箱账户登录)。您应该看到交易金额是您购物车的价值。

结账模态框中的交易价值等于购物车金额

继续完成购买。您应该在浏览器中看到确认消息。

浏览器中成功结账的确认

第四部分:结论

本演示介绍了使用PayPal按钮组件直接集成PayPal标准结账的方法。您可以根据您的用例进一步自定义。阅读我们的结账文档以获取这些自定义的示例。PayPal开发者GitHub仓库还有在各种代码环境(如React和Angular)中集成的几个示例。

第五部分:其他PayPal支付集成

  • 稍后付款
  • 自定义借记卡/信用卡字段(高级结账)

加入PayPal开发者社区!

我们的开发者社区成员在集成PayPal技术、贡献开源、扩展知识和网络以及改进PayPal产品和文档方面相互支持。我们很希望您加入我们!💙

  • 网站
  • Twitter
  • GitHub
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计