Replicate CURL multipart/form-data request with Guzzle / League OAuth2 Client - oauth-2.0

I am attempting to replicate a CURL POST request in Guzzle, but Guzzle request is failing.
This is the CURL request that works successfully:
$file = new \CURLFile( $document );
$file->setPostFilename( basename( $document ) );
$ch = curl_init();
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_URL, $endpoint );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $accessToken,
"Content-Type: multipart/form-data",
] );
curl_setopt( $ch, CURLOPT_POSTFIELDS, [ 'fileData' => $file ] );
$response = curl_exec( $ch );
And here is what I am currently using for the Guzzle request but it does not work:
$options['multipart'][] = [
'name' => 'fileData',
'contents' => fopen( $document, 'r' ),
'filename' => basename( $document ),
];
$request = $provider->getAuthenticatedRequest( 'POST', $endpoint, $accessToken, $options );
$response = $provider->getParsedResponse( $request );
The response from the Guzzle request is as follows:
{"message":"File cannot be empty","errors":[{"code":"Missing","fields":["document"]}]}
It's worth noting I am using the thephpleague/oauth2-client library to send the request. I'm looking for any discrepencies between the two request or information on how I can troubleshoot this further myself as I have been spinning my wheels all day on this. Much appreciated

thephpleague/oauth2-client uses different Providers to create the requests and these Providers implement AbstractProvider
The argument $options of AbstractProvider 's getAuthenticatedRequest() is different from GuzzleHttp\Client 's request():
/**
* Returns an authenticated PSR-7 request instance.
...
* #param array $options Any of "headers", "body", and "protocolVersion".
* #return RequestInterface
*/
public function getAuthenticatedRequest($method, $url, $token, array $options = [])
Only keys allowed for $options are "headers", "body", and "protocolVersion".
You should do the extra effort and create the headers and body needed:
$file = new \CURLFile( $document );
$file->setPostFilename( basename( $document ) );
$data = array(
'uploaded_file' => $file
);
$options = array(
'headers' => array("Content-Type" => "multipart/form-data"),
'body' => $data
);
$request = $provider->getAuthenticatedRequest( 'POST', $endpoint, $accessToken, $options );
Reference
Send file via cURL from form POST in PHP

Related

Hubspot Webhooks: Redirect Auth & BAD_GRANT_TYPE Message

