Odoo XML-RPC Traceback (most recent call last) - php

I'm new one on Odoo, and I don't have experience with the system and try to follow the documentation how they do it.
For my first thing what I need is to connect external PHP web application whit our Odoo system.
I see this is possible and I follow the steps on that documentation: Odoo Documentation
So I'm stick here:
$common = ripcord::client("$url/xmlrpc/2/common");
$common->version();
When I execute that lines of code I get that error:
[faultString] => Traceback (most recent call last):
File "/home/odoo/src/odoo/12.0/odoo/addons/base/controllers/rpc.py", line 63, in xmlrpc_2
response = self._xmlrpc(service)
File "/home/odoo/src/odoo/12.0/odoo/addons/base/controllers/rpc.py", line 42, in _xmlrpc
params, method = loads(data)
File "/usr/lib/python3.5/xmlrpc/client.py", line 1000, in loads
p.close()
File "/usr/lib/python3.5/xmlrpc/client.py", line 447, in close
parser.Parse(b"", True) # end of data
xml.parsers.expat.ExpatError: no element found: line 1, column 0
I use demo URL (https://demo.odoo.com/) which their recommend. And from first example I get username, password, database name, successfully. But after that I cannot do anything.
UPDATE:
That is my PHP class which I call for testing:
require_once(__DIR__ . '/Ripcode/ripcord.php');
class Ripcode
{
private $_url = 'https://demo.odoo.com/';
private $_server = [];
private $_connection = null;
private $_common = null;
public function __construct()
{
$this->_server = \ripcord::client($this->_url . 'start')->start();
$common = \ripcord::client($this->_url . "xmlrpc/2/common");
$common->version();
$models = \ripcord::client($this->_url . "xmlrpc/2/object");
$uid = $common->authenticate(
$this->_server['database'],
$this->_server['user'],
$this->_server['password'],
array()
);
showArray([
'server' => $this->_server,
'uid' => $uid
]);
showArray([
'server' => $this->_server,
'models' => $models,
'uid' => $uid
'common' => $common->version()
]);
}
}

The problem is ripcord. I tested one cloned from https://github.com/poef/ripcord with an Odoo v12 running locally and debugged from the reception of the request all the way through until the response is sent. Everything works seamlessly until it gets to ripcord.
May I suggest using another XML-RPC client?

Related

Magento 2 access Rest API interface from root file

I have created a script file in root and I want to create a new customer from that file below is my code for that.
use Magento\Framework\App\Bootstrap;
//use Magento\Customer\Api\Data\CustomerInterface;
require __DIR__ . '/../../app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$obj = $bootstrap->getObjectManager();
$obj->get('Magento\Framework\App\State')->setAreaCode('frontend');
$customerData = [
'customer' => [
'email' => 'demo#user.com',
'firstname' => 'John',
'lastname' => 'Wick',
],
'password' => 'John123'
];
$customer=$obj->get('\Magento\Customer\Api\AccountManagementInterface');
$customer->createAccount($customerData);
but when i run this code it gives me below error.
Fatal error: Uncaught TypeError: Argument 1 passed to Magento\Customer\Model\AccountManagement\Interceptor::createAccount() must be an instance of Magento\Customer\Api\Data\CustomerInterface, array given, called in C:\wamp64\www\mg\m2\rest\v3\Customer.php on line 82 and defined in C:\wamp64\www\mg\m2\generated\code\Magento\Customer\Model\AccountManagement\Interceptor.php:124
Stack trace:
0 C:\wamp64\www\mg\m2\rest\v3\Customer.php(82): Magento\Customer\Model\AccountManagement\Interceptor->createAccount(Array)
1 C:\wamp64\www\mg\m2\rest\v3\api.php(7): require_once('C:\wamp64\www\m...')
2 {main}
thrown in
C:\wamp64\www\mg\m2\generated\code\Magento\Customer\Model\AccountManagement\Interceptor.php on line
124
Please help. actually i want to access web api method directly from code and get response so that i can modify that response accordingly. because we already have app running in magento 1.9. so we don't want to change response
It's just like the error message says. You have to pass an implementation of Magento\Customer\Api\Data\CustomerInterface to the createAccount method.
So instead of passing a simple array like $customerData, you should create a new instance of a CustomerInterface implementation instead ... and fill it with the required data.
Searching through their github repo I found this:
Magento\Customer\Model\Data\Customer
https://github.com/magento/magento2/search?utf8=%E2%9C%93&q=%22implements+Magento%5CCustomer%5CApi%5CData%5CCustomerInterface%22&type=
So unless you want to create your own implementation, this is what you should pass to createAccount
You should be able to create one via the factory like so:
try {
$objectManager = $bootstrap->getObjectManager();
$objectManager->get(Magento\Framework\App\State::class)
->setAreaCode(\Magento\Framework\App\Area::AREA_FRONTEND);
/** #var \Magento\Customer\Api\Data\CustomerInterfaceFactory $customerFactory */
$customerFactory = $objectManager->create(\Magento\Customer\Api\Data\CustomerInterfaceFactory::class);
$customer = $customerFactory->create();
$customer
->setEmail('justincase#test123.xyz')
->setFirstname('Justin')
->setLastname('Case');
/** #var \Magento\Customer\Api\AccountManagementInterface $accountManager */
$accountManager = $objectManager->create(\Magento\Customer\Api\AccountManagementInterface::class);
$accountManager->createAccount($customer);
} catch (Exception $e) {
echo $e->getMessage();
}
Ok, since I was curious, I quickly (lol) installed magento2 myself. With the above example I was able to create a customer on a fresh magento2 install.

Sightengine API not working correctly?

I have recently come across an API called Sightengine which checks images for nudity, violence and some more things. I have followed their site to set up this API and got the following code in my PHP-file:
require __DIR__."/../Sightengine/src/SightengineClient.php";
require __DIR__."/../Sightengine/src/Check.php";
$filterImage = new Sightengine\SightengineClient('189981095', '5snnKqMiPU8cx2fHuUff');
$resultFilterImage = $filterImage->check(['nudity'])->set_url('https://d3m9459r9kwism.cloudfront.net/img/examples/example7.jpg');
Now, this should work and give back a JSON with information in it about how nude the picture is, but when trying to run this, it gives me the follow error:
Fatal error: Uncaught Error: Class 'GuzzeleHttp\Client' not found in C:\xampp\htdocs\ugesco\Sightengine\src\SightengineClient.php:13
Stack trace:
#0 C:\xampp\htdcos\ugesco\Controller\controller.php(234):
Sightengine\SightengineClient->__construct('my user key', 'my pass key')
#1 {main}
thrown in C:\xampp\htdocs\Ugesco\Sightengine\src\SightengineClient.php on line 13
Now, what I get out of this is that the class GuzzleHttp\Client can't be found in the SightengineClient.php-file. Thing is, I copied this from the Sightengine-company their Github, so I have no clue why it is not there..?
This is the code in the SightengineClient.php:
<?php
namespace Sightengine;
class SightengineClient {
private $api_user;
private $api_secret;
private $endpoint = 'https://api.sightengine.com/';
private $http;
function __construct($api_user, $api_secret) {
$this->api_user = $api_user;
$this->api_secret = $api_secret;
$this->http = new \GuzzleHttp\Client(['base_uri' => $this->endpoint, 'User-Agent' => 'SE-SDK-PHP' . '1.0']);
}
public function feedback($model, $modelClass, $image) {
$url = '1.0/feedback.json';
if (filter_var($image, FILTER_VALIDATE_URL)) {
$r = $this->http->request('GET', $url, ['query' => ['api_user' => $this->api_user, 'api_secret' => $this->api_secret, 'model' => $model,'class' => $modelClass,'url' => $image]]);
return json_decode($r->getBody());
}
else {
$file = fopen($image, 'r');
$r = $this->http->request('POST', $url, ['query' => ['api_user' => $this->api_user, 'api_secret' => $this->api_secret, 'model' => $model,'class' => $modelClass],'multipart' => [['name' => 'media','contents' => $file]]]);
return json_decode($r->getBody());
}
}
public function check($models) {
return new Check($this->api_user, $this->api_secret, $models);
}
}
As you can see on line 13 it wants to make a new GuzzeleHttp\Client but that Client-class is nowhere to be found. You can check their Github yourself: https://github.com/Sightengine/client-php
This is a real company who offers packages of image checks for money, so how could this be that their code is not working anymore (or is this an easy fix?).
Thanks in advance!
It does work if you perform a proper install using composer:
composer require sightengine/client-php
guzzlehttp/guzzle is correctly listed as a dependency in the composer.json file: https://github.com/Sightengine/client-php/blob/master/composer.json

AWS SQS Delete Messages Using Receipt Handle

I am trying to set up SQS and after receiving the message, I need to delete it from the queue.
Creating Client -
$client = Aws\Sqs\SqsClient::factory(array(
'key' => '******',
'secret' => '******',
'region' => 'ap-southeast-1'
));
Sending Message
public static function SendMessage()
{
if(!isset(self::$queueUrl))
self::getQueueUrl();
$command = "This is a command";
$commandstring = json_encode($command);
self::$client->sendMessage(array(
'QueueUrl' => self::$queueUrl,
'MessageBody' => $commandstring,
));
}
Receiving Message
public static function RecieveMessage()
{
if(!isset(self::$queueUrl))
self::getQueueUrl();
$result = self::$client->receiveMessage(array(
'QueueUrl' => self::$queueUrl,
));
// echo "Message Recieved >> ";
print_r($result);
foreach ($result->getPath('Messages/*/Body') as $messageBody) {
// Do something with the message
echo $messageBody;
//print_r(json_decode($messageBody));
}
foreach ($result->getPath('Messages/*/ReceiptHandle') as $ReceiptHandle) {
self::$client->deleteMessage(self::$queueUrl, $ReceiptHandle);
}
}
When I try to delete the message using the Receipt Handle in the receive message code, I get error from Guzzle -
Catchable fatal error: Argument 2 passed to Guzzle\Service\Client::getCommand() must be an array, string given,
Now after searching a lot for it, I was able to find similar questions which state that they were using wrong SDK version. I am still not able to narrow it down though. I am using the zip version of the latest sdk 2.6.15
Why don't you give this a try this:
self::$client->deleteMessage(array(
'QueueUrl' => self::$queueUrl,
'ReceiptHandle' => $ReceiptHandle,
));
The Basic formatting example in the API docs for SqsClient::deleteMessage() (and other operations) should help. All of the methods that execute operations take exactly one parameter, which is an associative array of the operation's parameters. You should read through the SDK's Getting Started Guide (if you haven't already), which talks about how to perform operations in general.

AWS PHP SDK 2 (aws.phar) does not work with Restler Framework

I have been testing some PHP scripts that uses the aws-sdk-php to upload files to S3 storage. These scripts seems to work nicely when they are executed directly from the browser, but fails when trying to use it through an API class in Luracast Restler 3.0
A sample script that upload some dummy file is like the following:
<?php
require_once (dirname(__FILE__) . "/../lib/aws/aws.phar");
use Aws\Common\Aws;
use Aws\S3\Enum\CannedAcl;
use Aws\S3\Exception\S3Exception;
use Aws\Common\Enum\Region;
function test(){
// Instantiate an S3 client
$s3 = Aws::factory(array(
'key' => 'key',
'secret' => 'secret',
'region' => Region::EU_WEST_1
))->get('s3');
try {
$s3->putObject(array(
'Bucket' => 'my-bucket',
'Key' => '/test/test.txt',
'Body' => 'example file uploaded from php!',
'ACL' => CannedAcl::PUBLIC_READ
));
} catch (S3Exception $e) {
echo "There was an error uploading the file.\n";
}
}
This script is placed in the folder /util/test.php, while the aws-php-sdk is at /lib/aws/aws.phar
To test that this test method is well written I have created another php script at /test/upload.php with the following code:
<?php
require_once (dirname(__FILE__) . '/../util/test.php');
test();
So I can enter in the browser http://mydomain.com/test/upload.php and all is working as expected and the file is uploaded in S3 storage.
However when I call the function test() from an API class with the Restler framework, I have an error that says that Aws cannot be found:
Fatal error: Class 'Aws\Common\Aws' not found in /var/app/current/util/test.php on line 12
However the code is exactly the same that perfectly works when called from upload.php. I have been wasting hours trying to figure out what is happening here, but I cannot get any conclusion. Is like the aws-php-sdk autoloader does not work well under some circumstances.
Any hints?
This held me back quite some time,
The issue is caused by reslters autoloader which sets spl_autoload_unregiste
as described here:
https://github.com/Luracast/Restler/issues/72
One way to get arround the problem is to comment out the relevant lines in vendor/Luracast/Restler/AutoLoader.php
public static function thereCanBeOnlyOne() {
if (static::$perfectLoaders === spl_autoload_functions())
return static::$instance;
/*
if (false !== $loaders = spl_autoload_functions())
if (0 < $count = count($loaders))
for ($i = 0, static::$rogueLoaders += $loaders;
$i < $count && false != ($loader = $loaders[$i]);
$i++)
if ($loader !== static::$perfectLoaders[0])
spl_autoload_unregister($loader);
*/
return static::$instance;
}

cakephp & nusoap - Function ("my_function") is not a valid method for this service

I have taken over an application from a previous developer, and there was some code which was half finished using Nusoap, I am getting the error:
Call to register_donation() web service failed due to an exception:
Function ("register_donation") is not a valid method for this service
The application is built on: CakePHP 1.2.10 & using nuSoap 0.9.5.
I have already ini_set('soap.wsdl_cache_enabled', 0); (This doesnt help.)
My code is below (I shortened it for readability), Am I processing this response correctly?
(The code was taken over by myself from a previous developer).
The Pastebin (of the full code) is here: PasteBin Link
A shortened version is below for a glance over, the full version is in the pastebin link above.
<?php
ini_set('soap.wsdl_cache_enabled', 0);
class ServicesController extends AppController
{
var $uses = array("Donation");
var $components = array( "Email", "MatchingEvents" );
function registerDonation($donation = null){
$this->log('hit registerDonation', 'donation');
$this->autoRender = false;
App::import('Vendor','nusoap');
Configure::write('debug',0);
Configure::write('Session.start', false);
//init soap server
$server = new soap_server();
$endpoint = 'http://new.mysite.com/services/registerDonation';
//initialize WSDL support
$server->configureWSDL('donations', 'urn:donations', $endpoint);
//setup service type
$server->wsdl->addComplexType(
'DonationResult',
'complexType',
'struct',
'all',
'',
array(
'success' => array('name' => 'success', 'type' => 'xsd:boolean'),
'msg' => array('name' => 'msg', 'type' => 'xsd:string'),
'error_number' => array('name' => 'error_number', 'type' => 'xsd:string')
)
);
//register the method to expose
$server->register('register_donation',
array('ct_number' => 'xsd:string', 'project_id' => 'xsd:int', 'donation_amount' => 'xsd:decimal',
// Stripped all other params
),
array(
'result' => 'tns:DonationResult'
),
'urn:donations',
'urn:donations#register_donation',
'rpc',
'encoded',
'Accepts the results of a donation to a charity or project on the site'
);
//This inner function is registered and then called (keep within outer function!)
function register_donation(
// Pass in all the params (Stripped for readability)
$ct_number = null, $project_id = null, $donation_amount = null
){
// This function is never hit!.. its not registered, why?
$this->log('hit #3-register_donation called!', 'donation');
$return = $this->Donation->add(array(
'unique_id' => $unique_id,
'ct_number' => $ct_number,
'project_id' => $project_id,
'donation_amount' => $donation_amount,
// Pass in all other params, (Stripped for readability)
));
// Process that request
$log = $this->Donation->log . 'Result: ' . $return['msg'] . "\n";
$this->log( $log, 'donation' );
if ( isset($this->Donation->matching['events']) )
{
//Reserved donations should already have had their events handled
$this->MatchingEvents->handle($this->Donation->matching, !$this->Donation->matching['reserved']);
}
if ( !empty($this->Donation->cacheSaved) )
$this->_sendDonationEmails($this->Donation->cacheSaved);
return $return;
}
$HTTP_RAW_POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
$server->service($HTTP_RAW_POST_DATA);
}
function _sendDonationEmails($donation)
{
// Send the emails
}
}
?>
If there is any more information I can provide, please let me know.
To Summarise: How do I process a nusoap response coming from a external source.
Any debugging ideas, hints & tips or solution will be rewarded (+1!).
In the code posted there's a function named registerDonation inside a controller named ServicesController. Inside that function there is another function called register_donation (This obviously doesn't make sense [Old Code]).
Remove the function named register_donation out of the registerDonation method and place it as a method inside the ServicesContoller.
Then change the following line (where you register the function to expose).
From: $server->register('register_donation',
To: $server->register('ServicesController.register_donation',
So you're calling class.method as opposed to method only (This would work in PHP4 procedural programming, but in OOP, you need to specify the controller.method when exposing the function).
Having other problems?
Q: CakePHP & nuSOAP is not hitting my controller/method, but redirects to app/webroot
A: Using CakePHP 1.2, I found when it did not have a services model (because it wasn't
technically required), The request does not hit the controller. So if you're having this issue, create a model for your controller, even if you're not using it. For your reference, here a modal example:
<?php // You may not need this modal, but cakephp requires it to be there.
class Services extends AppModel {
public $name = 'Services';
public $useTable = false;
}
?>
Q:What URL should I be receiving responses to?
A: The URL you set your response to hit must include ?wsdl.
So.. for eg: you have a controller named SOAPController and method named process.
In CakePHP, your URL would look like this: mydomain.com/SOAP/process.
So your WSDL is located at mydomain.com/SOAP/process?wsdl. Make sure your callback URL is set to this (including the wsdl).
Q: How do I debug SOAP requests/responses using CakePHP?
A: CakePHP has a logging feature which proved invaluable in debugging SOAP. In your controller (or modal) you can use:
$this->log('your message or variable', 'name_of_file_to_save_to);
You can use this through your SOAP request or response to see what parts are being hit/called and debugging variables (eg: $HTTP_RAW_POST_DATA).
Q: My WSDL location is shown as `domain.com/app/webroot` when I visit the SOAP page.
A: I thought this was the issue causing all the problems, Looking at the source code Nusoap uses PHP_SELF to get the current script (which in cakePHP is app/webroot/index.php), Don't worry about this, you can access the wsdl by appending the URL with ?wsdl, This will show you your generated WSDL file, You don't need to worry about fixing this. Its not interfering with your SOAP request whatsoever, It's merely there for your convenience.
Q: My SOAP address location is showing 'domain.com/app/webroot/index.php`
A: This was a issue I fixed by including the $endpoint in the configureWSDL().
//Set our endpoint, Replace with your URL
$endpoint = 'http://yourdomain.com/controller/method';
//initialize WSDL support - Include the $endpoint.
$server->configureWSDL('donations', 'urn:donations', $endpoint);
// Now your Soap Address Location should be what you set as the $endpoint

Categories