Secure payment with paypal
Asked Answered
K

3

9

I am trying to implement a secure payment option with react-paypal-express-checkout... but I saw that user can easily change the amount with chrome dev tools ... shouldn't I make the API request to paypal from my server and validate the amount with my DB? I didn't saw any option to do that with paypal...

here is my code:

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);
Kofu answered 29/11, 2018 at 18:7 Comment(1)
did any of the answers help you solve the issue you were having? If so, please don't forget to mark the answer accepted which helped most in solving the problem.Calhoun
C
8

Paypal allows both types of uses, from the client and from the server. I guess it's possible for the client to modify the request on their end to pay less. But, in the end, whatever your business is, you'll get an order and a payment. Just check if the payment is different than it should be and don't fulfil the order, make a refund.

If you want to save the trouble, then use the server option that makes the payment through your server.

In any case, like with any other payment method, I would recommend you take the time to implement it yourself following the great and well documented API provided by Paypal. They have a lot of examples and use cases, with code for the browser and the server.

Calhoun answered 1/12, 2018 at 20:35 Comment(1)
I dont see anything great about the documentation.Aikido
I
2

Never trust values coming from the client side. You should absolutely validate the amount on the server-side.

As @jorbuedo said, you can create a server integration so the values are never exposed client side. Send a session ID or Order Number or something to your server, retrieve the order from your DB, and perform a redirect to PayPal to process the transaction server-side.

Alternatively, you can keep the client-side stuff you have, but then validate the transaction after it's been complete. You could use Instant Payment Notifications or the newer Webhooks to do this.

You could pass a custom variable into the paymentOptions property of <PaypalExpressButton ...>, and then use this value to validate the correct amount has been paid in IPN.

For example:

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

Then, as part of IPN, you can pull the Session ID out the DB, check the expected payment amount (which you'll need to store, or calculate based on the items/prices saved against the session ID) is the same as the payment amount Paypal provides (mc_gross for example). A full list of variables you get as part of IPN is available here.

There are no fees for using IPN. If you didn't want to build out this flow, then you'd have to manually validate every order that's made to ensure the amount is correct. If you're running something small, this might be an acceptable compromise.

Edit: Don't just send the expected amount as the Custom variable, and compare that to the mc_gross value, as this can also be changed using F12 or a browser extension. The value needs to be something opaque that you can translate server-side into something meaningful.

Instancy answered 7/12, 2018 at 11:16 Comment(0)
T
1

@jorbuedo and @Dave Salomon give great answers about Security and you should take them in to consideration.

However, If you really don't want to user to change your Component state and props, You can disable React Devtools with this hack.

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

Basically it mocks some methods of react-devtools and Devtool cannot find your component tree anyway.

This answer is only for disabling user to edit your components. This is not best solution for security)

Thresathresh answered 7/12, 2018 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.