<?php
namespace App\Http\Controllers\User;
use Exception;
use Carbon\Carbon;
use App\Models\Card;
use App\Models\User;
use GuzzleHttp\Psr7\Uri;
use App\Models\Transaction;
use Jenssegers\Agent\Agent;
use App\Constants\CardConst;
use Illuminate\Http\Request;
use App\Models\TemporaryData;
use App\Constants\GlobalConst;
use App\Http\Helpers\Response;
use App\Models\MerchantDetails;
use App\Models\UserNotification;
use Illuminate\Support\Facades\DB;
use App\Models\Admin\BasicSettings;
use App\Http\Controllers\Controller;
use App\Constants\PaymentGatewayConst;
use App\Models\UserWallet;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Notification;
use App\Notifications\User\CardPaymentEmailNotification;
class CheckoutController extends Controller
{
public $charge_payable = true;
/**
* Method for checkout index page
* @param $order_id
* @param Illuminate\Http\Request $request
*/
public function checkout(Request $request,$order_id){
$page_title = "Order Checkout";
$order = TemporaryData::where('identifier',$order_id)->first();
$user = User::with(['merchant_api_keys','merchant_details'])
->where('id',auth()->user()->id)
->first();
if($order->data->merchant_api_key->env == GlobalConst::ENV_SANDBOX){
$card_payments = Card::where('type',CardConst::TEST)->orderBy('id','desc')->get();
}else{
$card_payments = Card::auth()->orderBy('id','desc')->get();
}
$user_wallet = UserWallet::auth()->with(['currency'])->first();
return view('order.pages.checkout',compact(
'page_title',
'order',
'user',
'card_payments',
'user_wallet'
));
}
/**
* Method for submit checkout page information.Specifically: CardPayment
* @param $order_id
* @param Illuminate\Http\Request $request
*/
public function submit(Request $request,$order_id){
$basic_settings = BasicSettings::first();
$user = User::with(['merchant_api_keys','merchant_details'])
->where('id',auth()->user()->id)->first();
if($user->kyc_verified != GlobalConst::VERIFIED) return back()->with(['error' => ['Sorry! You are not KYC verified user. Please verify your KYC.']]);
$validator = Validator::make($request->all(),[
'card_payment' => 'required',
'type' => 'required',
]);
if($validator->fails()) return back()->withErrors($validator)->withInput($request->all());
$validated = $validator->validate();
$order = TemporaryData::where('identifier',$order_id)->first();
if(!$order) return back()->with(['error' => ['Data not found!']]);
if (Carbon::parse($order->data->expiration) < Carbon::now()) {
$order->delete();
return redirect()->away($order->data->cancel_url)->with(['error'=> ['Sorry! Link is expired.']]);
}
if(!$order) return back()->with(['error' => ['Order not found!']]);
if($validated['type'] == GlobalConst::WALLET){
$user_wallet = UserWallet::auth()->where('id',$validated['card_payment'])->first();
if(!$user_wallet) return back()->with(['error' => ['Wallet not found!']]);
if($user_wallet->balance < $order->data->total_payable) return back()->with(['error' => ['Insufficient wallet balance!']]);
$status = PaymentGatewayConst::STATUSSUCCESS;
$type = GlobalConst::WALLET;
$card_payment = null;
$charges = null;
$wallet_id = $user_wallet->id;
$receiver_info = MerchantDetails::where('merchant_id',$order->data->merchant_account->merchant_id)->first();
$merchant_wallet = UserWallet::where('user_id',$receiver_info->user_id)->first();
$merchant = User::where('id',$receiver_info->user_id)->first();
$merchant_wallet_id = $merchant_wallet->id;
try{
$attribute = PaymentGatewayConst::SEND;
$this->transactionInformation($user,$card_payment,$order,$status,$basic_settings,$charges,$wallet_id,$type,$attribute,$merchant);
$this->transactionReceiveInformation($merchant,$card_payment,$order,$status,$basic_settings,$charges,$merchant_wallet_id,$type,$attribute = PaymentGatewayConst::RECEIVED,$sender_info = $user);
$user_wallet->update([
'balance' => $user_wallet->balance - $order->data->total_payable
]);
$merchant_wallet->update([
'balance' => $merchant_wallet->balance + $order->data->amount
]);
}catch(Exception $e){
return back()->with(['error' => ['Something went wrong!']]);
}
$success_url = $order->data->success_url;
return redirect()->away($success_url)->with(['success' => ['Payment Successfully Done.']]);
}else{
$card_payment = Card::where('id',$validated['card_payment'])->first();
if(!$card_payment) return back()->with(['error'=> ['Card Payment not found!']]);
$merchant_stripe_secret = $order->data->merchant_api_key->stripe_secret;
$receiver_info = MerchantDetails::where('merchant_id',$order->data->merchant_account->merchant_id)->first();
$merchant = User::where('id',$receiver_info->user_id)->first();
$card_number = decrypt($card_payment->card_number);
$expiry_date = decrypt($card_payment->expiry_date);
$expiry_month = trim(explode("/",$expiry_date)[0]);
$expiry_year = trim(explode("/",$expiry_date)[1]);
$card_cvc = decrypt($card_payment->card_cvc);
if($card_payment->type == card_payment_const()::TEST){
$status = PaymentGatewayConst::STATUSTEST;
}else{
$status = PaymentGatewayConst::STATUSSUCCESS;
}
$trx_id = generateTrxString("transactions","trx_id","CP",8);
try{
$stripe = new \Stripe\StripeClient($merchant_stripe_secret);
$response = $stripe->tokens->create([
'card' => [
'number' => $card_number,
'exp_month' => $expiry_month,
'exp_year' => $expiry_year,
'cvc' => $card_cvc,
],
]);
if($this->charge_payable == true){
$charges = $stripe->charges->create([
'amount' => $order->data->total_payable * 100,
'currency' => 'usd',
'source' => $response->id,
]);
if($charges->status == 'succeeded'){
$wallet = null;
$type = "card";
$attribute = PaymentGatewayConst::SEND;
$this->transactionInformation($user,$card_payment->id,$order,$status,$basic_settings,$charges,$wallet,$type,$attribute,$merchant);
}else{
return back()->with(['error' => ['Something went wrong! Please try again.']]);
}
}else{
$wallet = null;
$type = "card";
$attribute = PaymentGatewayConst::SEND;
$this->transactionInformation($user,$card_payment->id,$order,$status,$basic_settings,$charges=null,$wallet,$type,$attribute,$merchant);
}
}catch (Exception $e) {
return back()->with(['error' => [$e->getMessage()]]);
}
$transaction_data = Transaction::where('trx_id',$trx_id)->first();
if($transaction_data == null){
$wallet = null;
$type = "card";
$attribute = PaymentGatewayConst::SEND;
$this->transactionInformation($user,$card_payment->id,$order,$status,$basic_settings,$charges,$wallet,$type,$attribute,$merchant);
}
$success_url = $order->data->success_url;
if(filter_var($success_url,FILTER_VALIDATE_URL)){
$url = new Uri($success_url);
if($this->charge_payable == true){
$token = $charges->id;
}else{
$token = $response->id;
}
$new_url = $url->withQuery(http_build_query([
'token' => $token,
'transaction_id' => $trx_id
]));
return redirect()->away($new_url)->with(['success' => ['Payment Successfully Done.']]);
}else {
return redirect()->away($order->data->cancel_url)->with(['error' => ['Success Url Not found.']]);
}
}
}
// save the transaction information
function transactionInformation($user,$card_payment,$order,$status,$basic_settings,$charges,$wallet,$type,$attribute,$merchant){
$trx_id = generateTrxString("transactions","trx_id","CP",8);
$data = [
'trx_id' => $trx_id,
'type' => PaymentGatewayConst::CARD_PAYMENT,
'user_id' => $user->id,
'user_wallet_id' => $wallet,
'card_id' => $card_payment,
'payment_type' => $type,
'payable_charge' => $this->charge_payable,
'request_amount' => $order->data->amount,
'fixed_charge' => $order->data->fixed_charge,
'percent_charge' => $order->data->percent_charge,
'total_charge' => $order->data->total_charge,
'total_payable' => $order->data->total_payable,
'request_currency' => $order->data->currency,
'available_balance' => null,
'payment_currency' => $order->data->currency,
'remark' => ucwords(remove_special_char("Order Placed"," ")) . " Using" . " " . $type,
'details' => [
'token' => $order->data->token,
'order' => $order->data,
'payment_info' => $charges,
'receiver_info' => [
'name' => $merchant->fullname,
'email' => $merchant->email,
]
],
'attribute' => $attribute,
'status' => $status,
];
$transaction = Transaction::create($data);
$this->transactionDevice($transaction->id);
$this->userNotification($user->id,$transaction->id,$order->data->amount,$order->data->currency,$type);
if($basic_settings->email_notification == true){
try{
Notification::route('mail',$user->email)->notify(new CardPaymentEmailNotification($transaction->id,$user));
}catch(Exception $e){}
}
$order->delete();
}
// transaction received data
function transactionReceiveInformation($user,$card_payment,$order,$status,$basic_settings,$charges,$wallet,$type,$attribute,$sender_info){
$trx_id = generateTrxString("transactions","trx_id","CP",8);
$data = [
'trx_id' => $trx_id,
'type' => PaymentGatewayConst::CARD_PAYMENT,
'user_id' => $user->id,
'user_wallet_id' => $wallet,
'card_id' => $card_payment,
'payment_type' => $type,
'payable_charge' => $this->charge_payable,
'request_amount' => $order->data->amount,
'fixed_charge' => $order->data->fixed_charge,
'percent_charge' => $order->data->percent_charge,
'total_charge' => $order->data->total_charge,
'total_payable' => $order->data->total_payable,
'request_currency' => $order->data->currency,
'available_balance' => null,
'payment_currency' => $order->data->currency,
'remark' => ucwords(remove_special_char("Order Received"," ")) . " Using" . " " . $type,
'details' => [
'token' => $order->data->token,
'order' => $order->data,
'payment_info' => $charges,
'sender_info' => [
'name' => $sender_info->fullname,
'email' => $sender_info->email
],
],
'attribute' => $attribute,
'status' => $status,
];
$transaction = Transaction::create($data);
$this->transactionDevice($transaction->id);
$this->userNotification($user->id,$transaction->id,$order->data->amount,$order->data->currency,$type);
if($basic_settings->email_notification == true){
try{
Notification::route('mail',$user->email)->notify(new CardPaymentEmailNotification($transaction->id,$user));
}catch(Exception $e){}
}
$order->delete();
}
// save the transaction device information
function transactionDevice($id){
$client_ip = request()->ip() ?? false;
$location = geoip()->getLocation($client_ip);
$agent = new Agent();
$mac = "";
DB::beginTransaction();
try{
DB::table("transaction_devices")->insert([
'transaction_id'=> $id,
'ip' => $client_ip,
'mac' => $mac,
'city' => $location['city'] ?? "",
'country' => $location['country'] ?? "",
'longitude' => $location['lon'] ?? "",
'latitude' => $location['lat'] ?? "",
'timezone' => $location['timezone'] ?? "",
'browser' => $agent->browser() ?? "",
'os' => $agent->platform() ?? "",
]);
DB::commit();
}catch(Exception $e) {
DB::rollBack();
throw new Exception($e->getMessage());
}
}
//user notification
public function userNotification($user_id,$id,$amount,$currency,$type){
UserNotification::create([
'user_id' => $user_id,
'transaction_id' => $id,
'details' => [
'title' => 'Your Order Using ' . $type,
'amount' => floatval($amount),
'currency' => $currency,
'message' => "Successfully placed."
],
]);
}
/**
* Method for retrieve the payment information
* @param $id
* @param Illuminate\Http\Request $request
*/
public function details(Request $request){
$transaction = Transaction::auth()->with(['user'])->where('trx_id',$request->transaction_id)->first();
if(!$transaction) return Response::error(['Transaction data not found'],[],400);
$response = [
'token' => $transaction->details->token ?? '',
'trx_id' => $transaction->trx_id ?? '',
'payer' => [
'username' => $transaction->user->username,
'email' => $transaction->user->email,
],
'status' => $this->getStatusBadge($transaction->status)
];
return Response::success(['Success'],[
'data' => $response
],200);
}
// get the status data
function getStatusBadge($status) {
if ($status == PaymentGatewayConst::STATUSPENDING) {
$statusText = "Pending";
return $statusText;
} else if ($status == PaymentGatewayConst::STATUSSUCCESS) {
$statusText = "Success";
return $statusText;
} else if ($status == PaymentGatewayConst::STATUSREJECTED) {
$statusText = "Rejected";
return $statusText;
} else if ($status == PaymentGatewayConst::STATUSWAITING) {
$statusText = "Waiting";
return $statusText;
} else if ($status == PaymentGatewayConst::STATUSHOLD) {
$statusText = "Hold";
return $statusText;
} else {
$statusText = "Test";
return $statusText;
}
}
}
Payment Accept
Our platform simplifies payment acceptance, making transaction management effortless. With secure processing and user-friendly tools, you can easily handle payments from credit cards, debit cards, and digital methods. Our intuitive interface is designed for efficiency, ensuring a seamless experience for both you and your customers. Manage your transactions with ease and confidence.