How to add a list using (api sendgrid) cakephp - api

I'm trying to make requests in external Web Services with Cake HttpSocket, I'm trying to create a new list I'm getting an error from api sendgrid
[body] => {"errors":[{"message":"request body is invalid"}]}
public function addemail() {
$HttpSocket = new HttpSocket();
$lista = array('name' => 'Teste');
$retorno = $HttpSocket->post('https://api.sendgrid.com/v3/contactdb/lists', $lista,
array(
'header' => array(
'Content-Type' => 'application/json',
'Authorization' => 'Bearer SG.XXXXXXXXX'
)
));
if ($retorno->isOk()) {
debug($retorno->body());
}
}
what is wrong? in the sendgrid documentation says that the body should be this way
{
"name": "listname"
}

You need to json encode the array like so:
$lista = json_encode(array('name' => 'Teste'));

Related

Lumen Google reCAPTCHA validation

I already seen some tuts and example about it and I have implemented it somehow.
Method in controller looks like this:
The logic used is just php and I would like to use more a lumen/laravel logic and not just simple vanilla php. Also I have tried and did not worked anhskohbo / no-captcha
public function create(Request $request)
{
try {
$this->validate($request, [
'reference' => 'required|string',
'first_name' => 'required|string|max:50',
'last_name' => 'required|string|max:50',
'birthdate' => 'required|before:today',
'gender' => 'required|string',
'email' => 'required|email|unique:candidates',
'g-recaptcha-response' => 'required',
]);
//Google recaptcha validation
if ($request->has('g-recaptcha-response')) {
$secretAPIkey = env("RECAPTCHA_KEY");
// reCAPTCHA response verification
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secretAPIkey.'&response='.$request->input('captcha-response'));
$response = json_decode($verifyResponse);
if ($response->success) {
//Form submission
//Saving data from request in candidates
$candidate = Candidate::create($request->except('cv_path'));
$response = array(
"status" => "alert-success",
"message" => "Your mail have been sent."
);
} else {
$response = array(
"status" => "alert-danger",
"message" => "Robot verification failed, please try again."
);
}
}
} catch(Exception $e) {
return response()->json($e->getMessage());
}
return response()->json(['id' => $candidate->id, $response]);
}
Okey. Google has an package for this:reCAPTCHA PHP client library
just: composer require google/recaptcha "^1.2"
and in your method inside controller:
$recaptcha = new \ReCaptcha\ReCaptcha(config('app.captcha.secret_key'));
$response = $recaptcha->verify($request->input('g-recaptcha-response'), $_SERVER['REMOTE_ADDR']);
if ($response->isSuccess()) {
//Your logic goes here
} else {
$errors = $response->getErrorCodes();
}
config('app.captcha.site_key') means that I got the key from from config/app.php and there from .env file.
If you have not config folder, you should create it, also create app.php file same as in laravel.

How to call an API using raw input using Guzzle

I have an API which is working well with Postman but upon trying to call it in code, I get errors. See below
In Postman
Below is how I am calling the API in code:
In Code
public function pay_bill(Request $request){
$client = new Client(); //GuzzleHttp\Client
$username = 'xxxx';
$password = 'xxx#2020*';
$credentials = base64_encode("$username:$password");
$transaction_id = intval($request->input('transaction_id'));
$amount = (int)$request->input('amount');
$bill_number = (int)$request->input('bill_number');
$return_url = $request->input('return_url');
$response = $client->post('https://gatewaytest.e.com:5000/gateway/initialize', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Basic ' . $credentials,
'X-API-KEY' => '7c4a8d09ca3762af61e59520943dc26494f8941b',
],
'form_params' => [
'transaction_id' => $transaction_id,
'total_amount' => $amount,
'bills' => ["bill_ref" => $bill_number, "amount" => $amount],
'return_url'=> $return_url
],
'verify' => true
]);
$transaction_data = $response->getBody();
return $transaction_data;
}
What am I doing wrong? How do I send body as raw like is done in postman? I imagine the problem could be due to using form_params
I finally found the solution as shown below:
'bills' => [["bill_ref" => $bill_number, "amount" => $amount]]

