Questions and discussion about using ProcessMaker: user interface, running cases & functionality

Moderator: amosbatto

#815803
Hello,

Since I upgraded PocessMaker from 3.2.1 to 3.2.3 I have this error :
Code: Select all
{
    "error": {
        "code": 401,
        "message": "Unauthorized"
    }
}
My request (I tested it with postman and in javascript):
Code: Select all
POST
http://PROCESSMAKER_IP/api/1.0/workflow/cases/?access_token=9a46b5eaaeb7e9de6b98bba5590294e5d40ddf8d&pro_uid=1627488305a8bf1c34f68b7055359592%26&tas_uid=2443015575a8bfe0806c0e3006365963
Is there any change in this version that can impact my requests?

Thanks for your help.
Rym.
#815813
I just tried the POST /cases endpoint in PM 3.2.3 Community (manual install in Debian 8.4 with PHP 5.6.20 and MySQL 5.5.47) and I don't have any problem calling it with HttpRequester (in firefox 51) and using PHP.

What versions of PHP and MySQL do you have installed?

Here is my HttpRequester:
httpRequesterIn323.png
httpRequesterIn323.png (30.2 KiB) Viewed 2180 times
httpRequesterAuthorization.png
httpRequesterAuthorization.png (25.38 KiB) Viewed 2180 times
Please try it this same way using Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXX

Here is my PHP code:
Code: Select all
//PM 3.2.3 Community:
$pmServer     = 'http://localhost:323';
$clientId     = 'YMLZWDATXYSIAASVTOGNPHRCYGUUAQNY';
$clientSecret = '1307993235b7f7467ca2c59050850691';
 
function pmRestLogin($clientId, $clientSecret, $username, $password) {
   global $pmServer, $pmWorkspace;
   $postParams = array(
      'grant_type'    => 'password',
      'scope'         => '*',       //set to 'view_process' if not changing the process
      'client_id'     => $clientId,
      'client_secret' => $clientSecret,
      'username'      => $username,
      'password'      => $password
   );
   $loginUrl = "$pmServer/$pmWorkspace/oauth2/token";
 
   $ch = curl_init($loginUrl);
   curl_setopt($ch, CURLOPT_TIMEOUT, 30);
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, $postParams);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
   $oToken = json_decode(curl_exec($ch));
   $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
   curl_close($ch);
 
   if ($httpStatus != 200) {
      print "Error in HTTP status code: $httpStatus";
   }
   elseif (isset($oToken->error)) {
      print "Error logging into $pmServer:\n" .
         "Error:       {$oToken->error}\n" .
         "Description: {$oToken->error_description}\n";
   }
   else {
      //At this point $oToken->access_token can be used to call REST endpoints.
 
      //If planning to use the access_token later, either save the access_token
      //and refresh_token as cookies or save them to a file in a secure location.
 
      //If saving them as cookies:
      //setcookie("access_token",  $oToken->access_token,  time() + 86400);
      //setcookie("refresh_token", $oToken->refresh_token); //refresh token doesn't expire
      //setcookie("client_id",     $clientId);
      //setcookie("client_secret", $clientSecret);
 
      //If saving to a file:
      //file_put_contents("/secure/location/oauthAccess.json", json_encode($tokenData));
   }
 
   return $oToken;
}

 
/*Function to obtain a new access token, using a refresh token. If the parameters are not specified
then get them from the cookie if they exist. The new access token is set as a cookie available at $_COOKIE["access_token"]
Parameters:
  clientId:     The cliend ID.
  clientSecret: The client secret code.
  refreshToken: The refreshToken from a previous call to /oauth2/token endpoint.
Return value:
  Object returned by /oauth2/token endpoint, which either contains access token or error message.*/
function pmRestRefresh($clientId=null, $clientSecret=null, $refreshToken=null) {
   global $pmServer, $pmWorkspace;
   $clientId     = ($clientId === null and isset($_COOKIE['client_id']))         ? $_COOKIE['client_id']     : $clientId;
   $clientSecret = ($clientSecret === null and isset($_COOKIE['client_secret'])) ? $_COOKIE['client_secret'] : $clientSecret;
   $refreshToken = ($refreshToken === null and isset($_COOKIE['refresh_token'])) ? $_COOKIE['refresh_token'] : $refreshToken;
 
   $aVars = array(
      'grant_type'    => 'refresh_token',
      'client_id'     => $clientId,
      'client_secret' => $clientSecret,
      'refresh_token' => $refreshToken
   );
 
   $ch = curl_init("$pmServer/$pmWorkspace/oauth2/token");
   curl_setopt($ch, CURLOPT_TIMEOUT, 30);
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, $aVars);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
   $oToken = json_decode(curl_exec($ch));
   $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
   curl_close($ch);
 
   if ($httpStatus != 200) {
      print "Error in HTTP status code: $httpStatus\n";
   }
   elseif (isset($oToken->error)) {
      print "Error logging into $pmServer:\n" .
         "Error:       {$oToken->error}\n" .
         "Description: {$oToken->description}\n";
   }
   else {
      //Save access token as a cookie that expires in 86400 seconds:
      setcookie("access_token",  $oToken->access_token, time() + 86400);
 
      //If saving to a file:
      //file_put_contents("/secure/location/oauthAccess.json", json_encode($oToken));
   }
   return $oToken;
}
 
