'PayPal Checkout: Is it safe to receive a payment with only client-side code?

I'm using the PayPal API to put payment options to my website. In the tutorial they have, they are rendering the button and setting up the transaction entirely at the client side with JavaScript. Here is the sample code:

<script>
  paypal.Buttons({
    createOrder: function(data, actions) {
      // This function sets up the details of the transaction, including the amount and line item details.
      return actions.order.create({
        purchase_units: [{
          amount: {
            value: '0.01'
          }
        }]
      });
    },
    onApprove: function(data, actions) {
      // This function captures the funds from the transaction.
      return actions.order.capture().then(function(details) {
        // This function shows a transaction success message to your buyer.
        alert('Transaction completed by ' + details.payer.name.given_name);
      });
    }
  }).render('#paypal-button-container');
  //This function displays Smart Payment Buttons on your web page.
</script>

Is this secure?

The user can just change the payment amount in the code on his side and pay less. Even if I set up client-side code to send transaction-id once the transaction is successful (ie. make a POST request at onApprove), so that I can have a server-side code check if the amount sent is correct, the client can still change the code on his side to send a fake transaction-id.

I basically need a mechanism to check if I definitely received the right amount, before delivering the product. I obviously need to make this check at the server-side but I can't figure out a secure way to do it because I need to get some info from the client-side which might be fake. How do I prevent the user from pretending to have paid for example by sending a past transaction-id?



Solution 1:[1]

You are correct that the user can always change the amount in client-side code, and send a payment for a lower amount. That's how client side payments work.

Any logic to keep track of which payments are real and for the correct amount must be on your server.

For PayPal Checkout, here's the front-end UI you should use: https://developer.paypal.com/demo/checkout/#/pattern/server

You'll need two corresponding routes on your server, one for 'Create Order' and one for 'Capture Order'. You can use one of the Checkout-lanuagename-SDK's for the routes' API calls to PayPal, or your own HTTPS implementation of first getting an access token and then doing the call. Both of these routes should return only JSON data (no HTML or text). Inside the 2nd route, when the capture API is successful you should verify the amount was correct and store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as sending confirmation emails or reserving product) immediately before forwarding your return JSON to the frontend caller. In the event of an error forward the JSON details of it as well, since the frontend must handle such cases.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1