Create user using Moodle webservice - php

I have tried to create a new user on the Moodle by web service api.
I tried with a example that i found on the github and with another php code
In the both i receive the same response:
"Missing required key in single structure: users"
the response:
{
"exception":"invalid_parameter_exception",
"errorcode":"invalidparameter",
"message":"Invalid parameter value detected",
"debuginfo":"Missing required key in single structure: users"
}
I try to change the object by a array, but the error continues.
my code:
$functionname = 'core_user_create_users';
$user1 = new stdClass();
$user1->id = 1;
$user1->username = 'testusername1';
$user1->password = 'testpassword1';
$user1->firstname = 'testfirstname1';
$user1->lastname = 'testlastname1';
$user1->email = 'testemail1#moodle.com';
$user1->auth = 'manual';
$user1->idnumber = 'testidnumber1';
$user1->description = 'Hello World!';
$user1->city = 'testcity1';
$user1->country = 'BR';
$token = 'mytoken';
$domainname = 'localhost/moodle';
$functionname = 'core_user_create_users';
$restformat = 'json';
$serverurl = $domainname . '/webservice/rest/server.php'. '?wstoken=' . $token . '&wsfunction='.$functionname.'&moodlewsrestformat=' . $restformat;
$users = array($user1);
$params = array('users' => $users);
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => 'Content-Type: text/plain',
'content' => $params
)
));
$contents = file_get_contents($serverurl, null, $context);
//print_r($contents);
$resposta = json_decode($contents);
I have a valid token and the user is allowed to use the core_user_create_users function

get same problem with required key 'users'
solve problem with this =>
$serverurl = $domainname . '/webservice/rest/server.php'. '?wstoken=' . $token . '&wsfunction='.$functionname;
//require_once('../curl.php');
$curl = new curl;
$params = "&users[0][username]=loginnn&users[0][password]=4815162342Qq*&users[0][firstname]=allala&users[0][lastname]=trest&users[0][email]=ty#mail.ru";
//if rest format == 'xml', then we do not add the param for backward compatibility with Moodle < 2.2
$restformat = ($restformat == 'json')?'&moodlewsrestformat=' . $restformat:'';
$resp = $curl->post($serverurl . $restformat, $params);

I think You must high the debugging level in your moodle system, I hope you will get more useful information regarding this error, debugging will help you to reach the exact problem. go through following path:
Home ► Site administration ► Development ► Debugging
choose Developer level from the debug messages and save the changes

I have a similar problem once, in my experience is a problema with $user1->password = 'testpassword1'; Moodle needs a password with one uppercase letter and at least one simbol like / . , - _ etc.
try a new password maybe it works...

Do not pass the ID into the user array, as it doesn't accept it as a parameter. For more details, please read the WebService API documentation for creating a user in Moodle.

came across the same need today and I used your post to get the code from GitHUB so I guess I'd tell you how I fixed the error:
change your code to the following:
$users = array((array)$user1);
$params = array('users' => (array)$users);
The code from GitHUB $user1 is an object. Moodle required an Array.
Below is copied from Moodle's documentation.
[users] =>
Array
(
[0] =>
Array
(
[username] => string
[password] => string
[firstname] => string
[lastname] => string
[email] => string
[auth] => string
[idnumber] => string
[lang] => string
[calendartype] => string
[theme] => string
[timezone] => string
[mailformat] => int
[description] => string
[city] => string
[country] => string
[firstnamephonetic] => string
[lastnamephonetic] => string
[middlename] => string
[alternatename] => string
[preferences] =>
Array
(
[0] =>
Array
(
[type] => string
[value] => string
)
)
[customfields] =>
Array
(
[0] =>
Array
(
[type] => string
[value] => string
)
)
)
)

In our case, we added Https support, but we were still calling the Http version of the Moodle url. Changing to Https solved the problem.