I'm trying to add a custom app in Hubspot. I'm using PHP. I have:
A Hubspot app
A working webhook URL
A redirect URL with the following code
$url = 'https://api.hubapi.com/oauth/v1/token';
$code = $_GET['code']; // Getting code parameter from redirect URL
//echo $code;
$fields = array();
$fields['grant_type'] = 'authorization_code'; // Have also tried 'refresh_token' - same result
$fields['client_id'] = '{CLIENT_ID}';
$fields['client_secret'] = '{CLIENT_SECRET}';
$fields['redirect_uri'] = '{REDIRECT_URI}';
$fields['code'] = trim($code);
//$fields['refresh_token'] = trim($code); // Have also tried 'refresh_token' - same result
$request_type = 'POST';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', $headers));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, POST);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, 1);
if($fields){
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$return = curl_exec($ch);
curl_close($ch);
echo var_dump ($return);
My understanding is that Hubspot will use the 'code' parameter passed to the on the "authorization" URL to validate the authorization. However, I keep getting this error:
string(171) "{"status":"BAD_GRANT_TYPE","message":"missing or unknown grant type","correlationId":"f0508752-24bc-40e4-b0bc-51e358459653","requestId":"96044613d4e4a5aab7356fab04001e5c"}"
I had the same error response and it seemed that this is an encoding issue.
I debugged with Postman and found out that the following code works:
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.hubapi.com/oauth/v1/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "grant_type=authorization_code&code=string&redirect_uri=string&client_id=string&client_secret=string",
CURLOPT_HTTPHEADER => array(
"content-type: application/x-www-form-urlencoded",
"Cookie: __cfduid=someidfrompostman"
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;

Sending Firebase push notifications from Laravel

I am writing an iOS application, using laravel for API and google firebase for push notifications. When I send a push notification using firebase cloud messaging, it comes to my device. When I send push notifications using laravel, it does not affect. Here is my script for sending push notifications from laravel:
function sendNotification(Request $request)
{
$friendToken = [];
$usernames = $request->all()['friend_usernames'];
$dialog_id = $request->all()['dialog_id'];
foreach ($usernames as $username) {
$friendToken[] = DB::table('users')->where('user_name', $username)
->get()->pluck('device_token')[0];
}
$url = 'https://fcm.googleapis.com/fcm/send';
foreach ($friendToken as $tok) {
$fields = array(
'to' => $tok,
'data' => $message = array(
"message" => $request->all()['message'],
"dialog_id" => $dialog_id
)
);
$headers = array(
'Authorization: key=*mykey*',
'Content-type: Application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
curl_exec($ch);
curl_close($ch);
}
$res = ['error' => null, 'result' => "friends invited"];
return $res;
}
It returns a successful result, but notification not sent to iOS devices.
PS: It works successfully on Android devices.
After some research I have found a solution to my question. In order to work for iOS platform, we need to add notification in fields:
$notification = array('title' =>"" , 'text' => $request->all()['message']);
$fields = array(
'to' => $tok,
'data' => $message = array(
"message" => $request->all()['message'],
"dialog_id" => $dialog_id
),
'notification' => $notification
);

iOS empty Firebase Push notification doesn't show up

I'm having a weird problem with Firebase notification on iOS. It works perfectly but the only problem is if I keep the 'body' parameter on the server empty it does play notification sound on the app but doesn't show anything. Same thing displays notification on Android. Is it some kind of Apple security that I'm running into? if I only add an empty space " " in 'body' it would show up but nothing without it. If any body could suggest me anything please.
my server side code
$msg = array
(
'title' => '',
'body' => ' ',
'click_action' => '.InstagramLoader',
'icon' => 'myicon',/*Default Icon*/
'sound' => 'mySound'/*Default sound*/
);
$data = array(
'text' => $title,
'img_url' => $img_url
);
$fields = array
(
'to' => $registrationIds,
'notification' => $msg,
'data' => $data
);
$headers = array
(
'Authorization: key=' . API_ACCESS_KEY,
'Content-Type: application/json'
);
#Send Reponse To FireBase Server
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
Yes that's an iOS thing, why show an empty push notification right? You could use isNaN() in your server side code and check for an empty body and set it to a default value.

post data with curl and change page url

I have a shopping site and I have to send username and password and some other data to the bank, so I have used curl for posting data .because it should be safe.
but my problem is when I post data with curl to the bank, page url dont change! I see banks result in my server page !!!
I need this posting data same as posting data in html page redirect too the url which has been determined !!
$data = array(
"MID" => "0113-19",
"RedirectURL" => $SERVER . "/shop/profile.php",
"Amount" => $sum,
"ResNum" => $ResNum,
"username" => "xxxx",
"password" => "1234");
//traverse array and prepare data for posting (key1=value1)
foreach ( $data as $key => $value) {
$data[] = $key . '=' . urlencode($value);
}
$post_string = implode ('&', $data);
$res = array();
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_POST => true, // return web page
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_AUTOREFERER => false, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLOPT_POSTFIELDS => $post_string, // stop after 10 redirects
CURLOPT_SSL_VERIFYPEER => false , // stop after 10 redirects
CURLOPT_COOKIEJAR => "cookie.txt" , // stop after 10 redirects
CURLOPT_COOKIEFILE => "cookie.txt" , // stop after 10 redirects
CURLOPT_SSL_VERIFYPEER => false , // stop after 10 redirects
CURLOPT_USERAGENT => "Mozilla/5.0 (Windows; U;
Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1" // stop after 10 redirects
);
//////////////////////
$ch = curl_init( $url );
curl_setopt_array( $ch, $options );
$content = curl_exec( $ch );
$err = curl_errno( $ch );
$errmsg = curl_error( $ch );
$header = curl_getinfo( $ch );
curl_close( $ch );

paypal access oauth login json_decode returned null

i have 2 PHP files, one index.php and the other one paypal.php.
The code for paypal.php is:
<?php
session_start();
$client_id = 'xxxxxxxxxxxx';
$client_secret = 'xxxxxxxxxxxxxxxxxxxx';
$scopes = 'email profile';
$app_return_url = 'http://xxx.com/xxx/paypal.php';
$nonce = time() . rand();
$code = $_REQUEST["code"];
if(empty($code)) {
$_SESSION['state'] = md5(uniqid(rand(), TRUE));
$paypal_auth_url = "https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize?"
."client_id=".$client_id
."&response_type=code"
."&scope=".$scopes
."&nonce=".$nonce
."&state=".$_SESSION['state']
."&redirect_uri=".urlencode($app_return_url);
header("Location: $paypal_auth_url");
}else{
$token_url = "https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/tokenservice";
$postvals = "client_id=".$client_id
."&client_secret=".$client_secret
."&grant_type=authorization_code"
."&code=".$code;
$ch = curl_init($token_url);
$options = array(
CURLOPT_POST => 1,
CURLOPT_VERBOSE => 1,
CURLOPT_POSTFIELDS => $postvals,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSLVERSION => 3
);
curl_setopt_array( $ch, $options );
$response = curl_exec($ch);
curl_close($ch);
$atoken = json_decode($response);
$profile_url = "https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/userinfo?"
."schema=openid"
."access_token=".$atoken->access_token;
$ch = curl_init($profile_url);
$options = array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSLVERSION => 3
);
curl_setopt_array( $ch, $options );
$response = curl_exec($ch);
curl_close($ch);
$profile= json_decode($response,true);
$_SESSION['paypal_user'] = "true";
$_SESSION['profile'] = $profile;
echo("<script> top.location.href='index.php'</script>");
}
?>
The code for index.php is:
<?php
session_start();
// LOGOUT
if ($_GET['logout'] == 'true'){
$_SESSION['paypal_user']="";
}
if (strlen($_SESSION['paypal_user'])){
// LOGGED USER
echo "<pre>";
print_r($_SESSION['profile']);
echo "</pre>";
echo "<br><BR> <a href='?logout=true'>LOGOUT</a>";
}else{
// LOGIN
?>
<a href='paypal.php' title='Paypal oAuth Login'>
<img src='https://www.paypalobjects.com/en_US/Marketing/i/btn/login-with-paypal-button.png'>
</a>
<?
}
?>
Any ideas why this code is not working? I tried var_dump json_decode and it returns null.
Thank you!
I may be wrong, but I believe you scopes need to be...
"scopes": "email https://uri.paypal.com/services/paypalattributes",
The URL is the profile
simply add '&' on before access token,he missed & symbol between two variables
$profile_url = "https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/userinfo?" ."schema=openid" ."**&**access_token=".$atoken->access_token;

Resources