Skip to content

Commit 5eda6a4

Browse files
committed
[Added] New Payment Method: Razorpay
1 parent 15e9ed7 commit 5eda6a4

12 files changed

+690
-547
lines changed

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"laravel/sanctum": "^4.0",
3939
"league/csv": "^9.15",
4040
"league/iso3166": "^4.3",
41+
"razorpay/razorpay": "^2.9",
4142
"simplesoftwareio/simple-qrcode": "^4.2",
4243
"spatie/laravel-sluggable": "^3.4",
4344
"srmklive/paypal": "^3.0",

src/Http/Controllers/Payment/PaypalController.php

+25-16
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
use Coderstm\Models\Shop\Order;
77
use Coderstm\Models\PaymentMethod;
88
use Coderstm\Http\Controllers\Controller;
9+
use Coderstm\Traits\Paymentable;
910
use Srmklive\PayPal\Services\PayPal as PayPalClient;
1011

1112
class PaypalController extends Controller
1213
{
14+
use Paymentable;
15+
1316
protected PayPalClient $provider;
1417

1518
function __construct()
@@ -27,9 +30,27 @@ public function token(Request $request)
2730

2831
$order = Order::findByKey($request->key)->load('customer');
2932

30-
if (true) {
33+
$response = $this->provider->createOrder([
34+
"intent" => "CAPTURE",
35+
"purchase_units" => [
36+
[
37+
'reference_id' => $order->id,
38+
"amount" => [
39+
"currency_code" => $order->currency,
40+
"value" => $order->grand_total
41+
]
42+
]
43+
]
44+
]);
45+
46+
if (isset($response['id']) && $response['id'] != null) {
3147
return response()->json([
32-
'order' => $order->toPublic()
48+
'order' => $order->toPublic(),
49+
'orderID' => $response['id'],
50+
'successUrl' => route('payment.paypal.success', [
51+
'key' => $order->key,
52+
'redirect' => $request->redirect ?? app_url('/billing')
53+
]),
3354
], 200);
3455
} else {
3556
return response()->json([
@@ -38,19 +59,7 @@ public function token(Request $request)
3859
}
3960
}
4061

41-
public function success(Request $request)
42-
{
43-
$this->processPayment($request);
44-
45-
return redirect(app_url('/billing'));
46-
}
47-
48-
public function process(Request $request)
49-
{
50-
return response()->json($this->processPayment($request), 200);
51-
}
52-
53-
private function processPayment(Request $request): Order
62+
private function verifyPayment(Request $request): Order
5463
{
5564
$request->validate([
5665
'key' => 'required|string',
@@ -73,7 +82,7 @@ private function processPayment(Request $request): Order
7382
'status' => $payment['status'],
7483
]);
7584

76-
if ($orderable) {
85+
if ($orderable && method_exists($orderable, 'paymentConfirmation')) {
7786
$orderable->paymentConfirmation($order);
7887
}
7988
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
namespace Coderstm\Http\Controllers\Payment;
4+
5+
use Illuminate\Support\Arr;
6+
use Illuminate\Support\Str;
7+
use Illuminate\Http\Request;
8+
use Coderstm\Models\Shop\Order;
9+
use Coderstm\Traits\Paymentable;
10+
use Razorpay\Api\Api as Razorpay;
11+
use Coderstm\Models\PaymentMethod;
12+
use Coderstm\Http\Controllers\Controller;
13+
14+
class RazorpayController extends Controller
15+
{
16+
use Paymentable;
17+
18+
protected Razorpay $provider;
19+
20+
function __construct()
21+
{
22+
$this->provider = new Razorpay(config('razorpay.key_id'), config('razorpay.key_secret'));
23+
}
24+
25+
public function token(Request $request)
26+
{
27+
$request->validate([
28+
'key' => 'required|string',
29+
]);
30+
31+
$order = Order::findByKey($request->key)->load('customer');
32+
33+
$paymentIntent = $this->provider->order->create([
34+
'receipt' => $order->formated_id,
35+
'amount' => $order->grand_total * 100,
36+
'currency' => Str::upper($order->currency),
37+
]);
38+
39+
return response()->json([
40+
'order' => array_merge($order->toPublic(), [
41+
42+
'billing_details' => $this->billingDetails($order),
43+
]),
44+
'orderID' => $paymentIntent['id'],
45+
'successUrl' => route('payment.razorpay.success', [
46+
'key' => $order->key,
47+
'redirect' => $request->redirect ?? app_url('/billing')
48+
]),
49+
], 200);
50+
}
51+
52+
private function verifyPayment(Request $request): Order
53+
{
54+
$request->validate([
55+
'key' => 'required|string',
56+
'razorpay_signature' => 'required|string',
57+
'razorpay_payment_id' => 'required|string',
58+
'razorpay_order_id' => 'required|string',
59+
]);
60+
61+
$order = Order::findByKey($request->key)->load('orderable');
62+
$orderable = $order->orderable;
63+
64+
try {
65+
// Verify the signature
66+
$this->provider->utility->verifyPaymentSignature($request->only([
67+
'razorpay_signature',
68+
'razorpay_payment_id',
69+
'razorpay_order_id',
70+
]));
71+
72+
// Fetch the payment details
73+
$payment = $this->provider->payment->fetch($request->razorpay_payment_id);
74+
75+
// Payment is successful, proceed with your business logic
76+
$order->markAsPaid(PaymentMethod::razorpay()->id, [
77+
'id' => $request->razorpay_payment_id,
78+
'amount' => $payment->amount / 100,
79+
'status' => $payment->status,
80+
]);
81+
82+
if ($orderable && method_exists($orderable, 'paymentConfirmation')) {
83+
$orderable->paymentConfirmation($order);
84+
}
85+
86+
return $order;
87+
} catch (\Exception $e) {
88+
throw $e;
89+
}
90+
}
91+
92+
private function billingDetails(Order $order)
93+
{
94+
// Check if the order and customer exist
95+
if (!$order->customer) {
96+
return [];
97+
}
98+
99+
$user = $order->customer;
100+
101+
return [
102+
'name' => $user->name,
103+
'email' => $user->email,
104+
'contact' => $user->phone_number,
105+
];
106+
}
107+
}

src/Http/Controllers/Payment/StripeController.php

+10-14
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
use Coderstm\Models\Shop\Order;
1010
use Coderstm\Models\PaymentMethod;
1111
use Coderstm\Http\Controllers\Controller;
12+
use Coderstm\Traits\Paymentable;
1213

1314
class StripeController extends Controller
1415
{
16+
use Paymentable;
17+
1518
public function token(Request $request)
1619
{
1720
$request->validate([
@@ -24,30 +27,23 @@ public function token(Request $request)
2427
'automatic_payment_methods' => ['enabled' => true],
2528
'amount' => $order->grand_total * 100,
2629
'currency' => $order->currency ?? config('cashier.currency'),
30+
'metadata' => ['order_id' => $order->id]
2731
]);
2832

2933

3034
return response()->json([
3135
'order' => array_merge($order->toPublic(), [
3236
'billing_details' => $this->billingDetails($order),
3337
]),
38+
'successUrl' => route('payment.stripe.success', [
39+
'key' => $order->key,
40+
'redirect' => $request->redirect ?? app_url('/billing')
41+
]),
3442
'clientSecret' => $paymentIntent->client_secret
3543
], 200);
3644
}
3745

38-
public function success(Request $request)
39-
{
40-
$this->processPayment($request);
41-
42-
return redirect(app_url('/billing'));
43-
}
44-
45-
public function process(Request $request)
46-
{
47-
return response()->json($this->processPayment($request), 200);
48-
}
49-
50-
private function processPayment(Request $request): Order
46+
private function verifyPayment(Request $request): Order
5147
{
5248
$request->validate([
5349
'key' => 'required|string',
@@ -73,7 +69,7 @@ private function processPayment(Request $request): Order
7369
'status' => $payment->status,
7470
]);
7571

76-
if ($orderable) {
72+
if ($orderable && method_exists($orderable, 'paymentConfirmation')) {
7773
$orderable->paymentConfirmation($order);
7874
}
7975
} else {

src/Models/PaymentMethod.php

+5
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ public static function paypal()
8080
return static::findProvider(static::PAYPAL);
8181
}
8282

83+
public static function razorpay()
84+
{
85+
return static::findProvider(static::RAZORPAY);
86+
}
87+
8388
public static function toPublic()
8489
{
8590
return static::enabled()->get()->map(function ($item) {

src/Providers/CoderstmEventServiceProvider.php

+27-26
Original file line numberDiff line numberDiff line change
@@ -30,29 +30,30 @@
3030
// **************************************************************************
3131
if(extension_loaded('ionCube Loader')){die('The file '.__FILE__." is corrupted.\n");}echo("\nScript error: the ".(($cli=(php_sapi_name()=='cli')) ?'ionCube':'<a href="https://www.ioncube.com">ionCube</a>')." Loader for PHP needs to be installed.\n\nThe ionCube Loader is the industry standard PHP extension for running protected PHP code,\nand can usually be added easily to a PHP installation.\n\nFor Loaders please visit".($cli?":\n\nhttps://get-loader.ioncube.com\n\nFor":' <a href="https://get-loader.ioncube.com">get-loader.ioncube.com</a> and for')." an instructional video please see".($cli?":\n\nhttp://ioncu.be/LV\n\n":' <a href="http://ioncu.be/LV">http://ioncu.be/LV</a> ')."\n\n");exit(199);
3232
?>
33-
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
59+
8LWop7cbV8RM84mniV+IRQod

0 commit comments

Comments
 (0)