omnipay/Braintree find customer not working - laravel-5

i am working on laravel api, integrated omnipay/braintree, i have successfully created my customer, what i need to get customer data through this,
$mycustomer = $omnipay_gateway->findCustomer(5)->send();
but it giving me bad response like,
<pre>Omnipay\Braintree\Message\CustomerResponse Object
(
[request:protected] => Omnipay\Braintree\Message\FindCustomerRequest Object
(
[braintree:protected] => Braintree\Gateway Object
(
[config] => Braintree\Configuration Object
its a huge chunck of data which i am not pasting here, how i get my customer details through this type of data, and it shows in this format, why not in proper json or some other format?
Note:
Not only findCustomer , all functions give same sort of response,
how we can traverse it.

Call $mycustomer = $omnipay_gateway->findCustomer(5)->send()->getData(); please

The simple answer for future readers is something like
// Process response
if ($response->isSuccessful()) {
// Payment was successful
// $url = $response->getRedirectUrl();
print_r($response->getData());
} elseif ($response->isRedirect()) {
// Redirect to offsite payment gateway
$response->redirect();
} else {
// Payment failed
echo $response->getMessage();
}

Related

Calling at the users at once and disconnect other calls if any one of the user receives the call

I want to have the round robin call functionality using twilio.
Let's say. I have 100 users and their phone numbers.
I want to call of them at the same time.
Then whoever the first person receives the call I will connect that call to my sales department and immediately cut or disconnect a the other calls.
I known through twiML I could dial to my sales team and I also know I could check the in-progess event to check to see call is connected.
However I am stuck at calling all my users at the same time and disconnecting after the first user is connected to the call which is my first step.
i am making more updates as my scenario has been changed a little.
in this case i am first calling the user who has filled out my lead form. once the lead user receives the call then i am going to call 10 agents from my sales team but i want to track which agent has received the lead call and want to save the agent information into my database and cut the other calls.
in my countroller
<?php
namespace App\Http\Controllers;
use App\Listing;
use App\User;
use Illuminate\Http\Request;
use Twilio\Rest\Client;
use Twilio\TwiML\VoiceResponse;
use Twilio\Twiml;
class TwilioController extends Controller
{
public function leadCall(Request $request)
{
// Lead user
$lead = Lead::where('id', $request->lead_id)->first();
$country_code = "+1";
$visitor_phone = $country_code . $lead->details_phone;
$url = "https://www.samplewebsite.com/outbound?multi_call=true";
// Twilio Credentials
$AccountSid = 'xyz';
$AuthToken = 'xyz';
$twilio_number = "123";
$client = new Client($AccountSid, $AuthToken);
// Calling the lead visitor first
try {
$call = $client->account->calls->create($visitor_phone, $twilio_number,
array(
"url" => $url
)
);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
}
if($request->multi_call)
{
// Fetch 10 agents
$users = User::all()->take(10);
// Calling Twilio
$twiml = new VoiceResponse();
$twiml->say('Please hold, we are connecting your call to one of our agent.', array('voice' => 'alice'));
$dial = $twiml->dial();
foreach ($users as $user) {
if($user->phone && $user->live_call)
{
$dial->number($user->phone,
['statusCallbackEvent' => 'answered',
'statusCallback' => 'https://www.samplewebsite.com/outbound?agent_call=true',
'statusCallbackMethod' => 'GET']);
}
}
$response = response()->make($twiml, 200);
$response->header('Content-Type', 'text/xml');
return $response;
}
if($request->agent_call)
{
return "Call was made to: " . $request->to;
}
}
this is what i have done so far
and in routes file
Route::post('lead-call', 'TwilioController#leadCall')->name('leadCall');
Route::get('outbound', 'TwilioController#outboundMultiCall');
And TwiML resonse
<Response>
<Say voice="alice">Please hold, we are connecting your call to one of our agent.</Say>
<Dial>
<Number statusCallbackEvent="answered" statusCallback="https://www.samplewebsite.com/outbound?agent_call=true" statusCallbackMethod="GET">xxx-xxx-xxxx</Number>
<Number statusCallbackEvent="answered" statusCallback="https://www.samplewebsite.com/outbound?agent_call=true" statusCallbackMethod="GET">xxx-xxx-xxxx</Number>
<Number statusCallbackEvent="answered" statusCallback="https://www.samplewebsite.com/outbound?agent_call=true" statusCallbackMethod="GET">xxx-xxx-xxxx</Number>
</Dial>
</Response>
i am having two problems. when i add the get parameter like multi_call=true in my webhook then i get application error. so i can't make 10 dials to my agents.
plus i want to keep track of which user has attend the call first so i could maintain into my database and increase their rating.
Thank you
Twilio developer evangelist here.
First, I just need to warn you that by default Twilio accounts have a limit of creating 1 call per second, so with any code, you calls will still be placed sequentially.
If you can make one call then you can make more than one call at a time. You need to loop through the numbers you want to place calls to and make an API request for each call you want to create.
The next part is to cancel the other calls once one call connects. When you create the call, you will receive a response from the API with the call SID. Once your first call connects, you will receive a webhook to your application. The parameters will include the call SID. So, to cancel the other calls you need to take the list of call SIDs that you have created remove the one that connected and then make API calls to update the the other calls to the "completed" status, which will hang up the call.
Edit:
I see that you're connecting your outbound call first, then using TwiML to multi-dial. That should work, there's just a couple of things you've done wrong.
First, you are using multiple <Dial>s instead of multiple <Number>s within a <Dial> to make the multi calls. Try the following:
public function outboundMultiCall(Request $request)
{
if($request->multi_call)
{
// Fetch 10 agents
$users = User::all()->take(10);
// Calling Twilio
$twiml = new VoiceResponse();
$twiml->say('Please hold, we are connecting your call to one of our agent.', array('voice' => 'alice'));
$dial = $twiml->dial();
foreach ($users as $user) {
$dial->number($user->phone);
}
$response = response()->make($twiml, 200);
$response->header('Content-Type', 'text/xml');
return $response;
}
return 'Some other action based on GET URL paramter';
}
Second, Twilio webhooks are POST requests by default. So, you should either turn your route into a POST:
Route::post('outbound', 'TwilioController#outboundMultiCall');
Or, you can pass a method parameter when you create the call:
$call = $client->account->calls->create($visitor_phone, $twilio_number,
array(
"url" => $url,
"method" => "GET"
)
);
Finally, to record who answers the call you can use a statusCallback URL attribute on the <Number>. Twilio will send a webhook when the call transitions into a new state. The events are "initiated", "ringing", "answered" and "completed". The webhook will include all the normal voice call parameters so you can tell who the call was made to with the To parameter. There are extra parameters too, which might be useful.

What is the correct way to send validation errors back to a Vue component from a Laravel controller?

[I've revised this question a bit to consider another approach. I also apologize if this question seems unduly long. I suppose I'm a bit long-winded but I'm really just trying to be very clear.]
I am fairly new to Laravel, Vue and Vuetify but, after a lot of struggling, I've gotten my CRUD app to work with MySQL, at least as long as I pass my Controller good data. But now I'm struggling with the right way to do error handling.
I use Vuetify to do my front-end error checking and it seems to work very well. I've been able to write validations for every condition I could think of and display a meaningful error message where it is most appropriate to show it. I know I need to do the same validations in my Laravel controller back-end and writing good validations there seems pretty straightforward too. However, I'm having trouble figuring out how to communicate a back-end validation error to my Vue component.
My CRUD app is doing the classic To Do List. One of the fields on my input form for adding a new task is the due date for the new task and one of the edits that should be done on both the front-end and the back-end is that the due date can't be in the past. I've "accidentally" omitted that check on the front-end but have included it on the back-end to be sure the back-end will detect it when I choose a past date as my due date. My Laravel controller detects that as intended and my browser console shows this:
Clearly, the validations in the controller are working and they have correctly detected the problem with the due date. Now, my problem is how to get the relevant information to my Vue component and, when relevant (as it is in this case), how do I display it to my user?
All the examples I could find that were for Laravel apps that use Vue components had them using the then and catch blocks to deal with the Axios response and error information. The other option that occurs to me is to access the error bag generated by the Laravel controller but I can't find any information on how that could be done in a Vue component so it looks like I have to take the Axios approach....
I cannot figure out how to display the relevant information from the Response Payload in my Vue component in the catch block. In every example I've found, the Response is returned to the then block and the Error is returned to the catch block but when there is an error, the then block never gets executed in favour of the catch block. But when the catch block executes, it can't see the Response so it can't show me anything from the Response, like the validation message. All the searching I've done for answers has left me more confused than enlightened since many answers assume the validation errors are going back to a Laravel blade while others are for much older versions of Laravel. (I am running Laravel 8.x.)
I know that not all errors will be user errors. For example, the database could be down, making all access to the database impossible. I also need to note those situations. The user needs to be told something - perhaps "The database is down. Please try again later." - and the admins need to be advised that the database is down. I'm still trying to figure out the best way to do that but am leaning towards ErrorBoundary as the solution.
For the moment, I'll be delighted if someone can explain how to get the information I want from the Response payload when there is a user-fixable error. Some advice on how to handle situations where the error is NOT user-fixable would be even better.
Here is the relevant bit of my Insert logic in the Vue component:
/* We are creating a new item so determine the id for the new item. It should be
one greater than the highest id currently in the array. Every id of an existing
task should always be at least 1. */
console.log(this.name + ".save() - saving a new item");
var highestTaskID = 0; //must be one less than the lowest possible id value
for (let todo of this.todos) {
if (todo.id > highestTaskID) highestTaskID = todo.id;
}
var newTaskID = highestTaskID + 1; /* Calculate the ID of the new task. */
this.editedItem.id = newTaskID;
this.form.id = this.editedItem.id;
this.form.description = this.editedItem.description;
this.form.status = this.editedItem.status;
this.form.priority = this.editedItem.priority;
this.form.due = this.editedItem.due;
let data = new FormData();
data.append('id', this.form.id);
data.append('description', this.form.description);
data.append('status', this.form.status);
data.append('priority', this.form.priority);
data.append('due', this.form.due);
axios.post('/task', data)
.then((res) => {
console.log(this.name + ".save() - response from insert (then): " + res);
this.snackbarMessage = "Created new task";
this.showMessageSnackbar = true;
this.showTable = true; //start showing ToDo table again
this.form.reset();
this.getTasks();
})
.catch((error) => {
console.log(this.name + ".save() - response from insert (catch): " + res);
console.log(this.name + ".save() - error: " + error);
this.snackbarMessage = "Failed to create new task";
this.showMessageSnackbar = true;
this.showTable = true; //start showing ToDo table again
})
This is the store() method in my TaskController:
public function store(Request $request)
{
app('debugbar')->info('TaskController.store() started');
$today = date('Y-m-d');
$this->validate($request, [
'description' => ['required', 'min:5', 'max:191'],
'status' => ['required'],
'priority' => ['required'],
'due' => ['required', 'after-or-equal:' . Date('Y-m-d')]
],
[
'description.required' => 'You must provide a non-blank task description',
'description.min' => 'The task description must contain at least 5 characters',
'description.max' => 'The task description must not exceed 191 characters',
'status.required' => 'You must provide a task status',
'status.in' => 'You must choose a task status from: Pending or Completed',
'priority.required' => 'You must provide a task priority',
'priority.in' => 'You must choose a task priority from: Low, Medium or High',
'due' => 'You must provide a task due date',
'due.after_or_equal' => 'You must provide a due date greater than or equal to today'
]
);
app('debugbar')->info('TaskController.store() validations completed');
Task::create($request->all());
}
Should I be logging any and all errors I detect in the Controller itself, rather than in the Vue component? That might be a lot easier in some respects, although I still have to be able to detect which errors can be passed back to the user for them to handle and when I simply have to tell them to try later because the app isn't working fully yet.
First of all, I'd advise using axios' Response Interceptor which is essentially a callback that gets executed every time a request has been completed so you don't have to do error handling on each and every request.
Create a new file (for example axiosInstance.js)
const axiosInstance = axios.create({
baseURL: 'https://example.com/api',
});
axiosInstance.interceptors.response.use((response) => {
return response;
}, (error) => {
switch(error.response.status) {
case 422:
// Here you will be able to process Laravel Validation Errors.
// You can for example display an error message using your favorite library
console.log("Error Message: " + error.response.data.message);
console.log("Error Object: " + error.response.data.errors);
break;
}
return Promise.reject(error);
}
export default axiosInstance;
As you can see you can access your response by using error.response. This works for catch blocks in simple axios requests aswell.
axios.get('https://example.com/xyz').catch(e => {
console.log(e.response);
});
The above interceptor in my first code block will do special handling for all Laravel Validation Errors since those are returned using HTTP Status 422 (Unprocessable Entity) by default.
To use it, instead of doing axios.get() you can do:
import axiosInstance from './axiosInstance.js';
axiosInstance.get('https://example.com/xyz');
The logic you defined in the catch block of the interceptor will then be executed every time a request that was initiated using axiosInstance. You can also append .catch() again to the request to handle additional logic if a specific requests fails.
To handle additional error types, extend the interceptors switch conditional statement. For example, exceptions like "The database is not available" are returned with status code 500 by Laravel. Usually, a simple message is then available to display to the user by using error.response.data.message.
tl;dr
This is what you could do achieve what you are trying to do using your code:
axios.post('/task', data)
.then((res) => {
console.log(this.name + ".save() - response from insert (then): " + res);
this.snackbarMessage = "Created new task";
this.showMessageSnackbar = true;
this.showTable = true; //start showing ToDo table again
this.form.reset();
this.getTasks();
})
.catch((error) => {
console.log(this.name + ".save() - response from insert (catch): " + error.response);
// Given that your erroneous response contains 'message' (like laravel validation errors do):
console.log(this.name + ".save() - error: " + error.response.data.message);
this.snackbarMessage = "Failed to create new task";
this.showMessageSnackbar = true;
this.showTable = true; //start showing ToDo table again
})

laravel api without respond

I have a issue, after i eliminate cors policy on laravel i sending some json data to check respond. But nothing happens...
I sending request by axios using react.js, i sending json data collected from state.
and now i trying to collect that data by laravel, but that is hardest patch.
already try something like that:
$content='test';
return Response::$content;
or just echo 'test' but nothing comes...
My code is inside controller.
class testRequest extends Controller
{
public function show(Request $request)
{
//$data = $request->json()->all();
// $experience = $data->experience;
$content='test';
return Response::$content;
}
}
for now i expect to get respond like 'test' but after that i will need to send a link to file path for respond.
the Response::$content is just wrong... the :: operator is used to access static member functions or attributes of the Response class... you should do something like this:
return Response::json(['test' => $content]);
or
return response()->json(['test' => $content]);
in order to respond with a JSON document.

How to customize the CRUD response toaster message [admin-on-rest]

I want to add server response message in CRUD response toaster. For Example when we do an update, we will get 'Element updated' toaster message. Instead of it I want to show some dynamic (not static) server responded message.
This is only supported for error messages currently. If this is really important, please open a feature request and we'll consider it.
A slightly long winded way to do this. But definitely possible.
1) Write a custom restWrapper or RestClient
https://marmelab.com/admin-on-rest/RestClients.html
2) Handle the request and response from it like below.
function handleRequestAndResponse(url, options={}, showAlert={}) {
return fetchUtils.fetchJson(url, options)
.then((response) => {
const {headers, json} = response;
//admin on rest needs the {data} key
const data = {data: json}
if (headers.get('x-total-count')) {
data.total = parseInt(headers.get('x-total-count').split('/').pop(), 10)
}
// handle get_list responses
if (!isNaN(parseInt(headers.get('x-total-count'), 10))) {
return {data: json,
total: parseInt(headers.get('x-total-count').split('/').pop(), 10)}
} else {
return data
}
})
}
3) you now have a place in your code where you can intercept the data from the server. In above code you can define and shoot actions containing your data whenever you need. Create a reducer that takes the data from your action and populates a field in the state you can call it notification.
4) Use the redux-saga select method
How to get something from the state / store inside a redux-saga function?
You can now access the notification data from the store and show custom toaster messages to your heart's content :)

laravel api with vue 2 js not returning data - could 'localhost:8000' (or '127.0.0.1:8000') be the issue?

I am using the repo https://github.com/mschwarzmueller/laravel-ng2-vue/tree/03-vue-frontend so I have 100% confidence in the reliability of the code. I can post through the laravel api endpoint through the very simple Vue client, and also through Postman. Through Postman I can retrieve the table data array, but not so in the client app. In POSTMAN:
localhost:8000/api/quotes
works just fine.
IN THE vue 2 js CLIENT APP:
methods: {
onGetQuotes() {
axios.get('http://localhost:8000/api/quotes')
.then(
response => {
this.quotes = (response.data.quotes);
}
)
.catch(
error => console.log(error)
);
}
returns nothing. returning the response to Console.log returns nothing. The Network/XHR tab shows the table data rows, but I am not sure what that means.
I know for sure that this code works for others with their unique api endpoints, which I assume may not use localhost or '127:0.0.1:1080.
Edit: in response to request for more info
public function getQuotes()
{
$quotes = Quote::all();
$response = [$quotes];
return response()->json($response, 200);
}
and the relevant route:
Route::get('/quotes', [
'uses' => 'QuoteController#getQuotes'
]);
Just to confirm: I am using verified github repo code in which the ONLY change is my api endpoint addressas mentioned in the first line of the body of this question. . Note that the Laravel back end is also derived from a related repo in Max's fine tutorial. The running code can be seen at
So I really don't think this is a coding error- but is it a configuration error due to me using local host??
EDIT: It WAS a coding error in the laravel controller as shown below
The reason your code isn't working if because you haven't provided a key for your $quotes in your controller but you're looking for it in your vue file (response.data.quotes).
[$quotes] is essentially [0 => $quotes] so when the json response comes through it be 0: [...] not quotes: [...].
To get this to work you just need to change:
$response = [$quotes];
to:
$response = ['quotes' => $quotes];
Furthermore, just an FYI, you don't need to provide the 200 in response->json() as it's the default and you can just return an array and Laravel automatically return the correct json response e.g.:
public function getQuotes()
{
$quotes = \App\Models\Artist::all();
return compact('quotes'); //<-- This is just another way of writting ['quotes' => $quotes]
}
Obviously, you don't have to if you don't want to.
Hope this helps!

Resources