I am trying to figure out how to setup a callback url to receive payment status information from a payment gateway.
Here's a summary of the whole setup. There is a backend (API endpoints)built with Laravel 5.8 that will be consumed by a react app and a mobile app. Both apps will be using the payment gateway's web and mobile sdks to initiate payment transactions.
Then the payment gateway should respond with a payment status by calling the callback api I need to set up.
This is my first attempt at doing something like this so pardon me if I am way off but here's what I have written
Callback endpoint
Route::post('order/payment/status', 'PaymentController@getStatus'); // receives payment status
PaymentController getstatus() method
public function getStatus(Request $request)
{
$paymentMethod = $request->paymentMethod;
$amount = $request->amount;
$providerCode = $request->provider;
$customerName = $request->customerName;
$customerEmail = $request->customerEmail;
$paymentDescription = $request->paymentDescription;
$paymentStatus = $request->paaymentStatus;
$transactionReference = $request->transactionReference;
// update my record based on the paymentStatus
}
Is this the proper way to do it? I feel like it should be a get request and not a post. Please help.
I'll leave you with some tips and advises that I wish I knew back then.
1) Define your route outside of your auth middleware group and disable CSRF protection for its url, that can be achieved in the App\Http\Middleware\VerifyCsrfToken middleware.
2) get, post or any: post is the recommended. But, perhaps that's not something you can choose. The far majority of gateways will send your backend a post request, however, once I've worked with a gateway that sent get requests, if that's your case, define an any route.
3) Get, post or any, ALWAYS validate the signature of the received request with the payment gateway. That's a safety must that will discard requests not sent from the payment gateway. Every payment gateway has got to have this, find it in the documentation.
4) Log every request payload ($request->all()) to file or database before anything in your controller, or if you prefer, integrate your system with an error tracking service like Sentry, for example (that's the neat way). That will save you a lot of trouble in case an error stops script execution.
5) The easiest way to speed up the development process is to test your code locally (without the need to go through checkout every time), to do so, get a hold of the request payload from the payment gateway (json, probably), save on Postman and use it to send your local backend posts, simulating the request from the payment gateway (bypass signature validation when testing, of course).
6) Don't fit the payment gateway molds, but make them fit yours instead. Meaning: don't go saving a raw meaningful data in your database without transforming it into a pattern that your logic recognizes. That's a best practice that will avoid you headaches in the future (in case you need to change payment gateway).
Dirty pratical example for comprehension:
switch ($request->paymentStatus) {
case 'SUCCESS':
$status = 'success';
break;
case 'CANCELLED_BY_USER':
case 'CANCELLED_BY_ANTIFRAUD':
$status = 'canceled';
break;
default:
$status = 'unknown';
break;
}
7) Continuing on about the best practice mentioned above, if you ever need to code checkout in PHP, consider using a known payment processing library like Omnipay, for example. It's a whole new learning, but, that learning will be enough for life.
8) Log every user action taken in your Admin (a charge button, a status creation button, a notification send button, everything...). You never know when you're gonna get that call.
That's it. Hope it helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With