API returning 400 Bad Request response

I have built an API and an application that uses that API. Everything was working but now, for some reason, I get a 400 Bad Request response. I am not sure if I changed something in the code so I wanted to double check it was correct.
So my API call is this
$client = new GuzzleHttp\Client();
$jsonData = json_encode($data);
$req = $client->request('POST', 'https://someurl.com/api/v1/createProject', [
'body' => $jsonData,
'headers' => [
'Content-Type' => 'application/json',
'Content-Length' => strlen($jsonData),
]
]);
$output = $req->getBody()->getContents();
The API has a route set up correctly which uses post. The function it calls is correct, and I have changed it for testing to simply return
return response()->json(["Success", 200]);
When I test the API out within Postman, I can see that Success is returned. When I test the API within the other application I have built, I dont even see a POST request within the console, I am just displayed a Laravel error 400 Bad Request.
What could be the cause of this issue?
Thanks
Update
I have changed the request to this
$data= json_encode($data);
$req = $client->post('https://someurl.com/api/v1/createProject', [
'body' => $data
]);
If I output $data after it has been encoded, I get something like this
{
"projectName":"New Project",
"clientName":"Test Client",
}
Within the controller function of the API that is being called, I simply do
return response()->json(['name' => $request->input('clientName')]);
The 400 error has now gone, but I now get null returned to me
{#326 ▼
+"name": null
}
Request is being injected into the function as it should be. Should I be returning the data in a different way?
Thanks
Probably you did $ composer update and Guzzle updated.
So if you are using newest Guzzle (guzzlehttp/guzzle (6.2.2)) you do POST request:
$client = new GuzzleHttp\Client();
$data = ['name' => 'Agent Smith'];
$response = $client->post('http://example.dev/neo', [
'json' => $data
]);
You do not need to specify headers.
To read response you do following:
$json_response = json_decode($response->getBody());
My full example (in routes file web.php routes.php)
Route::get('smith', function () {
$client = new GuzzleHttp\Client();
$data = ['name' => 'Agent Smith'];
$response = $client->post('http://example.dev/neo', [
'json' => $data,
]);
$code = $response->getStatusCode();
$result = json_decode($response->getBody());
dd($code, $result);
});
Route::post('neo', function (\Illuminate\Http\Request $request) {
return response()->json(['name' => $request->input('name')]);
});
or you could use following (shortened), but code above is "shorter"
$json_data = json_encode(['name' => 'Agent Smith']);
$response = $client->post('http://example.dev/neo', [
'body' => $json_data,
'headers' => [
'Content-Type' => 'application/json',
'Content-Length' => strlen($json_data),
]
]);
note: If you are running PHP5.6, change always_populate_raw_post_data to -1 (or uncomment the line) in php.ini and restart your server. Read more here.
In my case I was using public IP address in BASE_URL while I should have been using the private IP. From mac you can get your IP by going into system preferences -> network.
This is with Android + Laravel (API)

How can i use post request in pecl_http library