This is tested and working on Moodle 3.1.2 - I find this a much cleaner and easier to understand solution, using a proper array (as Moodle expects) native cURL and http_build_query...
Make sure the password you are providing to Moodle meets your security requirements.
$moodledata['users'][] = array(
'username' => 'testuser123',
'password' => 'TestPass1!',
'firstname' => 'Firstname',
'lastname' => 'Lastname',
'email' => 'test#test.com',
);
//open connection
$token = 'your-token-goes-here';
$domainname = 'https://yourmoodlesite.tld';
$functionname = 'core_user_create_users';
$url = $domainname . '/webservice/rest/server.php?wstoken=' . $token . '&wsfunction='.$functionname."&moodlewsrestformat=json";
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($moodledata));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//execute post, and get our JSON as defined above with moodlewsrestformat=json
$result = curl_exec($ch);
//if you want it in an array
//$result = json_decode($result, true);

Related

make same Rest call from azure to sugarcrm return different result

my sugarcrm site local on a linux ubantu site , and I write some PHP files make rest call to this site , these PHP files on azure cloud.
I find even for a simple rest call , sometimes it will return correct result , but sometimes it return "Invalid session" , just like below :
Array ( [name] => Invalid Session ID [number] => 11 [description] => The session ID is invalid )
I mean when I refresh the request php constently , what it return is not certain . If I locate these PHP file in my local machine , not azure , then no matter how many request I test , all will get correct result.
my rest request 's sequence is :
first login with admin username and pwd like below :
$url = "http://crm.abc.xyz/service/v4_1/rest.php";
ini_set('max_execution_time', 300);
function restRequest($method, $arguments){
global $url;
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$post = array(
"method" => $method,
"input_type" => "JSON",
"response_type" => "JSON",
"rest_data" => json_encode($arguments),
);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($curl);
curl_close($curl);
return json_decode($result,1);
}
$carrierID = '9';
$userAuth = array(
'user_name' => 'admin',
'password' => md5('XXXXXXX'),
);
$appName = 'My SuiteCRM REST Client';
$nameValueList = array();
$args = array(
'user_auth' => $userAuth,
'application_name' => $appName,
'name_value_list' => $nameValueList);
$result = restRequest('login',$args);
$sessId = $result['id'];
once get return session id into variable $sessId , use this session to make other rest call :
$entryArgs = array(
'session' => $sessId,
'module_name' => 'Accounts',
'query' => "carrierid_c ='999'",
'max_results' => 2,
'deleted' => 0,
);
$result = restRequest('get_entry_list',$entryArgs);
print_r($result);
when print_r($result); sometimes it display :
Array ( [result_count] => 0 [total_count] => 0 [next_offset] => 0 [entry_list] => Array ( ) [relationship_list] => Array ( ) )
mean no this account , this is correct ,
but somethimes it display :
Array ( [name] => Invalid Session ID [number] => 11 [description] => The session ID is invalid )
My guess is when the request send to ubantu site from azure , it maybe from different instance , so sugarcrm at ubantu recv same user 's request from different IP and think it is fake session , I do not know if this guess is correct , also do not know how to fix it in azure , appreciate for your help .
I have find the answer , azure do send request to sugarcrm var different IP , to avoid "invalid session " , I need uncheck "validate client IP" in system setting ----> advance

Sharepoint GetListItemChangesSinceToken CURL request in PHP

