在React Native应用中原生添加支付界面的方法并不多。因此,许多移动开发者选择使用PayPal SDK建立自己的支付界面。
PayPal是世界上最早和最大的互联网支付服务之一。它在200个国家的可用性使其成为企业和个人的可靠支付界面。PayPal有一个庞大的库,可以与各种编程语言整合,包括Python、Java、JavaScript、PHP等。
在本教程中,我们将向你展示如何通过使用PayPal SDK for JavaScript将网络和本地技术相互联系起来,建立一个支付界面。
我们将从构建基本的React Native和React应用开始。要继续学习,你应该已经熟悉了JavaScript、Node.js工具,如npx 和npm 或yarn 、模块和基本的React组件。你还需要一个PayPal开发者账户来创建支付集成的凭证。
我们将使用PayPal的集成API,用于网页的JavaScript。我们将在React中建立支付界面,作为一个单页应用,并将其托管在Firebase主机上。最后,我们将使用React Native WebView来创建React Native应用和React Web应用之间的链接。
React Native PayPal集成。基本设置
首先,我们将创建一个基本的React Native应用。要创建该应用,只需输入以下命令。
$ npx react-native init myPayPalApp
我们还需要创建一个React应用。要创建网络应用,请输入以下命令。
npx create-react-app my-paypal-web
当这些应用程序正在初始化时,我们将使用我们的PayPal开发者账户来创建新的应用程序和整合所需的证书。
进入developer.paypal.com并登录你的开发者账户。登录后,你将被重定向到你的仪表板,它将看起来像这样。
你会看到列出了一个默认的应用程序。在本教程中,我们将采取以下步骤来创建一个新的应用程序。
单击 "创建应用程序"按钮。我们使用PayPal沙盒进行测试,所以可以根据自己的喜好自由填充。然后点击,创建应用。
应用程序创建后,你将被重定向到设置和证书页面。你可以看到你的应用程序的沙盒帐户的电子邮件,客户ID,和其他设置。客户端ID是我们在本教程中所需要的。
为了测试,我们还需要沙盒客户账户。要创建客户账户,在左边的导航菜单中点击沙盒下的账户。
现在点击创建账户,然后选择美国并点击创建。
帐户创建后,要查看帐户凭证(即电子邮件和密码),以便在测试支付网关上登录,请将鼠标停留在新创建的帐户旁边的菜单按钮上,点击查看/编辑帐户。
你会看到像这样的东西。
你会看到电子邮件ID以及系统生成的密码。你可以通过点击 "更改密码"链接来改变密码,或者你可以在付款时使用系统生成的密码来登录。
现在我们已经完成了基本要求,我们可以继续构建支付界面。
构建支付界面
对于支付界面,我们将对上面创建的React项目进行修改(my-paypal-web)。我们将在我们的网页上添加PayPal按钮,并将结果作为我们的回调。
从你刚才在PayPal上创建的新应用页面中复制客户ID(如上图所示),并将其粘贴到项目中的public/index.html 文件的<head> 。
<script src="https://www.paypal.com/sdk/js?client-id=[replace-this-with-your-client-id]¤cy=USD"></script>
你的代码应该看起来像这样。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<script src="https://www.paypal.com/sdk/js?client-id=AXEWcCDcoTu8Wt1Ud0ifqLZM2A4_MbgJhNaTByCizxG0yi8V4o6sccW5RgXtXNesMh7n38Rp0Cv2KN63¤cy=USD"></script>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
用你自己的客户ID添加这个脚本标签后,现在是时候为你的应用程序创建PayPal按钮了。
编辑App.js 文件。首先,创建一个对PayPal按钮的引用,作为一个React组件。
const PayPalButton = window.paypal.Buttons.driver("react", { React, ReactDOM });
你可以在你的App.js 组件中使用它作为一个组件。只要删除父组件的内容,并添加PayPalButton 。你的App.js 应该看起来像这样。
import React from "react";
import ReactDOM from "react-dom";
import "./App.css";
const PayPalButton = window.paypal.Buttons.driver("react", { React, ReactDOM });
function App() {
function _createOrder(data, actions) {
return actions.order.create({
purchase_units: [
{
amount: {
value: "1",
},
},
],
});
}
return (
<div className="App">
<PayPalButton
createOrder={(data, actions) => _createOrder(data, actions)}
/>
</div>
);
}
export default App;
进入项目目录,根据你的偏好,输入yarn start 或npm start 。React服务器在localhost上启动和运行后,会在浏览器窗口自动打开localhost:3000 。如果没有,请访问 [http://localhost:3000](http://localhost:3000)从你喜欢的浏览器访问。你会看到一个像这样的输出。
你可以随心所欲地设计页面的样式,我们在此不做赘述。你可以根据你的喜好进行修改。
如果你看一下代码,你可以看到,我们已经为PayPalButton 定义了一个道具,名为 [createOrder](https://developer.paypal.com/docs/business/javascript-sdk/javascript-sdk-reference/#createorder),这使你能够指定请求的内容。在这个例子中主要是金额,但你也可以指定货币等。
对于回调,我们将创建函数并将它们作为道具添加到PayPalButton 。首先,我们将添加onApprove 。这个函数在订单被PayPal批准时被调用。
要创建一个异步的_onApprove 函数。
async function _onApprove(data, actions) {
let order = await actions.order.capture();
console.log(order);
return order;
}
这里,await关键字被用来获取订单的详细信息。然后,我们将console.log 订单的详细信息。
同时将这个函数添加到PayPalButton 道具中。
<PayPalButton
createOrder={(data, actions) => _createOrder(data, actions)}
onApprove={(data, actions) => _onApprove(data, actions)}
/>
此外,我们将添加onCancel 和onError props,以便在用户取消付款或PayPal端出现一些错误时获得回调。我们将只创建一个调用函数,并在这两个props上使用它。
function _onError(err) {
console.log(err);
}
你的PayPal按钮代码应该是这样的。
<PayPalButton
createOrder={(data, actions) => _createOrder(data, actions)}
onApprove={(data, actions) => _onApprove(data, actions)}
onCancel={() => _onError("Canceled")}
onError={(err) => _onError(err)}
/>
添加这些内容后,你的App.js 文件应该是这样的。
import React from "react";
import ReactDOM from "react-dom";
import "./App.css";
const PayPalButton = window.paypal.Buttons.driver("react", { React, ReactDOM });
function App() {
function _createOrder(data, actions) {
return actions.order.create({
purchase_units: [
{
amount: {
value: "1",
},
},
],
});
}
async function _onApprove(data, actions) {
let order = await actions.order.capture();
console.log(order);
return order;
}
function _onError(err) {
console.log(err);
}
return (
<div className="App">
<PayPalButton
createOrder={(data, actions) => _createOrder(data, actions)}
onApprove={(data, actions) => _onApprove(data, actions)}
onCancel={() => _onError("Canceled")}
onError={(err) => _onError(err)}
/>
</div>
);
}
export default App;
我们所做的是创建一个来自用户的1美元的支付请求,并记录它以查看结果。
要测试你的支付网关,只需点击PayPal按钮,输入用户凭证(即第一步的电子邮件和密码),然后付款。
付款完成后,你会被重新定向到你的应用程序页面。通过右击打开开发者控制台,检查元素,然后转到控制台标签。你会看到你刚刚进行的虚拟支付的结果。
设置Firebase主机
由于我们使用Firebase来托管我们的React Web应用,首先要注册一个Firebase账户。
一旦你有了一个账户,点击添加项目并设置一个项目名称。
你可以选择是否启用或禁用分析功能。
现在你已经创建了你的Firebase项目,点击继续。
要设置主机,去侧边栏的主机标签,然后点击开始按钮。
打开一个终端窗口,在你的系统上安装firebase-tools 。
$ npm install -g firebase-tools
用你的Firebase账户登录,这样你就可以很容易地从终端窗口连接到项目。
$ firebase login
用你的账户授权登录。在你成功登录后,进入my-paypal-web 项目目录,输入以下命令。
$firebase init
使用键盘上的方向键,导航到Hosting 。按空格键选择,按回车/回车键继续。
因为我们已经创建了一个项目,我们将选择Use and existing project 。
接下来,从列表中选择我们创建的项目,然后点击return/enter。
在下一步,输入以下配置。
=== Hosting Setup
Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.
? What do you want to use as your public directory? build
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
? Set up automatic builds and deploys with GitHub? No
完成这些后,你会在底部看到一条成功信息。
✔ Wrote build/index.html
i Writing configuration info to firebase.json...
i Writing project information to .firebaserc...
✔ Firebase initialization complete!
要推送你的网络应用,请输入以下命令。
$ yarn build
构建完成后,输入。
$ firebase deploy
你会看到一个带有托管URL的结果。
=== Deploying to 'my-pay-web'...
i deploying hosting
i hosting[my-pay-web]: beginning deploy...
i hosting[my-pay-web]: found 18 files in build
✔ hosting[my-pay-web]: file upload complete
i hosting[my-pay-web]: finalizing version...
✔ hosting[my-pay-web]: version finalized
i hosting[my-pay-web]: releasing new version...
✔ hosting[my-pay-web]: release complete
✔ Deploy complete!
Project Console: https://console.firebase.google.com/project/my-pay-web/overview
Hosting URL: https://my-pay-web.web.app
你可以直接复制托管URL,并将其粘贴到你喜欢的浏览器中。下面是我的看起来像什么。
https://my-pay-web.web.app
在React Native中构建基本的WebView
如果你之前有使用React Native的经验,那就更棒了。如果没有,官方文档提供了一个设置环境和安装应用的指南。如果你还没有这样做,只要进入项目目录,使用下面的命令来安装React Native的WebView模块。
yarn add react-native-webview
接下来,用USB连接你的设备,并输入以下命令。
npx react-native run-android
在你的设备或模拟器上成功安装了该应用后,打开App.js 文件。删除默认的额外代码并导入WebView模块。
import { WebView } from 'react-native-webview';
为了从React Native初始化支付网关,我们将创建一个按钮,在模式中显示网络视图,并从WebView中获得响应。我们还将创建一个useState() 钩子来显示和隐藏WebView。
const [showGateway, setShowGateway] = useState(false);
按钮。
<View style={styles.btnCon}>
<TouchableOpacity
style={styles.btn}
onPress={() => setShowGateway(true)}>
<Text style={styles.btnTxt}>Pay Using PayPal</Text>
</TouchableOpacity>
</View>
按钮的样式。
btnCon: {
height: 45,
width: '70%',
elevation: 1,
backgroundColor: '#00457C',
borderRadius: 3,
},
btn: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
btnTxt: {
color: '#fff',
fontSize: 18,
},
按钮的输出。
现在,从react-native 中导入Modal 组件,并创建带有基本Web视图的模态,显示google.com 。
Modal和WebView。
{showGateway ? (
<Modal
visible={showGateway}
onDismiss={() => setShowGateway(false)}
onRequestClose={() => setShowGateway(false)}
animationType={"fade"}
transparent>
<View style={styles.webViewCon}>
<View style={styles.wbHead}>
<TouchableOpacity
style={{padding: 13}}
onPress={() => setShowGateway(false)}>
<Feather name={'x'} size={24} />
</TouchableOpacity>
<Text
style={{
flex: 1,
textAlign: 'center',
fontSize: 16,
fontWeight: 'bold',
color: '#00457C',
}}>
PayPal GateWay
</Text>
<View style={{padding: 13}}>
<ActivityIndicator size={24} color={'#00457C'} />
</View>
</View>
<WebView
source={{uri: 'https://www.google.com'}}
style={{flex: 1}}
/>
</View>
</Modal>
) : null}
我们正在使用<Feather /> ,从 [react-native-vector-icons](https://github.com/oblador/react-native-vector-icons)和ActivityIndicator ,从react-native 。
模态和WebView的输出。
现在,我们将在页面加载后显示/隐藏ActivityIndicator ,以获得WebView的回调。如果页面已经加载,我们将添加以下钩子和道具。
const [prog, setProg] = useState(false);
const [progClr, setProgClr] = useState('#000');
WebView的道具。
onLoadStart={() => {
setProg(true);
setProgClr('#000');
}}
onLoadProgress={() => {
setProg(true);
setProgClr('#00457C');
}}
onLoadEnd={() => {
setProg(false);
}}
onLoad={() => {
setProg(false);
}}
为了增加用户体验,这段代码会根据页面的进度改变ActivityIndicator 的颜色。
你的App.js 文件现在应该是这样的。
import React, {useState} from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
View,
TouchableOpacity,
Modal,
ActivityIndicator,
} from 'react-native';
import {WebView} from 'react-native-webview';
import Feather from 'react-native-vector-icons/Feather';
const App = () => {
const [showGateway, setShowGateway] = useState(false);
const [prog, setProg] = useState(false);
const [progClr, setProgClr] = useState('#000');
return (
<SafeAreaView style={{flex: 1}}>
<View style={styles.container}>
<View style={styles.btnCon}>
<TouchableOpacity
style={styles.btn}
onPress={() => setShowGateway(true)}>
<Text style={styles.btnTxt}>Pay Using PayPal</Text>
</TouchableOpacity>
</View>
</View>
{showGateway ? (
<Modal
visible={showGateway}
onDismiss={() => setShowGateway(false)}
onRequestClose={() => setShowGateway(false)}
animationType={"fade"}
transparent>
<View style={styles.webViewCon}>
<View style={styles.wbHead}>
<TouchableOpacity
style={{padding: 13}}
onPress={() => setShowGateway(false)}>
<Feather name={'x'} size={24} />
</TouchableOpacity>
<Text
style={{
flex: 1,
textAlign: 'center',
fontSize: 16,
fontWeight: 'bold',
color: '#00457C',
}}>
PayPal GateWay
</Text>
<View style={{padding: 13, opacity: prog ? 1 : 0}}>
<ActivityIndicator size={24} color={progClr} />
</View>
</View>
<WebView
source={{uri: 'https://www.google.com'}}
style={{flex: 1}}
onLoadStart={() => {
setProg(true);
setProgClr('#000');
}}
onLoadProgress={() => {
setProg(true);
setProgClr('#00457C');
}}
onLoadEnd={() => {
setProg(false);
}}
onLoad={() => {
setProg(false);
}}
/>
</View>
</Modal>
) : null}
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
},
btnCon: {
height: 45,
width: '70%',
elevation: 1,
backgroundColor: '#00457C',
borderRadius: 3,
},
btn: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
btnTxt: {
color: '#fff',
fontSize: 18,
},
webViewCon: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
wbHead: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f9f9f9',
zIndex: 25,
elevation: 2,
},
});
export default App;
使用WebView将PayPal界面连接到React Native应用中
为了从WebView页面接收数据到我们的React Native应用,我们将使用onMessage 道具。我们还需要在我们的Web应用中添加一些代码来发送所需的数据。window.ReactNativeWebView.postMessage 方法是用来从WebView发送数据到我们的React Native应用。
在对你的_onApprove 和_onError 函数进行必要的修改后,你的代码应该是这样的。
async function _onApprove(data, actions) {
let order = await actions.order.capture();
console.log(order);
window.ReactNativeWebView &&
window.ReactNativeWebView.postMessage(JSON.stringify(order));
return order;
}
function _onError(err) {
console.log(err);
let errObj = {
err: err,
status: "FAILED",
};
window.ReactNativeWebView &&
window.ReactNativeWebView.postMessage(JSON.stringify(errObj));
}
我们使用JSON.stringify ,因为postMessage只能接受字符串参数。
记住要建立网络应用,并将其部署到Firebase。
$ yarn build
$ firebase deploy
为了获得React Native方面的数据,我们将使用onMessage 。创建以下函数并将其添加到onMessage 道具中。
function onMessage(e) {
let data = e.nativeEvent.data;
setShowGateway(false);
console.log(data);
}
添加onMessage 道具,并将源uri 设置为你的web应用的URI。
<WebView
source={{uri: 'https://www.google.com'}}
onMessage={onMessage}
...
/>
现在是测试支付网关的时候了。在这一点上,我们在React Native应用中记录来自postMessage 的结果。
点击使用PayPal支付,显示支付页面。输入你的凭证并进行支付。
付款成功(或不成功)后,你会看到控制台中打印的结果。
你可以通过在onMessage 函数中添加一个警报,提醒用户他们刚刚付款的状态。
function onMessage(e) {
...
let payment = JSON.parse(data);
if (payment.status === 'COMPLETED') {
alert('PAYMENT MADE SUCCESSFULLY!');
} else {
alert('PAYMENT FAILED. PLEASE TRY AGAIN.');
}
}
下面是输出结果。
完整的代码如下。
App.js (Reactmy-paypal-web)。
import React from "react";
import ReactDOM from "react-dom";
import "./App.css";
const PayPalButton = window.paypal.Buttons.driver("react", { React, ReactDOM });
function App() {
function _createOrder(data, actions) {
return actions.order.create({
purchase_units: [
{
amount: {
value: "1",
},
},
],
});
}
async function _onApprove(data, actions) {
let order = await actions.order.capture();
console.log(order);
window.ReactNativeWebView &&
window.ReactNativeWebView.postMessage(JSON.stringify(order));
return order;
}
function _onError(err) {
console.log(err);
let errObj = {
err: err,
status: "FAILED",
};
window.ReactNativeWebView &&
window.ReactNativeWebView.postMessage(JSON.stringify(errObj));
}
return (
<div className="App">
<PayPalButton
createOrder={(data, actions) => _createOrder(data, actions)}
onApprove={(data, actions) => _onApprove(data, actions)}
onCancel={() => _onError("CANCELED")}
onError={(err) => _onError("ERROE")}
/>
</div>
);
}
export default App;
App.js (React NativemyPayPalApp)。
import React, {useState} from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
View,
TouchableOpacity,
Modal,
ActivityIndicator,
} from 'react-native';
import {WebView} from 'react-native-webview';
import Feather from 'react-native-vector-icons/Feather';
const App = () => {
const [showGateway, setShowGateway] = useState(false);
const [prog, setProg] = useState(false);
const [progClr, setProgClr] = useState('#000');
function onMessage(e) {
let data = e.nativeEvent.data;
setShowGateway(false);
console.log(data);
let payment = JSON.parse(data);
if (payment.status === 'COMPLETED') {
alert('PAYMENT MADE SUCCESSFULLY!');
} else {
alert('PAYMENT FAILED. PLEASE TRY AGAIN.');
}
}
return (
<SafeAreaView style={{flex: 1}}>
<View style={styles.container}>
<View style={styles.btnCon}>
<TouchableOpacity
style={styles.btn}
onPress={() => setShowGateway(true)}>
<Text style={styles.btnTxt}>Pay Using PayPal</Text>
</TouchableOpacity>
</View>
</View>
{showGateway ? (
<Modal
visible={showGateway}
onDismiss={() => setShowGateway(false)}
onRequestClose={() => setShowGateway(false)}
animationType={'fade'}
transparent>
<View style={styles.webViewCon}>
<View style={styles.wbHead}>
<TouchableOpacity
style={{padding: 13}}
onPress={() => setShowGateway(false)}>
<Feather name={'x'} size={24} />
</TouchableOpacity>
<Text
style={{
flex: 1,
textAlign: 'center',
fontSize: 16,
fontWeight: 'bold',
color: '#00457C',
}}>
PayPal GateWay
</Text>
<View style={{padding: 13, opacity: prog ? 1 : 0}}>
<ActivityIndicator size={24} color={progClr} />
</View>
</View>
<WebView
source={{uri: 'https://my-pay-web.web.app/'}}
style={{flex: 1}}
onLoadStart={() => {
setProg(true);
setProgClr('#000');
}}
onLoadProgress={() => {
setProg(true);
setProgClr('#00457C');
}}
onLoadEnd={() => {
setProg(false);
}}
onLoad={() => {
setProg(false);
}}
onMessage={onMessage}
/>
</View>
</Modal>
) : null}
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
},
btnCon: {
height: 45,
width: '70%',
elevation: 1,
backgroundColor: '#00457C',
borderRadius: 3,
},
btn: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
btnTxt: {
color: '#fff',
fontSize: 18,
},
webViewCon: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
wbHead: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f9f9f9',
zIndex: 25,
elevation: 2,
},
});
export default App;
结论
如果你已经走到了这一步,恭喜你--你已经成功地为React Native设置了使用PayPal的测试支付网关。虽然上面的代码应该足以满足基本的支付系统,但你可以根据自己的需要来改变它。你也可以参考官方的PayPal指南来进一步参考。
The postHow to integrate PayPal payments with React Nativeappeared first onLogRocket Blog.