I am trying to POST JSON encoded data to a webhook endpoint that resides in one of our companies Microsoft Teams channels. It accepts basic JSON encoded payloads.
I started off in PostMan on my local machine and POST'd the following to my Teams Channel connector webhook URL:
{
"#context": "https://schema.org/extensions"
"#type": "MessageCard",
"themeColor": "0072C6",
"title": "Test From PostMan",
"text": "This is the text body of the notification card",
"potentialAction": [
{
"#type": "OpenUri",
"name": "View in Browser...",
"targets": [
{ "os": "default", "uri": "https://<REDACTED>" }
]
}
]
}
This works fine, it posts the card into the Teams Channel, with the action button below it.
So I moved to PHP, and I made the code below:
<?php
//api endpoint
$url = 'https://<REDACTED>';
//new curl connection
$ch = curl_init($url);
//build json data array
$postdata = array(
'#context' => 'https://schema.org/extensions',
'#type' => 'MessageCard',
'themeColor' => '0072C6',
'title' => 'Test from curl in PHP',
'text' => 'test string.. test string.. test string.. test string.. test string.. test string.. test string..',
'potentialAction' => array (
'#type' => 'OpenUri',
'name' => 'View in Browser...',
'targets' => array (
'os' => 'default',
'uri' => 'https://<REDACTED>'
)
)
);
//encode json data array
$encodeddata = json_encode($postdata);
//set curl options
curl_setopt($ch, CURLOPT_POSTFIELDS, $encodeddata);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
//debug
echo $result;
//close
curl_close($ch);
?>
When I run the above, the API errors and responds saying it was an invalid payload. So I stripped my code down so that my $postdata array was a lot simpler, as below:
//build json data array
$postdata = array(
'#context' => 'https://schema.org/extensions',
'#type' => 'MessageCard',
'themeColor' => '0072C6',
'title' => 'Test from curl in PHP',
'text' => 'test string.. test string.. test string.. test string.. test string.. test string.. test string..'
);
And this works fine, my PHP script is able to post a card into the Teams Channel, just with no action button underneath it. So my issue here lies in how I'm encoding the additional arrays inside of $postdata ?
I'll be honest, my knowledge of arrays in PHP is limited, I think I'm doing this correctly, but clearly I'm having problems, lol. Is there a different/better/more correct way to encode multiple arrays inside of an array into JSON data to POST?
potentialAction in your original JSON is an array of objects, but you made it a single level array only in your PHP data structure.
You need to wrap this into an additional level:
$postdata = array(
'#context' => 'https://schema.org/extensions',
'#type' => 'MessageCard',
'themeColor' => '0072C6',
'title' => 'Test from curl in PHP',
'text' => 'test string.. test string.. test string.. test string.. test string.. test string.. test string..',
'potentialAction' => array (
array (
'#type' => 'OpenUri',
'name' => 'View in Browser...',
'targets' => array (
array (
'os' => 'default',
'uri' => 'https://<REDACTED>'
)
)
)
)
);
This will give you an array of objects in that place, when you encode it as JSON. (The outer array has a zero-based numeric index, so it stays an array when converted to JSON; the inner array has associative keys, so it automatically becomes an object.)
Edit: As mentioned in comments, same thing for the targets property inside. Edited the code, to insert an additional level there as well.
Related
I am using the Xero API, and following the docs but having a problem sending some specific data to this end point: https://developer.xero.com/documentation/api/accounting/invoices#post-invoices
Here is my array in PHP:
$customer_details = array(
'Name' => CompanyName($result["customer"], 'company'),
'AccountNumber' => '',
'EmailAddress' => '',
'Addresses' => (array(
'AddressType' => 'POBOX',
//'AddressLine 1,2,3,4' => array($address["line1"], $address["line2"], $address["line3"]),
'City' => $address["town"],
'Region' => $address["county"],
'PostalCode' => $address["postcode"],
)),
);
$invoice_line_items = array();
$sql2 = $mysqli->query("SELECT * FROM invoices_export WHERE export = '' GROUP BY customer;");
while($result2 = $sql2->fetch_array()) {
$invoice_line_items[]= array(
'Description' => $result["description"],
'Quantity' => $result["quantity"],
'UnitAmount' => $result["unit_price"],
'AccountCode' => '200',
);
}
$invoice_data = array(
'Type' => 'ACCREC',
'Status' => 'DRAFT',
'Contact' => $customer_details,
'LineItems' => $invoice_line_items,
);
But the error I receive is this:
string(362) "{"Type":"ACCREC","Status":"DRAFT","Contact":{"Name":"ABC Co","AccountNumber":"","EmailAddress":"","Addresses":{"AddressType":"POBOX","City":"City here","Region":"Region here","PostalCode":"AB1 2CD"}},"LineItems":[{"Description":"test","Quantity":"1","UnitAmount":"1","AccountCode":"200"},{"Description":"test","Quantity":"1","UnitAmount":"1","AccountCode":"200"}]}" array(3) { ["data"]=> array(3) { ["ErrorNumber"]=> int(14) ["Type"]=> string(24) "PostDataInvalidException" ["Message"]=> string(660) "JSON for post data was invalid,Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'Xero.API.Library.DataContracts.Addresses' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'Contact.Addresses.AddressType', line 1, position 132." } ["http_code"]=> int(400) ["error_msg"]=> string(30) "Error : Failed to post invoice" }
If I remove the 'Addresses', it works fine. I have added json_encode to the Addresses values, but no luck with that either.
Anyone have any ideas what I can do to fix this?
According to the docs, Addresses needs to be an array of objects, you provided an object only. (You provided an associative array, to be precise, but encoding as JSON will turn that into an object.)
'Addresses' => (array( - just wrapping stuff into an additional set of braces does not create an additional array dimension, this needs to be 'Addresses' => array(array(
I am trying to post a message via the Canvas API using PHP.
I believe this is more of a PHP question than Canvas.
The following code WORKS when I include a single userID for a "recipients[]' ('79' is a specific user idea and the API sends them a message - like an email).
See below for the API documentation and the issue trying to post to multiple IDs.
$post = [
'recipients[]' => 79,
'group_conversation' => true,
'bulk_message' => true,
'subject'=>$msg_subject,
'body'=>$msg_body,
];
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $token_url,
CURLOPT_HTTPHEADER => $header,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $post,
CURLOPT_RETURNTRANSFER => true
));
$lti_msgresponse = curl_exec($curl);
curl_close($curl);
echo($lti_msgresponse);
Here is the Canvas documentation:
https://edu.pretpriemacedu.mk/doc/api/conversations.html#method.conversations.create
Specifically:
recipients[] Required
string
An array of recipient ids. These may be user ids or course/group ids prefixed with “course_” or “group_” respectively, e.g. recipients[]=1&recipients=2&recipients[]=course_3
The API calls for a string to be sent for this "array" (brackets at the end?). You can't pass multiple "recipients" fields because only the last one will record (duh).
I think a solution might have to do with using http_build_query (see https://www.php.net/http_build_query) to send complex/nested arrays, but I have experimenting with various ways to pack more into "recipients[]" and they all fail.
Any PHP or general API wisdom def appreciated...
The post params ( specifically "recipients" ) should look like the following
$post = [
'recipients' => '59,48,19,55',
'group_conversation' => true,
'bulk_message' => true,
'subject' => $msg_subject,
'body' => $msg_body,
];
or, perhaps the following: 'recipients' => [59,48,19,55]. But recipients[] would be an odd parameter to pass, as it contains special-characters.
I am having the hardest time figuring out how to properly format a graphql api mutation POST request in php.
If I hard code the string and use it as the data in my POST request it works like this:
'{"query":"mutation{addPlay(input: {title: \"two\"}){ properties { title } } }"}'
But if I have a php array of the input values:
$test_data = array(
'title' => 'two'
);
I can't seem to format it correctly. json_encode also puts double quotes around the keys which graphql is rejecting with the error Syntax Error GraphQL request (1:26) Expected Name, found String.
I ultimately need a solution that will convert a larger more complex array to something usable.
Reformatting the query allowed me to use JSON directly.
So my new query looks like this:
$test_data = array(
'title' => 'two'
);
$request_data = array(
'query' => 'mutation ($input: PlayInput) { addPlay(input: $input) { properties { title } }}',
'variables' => array(
'input' => $test_data,
),
);
$request_data_json = json_encode($request_data);
Then the $request_data_json is used in a POST http request.
So I'm trying to prepopulate some fields in our DocuSign Templates when submitting them from our custom interface but the request doesn't seem to be able to find them in the templates. We're using REST, cURL and Codeigniter. My data array is as follows:
$data = array("accountId" => $accountId,
"emailSubject" => "Hello World!",
"emailBlurb" => "This comes from PHP",
"templateId" => "********-****-****-****-************",
"templateRoles" => array(
array(
"email" => "****#******.com",
"name" => "**** *****",
"roleName" => "LC3"
),
array(
"email" => $this->input->post("applicant_email"),
"name" => $this->input->post("applicant_name"),
"roleName" => "Applicant",
"tabStatuses" => array(
"textTabs" => array (
array (
"tabLabel" => "lic_num",
"tabValue" => $this->input->post("license_number")
),
array (
"tabLabel" => "ubi_num",
"tabValue" => $this->input->post("ubi_number")
),
array (
"tabLabel" => "tra_nam",
"tabValue" => $this->input->post("trade_name")
)
)
)
)
),
"status" => "sent");
I tried tabs instead of tabStatuses, but that didn't work either and our XML responses have TabStatuses instead of Tabs. Has something changed since the API Walkthroughs were put up?
EDIT: So after much trial and error with Chrome's Postman extension, this is the JSON request that I got to actually not error out:
{
"accountId":"c771ba8c-2947-4bec-acab-15b1b48a11b6",
"emailSubject":"Hello World!",
"emailBlurb":"This comes from PHP",
"templateId":"B96D0480-8792-43E8-AE11-E2AEAC74E601",
"templateRoles":[
{
"email":"mike#cloudpwr.com",
"name":"Mike Longmire",
"roleName":"LC3",
"tabStatuses":[
{
"tabStatus":[
{
"tabLabel":"lic_num",
"tabValue":"1111"
},
{
"tabLabel":"ubi_num",
"tabValue":"2222"
},
{
"tabLabel":"tra_nam",
"tabValue":"Flakey"
}
]
}
],
"email":"duckie715#gmail.com",
"name":"Mike Longmire",
"roleName":"Applicant"
}
],
"status":"sent"
}
I get back my same response:
{
"envelopeId": "0063d398-36b7-4e2f-8515-6ed9ab62aaeb",
"uri": "/envelopes/0063d398-36b7-4e2f-8515-6ed9ab62aaeb",
"statusDateTime": "2013-10-08T18:05:54.9926661Z",
"status": "sent"
}
Any ideas?
This is most likely caused by the values being returned from your function calls inside the JSON not being wrapped by quotation (") marks. To test that theory I would first just hardcode some values wherever you have a function call in your JSON (such as "email" => $this->input->post("applicant_email")) and replace with actual emails, etc and run.
If you still get the 400 error then something else is wrong with your request. If you don't, then you just need to prepend and append quotes around the values that are passed back by those function calls.
For instance, you can assign to variables, such as
$applicantEmail_1 = $this->input->post("applicant_email")
then setup your JSON like:
"templateRoles" => array(
array(
"email" => "****#******.com",
"name" => "**** *****",
"roleName" => "LC3"
),
array(
"email" => "$applicantEmail_1",
"name" => $this->input->post("applicant_name"),
"roleName" => "Applicant",
...
The nice thing about PHP is that even though that variable is in double quotes the value of the variable will still be inserted inside the quotes.
I'm using PHP to create a system that will fetch webhook payload when someone is unsubscribing newsletters, but I can figure out how to fetch the actual payload information in PHP.
Is there any POST data to fetch? How does PHP look for this POST data?
UPDATE: I may be on to something. Seems like the function http_get_request_body() will do the trick?
$http_get_request_body solves it :)
I recently ran into this issue and used the following PHP code for handling Campaign Monitor Web Hooks:
<?php
$json = file_get_contents('php://input');
$data = json_decode( $json, TRUE ); //convert JSON into array
foreach ($data['Events'] as $event)
{
// Process each entry in the request
}
The JSON data, once converted to an array will give you data in this format:
array (
'ListID' => 'LIST_ID_KEY',
'Events' => array (
0 =>
array (
'Type' => 'Subscribe',
'Date' => '2014-01-01 16:00:00',
'EmailAddress' => 'test#example.com',
'Name' => 'John Smith',
'CustomFields' => array (),
'SignupIPAddress' => 'API',
),
),
)