I'm trying to get the latest changes from my documentlist in Sharepoint using PHP and GetListItemChangesSinceToken. I'm using phpSPO as a SDK since there aren't any official Sharepoint SDK's for PHP.
So far I have this:
$payload = array(
'query' => array(
'__metadata' => array('type' => 'SP.ChangeLogItemQuery'),
'ViewName' => '',
'QueryOptions'=> '<QueryOptions><Folder>Shared Documents</Folder></QueryOptions>'
)
);
$headers = array();
$headers["X-HTTP-Method"] = "MERGE";
$changes = $this->request->executeQueryDirect($this->settings->URL . "/_api/web/Lists/GetByTitle('Documents')/GetListItemChangesSinceToken", $headers, $payload);
Which returns: {"error":{"code":"-2147467261, System.ArgumentNullException","message":{"lang":"en-US","value":"Value cannot be null.\r\nParameter name: query"}}}
I've tried changing the X-HTTP-Method and changing the array to fit the documented JSON/XML request (XML in JSON objects, come on Microsoft)
First approach
The following example demonstrates how to utilize GetListItemChangesSinceToken method:
$listTitle = "Documents";
$payload = array(
'query' => array(
'__metadata' => array('type' => 'SP.ChangeLogItemQuery'),
'ViewName' => '',
'QueryOptions'=> '<QueryOptions><Folder>Shared Documents</Folder></QueryOptions>'
)
);
$request = new ClientRequest($webUrl,$authCtx);
$options = array(
'url' => $webUrl . "/_api/web/Lists/GetByTitle('$listTitle')/GetListItemChangesSinceToken",
'data' => json_encode($payload),
'method' => 'POST'
);
$response = $request->executeQueryDirect($options);
//process results
$xml = simplexml_load_string($response);
$xml->registerXPathNamespace('z', '#RowsetSchema');
$rows = $xml->xpath("//z:row");
foreach($rows as $row) {
print (string)$row->attributes()["ows_FileLeafRef"] . "\n";
}
Second approach
Since SharePoint REST Client SDK for PHP now supports GetListItemChangesSinceToken method, the previous example could be invoked like this:
$list = $ctx->getWeb()->getLists()->getByTitle($listTitle);
$query = new ChangeLogItemQuery();
//to request all the items set ChangeToken property to null
$query->ChangeToken = "1;3;e49a3225-13f6-47d4-a146-30d9caa05362;635969955256400000;10637059";
$items = $list->getListItemChangesSinceToken($query);
$ctx->executeQuery();
foreach ($items->getData() as $item) {
print "[List Item] $item->Title\r\n";
}
More examples could be found here under phpSPO repository.

need to extract a particular field from $response object

