PayPal Smart Payment Button: setting an invoice id to avoid duplicate transactions

Viewed 573

Sometime a user charged multiple times because of accidental clicks on the pay button in paypal smart payment button. In paypal dashboard > payment preferences I have already enabled the option "Yes, block multiple payments per invoice ID".

Now I want to set the invoice id in my smart button script code, which is as follows:

function initPayPalButton() {
      paypal.Buttons({
        style: {
          shape: 'rect',
          color: 'gold',
          layout: 'vertical',
          label: 'pay',
        },

        createOrder: function(data, actions) {
          return actions.order.create({
            purchase_units: [{"amount":{"currency_code":"USD","value":total_amount}}],
                            application_context: {
                                shipping_preference: 'NO_SHIPPING'
                            }
          });
        },

        onApprove: function(data, actions) {
          return actions.order.capture().then(function(details) {
            window.location = 'success_url';
          });
        },

        onError: function(err) {
          console.log(err);
                                        alert('Something went wrong. Please refresh the page and try again.');
        }
      }).render('#button_container_id');
    }
    initPayPalButton();

2 Answers

Add invoice_id with a unique identifier from your system to avoid duplicate payments.

See: https://developer.paypal.com/docs/multiparty/checkout/standard/integrate/#link-addpaymentbuttons

Other useful purchase unit parameters include:

A unique invoice_id that hasn't been used for a previously-completed transaction to identify the order for accounting purposes and to prevent duplicate payments.

A custom_id value of your choice for your system or own reference. This value is not indexed or visible to the buyer.

This is what my code looks like:

paypal.Buttons({
    style: {
        shape: 'rect',
        color: 'silver',
        label: 'buynow'
    },
    onError: function (err) {
        // FIXME: show the user an error message
    },
    onClick: function(data)  {
        // FIXME: do something cool when the button is clicked
    },
    // Set up the transaction
    createOrder: function(data, actions) {
        return actions.order.create({
            purchase_units: [{
                description: 'My awesome product',
                amount: {
                    currency_code: "USD",
                    value: 9.99,
                    breakdown: {
                        item_total: {
                            currency_code: 'USD',
                            value: 9.99
                        },
                        discount: {
                            currency_code: "USD",
                            value: 1.25
                        }
                    }
                },
                invoice_id: 'UNIQUE-ID',
                custom_id: 'ANOTHER-SYSTEM-ID'
            }],
            application_context:  { 
                shipping_preference: "NO_SHIPPING"
            }
        });
    },
    // Finalize the transaction
    onApprove: function(data, actions) {
        return actions.order.capture().then(function(details) {
            // FIXME: finalise the order and show the success message
            console.log("order id: "+details.id);
        });
    }
}).render('#paypal-button-container');

}

Related