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 1394 times
httpRequesterAuthorization.png
httpRequesterAuthorization.png (25.38 KiB) Viewed 1394 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 1270 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.
Custom fonts in skin

Dear Amosbatto, Sorry again, Probably,that was mi[…]

pmConnector error

/api/1.0/workflow/department/3720151675cda17ec8623[…]

Customize Case Number

Hey, Im using Process Maker 3.3.6 community versio[…]

I was able to enable oci8 based on the image, but […]