Created
November 21, 2024 08:18
-
-
Save kidino/800c59559c804e45bf0c7430d37c4520 to your computer and use it in GitHub Desktop.
SecurePay on Laravel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers; | |
use Carbon\Carbon; | |
use App\Models\Plan; | |
use App\Models\User; | |
use App\Models\Payment; | |
use Illuminate\Support\Str; | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Facades\Auth; | |
class CheckoutController extends Controller | |
{ | |
/** | |
* public function index() -- used in routing | |
* -- to redirect to payment gateway | |
* | |
* public function verify() -- used in routing | |
* -- returning from payment gateway | |
**/ | |
/** | |
* protected function record_payment() | |
* -- to create a payment record before going to payment gateway | |
* | |
* protected function process_payment() | |
* -- to process payment & membership after returning from payment gateway | |
* | |
* protected function {payment-gateway}_go() | |
* -- called by index() based on selected payment gateway | |
* | |
* protected function {payment-gateway}_verify() | |
* -- called by verified based on selected payment gateway | |
*/ | |
/** | |
* | |
* /checkout/{plan}/{payment_gateway} | |
*/ | |
protected const PG_NAMESPACE = "\\App\\Libraries\\PaymentGateway\\"; | |
public function index(Request $request, Plan $plan, $payment_method) { | |
// dd($plan, $payment_method); | |
if(!in_array($payment_method, Payment::SUPPORTED_PAYMENTS)) { | |
abort(405, 'Unknown payment method'); | |
} | |
$payment = $this->record_payment($plan, $payment_method); | |
$pg_classname = self::PG_NAMESPACE . ucfirst( $payment_method ); | |
$payment_gateway = new $pg_classname(); | |
$redirect_url = $payment_gateway->go($plan, $payment); | |
return redirect( $redirect_url ); | |
} | |
protected function record_payment(Plan $plan, $payment_method) { | |
$user = Auth::user(); | |
return Payment::create([ | |
'plan_id' => $plan->id, | |
'user_id' => $user->id, | |
'amount' => $plan->price, | |
'payment_method' => $payment_method, | |
'payment_status' => 'pending', | |
'payment_code' => Str::random(20), | |
'remarks' => ucfirst($payment_method). ' payment for '. $plan->code | |
]); | |
} | |
/* /verify/{payment}/{payment_gateway} | |
* | |
*/ | |
public function verify(Request $request, Payment $payment, $payment_method) { | |
if(!in_array($payment_method, Payment::SUPPORTED_PAYMENTS)) { | |
abort(405, 'Unknown payment method'); | |
} | |
$pg_classname = self::PG_NAMESPACE . ucfirst( $payment_method ); | |
$payment_gateway = new $pg_classname(); | |
$result = $payment_gateway->verify( $request, $payment ); | |
if($result['success'] && ($payment->payment_status == 'pending')) { | |
$this->process_payment($payment); | |
} | |
return view('checkout.thankyou'); | |
} | |
protected function process_payment(Payment $payment) { | |
$user = User::find( $payment->user_id ); | |
$plan = Plan::find( $payment->plan_id ); | |
$duration = 0; | |
switch( $plan->term ) { | |
case 'monthly' : $duration = '1 month'; break; | |
case 'yearly' : $duration = '1 year'; break; | |
case 'lifetime' : $duration = '1000 years'; break; | |
} | |
if( Carbon::parse( $user->expiry_date )->isFuture() ) { | |
$user->expiry_date = Carbon::parse( $user->expiry_date )->add( $plan->duration ); | |
} else { | |
$user->expiry_date = Carbon::today()->add( $duration ); | |
} | |
$user->plan_id = $plan->id; | |
$user->save(); | |
$payment->payment_status = 'completed'; | |
$payment->save(); | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Libraries\PaymentGateway; | |
use App\Models\Plan; | |
use App\Models\User; | |
use App\Models\Payment; | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Facades\Auth; | |
class Securepay { | |
private $uid; | |
private $auth_token; | |
private $checksum_token; | |
private $api_url; | |
function __construct() { | |
$this->api_url = 'https://'. ( (env('APP_ENV') == 'local') ? 'sandbox.' : '') .'securepay.my/api/v1/payments'; | |
$this->uid = env('SECUREPAY_UID'); | |
$this->auth_token = env('SECUREPAY_AUTH_TOKEN'); | |
$this->checksum_token = env('SECUREPAY_CHECKSUM_TOKEN'); | |
} | |
function go(Plan $plan, Payment $payment) { | |
$user = User::find($payment->user_id); | |
$buyer_phone = null; | |
$verify_url = route('checkout.verify', [ | |
'payment' => $payment->payment_code, | |
'payment_method' => 'securepay' | |
]); | |
$string = $user->email .'|'. | |
$user->name.'|'. | |
$buyer_phone.'|'. | |
$verify_url.'|'. | |
$payment->payment_code.'|'. | |
$payment->remarks.'|'. | |
$verify_url.'|'. | |
$payment->amount.'|'. | |
$this->uid; | |
$sign = hash_hmac('sha256', $string, $this->checksum_token ); | |
$post_data = 'buyer_name=' . urlencode( $user->name ) . | |
'&token=' . urlencode( $this->auth_token ) . | |
'&callback_url=' . urlencode( $verify_url ) . | |
'&redirect_url=' . urlencode( $verify_url ) . | |
'&order_number=' . urlencode( $payment->payment_code ) . | |
'&buyer_email=' . urlencode( $user->email ) . | |
'&buyer_phone=' . urlencode( $buyer_phone ) . | |
'&transaction_amount=' . urlencode( $payment->amount ) . | |
'&product_description=' . urlencode( $payment->remarks ) . | |
'&redirect_post=' . urlencode( 'true' ) . | |
'&checksum=' . urlencode( $sign ); | |
$ch = curl_init(); | |
curl_setopt( $ch, CURLOPT_URL, $this->api_url); | |
curl_setopt($ch, CURLOPT_POST, 1 ); | |
curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_data); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1); | |
if( env('APP_ENV') == 'local') { | |
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0); | |
} | |
$output = curl_exec( $ch ); | |
echo $output; | |
// dd($string, $sign, $output); | |
// return 'https://securepay.my'; | |
} | |
function verify(Request $request, Payment $payment) { | |
// dd($request); | |
$data = $request->all(); | |
$user = User::find($payment->user_id); | |
if( | |
($data['transaction_amount_received'] == $payment->amount) | |
&& ($data['payment_status'] == 'true') | |
&& ($data['currency'] == 'MYR') | |
) { | |
Auth::login($user); | |
return [ | |
'success' => true | |
]; | |
} | |
return [ | |
'success' => false, | |
'errors' => [] | |
]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment