curl PUT request with discord API resulting bad request - php

I'm using php, oauth2, and curl to connect to the Discord API and add a member to a server (guild).
I have successfully authenticated the user using Oath2 with the identify, guilds, and guilds.join scope.
I have the access_token & the bot token needed.
From my understanding in the Discord API docs:
https://discord.com/developers/docs/resources/guild#add-guild-member
I need to use a PUT request with the access_token (with guilds.join scope) and headers with Authentication: Bot Token to the endpoint: https://discordapp.com/api/guilds/GUILDID/members/USERID
I have done this but receive a 400 Bad Request error.
I am not sure what the problem could be.
Config
define('OAUTH2_CLIENT_ID', 'REDACTED');
define('OAUTH2_CLIENT_SECRET', 'REDACTED');
$guildid = REDACTED
$authorizeURL = 'https://discord.com/api/oauth2/authorize?client_id=REDACTED&permissions=0&redirect_uri=https%3A%2F%2FREDACTED%2Findex.php%3Faction%3Ddiscord&response_type=code&scope=identify%20guilds%20guilds.join%20bot';
$tokenURL = 'https://discordapp.com/api/oauth2/token';
$apiURLBase = 'https://discordapp.com/api/users/#me';
$apiURLGuilds = 'https://discordapp.com/api/users/#me/guilds';
$apiURLJoin = 'https://discordapp.com/api/guilds/'. $guildid . '/members/';
join function
function joinapiRequest($url,$userid) {
$url = $url.$userid;
$params = 'access_token='.session('access_token');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$bottoken = redacted;
$headers[] = 'Authorization: Bot ' . $bottoken;
$headers[] = 'Content-Type: application/json';
$headers[] = 'Content-Length: '.strlen($params);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$response = curl_exec($ch);
echo 'join guild response <br />';
var_dump($response);
if($http == 201){
return true;
} else {
return false;
}
}
response
string(42) "{"message": "400: Bad Request", "code": 0}"
Any help would be much appreciated.

For anyone looking for an answer, I fixed this by changing the syntax on sending the access_token to:
$params = '{"access_token" : "'.session('access_token').'"}';

Related

How to get access token using refresh token in DocuSign and PHP?

I want to update my access token using the previous refresh token in DocuSign? I am getting
{
"error": "invalid_grant",
"error_description": "unsupported_grant_type"
}
Below is how I made the request.
$client_id = env('DOCUSIGN_CLIENT_ID');
$client_secret = env('DOCUSIGN_CLIENT_SECRET');
$encoded_client_id = utf8_decode(base64_encode($client_id));
$encoded_client_secret = utf8_decode(base64_encode($client_secret));
$integrator_and_secret_key = "Basic " . "{$encoded_client_id}:{$encoded_client_secret}";
// $integrator_and_secret_key = "Basic " . utf8_decode(base64_encode("{$client_id}:{$client_secret}"));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://account-d.docusign.com/oauth/token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$data = array(
'refresh_token' => "My refresh token from previous successful request",
'grant_type' => 'refresh_token',
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$headers = array();
$headers[] = "Authorization: Basic " . "{$encoded_client_id}:{$encoded_client_secret}";
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
$headers[] = 'Cache-Control: no-cache';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
Log::info($result);
So, not confident that's the only issue, but the way you encode the clientId and clientSecret is different, you encode each part separately, instead of the whole thing with the colon.
https://www.docusign.com/blog/developers/authorization-code-grant-refresh-tokens shows that it's done like this:
string codeAuth = (clientId ?? "") + ":" + (clientSecret ?? "");
byte[] codeAuthBytes = Encoding.UTF8.GetBytes(codeAuth);
string codeAuthBase64 = Convert.ToBase64String(codeAuthBytes);
Note that the string that's encoded already had them combined, not each of them encoded separately.
Now, the error can also be because the Integration Key (IK or clientID) is not configured correctly, you use a bad refreshToken, it expired, you use the wrong environment (developer vs. production) and maybe a couple more reasons I forgot. Need to triple check all the values to ensure this if still not working.
For those who stuck on this issue:
The solution was just to change the content-type from application/x-www-form-urlencoded to application/json

2ba web API post request with php curl

Im using 2ba its API to receive product information which I later on want to store inside my database. I am trying to create a post request for receiving the data I need. This is the request I want to get to working. And this is my code:
postApiData.php
<?php
/**
* Posts API data based on given parameters at index.php.
*/
// Base url for all api calls.
$baseURL = 'https://api.2ba.nl';
// Version number and protocol.
$versionAndProtocol = '/1/json/';
// All parts together.
$url = $baseURL . $versionAndProtocol . $endPoint;
// Init session for CURL.
$ch = curl_init();
// Init headers. Security for acces data.
$headers = array();
$headers[] = "Authorization: Bearer " . $token->access_token;
// Options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
// Execute request.
$data = curl_exec($ch);
// If there is an error. Show whats wrong.
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
echo "<br>";
echo "Error location: postApiData";
exit();
}
// Ends the CURL session, frees all resources that belongs to the curl (ch).
curl_close($ch);
// String to array.
$data = json_decode($data);
?>
index.php
// Specified url endpoint. This comes after the baseUrl.
$endPoint = 'Product/forGLNAndProductcodes';
// Parameters that are required or/and optional for the endPoint its request.
$parameters = [
'gln' => '2220000075756',
'productcodes' => ['84622270']
];
// Get Supplier info
include("postApiData.php");
print_r($data);
exit();
My API key does for sure work since I have done alot of different GET requests already, also im not getting an access denied error.
The error I get with this code is: The requested URL returned error: 500 Internal Server Error
I also receive a "Bad request" 400 error when I remove the curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters)); part
Is there anyone who knows what im doing wrong?
PS: It's not really possible to try this code yourself unless you have a 2ba account with working key's etc.
Okey I fixed it already...
I had to add some extra headers and change the $parameters values like this:
postApiData.php
// Added this above the authorization.
$headers[] = "Connection: close";
$headers[] = "Accept-Encoding: gzip,deflate";
$headers[] = "Content-Type: application/json";
// Removed the http_build_query part.
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
index.php
// Encoded in a json way as asked by 2ba request.
$parameters = json_encode($parameters);

How to connect with 2ba it's API using PHP

Im trying to connect to the API services of 2ba. Somehow I just can't connect. I get the error: error: "invalid_client"
I dont know what to try, it feels like I need to hash my cliend_secret or complete url but I dont see that in the documentation.
This is my code (PHP):
<?php
// ---- GET TOKEN ----
// Base url for all api calls.
$baseURL = 'https://authorize.2ba.nl';
// Specified url endpoint. This comes after the baseUrl.
$endPoint = '/OAuth/Token';
// Parameters that are required or/and optianal for the endPoint its request.
$parameters = 'grant_type=password&username=abc#abc.com&password=123abc&client_id=myClientID&client_secret=myClientSecret';
// All parts together.
$url = $baseURL . $endPoint . '?' . $parameters;
//Init session for CURL.
$ch = curl_init();
// Options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
// Init headers for access to the binance API signed data.
$headers = array();
$headers[] = 'Content-type: application/x-www-form-urlencoded';
$headers[] = 'Content-Length: 0';
// Setting headers
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute request.
$data = curl_exec($ch);
// If there is an error. Show whats wrong.
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
// Ends the CURL session, frees all resources and deletes the curl (ch).
curl_close($ch);
$result = json_encode($data);
echo($data);
exit();
?>
The authentication is oauth2 and I want to use the "Password Grant" flow since I can login automaticly this way. Also I see in the example code in C# that they encode the url, something im not doing yet but did try. It did not work.
// Using $encodedUrl like this: curl_setopt($ch, CURLOPT_URL, $encodedUrl); but does not work.
$encodedUrl = urlencode($url);
Alright so I fixed it. I now got my access token and am able to recieve data from the API. This is what I did:
// ---- GET TOKEN - FLOW: USER PSW ----
// No changes
$baseURL = 'https://authorize.2ba.nl';
// No changes
$endPoint = '/OAuth/Token';
// $parameters is now an array.
$parameters = array(
'grant_type' => 'password',
'username' => 'myUsername',
'password' => 'myPassword',
'client_id' => 'myClientID',
'client_secret' => 'myClientSecret'
);
// Removed the $parameter part
$url = $baseURL . $endPoint;
//Init session for CURL.
$ch = curl_init();
// Init headers for access to the binance API signed data.
$headers = array();
$headers['Content-Type'] = "application/x-www-form-urlencoded";
// NOTE: http_build_query fixed it.
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters)); // Automaticly encodes parameters like client_secret and id.
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute request.
$data = curl_exec($ch);
// If there is an error. Show whats wrong.
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
// Ends the CURL session, frees all resources and deletes the curl (ch).
curl_close($ch);
$result = json_encode($data);
echo($data);
exit();

How can I get an Authentication Token for Microsoft Translator API?

I want to get an Authentication Token for the Microsoft Translator API. This is my code:
<?php
//1. initialize cURL
$ch = curl_init();
//2. set options
//Set to POST request
curl_setopt($ch, CURLOPT_POST,1);
// URL to send the request to
curl_setopt($ch, CURLOPT_URL, 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken');
//return instead of outputting directly
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//whether to include header in the output. here set to false
curl_setopt($ch, CURLOPT_HEADER, 0);
//pass my subscription key
curl_setopt($ch, CURLOPT_POSTFIELDS,array(Subscription-Key => '<my-key>'));
//CURLOPT_SSL_VERIFYPEER- Set to false to stop verifying certificate
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//3. Execute the request and fetch the response. check for errors
$output = curl_exec($ch);
if ($output === FALSE) {
echo "cURL Error" . curl_error($ch);
}
//4. close and free up the curl handle
curl_close($ch);
//5. display raw output
print_r($output);
?>
it gives me the following error:
{ "statusCode": 401, "message": "Access denied due to missing subscription key. Make sure to include subscription key when making requests to an API." }
which could mean that the key is invalid according to the website below, but I ensured the key is valid on the same website.
http://docs.microsofttranslator.com/oauth-token.html
I did find some examples online on how to get the Authenticationtoken, but they are outdated.
How can I get the AuthenticationToken/achieve that microsoft recognises my key?
You're passing the subscription-key wrong -
The subscription key should passed in the header (Ocp-Apim-Subscription-Key) or as a querystring parameter in the URL ?Subscription-Key=
And you should use Key1 or Key2 generated by the Azure cognitive service dashboard.
FYI - M$ has made a token generator available for testing purposes, this should give you a clue which keys are used for which purpose:
http://docs.microsofttranslator.com/oauth-token.html
Here's a working PHP script which translates a string from EN to FR (it's based on an outdated WP plugin called Wp-Slug-Translate by BoLiQuan which I've modified for this purpose):
<?php
define("CLIENTID",'<client-name>'); // client name/id
define("CLIENTSECRET",'<client-key>'); // Put key1 or key 2 here
define("SOURCE","en");
define("TARGET","fr");
class WstHttpRequest
{
function curlRequest($url, $header = array(), $postData = ''){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
if(!empty($header)){
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
if(!empty($postData)){
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($postData) ? http_build_query($postData) : $postData);
}
$curlResponse = curl_exec($ch);
curl_close($ch);
return $curlResponse;
}
}
class WstMicrosoftTranslator extends WstHttpRequest
{
private $_clientID = CLIENTID;
private $_clientSecret = CLIENTSECRET;
private $_fromLanguage = SOURCE;
private $_toLanguage = TARGET;
private $_grantType = "client_credentials";
private $_scopeUrl = "http://api.microsofttranslator.com";
private $_authUrl = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken";
// added subscription-key
private function _getTokens(){
try{
$header = array('Ocp-Apim-Subscription-Key: '.$this->_clientSecret);
$postData = array(
'grant_type' => $this->_grantType,
'scope' => $this->_scopeUrl,
'client_id' => $this->_clientID,
'client_secret' => $this->_clientSecret
);
$response = $this->curlRequest($this->_authUrl, $header, $postData);
if (!empty($response))
return $response;
}
catch(Exception $e){
echo "Exception-" . $e->getMessage();
}
}
function translate($inputStr){
$params = "text=" . rawurlencode($inputStr) . "&from=" . $this->_fromLanguage . "&to=" . $this->_toLanguage;
$translateUrl = "http://api.microsofttranslator.com/v2/Http.svc/Translate?$params";
$accessToken = $this->_getTokens();
$authHeader = "Authorization: Bearer " . $accessToken;
$header = array($authHeader, "Content-Type: text/xml");
$curlResponse = $this->curlRequest($translateUrl, $header);
$xmlObj = simplexml_load_string($curlResponse);
$translatedStr = '';
foreach((array)$xmlObj[0] as $val){
$translatedStr = $val;
}
return $translatedStr;
}
}
function bing_translator($string) {
$wst_microsoft= new WstMicrosoftTranslator();
return $wst_microsoft->translate($string);
}
echo bing_translator("How about translating this?");
?>
Add your key also in the URL.
curl_setopt($ch, CURLOPT_URL, 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken?Subscription-Key={your key}');
But leave it also in the CURLOPT_POSTFIELDS.

How to send message to youtube user using youtube API?

I am developing a script to send a message to a YouTube user. Actually, I have got the YouTube data feeds with the information - YouTube video id, author name, details etc.., for that corresponding author. I have to send a message using the YouTube api. Is this possible?
I have already written Oauth login and YouTube API feed to get video and user information for that corresponding video. I referred to this documentation in the YouTube API - https://developers.google.com/youtube/2.0/developers_guide_protocol_messages#Sending_a_message for send message, but there are no options for this. There are only options to send message as comments instead of new mail to the inbox of the corresponding video author.
So please update me if you know about that. I have pasted my script below.
$developer_key='###########################';
$client_id= '#################';
$client_secret='#################';
// error checking; user might have denied access
if (isset($_GET['error'])) {
if ($_GET['error'] == 'access_denied') {
echo('You have denied access. Click here to retry…');
} else {
echo("An error has occurred: ". $_GET['error']);
}
exit;
}
// Step 1: redirect to google account login if necessary
if(!isset($_GET['code']) || $_GET['code'] === '') {
Header('Location: https://accounts.google.com/o/oauth2/auth?client_id='. $client_id .
'&redirect_uri=http%3A%2F%2Flocalhost%2Ftest%2Foauth_1.php' .
'&scope=https://gdata.youtube.com&response_type=code&access_type=offline',
true, 307);
exit;
}
$authorization_code= $_GET['code'];
// Step 2: use authorization code to get access token
$url = "https://accounts.google.com/o/oauth2/token";
$message_post= 'code='. $authorization_code .
'&client_id='. $client_id .
'&client_secret='. $client_secret .
'&redirect_uri=http://localhost/test/oauth_1.php' .
'&grant_type=authorization_code';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $message_post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
if ($cur_error= curl_error($ch)) {
echo($cur_error);
curl_close($ch);
exit;
}
curl_close($ch);
$jsonArray= json_decode($result, true);
if ($jsonArray === null) {
echo("Could not decode JSON.");
exit;
}
if (isset($jsonArray['error'])) {
echo("An error has occurred: ". $jsonArray['error']);
exit;
}
if (!isset($jsonArray['access_token'])) {
echo("Access token not found.");
exit;
}
//The user's authentication token
$access_token= $jsonArray['access_token'];
$title ='krishna'; //The title of the caption track
$lang = 'en'; //The languageof the caption track
//$transcript = $_REQUEST['transcript']; //The caption file data
$ur='https://gdata.youtube.com/feeds/api/users/recepient_username/inbox';
$headers = array(
'Host: gdata.youtube.com',
'Content-Type: application/atom+xml utf-8',
'Content-Language: ' . $lang,
'Slug: ' . rawurlencode($title),
'Authorization: AuthSub token=' . $access_token,
'GData-Version: 2',
'X-GData-Key: key=' . $developer_key
);
$xml = '&xml=<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:yt="http://gdata.youtube.com/schemas/2007">
<id>cSVSeHFKBjU</id>
<summary>sending a message from the api</summary>
</entry>';
// create a new cURL resource
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_HEADER, TRUE );
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, urlencode($xml) );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1 );
$tt = curl_getinfo($ch);
print_r($tt);
$result = curl_exec($ch);
print_r($result);
// close cURL resource, and free up system resources
curl_close($ch);
echo "DONE! Token:" . $access_token . "<br />\n";
var_dump($result);
SO please check and update me if there any options to send mail to the video user instead of comments.
The YouTube v2.0 API does support sending new messages to a user's inbox, but the message must contain both a video and a comment about that video. You cannot send a text-only message.
Documentation, which includes a use case explaining how YouTube's messaging support is intended to be used, can be found here.

Categories