Enngage / ngx-paypal

Paypal integration for Angular
https://enngage.github.io/ngx-paypal/
MIT License
185 stars 68 forks source link

Providing "invoice_id" to prevent multiple payments. #100

Open ollucks opened 4 years ago

ollucks commented 4 years ago

We use this plugin on our check and have found that if a customer closes their browser or presses the back button on the return from PayPal but before onClientAuthorization() has completed then they are charged but the order isn't complete. There is around a 1 second window for this to happen.

Looking at the PayPal docs https://www.paypal.com/us/smarthelp/article/how-do-i-avoid-duplicate-transactions-ts1097 is the best way to protect against multiple payments.

I saw from https://github.com/Enngage/ngx-paypal/issues/17 that you'd added support for the invoice_id parameter. So I've used this and it does indeed prevent multiple payments but only because they all error in a similar way to https://github.com/Enngage/ngx-paypal/issues/98 where you said it's coming from PayPal but you might take a look if I can reproduce.

For this issue it's easy to reproduce just setup your config like this

this.payPalConfig = { currency: this.cart.currencyCode, clientId: this.paypalClientId, createOrderOnClient: (data) => { intent: 'CAPTURE', purchase_units: [ { invoice_id: "1234", // invoice_id: this.cart.id, amount: { currency_code: this.cart.currencyCode, value: this.orderTotal, breakdown: { item_total: { currency_code: this.cart.currencyCode, value: this.subTotal, }, shipping: { currency_code: this.cart.currencyCode, value: this.shippingTotal, } } }, items: items, reference_id: this.cart.id, } ] }, advanced: { commit: 'true' }, ...

so that invoice_id is hardcoded. Your first payment will work but all subsequent payments will fail until the invoice_id changes.

The issue I'm seeing is that onApprove() fires but onClientAuthorization() doesn't.

https://www.sandbox.paypal.com/smart/api/order/5LD08126N3975045N/capture 400 (Bad Request)

1 unhandled_error {err: "Error: Order could not be captured↵ at p (https…Task (http://localhost:8100/polyfills.js:5733:31)", timestamp: "1578064074730", referer: "localhost:8100", uid: "3fa3276310_mtq6ntu6mzu", env: "sandbox"} env: "sandbox" err: "Error: Order could not be captured↵ at p (https://www.sandbox.paypal.com/smart/buttons?

I think if you're able to catch this error then the same method could also be used for issue #98.

Thanks in advance for your help.

ollucks commented 4 years ago

Ideally onError() would fire where we can handle it appropriately.

labozilla commented 4 years ago

See if you can help me: when making the payment you are being charged twice the amount of an order. When placing the invoice_id you do not charge twice, however, the message appears stating "Duplicate Invoice ID detected. "