/*Function to call a ProcessMaker REST endpoint and return the HTTP status code and
response if any.
Parameters:
 $method:      HTTP method: "GET", "POST", "PUT" or "DELETE"
 $endpoint:    The PM endpoint, not including the server's address and port number.
               Ex: "/api/1.0/workflow/cases"
 $aVars:       Optional. Associative array containing the variables to use in the request
               if "POST" or "PUT" method.
 $accessToken: Optional. The access token, which comes from oauth2/token. If not defined
               then uses the access token in $_COOKIE['access_token']
 $isJson       Optional. If set to TRUE, then $aVars is treated as a JSON string, 
               rather than an array of variables. 
Return Value:
 object {
    response: Response from REST endpoint, decoded with json_decode().
    status:   HTTP status code: 200 (OK), 201 (Created), 400 (Bad Request), 404 (Not found), etc.
 }                                                                                              */
function pmRestRequest($method, $endpoint, $aVars = null, $accessToken = null, $isJson=false) {
   global $pmServer;
 
   if (empty($accessToken) and isset($_COOKIE['access_token']))
      $accessToken = $_COOKIE['access_token'];
 
   if (empty($accessToken)) { //if the access token has expired
      //To check if the PM login session has expired: !isset($_COOKIE['PHPSESSID'])
      //header("Location: loginForm.php"); //change to match your login method
      throw new Exception("Access token is empty");
   }
 
   //add beginning / to endpoint if it doesn't exist:
   if (!empty($endpoint) and $endpoint[0] != "/")
      $endpoint = "/" . $endpoint;
 
   $ch = curl_init($pmServer . $endpoint);
   curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer " . $accessToken));
   curl_setopt($ch, CURLOPT_TIMEOUT, 30);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   $method = strtoupper($method);
 
   switch ($method) {
      case "GET":
         break;
      case "DELETE":
         curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
         break;
      case "PUT":
         curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
      case "POST":
         curl_setopt($ch, CURLOPT_POST, 1);
         if ($isJson) {
             curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
                    'Content-Type: application/json',                                                                                
                    'Content-Length: ' . strlen($aVars)
                )                                                                       
             );
             curl_setopt($ch, CURLOPT_POSTFIELDS, $aVars);
         }
         else {
             curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($aVars));
         }
         break;
      default:
         throw new Exception("Error: Invalid HTTP method '$method' $endpoint");
         return null;
   }
 
   $oRet = new StdClass;
   $oRet->response = json_decode(curl_exec($ch));
   $oRet->status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
   curl_close($ch);
 
   /*if ($oRet->status == 401) { //if session has expired or bad login:
      throw new Exception("Bad login or login expired."); //header("Location: loginForm.php"); //change to match your login method  
   }
   else*/if ($oRet->status != 200 and $oRet->status != 201) { //if error
      if ($oRet->response and isset($oRet->response->error)) {
         print "Error in $pmServer:\nCode: {$oRet->response->error->code}\n" .
               "Message: {$oRet->response->error->message}\n";
      }
      else {
         print "Error: HTTP status code: $oRet->status\n";
      }
   }
 
   return $oRet;
}

//login and execute endpoint:
echo "<pre>";
$oToken = pmRestLogin($clientId, $clientSecret, 'admin', 'admin');

$processId = "9998859365b74f911797718085511966";
$taskId = "9483920005b74f93dba3d92097940618";
$url = "/api/1.0/workflow/cases";
$aVars = array(
		'pro_uid' => $processId,
		'tas_uid' => $taskId
);

$oRet = pmRestRequest("POST", $url, $aVars, $oToken->access_token);
var_dump($oRet);
#817424
Hi,

Sorry for the delay, I was working on an another subject.

I tried using Authorization: Bearer and I have the same error (see the attachment).

I have this versions :
PHP : 5.6.38
Mariadb : 5.5.60

Thanks for your help.
Attachments
2018-10-17 11_24_49-Postman.png
2018-10-17 11_24_49-Postman.png (43.61 KiB) Viewed 2056 times
#817593
ProcessMaker 3.2.3 wasn't tested with MariaDB. It probably works, but nobody here has tried it.

