Laravel 6 Paypal Subscription srmklive/paypal issue - php

I added srmklive/paypal package, I want to make paypal subscription. but it gives me this error message:
ErrorException
Undefined index: paypal_link
I am using laravel 6, and srmklive/paypal
Anyone can help me please to solve this issue ?
.env file
PAYPAL_MODE=sandbox
PAYPAL_SANDBOX_API_USERNAME=sb-ig0ex880582_api1.business.example.com
PAYPAL_SANDBOX_API_PASSWORD=3PZ2E986EZWQN2PN
PAYPAL_SANDBOX_API_SECRET=AZ2CBQPbtotiGlFrm1tAtmH-bBO3AfpRNGWDT6e68-yh69V.BeCgl7W6
PAYPAL_CURRENCY=USD
PAYPAL_SANDBOX_API_CERTIFICATE=
PaypalController.php file
public function payment(Request $request)
{
$data = [];
$data['items'] = [['name' => "Monthly Subscription", 'price' => 10, 'qty' => 1,],];
$data['subscription_desc'] = "Monthly Subscription #1";
$data['invoice_id'] = 1;
$data['invoice_description'] = "Monthly Subscription #1";
$data['return_url'] = url('/paypal/ec-checkout-success?mode=recurring');
$data['cancel_url'] = url('/');
$total = 0;
foreach ($data['items'] as $item) {
$total += $item['price'] * $item['qty'];
}
$data['total'] = $total;
//give a discount of 10% of the order amount
$data['shipping_discount'] = round((10 / 100) * $total, 2);
$provider = new ExpressCheckout;
// Use the following line when creating recurring payment profiles (subscriptions)
$response = $provider->setExpressCheckout($data);
$response = $provider->setExpressCheckout($data, true);
// The $token is the value returned from SetExpressCheckout API call
$startdate = Carbon::now()->toAtomString();
$profile_desc = !empty($data['subscription_desc']) ? $data['subscription_desc'] :
$data['invoice_description'];
$data = [
'PROFILESTARTDATE' => $startdate,
'DESC' => $profile_desc,
'BILLINGPERIOD' => 'Month', // Can be 'Day', 'Week', 'SemiMonth', 'Month', 'Year'
'BILLINGFREQUENCY' => 1, //
'AMT' => 10, // Billing amount for each billing cycle
'CURRENCYCODE' => 'USD', // Currency code
'TRIALBILLINGPERIOD' => 'Day',
'TRIALBILLINGFREQUENCY' => 10, // (Optional) set 12 for monthly, 52 for yearly
'TRIALTOTALBILLINGCYCLES' => 1, // (Optional) Change it accordingly
'TRIALAMT' => 0, // (Optional) Change it accordingly
];
$response = $provider->createRecurringPaymentsProfile($data, $response['TOKEN']);
// This will redirect user to PayPal
return redirect($response['paypal_link']);
}

Related

How can i check all selected value quantity?

