I use Guzzle for calling an API (Fitnet). Everything is ok with GET request, but i've a problem with a POST request. Looks like no data is being sent to the API
My code is :
$contract = array("companyId" => 1,
"companyName"=> "",
"contractCreator" => "",
"contractCurrency"=> "",
"deliveryAmount"=> 12346,
"title"=> "blabla7",
"orderNumber"=> "numéro de commande",
"upperLimit"=> "",
"beginDate"=> "10/10/2019",
"billingDate"=> "10/10/2021",
"endDate"=> "10/10/2021",
"businessUnit"=> 0,
"businessUnitName"=> "",
"customerId"=> 48,
"billingMode"=> 2,
"billingPlanning"=> 0,
"billingPlanningName"=> "",
"profitCenter"=> "",
"status"=> 1,
"statusName"=> "",
"description"=> "",
"billableExpenses"=> true,
"contractCategoryDesignation"=> "",
"contractCategoryId"=> 2);
$res = $client->post('https://myurl.fitnetmanager.com/FitnetManager/rest/contracts/create', [
'headers' => ['Content-type' => 'application/json'],
'auth' => ['myemail', 'mypassword'],
'json' => [ 'Contract' => json_encode($contract) ]
]);
Can you help me ?
Thanks in advance,
F.
It works with :
$res = $client->post('https://myurl.fitnetmanager.com/FitnetManager/rest/contracts/create', [
'auth' => ['myemail', 'mypassword'],
'json' => $contract
]);
Thank you to #formvega :-)
Guzzle will encode the data into JSON for you, you should not encode it beforehand.
$res = $client->post('https://myurl.fitnetmanager.com/FitnetManager/rest/contracts/create', [
'auth' => ['myemail', 'mypassword'],
'json' => $contract
]);
You also don't need to specify the content-type header.
Related
I have this function in my controller:
public function store(Request $request)
{
$client = new Client();
$headers = [
'Authorization' => $token,
'Content-Type' => 'application/json'
];
$body = '{
"DocNo": 1167722,
"AOQty": 0,
"TL": [
{
"Key": 11678,
"Code": "Screw Hex",
"Detail": true,
"DTL": []
}
]
}';
$request = new Psr7Request('POST', 'http://example.com/api/Order/', $headers, $body);
$res = $client->sendAsync($request)->wait();
echo $res->getBody();
}
that will store the data to the external API
but i want to POST the data from a form
when i work with normal routing (not API) i usually do this:
'Key' => $request->Key,
how can i achieve the above with guzzle?
currently when i submit the form from the view it will submit the above function (store) as static data, how can i submit the data from the form?
UPDATE:
When i use Http as showing below:
$store = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => $token,
])->post('http://example.com/api/Order/', [
'DocNo' => "SO-000284",
'AOQty' => 0.0,
'TL[Key]' => 11678,
'TL[Code]' => "SCREW HEX CAPHEAD 6X30MM",
'TL[Detail]' => true,
'TL[DTL]' => [],
]);
echo $store;
it will store everything before [TL] Array, it won't store anything of:
'TL[Key]' => 11678,
'TL[Code]' => "SCREW HEX CAPHEAD 6X30MM",
'TL[Detail]' => true,
'TL[DTL]' => [],
am i doing it wrong?
You can use HTTP client provided by Laravel.
$response = Http::withToken($token)->post('http://example.com/users', $request->only(['request_param_1', 'request_param_2']));
Or
$data = [];
$data['param_1'] = $request->get('param_1');
$data['param_2'] = $request->get('param_2');
$data['param_3'] = $request->get('param_3');
$response = Http::withToken($token)->post('http://example.com/users', $data);
Edit
$data = [
'DocNo' => "SO-000284",
'AOQty' => 0.0,
'TL' => [
'key' => 11678,
'Code' => "SCREW HEX CAPHEAD 6X30MM",
'Detail' => true,
'DTL' => [],
]
];
SOLUTION:
Using Http client:
'TL' => array ([
'Dtl' => "",
'Code' => "Screw Hex",
'IsDetail' => true,
"DTL" => [],
])
]);
I am trying to hit a POST API Endpoint with Guzzle in PHP (Wordpress CLI) to calculate shipping cost. The route expects a RAW JSON data in the following format:
{
"startCountryCode": "CH"
"endCountryCode": "US",
"products": {
"quantity": 1,
"vid": x //Variable ID
}
}
Link to the API I am consuming: https://developers.cjdropshipping.com/api2.0/v1/logistic/freightCalculate
$body = [
"endCountryCode" => "US",
"startCountryCode" => "CN",
"products" => [
'vid' => $vid,
'quantity' => 1
],
];
$request = $this->client->request(
'POST', 'https://developers.cjdropshipping.com/api2.0/v1/logistic/freightCalculate',
[
'headers' => [
'CJ-Access-Token' => $this->auth_via_cj(), // unnecessary, no auth required. Ignore this header
],
'body' => json_encode( $body )
],
);
I've also tried using 'json' => $body instead of the 'body' parameter.
I am getting 400 Bad Request error.
Any ideas?
Try to give body like this.
"json" => json_encode($body)
I spent so many hours on this to just realise that products is actually expecting array of objects. I've been sending just a one-dimensional array and that was causing the 'Bad Request' error.
In order to fix this, just encapsulate 'vid' and 'quantity' into an array and voila!
You don't need to convert data in json format, Guzzle take care of that.
Also you can use post() method of Guzzle library to achieve same result of request. Here is exaple...
$client = new Client();
$params['headers'] = ['Content-Type' => 'application/json'];
$params['json'] = array("endCountryCode" => "US", "startCountryCode" => "CN", "products" => array("vid" => $vid, "quantity" => 1));
$response = $client->post('https://developers.cjdropshipping.com/api2.0/v1/logistic/freightCalculate', $params);
I'm trying to secure my callback url when completed event is triggered.
My Controller:
public function callbackSubscriptionCompleted(
int $subscriptionId,
DocusignService $docusignService,
Request $request
) {
$signature = $request->headers->get("X-DocuSign-Signature-1");
$payload = file_get_contents('php://input');
$isValid = $docusignService->isValidHash($signature, $payload);
if (!$isValid) {
throw new ApiException(
Response::HTTP_BAD_REQUEST,
'invalid_subscription',
'Signature not OK'
);
}
return new Response("Signature OK", Response::HTTP_OK);
}
My DocusignService functions:
private function createEnvelope(Company $company, Subscription $subscription, LegalRepresentative $legalRepresentative, Correspondent $correspondent, $correspondents) : array
{
// ...
$data = [
'disableResponsiveDocument' => 'false',
'emailSubject' => 'Your Subscription',
'emailBlurb' => 'Subscription pending',
'status' => 'sent',
'notification' => [
'useAccountDefaults' => 'false',
'reminders' => [
'reminderEnabled' => 'true',
'reminderDelay' => '1',
'reminderFrequency' => '1'
],
'expirations' => [
'expireEnabled' => 'True',
'expireAfter' => '250',
'expireWarn' => '2'
]
],
'compositeTemplates' => [
[
'serverTemplates' => [
[
'sequence' => '1',
'templateId' => $this->templateId
]
],
'inlineTemplates' => [
[
'sequence' => '2',
'recipients' => [
'signers' => [
[
'email' => $legalRepresentative->getEmail(),
'name' => $legalRepresentative->getLastname(),
'recipientId' => '1',
'recipientSignatureProviders' => [
[
'signatureProviderName' => 'universalsignaturepen_opentrust_hash_tsp',
'signatureProviderOptions' => [
'sms' => substr($legalRepresentative->getCellphone(), 0, 3) == '+33' ? $legalRepresentative->getCellphone() : '+33' . substr($legalRepresentative->getCellphone(), 1),
]
]
],
'roleName' => 'Client',
'clientUserId' => $legalRepresentative->getId(),
'tabs' => [
'textTabs' => $textTabs,
'radioGroupTabs' => $radioTabs,
'checkboxTabs' => $checkboxTabs
]
]
]
]
]
]
]
],
'eventNotification' => [
"url" => $this->router->generate("api_post_subscription_completed_callback", [
"subscriptionId" => $subscription->getId()
], UrlGeneratorInterface::ABSOLUTE_URL),
"includeCertificateOfCompletion" => "false",
"includeDocuments" => "true",
"includeDocumentFields" => "true",
"includeHMAC" => "true",
"requireAcknowledgment" => "true",
"envelopeEvents" => [
[
"envelopeEventStatusCode" => "completed"
]
]
]
];
$response = $this->sendRequest(
'POST',
$this->getBaseUri() . '/envelopes',
[
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $this->getCacheToken()
],
json_encode($data)
);
}
public function isValidHash(string $signature, string $payload): bool
{
$hexHash = hash_hmac('sha256',utf8_encode($payload),utf8_encode($this->hmacKey));
$base64Hash = base64_encode(hex2bin($hexHash));
return $signature === $base64Hash;
}
I've created my hmac key in my Docusign Connect and i'm receiving the signature in the header and the payload but the verification always failed.
I've followed the Docusign documentation here
What's wrong ?
PS: Sorry for my bad english
Your code looks good to me. Make sure that you are only sending one HMAC signature. That way your hmacKey is the correct one.
As a check, I'd print out the utf8_encode($payload) and check that it looks right (it should be the incoming XML, no headers). Also, I don't think it should have a CR/NL in it at the beginning. That's the separator between the HTTP header and body.
Update
I have verified that the PHP code from the DocuSign web site works correctly.
The payload value must not contain either a leading or trailing newline. It should start with <?xml and end with >
I suspect that your software is adding a leading or trailing newline.
The secret (from DocuSign) ends with an =. It is a Base64 encoded value. Do not decode it. Just use it as a string.
Another update
The payload (the body of the request) contains zero new lines.
If you're printing the payload, you'll need to wrap it in <pre> since it includes < characters. Or look at the page source.
It contains UTF-8 XML such as
<?xml version="1.0" encoding="utf-8"?><DocuSignEnvelopeInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.docusign.net/API/3.0"><EnvelopeStatus><RecipientStatuses><RecipientStatus><Type>Signer</Type><Email>larry#worldwidecorp.us</Email><UserName>Larry Kluger</UserName><RoutingOrder>1</RoutingOrder><Sent>2020-08-05T03:11:13.057</Sent><Delivered>2020-08-05T03:11:27.657</Delivered><DeclineReason xsi:nil="true" /><Status>Delivered</Status><RecipientIPAddress>5.102.239.40</RecipientIPAddress><CustomFields /><TabStatuses><TabStatus><TabType>Custom</TabType><Status>Active</Status><XPosition>223</XPosition><YPosition>744....
We've done some more testing, and the line
$payload = file_get_contents('php://input');
should be very early in your script. The problem is that a framework can munge the php://input stream so it won't work properly thereafter.
Note this page from the Symfony site -- it indicates that the right way to get the request body is:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ParameterBag;
$app->before(function (Request $request) {
$payload = $request->getContent();
hmac_verify($payload, $secret);
});
I would try to use the Symfony code instead of file_get_contents('php://input');
I have an API and I need to send some data to it and I am using guzzle for handling it so here is my code:
$amount = $request->get('amount');
$client = new \GuzzleHttp\Client();
$requestapi = $client->post('http://192.168.150.16:7585/api/v1/Transaction/GetTransactionNumber', [
'headers' => ['Content-Type' => 'application/json'],
'body' => '{
"Amount":"i want to send $amount here",
"something":"1",
"Description":"desc",
}'
]);
so every thing is fine and static data is being send but I want to know how can I send a variable.
You can bind the data in form_params parameter like
$client = new \GuzzleHttp\Client();
$amount = $request->get('amount');
$requestapi = $client->post('http://192.168.150.16:7585/api/v1/Transaction/GetTransactionNumber', [
'form_params' => [
"Amount" => "i want to send $amount here",
"something" => "1",
"Description" => "desc",
]
]);
Hope this works for you.
Amount can pass in an array and after you can encode with json using ```json_encode``
Hope this works for you.
$amount = $request->get('amount');
$client = new \GuzzleHttp\Client();
$url = "http://192.168.150.16:7585/api/v1/Transaction/GetTransactionNumber";
$data = [
"amount" => $amount,
"something" => "1",
"description" => "desc",
];
$requestAPI = $client->post( $url, [
'headers' => ['Content-Type' => 'application/json'],
'body' => json_encode($data);
]);
You can try to use Guzzle json option:
$amount = $request->get('amount');
$client = new \GuzzleHttp\Client();
$response = $client->post(
'http://192.168.150.16:7585/api/v1/Transaction/GetTransactionNumber',
[
GuzzleHttp\RequestOptions::JSON => [
'Amount' => $amount,
'something' => '1',
'Description' => 'desc',
]
]
);
Check Guzzle manual - http://docs.guzzlephp.org/en/stable/request-options.html#json
I'm getting data from Couchdb to PHP using Guzzle library. Now I fetch data in POST format like this:
But I need response like this:
{
"status": 200,
"message": "Success",
"device_info": {
"_id": "00ab897bcb0c26a706afc959d35f6262",
"_rev": "2-4bc737bdd29bb2ee386b967fc7f5aec9",
"parent_id": "PV-409",
"child_device_id": "2525252525",
"app_name": "Power Clean - Antivirus & Phone Cleaner App",
"package_name": "com.lionmobi.powerclean",
"app_icon": "https://lh3.googleusercontent.com/uaC_9MLfMwUy6pOyqntqywd4HyniSSxmTfsiJkF2jQs9ihMyNLvsCuiOqrNxNYFq5ko=s3840",
"last_app_used_time": "12:40:04",
"last_app_used_date": "2019-03-12"
"bookmark": "g1AAAABweJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYorGBgkJllYmiclJxkkG5klmhuYJaYlW5paphibppkZmRmB9HHA9BGlIwsAq0kecQ",
"warning": "no matching index found, create an index to optimize query time"
} }
I only remove "docs": [{}] -> Anyone know I remove this ?
check My code:
$response = $client->post(
"/child_activity_stat/_find",
[GuzzleHttp\RequestOptions::JSON => ['selector' => ['parent_id' => ['$eq' => $userid], 'child_device_id' => ['$eq' => $deviceid]],]]
);
if ($response->getStatusCode() == 200) {
$result = json_decode($response->getBody());
$r = $response->getBody();
json_output(200, array(
'status' => 200,
'message' => 'Success',
"device_info" => $result
));
}
You just need to modify your data structure.
NOTE: Maybe you should add a limit of 1 if you want to only get one document. You will also need to validate that the result['docs'] is not empty.
Example:
<?php
$response = $client->post(
"/child_activity_stat/_find",
[GuzzleHttp\ RequestOptions::JSON => ['selector' => ['parent_id' => ['$eq' => $userid], 'child_device_id' => ['$eq' => $deviceid]], ]]
);
if ($response->getStatusCode() == 200) {
// Parse as array
$result = json_decode($response->getBody(),true);
// Get the first document.
$firstDoc = $result['docs'][0];
// Remove docs from the response
unset($result['docs']);
//Merge sanitized $result with $deviceInfo
$deviceInfo = array_merge_recursive($firstDoc,$result);
json_output(200, array(
'status' => 200,
'message' => 'Success',
"device_info" => $deviceInfo
));
}
In couchdb use PUT request is used to edit or to add data and DELETE remove data
$client = new GuzzleHttp\Client();
// Put request for edit
$client->put('http://your_url', [
'body' => [
'parent_id' => ['$eq' => $userid],
'child_device_id' => ['$eq' => $deviceid]
],
'allow_redirects' => false,
'timeout' => 5
]);
// To delete
$client->delete('htt://my-url', [
'body' = [
data
]
]);