Are you able to obtain an access token from ProcessMaker's oauth2 in Postman without any problems?
Have you tried executing other REST endpoints like GET /cases ?
POST /cases is tricky so try something easier first.

Just to verify that it truly doesn't work, can you try it in HttpRequester in Firefox? (Sorry, but I don't use Postman, so I'm not sure if your settings are correct.)
#822593
Hello Amosbatto,

Yes, I can obtain an access token from ProcessMaker.
I executed some GET requests and I have the same error.
I have the same problem in HttpRequester in Firefox.

I also removed MariaDB and installed MySQL (following the documentation) and I have the same error.

Thanks for your help.
Rym.
#822599
Let's do a test. Save the following script as a file named testrest.php on your computer:
Code: Select all
//PM 3.2.3 Community:
$pmServer     = 'http://localhost:323'; //set to domain or IP address of ProcessMaker server
$clientId     = 'YMLZWDATXYSIAASVTOGNPHRCYGUUAQNY';  
$clientSecret = '1307993235b7f7467ca2c59050850691';
 
function pmRestLogin($clientId, $clientSecret, $username, $password) {
   global $pmServer, $pmWorkspace;
   $postParams = array(
      'grant_type'    => 'password',
      'scope'         => '*',       //set to 'view_process' if not changing the process
      'client_id'     => $clientId,
      'client_secret' => $clientSecret,
      'username'      => $username,
      'password'      => $password
   );
   $loginUrl = "$pmServer/$pmWorkspace/oauth2/token";
 
   $ch = curl_init($loginUrl);
   curl_setopt($ch, CURLOPT_TIMEOUT, 30);
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, $postParams);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
   $oToken = json_decode(curl_exec($ch));
   $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
   curl_close($ch);
 
   if ($httpStatus != 200) {
      print "Error in HTTP status code: $httpStatus";
   }
   elseif (isset($oToken->error)) {
      print "Error logging into $pmServer:\n" .
         "Error:       {$oToken->error}\n" .
         "Description: {$oToken->error_description}\n";
   }
   else {
      //At this point $oToken->access_token can be used to call REST endpoints.
 
      //If planning to use the access_token later, either save the access_token
      //and refresh_token as cookies or save them to a file in a secure location.
 
      //If saving them as cookies:
      //setcookie("access_token",  $oToken->access_token,  time() + 86400);
      //setcookie("refresh_token", $oToken->refresh_token); //refresh token doesn't expire
      //setcookie("client_id",     $clientId);
      //setcookie("client_secret", $clientSecret);
 
      //If saving to a file:
      //file_put_contents("/secure/location/oauthAccess.json", json_encode($tokenData));
   }
 
   return $oToken;
} 
 
/*Function to call a ProcessMaker REST endpoint and return the HTTP status code and
response if any.
Parameters:
 $method:      HTTP method: "GET", "POST", "PUT" or "DELETE"
 $endpoint:    The PM endpoint, not including the server's address and port number.
               Ex: "/api/1.0/workflow/cases"
 $aVars:       Optional. Associative array containing the variables to use in the request
               if "POST" or "PUT" method.
 $accessToken: Optional. The access token, which comes from oauth2/token. If not defined
               then uses the access token in $_COOKIE['access_token']
 $isJson       Optional. If set to TRUE, then $aVars is treated as a JSON string, 
               rather than an array of variables. 
Return Value:
 object {
    response: Response from REST endpoint, decoded with json_decode().
    status:   HTTP status code: 200 (OK), 201 (Created), 400 (Bad Request), 404 (Not found), etc.
 }                                                                                              */
function pmRestRequest($method, $endpoint, $aVars = null, $accessToken = null, $isJson=false) {
   global $pmServer;
 
   if (empty($accessToken) and isset($_COOKIE['access_token']))
      $accessToken = $_COOKIE['access_token'];
 
   if (empty($accessToken)) { //if the access token has expired
      //To check if the PM login session has expired: !isset($_COOKIE['PHPSESSID'])
      //header("Location: loginForm.php"); //change to match your login method
      throw new Exception("Access token is empty");
   }
 
   //add beginning / to endpoint if it doesn't exist:
   if (!empty($endpoint) and $endpoint[0] != "/")
      $endpoint = "/" . $endpoint;
 
   $ch = curl_init($pmServer . $endpoint);
   curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer " . $accessToken));
   curl_setopt($ch, CURLOPT_TIMEOUT, 30);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   $method = strtoupper($method);
 
   switch ($method) {
      case "GET":
         break;
      case "DELETE":
         curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
         break;
      case "PUT":
         curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
      case "POST":
         curl_setopt($ch, CURLOPT_POST, 1);
         if ($isJson) {
             curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
                    'Content-Type: application/json',                                                                                
                    'Content-Length: ' . strlen($aVars)
                )                                                                       
             );
             curl_setopt($ch, CURLOPT_POSTFIELDS, $aVars);
         }
         else {
             curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($aVars));
         }
         break;
      default:
         throw new Exception("Error: Invalid HTTP method '$method' $endpoint");
         return null;
   }
 
   $oRet = new StdClass;
   $oRet->response = json_decode(curl_exec($ch));
   $oRet->status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
   curl_close($ch);
 
   /*if ($oRet->status == 401) { //if session has expired or bad login:
      throw new Exception("Bad login or login expired."); //header("Location: loginForm.php"); //change to match your login method  
   }
   else*/if ($oRet->status != 200 and $oRet->status != 201) { //if error
      if ($oRet->response and isset($oRet->response->error)) {
         print "Error in $pmServer:\nCode: {$oRet->response->error->code}\n" .
               "Message: {$oRet->response->error->message}\n";
      }
      else {
         print "Error: HTTP status code: $oRet->status\n";
      }
   }
 
   return $oRet;
}

