<?php
namespace App\Http\Controllers\Api\V1\User;
use Exception;
use App\Models\UserWallet;
use App\Models\Transaction;
use Illuminate\Http\Request;
use App\Models\TemporaryData;
use App\Http\Helpers\Response;
use App\Models\Admin\Currency;
use App\Models\UserNotification;
use Illuminate\Support\Facades\DB;
use App\Models\Admin\BasicSettings;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\RedirectResponse;
use App\Constants\PaymentGatewayConst;
use App\Traits\ControlDynamicInputFields;
use Illuminate\Support\Facades\Validator;
use App\Models\Admin\PaymentGatewayCurrency;
use Illuminate\Support\Facades\Notification;
use App\Traits\PaymentGateway\PaystackGateway;
use App\Notifications\User\AddMoneyNotification;
use App\Http\Helpers\PaymentGateway as PaymentGatewayHelper;
class AddMoneyController extends Controller
{
use ControlDynamicInputFields, PaystackGateway;
/**
* Method for get the add money information
* @return response
*/
public function info(){
$base_currency = Currency::default();
$currency_image_paths = [
'base_url' => url("/"),
'path_location' => files_asset_path_basename("currency-flag"),
'default_image' => files_asset_path_basename("currency-flag"),
];
$user_wallet = UserWallet::auth()->first();
$payment_gateways = PaymentGatewayCurrency::whereHas('gateway', function ($gateway) {
$gateway->where('slug', PaymentGatewayConst::add_money_slug());
$gateway->where('status', 1);
})->get()->map(function($data){
if($data->gateway->isManual()){
$name = $data->name . '(' . ("Manual") .')';
}else{
$name = $data->name;
}
return [
'name' => $name,
'alias' => $data->alias,
'code' => $data->currency_code,
'image' => $data->gateway->image,
'title' => $data->gateway->title,
'rate' => get_amount($data->rate),
'min_limit' => get_amount($data->min_limit),
'max_limit' => get_amount($data->max_limit),
'fixed_charge' => get_amount($data->fixed_charge),
'percent_charge' => get_amount($data->percent_charge),
];
});
$image_paths = [
'base_url' => url("/"),
'path_location' => files_asset_path_basename("payment-gateways"),
'default_image' => files_asset_path_basename("payment-gateways"),
];
$transactions = Transaction::auth()->where('type',PaymentGatewayConst::TYPEADDMONEY)->get()->map(function($data){
return [
'type' => $data->type,
'trx_id' => $data->trx_id,
'payment_gateway' => $data->payment_gateway->name,
'request_amount' => get_amount($data->request_amount),
'fixed_charge' => get_amount($data->fixed_charge),
'percent_charge' => get_amount($data->percent_charge),
'total_charge' => get_amount($data->total_charge),
'total_payable' => get_amount($data->total_payable),
'request_currency' => $data->request_currency,
'payment_currency' => $data->payment_currency,
'remark' => $data->remark,
'attribute' => $data->attribute,
'status' => $data->stringStatus->value,
];
});
return Response::success(['Transfer money fetch successfully.'],[
'base_currency' => $base_currency->code,
'flag' => $base_currency->flag,
'currency_image_paths' => $currency_image_paths,
'rate' => get_amount($base_currency->rate),
'wallet' => [
'code' => $user_wallet->currency->code,
'balance' => get_amount($user_wallet->balance)
],
'payment_gateways' => $payment_gateways,
'image_paths' => $image_paths,
'transactions' => $transactions
],200);
}
/**
* Method for confirm add money
* @param Illuminate\Http\Request $request
*/
public function confirm(Request $request){
$validator = Validator::make($request->all(),[
'amount' => 'required|numeric',
'payment_gateway' => 'required|string',
]);
if($validator->fails()) return back()->withErrors($validator)->withInput($request->all());
$validated = $validator->validated();
$request->merge(['currency' => $validated['payment_gateway']]);
try{
$instance = PaymentGatewayHelper::init($request->all())->type(PaymentGatewayConst::TYPEADDMONEY)->gateway()->api()->render();
if($instance instanceof RedirectResponse === false && isset($instance['gateway_type']) && $instance['gateway_type'] == PaymentGatewayConst::MANUAL) {
$data = $this->manualFields($request->all(),$instance);
return Response::success([__('Request response fetch successfully!')],$data,200);
}
}catch(Exception $e) {
return Response::error($e->getMessage(),[],400);
}
return Response::success([__('Payment gateway response successful')],[
'redirect_url' => $instance['redirect_url'],
'redirect_links' => $instance['redirect_links'],
'action_type' => $instance['type'] ?? false,
'address_info' => $instance['address_info'] ?? [],
],200);
}
/**
* Method for add money success method
*/
public function success(Request $request, $gateway){
try{
$token = PaymentGatewayHelper::getToken($request->all(),$gateway);
$temp_data = TemporaryData::where("identifier",$token)->first();
if(!$temp_data) {
if(Transaction::where('callback_ref',$token)->exists()) {
return Response::success([__('Transaction request sended successfully!')],[],400);
}else {
return Response::error([__('Transaction failed. Record didn\'t saved properly. Please try again')],[],400);
}
}
$update_temp_data = json_decode(json_encode($temp_data->data),true);
$update_temp_data['callback_data'] = $request->all();
$temp_data->update([
'data' => $update_temp_data,
]);
$temp_data = $temp_data->toArray();
$instance = PaymentGatewayHelper::init($temp_data)->type(PaymentGatewayConst::TYPEADDMONEY)->responseReceive();
if($instance instanceof RedirectResponse) return $instance;
}catch(Exception $e) {
return Response::error('Something went wrong! Please try again.',400);
}
return Response::success(["Payment successful, please go back your app"],[],200);
}
public function cancel(Request $request, $gateway) {
$token = PaymentGatewayHelper::getToken($request->all(),$gateway);
if($temp_data = TemporaryData::where("type",PaymentGatewayConst::TYPEADDMONEY)->where("identifier",$token)->first()) {
$temp_data->delete();
}
return Response::error(["Transaction Failed."],[],400);
}
public function postSuccess(Request $request, $gateway){
try{
$token = PaymentGatewayHelper::getToken($request->all(),$gateway);
$temp_data = TemporaryData::where("identifier",$token)->first();
if($temp_data && $temp_data->data->creator_guard != 'api') {
Auth::guard($temp_data->data->creator_guard)->loginUsingId($temp_data->data->creator_id);
}
}catch(Exception $e) {
return Response::error('Something went wrong! Please try again.',400);
}
return $this->success($request, $gateway);
}
public function postCancel(Request $request, $gateway){
try{
$token = PaymentGatewayHelper::getToken($request->all(),$gateway);
$temp_data = TemporaryData::where("type",PaymentGatewayConst::TYPEADDMONEY)->where("identifier",$token)->first();
if($temp_data && $temp_data->data->creator_guard != 'api') {
Auth::guard($temp_data->data->creator_guard)->loginUsingId($temp_data->data->creator_id);
}
}catch(Exception $e) {
return Response::error('Something went wrong! Please try again.',400);
}
return $this->cancel($request, $gateway);
}
/**
* Redirect Users for collecting payment via Button Pay (JS Checkout)
*/
public function redirectBtnPay(Request $request, $gateway){
try{
return PaymentGatewayHelper::init([])->type(PaymentGatewayConst::ADDMONEY)->handleBtnPay($gateway, $request->all());
}catch(Exception $e) {
return Response::error([$e->getMessage()], [], 500);
}
}
/**
* Method for paystack pay callback
*/
public function paystackPayCallBack(Request $request){
$instance = $this->paystackSuccess($request->all());
return Response::success(["Payment successful, please go back your app"],[],200);
}
/**
* Method for manual fields
*/
function manualFields($request,$payment_info){
$validator = Validator::make($request,[
'payment_gateway' => "required|string|exists:payment_gateway_currencies,alias",
]);
if($validator->fails()) return Response::error($validator->errors()->all(),[],400);
$validated = $validator->validate();
$gateway_currency = PaymentGatewayCurrency::where("alias",$validated['payment_gateway'])->first();
$gateway = $gateway_currency->gateway;
// Insert temp data
$info = [
'type' => PaymentGatewayConst::TYPEADDMONEY,
'identifier' => generate_unique_string("temporary_datas","identifier",16),
'data' => [
'gateway_currency_id' => $payment_info['currency']->id,
'amount' => $payment_info['amount'],
'wallet_id' => $payment_info['wallet']->id,
],
];
try{
$temp_data = TemporaryData::create($info);
}catch(Exception $e) {
return Response::error('Something went wrong! Please try again.',400);
}
$data['identifier'] = $temp_data->identifier;
$data['available'] = false;
$data['desc'] = strip_tags($gateway->desc);
$data['additional_fields'] = $gateway->input_fields;
return $data;
}
public function manualInputFields(Request $request) {
$validator = Validator::make($request->all(),[
'alias' => "required|string|exists:payment_gateway_currencies",
]);
if($validator->fails()) {
return Response::error($validator->errors()->all(),[],400);
}
$validated = $validator->validate();
$gateway_currency = PaymentGatewayCurrency::where("alias",$validated['alias'])->first();
$gateway = $gateway_currency->gateway;
if(!$gateway->isManual()) return Response::error([__('Can\'t get fields. Requested gateway is automatic')],[],400);
if(!$gateway->input_fields || !is_array($gateway->input_fields)) return Response::error([__("This payment gateway is under constructions. Please try with another payment gateway")],[],503);
try{
$input_fields = json_decode(json_encode($gateway->input_fields),true);
$input_fields = array_reverse($input_fields);
}catch(Exception $e) {
return Response::error([__("Something went wrong! Please try again")],[],500);
}
return Response::success([__('Payment gateway input fields fetch successfully!')],[
'gateway' => [
'desc' => strip_tags($gateway->desc)
],
'input_fields' => $input_fields,
'currency' => $gateway_currency->only(['alias']),
],200);
}
/**
* Method for submit manual data
* @param Illuminate\Http\Request $request
*/
public function manualSubmit(Request $request){
$tempDataValidate = Validator::make($request->all(),[
'identifier' => "required|string|exists:temporary_datas",
])->validate();
$tempData = TemporaryData::search($tempDataValidate['identifier'])->first();
if(!$tempData || $tempData->data == null || !isset($tempData->data->gateway_currency_id)) return redirect()->route('user.add.money.index')->with(['error' => ['Invalid request']]);
$gateway_currency = PaymentGatewayCurrency::find($tempData->data->gateway_currency_id);
if(!$gateway_currency || !$gateway_currency->gateway->isManual()) return redirect()->route('user.add.money.index')->with(['error' => ['Selected gateway is invalid']]);
$gateway = $gateway_currency->gateway;
$amount = $tempData->data->amount ?? null;
if(!$amount) return redirect()->route('user.add.money.index')->with(['error' => ['Transaction Failed. Failed to save information. Please try again']]);
$wallet = UserWallet::find($tempData->data->wallet_id ?? null);
if(!$wallet) return redirect()->route('user.add.money.index')->with(['error' => ['Your wallet is invalid!']]);
$this->file_store_location = "transaction";
$dy_validation_rules = $this->generateValidationRules($gateway->input_fields);
$validated = Validator::make($request->all(),$dy_validation_rules)->validate();
$get_values = $this->placeValueWithFields($gateway->input_fields,$validated);
$trx_id = generateTrxString("transactions","trx_id","AM",8);
// Make Transaction
DB::beginTransaction();
try{
$id = DB::table("transactions")->insertGetId([
'type' => PaymentGatewayConst::TYPEADDMONEY,
'trx_id' => $trx_id,
'user_id' => $wallet->user->id,
'user_wallet_id' => $wallet->id,
'payment_gateway_currency_id' => $gateway_currency->id,
'request_amount' => $amount->requested_amount,
'fixed_charge' => $amount->fixed_charge,
'percent_charge' => $amount->percent_charge,
'total_charge' => $amount->total_charge,
'total_payable' => $amount->total_amount,
'request_currency' => get_default_currency_code(),
'available_balance' => $wallet->balance,
'payment_currency' => $gateway_currency->currency_code,
'remark' => PaymentGatewayConst::MANUAL,
'details' => json_encode(['input_values' => $get_values]),
'attribute' => PaymentGatewayConst::RECEIVED,
'status' => PaymentGatewayConst::STATUSPENDING,
'created_at' => now(),
]);
$basic_settings = BasicSettings::first();
if($basic_settings->email_notification == true){
try{
Notification::route('mail',auth()->user()->email)->notify(new AddMoneyNotification($id));
}catch(Exception $e){}
}
$transaction = Transaction::with(['payment_gateway'])->where('trx_id',$trx_id)->first();
UserNotification::create([
'user_id' => auth()->user()->id,
'transaction_id' => $id,
'details' => [
'title' => 'Add Money using ' . $transaction->payment_gateway->name,
'receiver' => "",
'amount' => get_amount($transaction->request_amount),
'currency' => $transaction->request_currency,
'message' => "Successfully Received."
],
]);
DB::table("temporary_datas")->where("identifier",$tempDataValidate['identifier'])->delete();
DB::commit();
}catch(Exception $e) {
DB::rollBack();
return Response::error(['Something went wrong! Please try again.']);
}
return Response::success(['Payment successful, please go back your app'],[],200);
}
}
Before you begin integrating the Kueue Pay Developer API, make sure you have: