使用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¤cy=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¤cy=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产品和文档方面相互支持。我们很希望您加入我们!💙