Can anyone help me? how can i check all the product selected on the select or in the option? i'm using codeigniter 3 and i want to check if there was an available stock or none but i'm new and don't know how to do it i wish someone can help me. first it was working if i select a product with 0 quantity it will not process but if i select a first product with a quantity on hand greater than 0 and selected the second one with empty qty it will still process because it only check the stocks of the first product. how can i check all the qty selected in my select option?
my model:
public function create()
{
$user_id = $this->session->userdata('id');
// get store id from user id
$user_data = $this->model_users->getUserData($user_id);
$bill_no = 'BUBBLE-'.strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 4));
$data = array(
'bill_no' => $bill_no,
'date_time' => strtotime(date('Y-m-d h:i:s a')),
'gross_amount' => $this->input->post('gross_amount_value'),
'service_charge_rate' => $this->input->post('service_charge_rate'),
'service_charge_amount' => ($this->input->post('service_charge_value') > 0) ?$this->input->post('service_charge_value'):0,
'vat_charge_rate' => $this->input->post('vat_charge_rate'),
'vat_charge_amount' => ($this->input->post('vat_charge_value') > 0) ? $this->input->post('vat_charge_value') : 0,
'net_amount' => $this->input->post('net_amount_value'),
'discount' => $this->input->post('discount_amount_value'),
'paid_status' => 3,
'user_id' => $user_id,
'table_id' => $this->input->post('table_name'),
'discount_id' => json_encode($this->input->post('discount')),
'discount_percent' => $this->input->post('discount_perct_value'),
'datetoday' => date('Y-m-d h:i:s a'),
'payment_id' => json_encode($this->input->post('payment')),
);
$count_product = count($this->input->post('product'));
for($x = 0; $x < $count_product; $x++) {
$prodid = $this->input->post('product')[$x];
$prod_quan = $this->model_products->getProductData($prodid);
$inputQuantity = (int)$this->input->post('qty')[$x];
$check = $this->model_orders->check_stock($prodid, $inputQuantity);
if($check == TRUE)
{
$insert = $this->db->insert('orders', $data);
$order_id = $this->db->insert_id();
$count_product = count($this->input->post('product'));
for($x = 0; $x < $count_product; $x++) {
$items = array(
'order_id' => $order_id,
'product_id' => $this->input->post('product')[$x],
'qty' => $this->input->post('qty')[$x],
'rate' => $this->input->post('rate_value')[$x],
'amount' => $this->input->post('amount_value')[$x],
);
$this->db->insert('order_items', $items);
}
$this->load->model('model_tables');
$this->model_tables->update($this->input->post('table_name'), array('available' => 2));
return ($order_id) ? $order_id : false;
}
else
{
return false;
}
}
}
public function check_stock($productId, $inputQuantity)
{
$product = $this->db->get_where('products', ['id' => $productId])->row();
if(isset($product))
{
if($product->qty < $inputQuantity)
{
$this->session->set_flashdata('error','No more stock on some selected items');
return false;
}
else
{
return true;
}
}
}
and my select in view is something like this:
<select class="form-control select_group update-select" data-row-id="row_1" id="product_1" name="product[]" style="width:100%;" onchange="getProductData(1)" required>
<option disabled selected hidden value=''>--Select Products--</option>
<?php foreach ($products as $k => $v): ?>
<option value="<?php echo $v['id'] ?>"><?php echo $v['name'] ?></option>
<?php endforeach ?>
</select>
Easiest solution is to return false as soon as you find a product that is out of stock, something like the following:
Loop through the selected products and for each one check the stock. If you encounter a product that is out of stock, return false.
If all products are in stock, create the order, then loop through the selected products again and add those to the order in the database.
I haven't tested the code below, so there may be errors. I only changed the if($check == TRUE) part and some curly braces.
public function create()
{
$user_id = $this->session->userdata('id');
// get store id from user id
$user_data = $this->model_users->getUserData($user_id);
$bill_no = 'BUBBLE-'.strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 4));
$data = array(
'bill_no' => $bill_no,
'date_time' => strtotime(date('Y-m-d h:i:s a')),
'gross_amount' => $this->input->post('gross_amount_value'),
'service_charge_rate' => $this->input->post('service_charge_rate'),
'service_charge_amount' => ($this->input->post('service_charge_value') > 0) ?$this->input->post('service_charge_value'):0,
'vat_charge_rate' => $this->input->post('vat_charge_rate'),
'vat_charge_amount' => ($this->input->post('vat_charge_value') > 0) ? $this->input->post('vat_charge_value') : 0,
'net_amount' => $this->input->post('net_amount_value'),
'discount' => $this->input->post('discount_amount_value'),
'paid_status' => 3,
'user_id' => $user_id,
'table_id' => $this->input->post('table_name'),
'discount_id' => json_encode($this->input->post('discount')),
'discount_percent' => $this->input->post('discount_perct_value'),
'datetoday' => date('Y-m-d h:i:s a'),
'payment_id' => json_encode($this->input->post('payment')),
);
$count_product = count($this->input->post('product'));
for($x = 0; $x < $count_product; $x++) {
$prodid = $this->input->post('product')[$x];
$prod_quan = $this->model_products->getProductData($prodid);
$inputQuantity = (int)$this->input->post('qty')[$x];
$check = $this->model_orders->check_stock($prodid, $inputQuantity);
if($check != TRUE)
{
return false;
}
}
$insert = $this->db->insert('orders', $data);
$order_id = $this->db->insert_id();
$count_product = count($this->input->post('product'));
for($x = 0; $x < $count_product; $x++) {
$items = array(
'order_id' => $order_id,
'product_id' => $this->input->post('product')[$x],
'qty' => $this->input->post('qty')[$x],
'rate' => $this->input->post('rate_value')[$x],
'amount' => $this->input->post('amount_value')[$x],
);
$this->db->insert('order_items', $items);
}
$this->load->model('model_tables');
$this->model_tables->update($this->input->post('table_name'), array('available' => 2));
return ($order_id) ? $order_id : false;
}

how to retrieve the model id after successful payment in paypal - laravel