<?php
$apiKey = 'HnUvAYIy5hO7iPki';
$apiSecret = '9HBkibOphng7w4p1ZdiiVJgzRI4kpD4Q';
$msg = filter_input(INPUT_GET,"msg",FILTER_SANITIZE_STRING);
$message = array(
'message' => array(
'message' => ''.$msg.'',
'chatBotID' => 6,
'timestamp' => time()
),
'user' => array(
'firstName' => 'Tugger',
'lastName' => 'Sufani',
'gender' => 'm',
'externalID' => 'abc-639184572'
)
);
// construct the data
$host = "http://www.personalityforge.com/api/chat/";
$messageJSON = json_encode($message);
$hash = hash_hmac('sha256', $messageJSON, $apiSecret);
$url = $host."?apiKey=".$apiKey."&hash=".$hash."&message=".urlencode($messageJSON);
// Make the call using cURL
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// make the call
$response = curl_exec($ch);
curl_close($ch);
echo 'Response JSON: '.$response.'<br>';
?>
-----------------following is the outcome of above code--------------------------------
Response JSON:
Correct parameters and objects received
raw message: {"message":{"message":"hi","chatBotID":6,"timestamp":1407393907},"user":{"firstName":"Tugger","lastName":"Sufani","gender":"m","externalID":"abc-639184572"}}
apiSecret: 9HBkibOphng7w4p1ZdiiVJgzRI4kpD4Q
Do the following two match?
a702fc336f49b099764d35a548dd110fac2067bcd14a438676e4d579d70b6afc
a702fc336f49b099764d35a548dd110fac2067bcd14a438676e4d579d70b6afc
CORRECT MATCH!
Array
(
[message] => Array
(
[message] => hi
[chatBotID] => 6
[timestamp] => 1407393907
)
[user] => Array
(
[firstName] => Tugger
[lastName] => Sufani
[gender] => m
[externalID] => abc-639184572
)
)
sent on Thu, 07 Aug 2014 2:45:07 am
6 seconds ago. (limit is 300)
{"success":1,"errorMessage":"","message":{"chatBotName":"Desti","chatBotID":"6","message":"Yes, Tugger, I've heard that one before.","emotion":"normal"}}
now i need to get the message field content that is in italics
thanks in advance.... pls help... i tried a lot :-)
if you look forward to have a regex solution here it is
Regex
"message":"(.*?)"
TestString
{"success":1,"errorMessage":"","message":{"chatBotName":"Desti","chatBotID":"6","message":"Yes, Tugger, I've heard that one before.","emotion":"normal"}
Result
MATCH 1
[91-131] Yes, Tugger, I've heard that one before.
try demo here
PHP usage
preg_match('/(?<=success).*"message":"(.*?)"/', $response , $matches);
$message = $matches[1];
regex updated to match with the full response text
try demo here
use json_decode(), it will return
(
[success] => 1
[errorMessage] =>
[message] => stdClass Object
(
[chatBotName] => Desti
[chatBotID] => 6
[message] => Yes, Tugger, I've heard that one before.
[emotion] => normal
)
Sample :
$output = json_decode($input,true);
print_r($output);
echo "<br />".$output['message']['message'];
?>

OAuth Google Analytics Authentication with PHP

I am trying to get OAuth to work with Google Analytics, but I'm not having any luck. My code looks like this:
require_once('common.inc.php');
$consumerKey = "my.url.net";
$consumerSecret = "nzZ....TX";
$sig_method = "HMAC-SHA1";
$oauth_token = $token ? new OAuthToken($token, $token_secret) : NULL;
$token_endpoint = '/accounts/OAuthGetRequestToken';
$scope = 'https://www.google.com/analytics/feeds/';
$callback_url = "http://my.url.net/pete/oauth/";
$privKey = NULL;
$params = array('scope' => $scope, 'oauth_callback' => $callback_url);
$url = $token_endpoint . '?scope=' . urlencode($scope);
$consumer = new OAuthConsumer($consumerKey, $consumerSecret);
$req = OAuthRequest::from_consumer_and_token($consumer, $oauth_token, 'GET',
$url, $params);
//$req->sign_request($sig_method, $consumer, $oauth_token, NULL);
echo "<PRE>";
print_r($req);
// Fill response
echo json_encode(array(
'html_link' => '',
'base_string' => $req->get_signature_base_string(),
'response' => send_signed_request('GET', $url, array($req->to_header())),
'authorization_header' => $req->to_header()
));
So when this code runs it prints this:
OAuthRequest Object
(
[parameters:OAuthRequest:private] => Array
(
[oauth_version] => 1.0
[oauth_nonce] => 5f....11
[oauth_timestamp] => 1306433873
[oauth_consumer_key] => my.url.net
[scope] => https://www.google.com/analytics/feeds/
[oauth_callback] => http://my.url.net/pete/oauth/
)
[http_method:OAuthRequest:private] => GET
[http_url:OAuthRequest:private] => /accounts/OAuthGetRequestToken?scope=https%3A%2F%2Fwww.google.com%2Fanalytics%2Ffeeds%2F
[base_string] =>
)
When I uncomment this line:
//$req->sign_request($sig_method, $consumer, $oauth_token, NULL);
The script just fails to load showing Server Error. What am I doing wrong? Any advice would help, thanks!
Thanks for your comment Mark, this was actually because my "$sig_method" variable was actually just a string containing "HMAC..." when it actually needed to be an object called this:
$sig_method = new OAuthSignatureMethod_HMAC_SHA1();
Hope this helps someone in the future!

Zend_Service_Twitter Oauth Incorrect Signature

I have sucessfully connected to twitter using Zend_Oauth_Consumer and got an access token, however when i try to use this access token i am getting an error.
This is the code:
$token = unserialize($twsession->access_token); # would be in DB
$twitter = new Zend_Service_Twitter(array(
'username' => $token->screen_name,
'accessToken' => $token
));
$response = $twitter->account->verifyCredentials();
This outputs:
Zend_Rest_Client_Result Object (
[_sxml:protected] => SimpleXMLElement Object
(
[request] => /1/account/verify_credentials.xml
[error] => Incorrect signature
)
[_errstr:protected] => )
I assume the code is actually correct, its hard to tell as the examples on the ZF site are incomplete.
FWIW i am using Zend Framework 1.10.8
some fields were missing:
$token = unserialize($twsession->access_token); # would be in DB
$twitter = new Zend_Service_Twitter(array(
'username' => $token->screen_name,
'accessToken' => $token
));
$response = $twitter->account->verifyCredentials();
should be:
$token = unserialize($twsession->access_token); # would be in DB
$twitter = new Zend_Service_Twitter(array(
'username' => $token->screen_name,
'accessToken' => $token,
'consumerKey' => YOUR_APP_CONSUMER_KEY,
'consumerSecret' => YOUR_APP_CONSUMER_SECRET,
'callbackUrl' => YOUR_CALLBACK_URL
));
$response = $twitter->account->verifyCredentials();
To confirm, for a valid signature you need all the same fields that you are using with Zend_Oauth_Consumer

Categories