使用贝宝安全付款

Secure payment with paypal

我正在尝试使用 react-paypal-express-checkout 实现安全支付选项... 但我看到用户可以使用 chrome 开发工具轻松更改金额...我不应该从我的服务器向 paypal 发出 API 请求并使用我的数据库验证金额吗?我没有看到任何使用 paypal 的选项...

这是我的代码:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import 'react-credit-cards/es/styles-compiled.css'
import './checkout.css';
import PaypalExpressBtn from 'react-paypal-express-checkout';

class CheckOut extends Component {
    constructor(props) {
        super(props);

        this.state = {
            amount: 40
        }
    }

    render() {
        const client = {
            sandbox: 'XXXX',
            production: 'Your-Production-Client-ID',
        }
        return (
                <PaypalExpressBtn client={client} currency={'USD'} total={this.state.amount} />
        );
    }
}


export default connect(CheckOut);

Paypal 允许客户端和服务器两种类型的使用。我想客户有可能修改他们的请求以减少支付。但是,最终,无论您的业务是什么,您都会收到订单和付款。只需检查付款是否与应有的不同,并且不履行订单,退款。

如果你想省事,那就用server option通过你的服务器进行支付。

无论如何,与任何其他支付方式一样,我建议您花时间按照 Paypal 提供的出色且有据可查的 API 自己实施它。他们有很多示例和用例,以及用于浏览器和服务器的代码。

永远不要相信来自客户端的值。您绝对应该在服务器端验证金额。

正如@jorbuedo 所说,您可以创建一个 server integration,这样值就永远不会暴露在客户端。将会话 ID 或订单号或其他内容发送到您的服务器,从您的数据库中检索订单,然后重定向到 PayPal 以在服务器端处理交易。

或者,您可以保留您拥有的客户端内容,但在交易完成后验证交易。您可以使用 Instant Payment Notifications or the newer Webhooks 来执行此操作。

您可以将 custom 变量传递到 <PaypalExpressButton ...>paymentOptions 属性 中,然后使用该值来验证已在 IPN 中支付的金额是否正确。

例如:

<PaypalExpressButton
  client={client}
  currency="USD"
  total={this.state.amount}
  paymentOptions={{
    custom: this.props.sessionId
  }}
/>

然后,作为 IPN 的一部分,您可以从数据库中提取会话 ID,检查预期 支付金额(您需要存储,或根据根据会话 ID 保存的 items/prices)与 Paypal 提供的付款金额相同(例如 mc_gross)。您可以获得作为 IPN 一部分的变量的完整列表 here

使用 IPN 是免费的。如果您不想构建此流程,则必须手动验证下达的每个订单以确保金额​​正确。如果您 运行 小,这可能是一个可以接受的妥协。

编辑:不要只将预期金额作为自定义变量发送,并将其与 mc_gross 值进行比较,因为这也可以使用 F12 或 browser extension 进行更改。该值需要是不透明的,您可以将服务器端转化为有意义的东西。

@jorbuedo 和@Dave Salomon 给出了关于安全性的很好的答案,你应该考虑他们。

但是,如果您真的不想让用户更改您的组件状态和道具,您可以使用此 hack 禁用 React Devtools。

if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
  window.__REACT_DEVTOOLS_GLOBAL_HOOK__.emit = function() {};
}

基本上它模拟了 react-devtools 的一些方法并且 Devtool 无论如何都找不到你的组件树。

此答案仅用于禁止用户编辑您的组件。这不是安全的最佳解决方案)