i am using express checkout with this package :
https://github.com/srmklive/laravel-paypal
exactly as example repository one change i made is that the price and item info was hard coded but i passed a model to that function called event because i want to sell events . so it looks like below now :
protected function getCheckoutData($recurring = false,$event = null)
{
$data = [];
$order_id = Invoice::all()->count() + 1;
if ($recurring === true) {
$data['items'] = [
[
'name' => 'Monthly Subscription '.config('paypal.invoice_prefix').' #'.$order_id,
'price' => 12222,
'qty' => 1,
],
];
$data['return_url'] = url('/paypal/ec-checkout-success?mode=recurring');
$data['subscription_desc'] = 'Monthly Subscription '.config('paypal.invoice_prefix').' #'.$order_id;
} else {
$data['items'] = [
[
'name' => $event->title,
'price' => $event->price,
'qty' => 1,
'event_id' => $event->id,
]
];
$data['return_url'] = url('/paypal/ec-checkout-success');
}
$data['invoice_id'] = config('paypal.invoice_prefix').'_'.$order_id;
$data['invoice_description'] = $event->title;
$data['cancel_url'] = url('/');
$total = 0;
foreach ($data['items'] as $item) {
$total += $item['price'] * $item['qty'];
}
$data['total'] = $total;
return $data;
}
now on getExpressCheckoutSuccess function after payment it calls the getCheckoutData again but this time there is no model event on that like below :
public function getExpressCheckoutSuccess(Request $request)
{
$recurring = ($request->get('mode') === 'recurring') ? true : false;
$token = $request->get('token');
$PayerID = $request->get('PayerID');
$cart = $this->getCheckoutData($recurring);
// Verify Express Checkout Token
$response = $this->provider->getExpressCheckoutDetails($token);
.
.
.
so my question is that how can pass the paypal my event id and it returns that to me again or do some thing to detect the event
and pass it to getCheckoutData and verify the payment . thanks in advance

laravel condition add amount nested

Code: I have a condition on this, but it's not clear for me
$check_account1 = false;
$check_account2 = false;
$user1_amount = 100;
$user2_amount = 100;
if ($account->type == "A") {
$check_account1 = true;
$amount = 100;
if ($check_account1) {
$amount = $user1_amount;
} else {
$amount += $user1_amount;
}
} elseif ($account->type == "B") {
$amount = $user2_amount;
}
$insert = new Amount;
$insert->user_id = $account->id;
$insert->amount = $amount;
$insert->save();
EDIT: I have a users which has a rank of Basic, Junior, Premium, Advanced, Senior, which is every user has it's corresponding amount based on their rank.
If someone is not present or not available, the amount based on his rank will go to the rank next to him, if the user is present he will receive the amount based on his rank. So if Basic, Junior, Premium and Advanced is not present, the sum of their corresponding amount will go to Senior
Present meaning it's in the database table, if the loop doesn't get a user with that rank, I call it absent.
This is how it goes:
Basic - 10
Junior - 20
Premium - 30
Advanced - 40
Senior - 50
$amount_to_transfer = 0;
$amount_to_receive = 0;
foreach($users as $user){
if($user->rank == 'Basic'){
// basic is present, add 10 to himself, if not 10 will go to the next rank which is Junior
$amount->amount = 10;
$amount->save();
}
else{
//
}
}
Because you want to loop through your users, and transfer amount from those that are not present to the first next user that is present, here is the code that should accomplish that task:
$amount_to_transfer = 0;
$amount_to_receive = 100;
foreach($users as $user){
if($user->present){
$user->amount += $amount_to_receive + $amount_to_transfer;
$amount_to_transfer = 0;
// If you want to save the user here
// $user->save();
}
else{
$amount_to_transfer += $amount_to_receive;
}
}
I assumed that your user model has present property which tells if the user is present or not (boolean value) and that the amount is stored in amount field. You can adapt this condition based on your properties in your User model.
All in all, you just need to define a transfer amount, which starts off as zero and add it alongside with receiving amount every time the user is present. If user is not present, just increment the amount to transfer so it can be added to first next present user.
Adapted
Here is the adapted code, I used dummy collections and ranks. Please adapt this to your settings. In this example there is no Advanced rank, so senior will get 50 + 40 amount.
$ranks = collect([
(object) ['name' => 'Basic', 'amount' => 10],
(object) ['name' => 'Junior', 'amount' => 20],
(object) ['name' => 'Premium', 'amount' => 30],
(object) ['name' => 'Advanced', 'amount' => 40],
(object) ['name' => 'Senior', 'amount' => 50],
]);
$users = collect([
(object) ['rank' => 'Basic', 'amount' => 0],
(object) ['rank' => 'Junior', 'amount' => 0],
(object) ['rank' => 'Premium', 'amount' => 0],
(object) ['rank' => 'Senior', 'amount' => 0],
(object) ['rank' => 'Basic', 'amount' => 0],
]);
$amount_to_transfer = 0;
$available_ranks = $users->pluck('rank');
foreach($ranks as $rank){
if(!in_array($rank->name, $available_ranks->toArray()))
{
$amount_to_transfer += $rank->amount;
}
else{
$usersOfThisRank = $users->filter(function($usr, $key) use($rank){
return $usr->rank == $rank->name;
});
$usersOfThisRank->map(function($usr, $key) use($rank, $amount_to_transfer){
$usr->amount += $rank->amount + $amount_to_transfer;
// $usr->save();
});
$amount_to_transfer = 0;
}
}

How to increase the performance of this function

How to increase the performance of following function in phalcon framework. There are thousands of records in the table. I tried different ways, but I am stuck the point. How can I increase the efficiency and reduce the execution time. Following are two methods:
public function currentmonthAction()
{
$payload = $this->request->getJsonRawBody();
$this->setDB();
$ticketsmodel = new Tickets();
$fromcitycondition = "";
if( isset($payload->city->id) )
{
$fromcitycondition = "and fromcity='{$payload->city->id}'";
}
try{
$date = new \Datetime($payload->date);
$year = $date->format('Y');
$month = $date->format('m');
$month = '08';
$daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
/* result for all cities passenger */
$result = array();
// get all cities permutations
$tmpcitiesdata = array();
$rawresultset = Tickets::find (
array(
'columns' => 'fromcity,tocity',
'conditions' => "departure between '{$year}-{$month}-01' and '{$year}-{$month}-$daysInMonth' and tickettype in (1) ". $fromcitycondition,
'group' => 'fromcity,tocity'
));
foreach ($rawresultset as $rawresult) {
$tmpcitiesdata[$rawresult->fromcity.'-'.$rawresult->tocity]['fromcity'] = $rawresult->fromcity;
$tmpcitiesdata[$rawresult->fromcity.'-'.$rawresult->tocity]['tocity'] = $rawresult->tocity;
}
//var_dump($rawresultset);
// get tickets sold based on cities combinations
$total = 0;
foreach ($tmpcitiesdata as $tmpcities) {
$rawresultset = Tickets::find (
array(
'columns' => 'customer',
'conditions' => "departure between '{$year}-{$month}-01' and '{$year}-{$month}-$daysInMonth' and tickettype in (1) and fromcity=". $tmpcities['fromcity']." and tocity=".$tmpcities['tocity'],
'group' => 'customer'
));
$totalsoldRaw = count($rawresultset);
// get ticket cancellations
$rawresultset = Tickets::find (
array(
'conditions' => "departure between '{$year}-{$month}-01' and '{$year}-{$month}-$daysInMonth' and tickettype in (3) and fromcity=". $tmpcities['fromcity']." and tocity=".$tmpcities['tocity']
));
//make sure cancellations are tickets cancellations not booking cancellations
foreach($rawresultset as $rawresult)
{
$resultNumber = Tickets::find("departure='$rawresult->departure' and seatno={$rawresult->seatno} and id < {$rawresult->id} and tickettype = 1" );
if( count($resultNumber) > 0 ){
$totalsoldRaw = $totalsoldRaw-1;
}
}
$total += $totalsoldRaw;
array_push($result, array('total' => $totalsoldRaw, 'fromcity' => Cities::findFirstById($tmpcities['fromcity'])->name, 'tocity' => Cities::findFirstById($tmpcities['tocity'])->name));
}
//sort result based on counts
arsort($result);
//cut result to max 6 cities
$result = array_slice($result, 0, 6);
$this->response->setContentType('application/json')
->setJsonContent(
array( 'totaltickets' => $total, "allcities" => $result )
);
$this->response->send();
return;
}
catch(\PDOException $e)
{
$this->response->setStatusCode('422','Invalid Payload');
$this->response->setContentType('application/json')
->setJsonContent(array(
'flash' => array(
'class' => 'danger',
'message' => $e->getMessage()
)
));
$this->response->send();
return;
}
}
Use count instead of count(result of find). Also are you sure in // get ticket cancellations you don't need group ? Then you can select all tickets for customers in 1,3 tickettype and then filter resultset.
Also can't your first $rawresulset can't be:
$rawresultset = Tickets::find (
array(
'columns' => 'customer,fromcity,tocity,tickettype ',
'conditions' => "departure between '{$year}-{$month}-01' and '{$year}-{$month}-$daysInMonth' and tickettype in (1,3)".$fromcitycondition
'group' => 'customer,fromcity,tocity'
));
?
$ticketCanccelations = $rawresultset->filter(function($row){
if($row->tickettype == 3) {
return $row;
}
});
$resultNumber = Tickets::count("departure='$rawresult->departure' and seatno={$rawresult->seatno} and id < {$rawresult->id} and tickettype = 1" );

PayPal does not show order summary-Omnipay

I have a function for Paypal redirection for that I pass some values in params..
It only pass the Description field doesn't shows the amount to be paid,and rest of my order summaries..
Here is my function
public function postPayment()
{
$hot_id = \Session::get('hot_id');
$user_id = \Session::get('uid');
$check_in = \Session::get('check_in');
$check_out = \Session::get('check_out');
$mem_count = \Session::get('mem_count');
$rm_no = \Session::get('rm_no');
$check_in = strtotime($check_in);
$check_in = date('Y-m-d',$check_in);
$check_out = strtotime($check_out);
$check_out = date('Y-m-d',$check_out);
$datediff = strtotime($check_out) - strtotime($check_in);
$diff = floor($datediff/(86400));
$room_prize = \DB::select("SELECT `room_prize` FROM `abserve_hotel_rooms` WHERE `room_id` = ".$_POST['room_id']);
$arr = array();
foreach ($room_prize as $key => $value) {
$arr[]= (get_object_vars($value));
}
$room_prize = array();
foreach ($arr as $key => $value) {
$room_prize[]=($value['room_prize']);
}
if($rm_no == 1)
{
$room_prize = (int) $room_prize[0] * (int) $diff;
}
else
{
$room_prize = (int) $room_prize[0] * (int) $diff * (int) $rm_no;
}
$room_prize = number_format((float)$room_prize, 2, '.', '');
$room_id = $_POST['room_id'];
$today = new DateTime();
$created_at = $today->format('Y-m-d');
$values = array('user_id' => $user_id,'hotel_id' => $hot_id,'room_id'=>$room_id,'room_prize'=>$room_prize,'check_in'=>$check_in,'check_out'=>$check_out,'created_at'=>$created_at);
\DB::table('abserve_orders')->insert($values);
$order_id = DB::select("SELECT `id` FROM `abserve_orders` WHERE `room_id` = ".$_POST['room_id']." AND `user_id` = ".$user_id);
$arr = array();
foreach ($order_id as $key => $value) {
$arr[]= (get_object_vars($value));
}
$order_id = array();
foreach ($arr as $key => $value) {
$order_id[]=($value['id']);
}
$order_id = $order_id[0];
$params = array(
'cancelUrl' => url().'/cancel_order',
'returnUrl' => url().'/payment_success',
'name' => 'new order',
'description' => 'description1',
'amount' => $room_prize,
'currency' => 'USD',
'hot_id' => $hot_id,
'room_id' => $room_id,
'user_id' => $user_id,
'check_in' => $check_in,
'check_out' => $check_out,
'order_id' => $order_id,
'nights' => $diff,
);
// print_r($params);exit;
\Session::put('params', $params);
\Session::save();
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername('googley555_api1.yahoo.com');
$gateway->setPassword('3EQ6S6PB68A52JKZ');
$gateway->setSignature('AFcWxV21C7fd0v3bYYYRCpSSRl31AHaEiWOLAf5jQQ3-A9hLlhypSz9h');
$gateway->setTestMode(true);
$response = $gateway->purchase($params)->send();
if ($response->isSuccessful()) {
// payment was successful: update database
print_r($response);
} elseif ($response->isRedirect()) {
// redirect to offsite payment gateway
$response->redirect();
} else {
// payment failed: display message to customer
echo $response->getMessage();
}
}
I don't know what are missing in it..
Someone please help me..
You can't pass in arbitrary parameters such as hot_id, room_id, etc to PayPal (or omnipay) because it won't know what to do with them. PayPal is only intended to take certain parameters and the ones that PayPal does not take are ignored by Omnipay.
You may have to provide all of these extra parameters as part of the description parameter, which PayPal does understand.
Ideally these should be displayed by your application in some kind of useful format to the user before redirecting the user to the PayPal checkout page.

Categories