//login and execute endpoint:
echo "<pre>";
//change 'my_username' and  '[email protected]' to a username and password on your system:
$oToken = pmRestLogin($clientId, $clientSecret, 'my_username', '[email protected]');

$url = "/api/1.0/workflow/cases/";
$oRet = pmRestRequest("GET", $url, null, $oToken->access_token);
var_dump($oRet);
Change the following lines to match your system:
$pmServer = 'http://localhost:323'; //set to domain or IP address of ProcessMaker server
$clientId = 'YMLZWDATXYSIAASVTOGNPHRCYGUUAQNY';
$clientSecret = '1307993235b7f7467ca2c59050850691';
$oToken = pmRestLogin($clientId, $clientSecret, 'my_username', '[email protected]');

Then execute the script from the command line, like this:
php testrest.php

Does it work? If so, then you aren't calling the endpoints correctly in Postman for some reason. Post screenshots of what you are doing in Postman.
#824879
i am facing the same issue as mention above. when i call api through external application, gives 401 error.in postman, its showing data. i have even set the all permissions(pm_rest_application,cases) to admin but still getting issue.
#824883
Bhupender wrote: Thu Jun 13, 2019 9:45 am i am facing the same issue as mention above. when i call api through external application, gives 401 error.in postman, its showing data. i have even set the all permissions(pm_rest_application,cases) to admin but still getting issue.
Bhupender, What happens if you execute testrest.php from the command line? If it works, then the problem is the parameters you are sending to Postman. Post screen shots of your login to oauth2 and your REST call in Postman.
#824902
Code:-
after getting auth token
Code: Select all
if (isset($oToken) and isset($oToken->access_token)) {
        $accessToken = $oToken->access_token;
        $ch1 = curl_init();
        curl_setopt($ch1, CURLOPT_URL, $pmServer."/api/1.0/wf/cases");
        curl_setopt($ch1, CURLOPT_HTTPHEADER, array("Authorization: Bearer". $accessToken));
        curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
        $aUsers = json_decode(curl_exec($ch1));
        print_r($aUsers);
        $statusCode = curl_getinfo($ch1, CURLINFO_HTTP_CODE);
        curl_close($ch1);

    foreach ($aUsers as $oUser) {
        print_r($oUser);
      if ($oUser->usr_status == "ACTIVE") {
      //   print "{$oUser->usr_firstname} {$oUser->usr_lastname} ({$oUser->usr_username})\n";
        print_r($oUser->usr_firstname);
      }
Screenshot from 2019-06-14 12-44-09.jpg
Screenshot from 2019-06-14 12-44-09.jpg (135.69 KiB) Viewed 698 times
erro2.jpg
erro2.jpg (305.05 KiB) Viewed 698 times
#824912
In Postman, add the access token value in the header like:
Bearer ACCESS_TOKEN

For example, if "5e8ff9bf55ba3508199d22e984129be6" is your access token, then use:
Bearer 5e8ff9bf55ba3508199d22e984129be6
3.1RestPostmanHeaderToken.png
3.1RestPostmanHeaderToken.png (25.3 KiB) Viewed 677 times
Is routes.php (that contains the error) your file?
#824962
Can you post your complete code? I don't see a problem in the little bit of PHP code that you posted.

Is routes.php your file or it is it ProcessMaker's shared/sites/{workspace}/routes.php file? I'm trying to determine where the error is occurring.
Change template of reset password

Is possible to change the template is send by ma[…]

Display PDF OR Xlsx OR Xls in Panel

Hi, It is not working. can you please share pmx f[…]

open case through dashboard

Thank you

I have done using session id. I have used version […]