hotelbeds api
The api required to use post request with some fields, but i don't know where are the fields will be added!! ( in GET request i add the fields in the url like any request )
the api code
`
$apiKey = "8z8a7tupn5hubhjxqh8ubuz7";
$sharedSecret = "jsSJq2msbU";
$signature = hash("sha256", $apiKey.$sharedSecret.time());
$endpoint = "https://api.test.hotelbeds.com/activity-api/3.0/activities";
$request = new \http\Client\Request("POST",
$endpoint,
[ "Api-Key" => $apiKey,
"X-Signature" => $signature,
"Accept" => "application/json" ,
]);
$client = new \http\Client;
$client->enqueue($request)->send();
$response = $client->getResponse();
echo "<pre>";
print_r($response->getBody());
echo "</pre>";
the api said
The available filters for the search is listed below.
It contains an array of filter with the following structure:
[{"searchFilterItems": [{"type": "destination", "value": "BCN"}]}]
The Object “searchFilterItems” contains the following attributes: type > and value.
The following examples illustrate the different types and values for > each filter:
Country
{"type": "country", "value": "PT"}
I had the same issue, took me a little while to figure it out. Turns out you need to use the Body class to represent the post data.
$msg = new http\Message\Body();
$msg->addForm([
'field1' => 'value',
'field2' => 'value2'
]);
$headers = null;
$request = new http\Client\Request('POST', 'https://example.com', $headers, $msg);
$client = new http\Client();
$client->enqueue($request);
$client->send();
$response = $client->getResponse();
There are some more methods available in the Message and Body class for including files, etc.
Try this way
$request = new http\Client\Request;
$body = new http\Message\Body;
$body->append('{Your JSON}');
$request->setRequestUrl('https://api.hotelbeds.com/hotel-api/1.0 hotels');
$request->setRequestMethod('POST');
$request->setBody($body);
$request->setHeaders(array(
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'Api-Key' => $owapiKey,
'X-Signature' => $signature,
//'Accept-Encoding' => 'Gzip', //Deflate
'cache-control' => 'no-cache'
));
try {
$client = new http\Client;
$client->enqueue($request)->send();
$response = $client->getResponse();
if ($response->getResponseCode() != 200) {
echo("HTTP CONNECT FAILURE: -> ".
$response->getTransferInfo("effective_url").
$response->getInfo().$response->getResponseCode() );
} else {
$res=$response->getBody()->toString();
}
} catch (Exception $ex) { echo("Error while sending request, reason: %s\n".$ex->getMessage()); }

Get the CSRF token in test

I'm writing functional test and i need to make ajax post request. "The CSRF token is invalid. Please try to resubmit the form". How can i get the token in my functional test ?
$crawler = $this->client->request(
'POST',
$url,
array(
'element_add' => array(
'_token' => '????',
'name' => 'bla',
)
),
array(),
array('HTTP_X-Requested-With' => 'XMLHttpRequest')
);
CSRF token generator is normal symfony 2 service. You can get service and generate token yourself. For example:
$csrfToken = $client->getContainer()->get('form.csrf_provider')->generateCsrfToken('registration');
$crawler = $client->request('POST', '/ajax/register', array(
'fos_user_registration_form' => array(
'_token' => $csrfToken,
'username' => 'samplelogin',
'email' => 'sample#fake.pl',
'plainPassword' => array(
'first' => 'somepass',
'second' => 'somepass',
),
'name' => 'sampleuser',
'type' => 'DSWP',
),
));
The generateCsrfToken gets one important parameter intention which should be the same in the test and in the form otherwise it fails.
After a long search (i've found nothing in doc and on the net about how to retrieve csrf token) i found a way:
$extract = $this->crawler->filter('input[name="element_add[_token]"]')
->extract(array('value'));
$csrf_token = $extract[0];
Extract the token from response before make the request.
In symfony 3, in your WebTestCase, you need to get the CSRF token:
$csrfToken = $client->getContainer()->get('security.csrf.token_manager')->getToken($csrfTokenId);
To get the $csrfTokenId, the best way would be to force it in the options of your FormType ():
class TaskType extends AbstractType
{
// ...
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'csrf_token_id' => 'task_item',
));
}
// ...
}
So in this case: $csrfTokenId = "task_item";. Or you you can try to use the default value, that would be the name of your form.
Then use it as a post parameter:
$client->request(
'POST',
'/url',
[
'formName' => [
'field' => 'value',
'field2' => 'value2',
'_token' => $csrfToken
]
]
);
Just in case someone stumble on this, in symfony 5 you get the token this way:
$client->getContainer()->get('security.csrf.token_manager')->getToken('token-id')->getValue();
where 'token-id' is the id that you used in the configureOptions method in your form type, which would look something like this:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
"data_class" => Foo::class,
"csrf_protection" => true,
"csrf_field_name" => "field_name", //form field name where token will be placed. If left empty, this will default to _token
"csrf_token_id" => "token-id", //This is the token id you must use to get the token value in your test
]);
}
Then you just put the token in the request as a normal field.