Migrating SOAP functionality from PHP to Perl using SOAP::WSDL - perl

I'm struggling to get SOAP working in perl.
In PHP it works perfectly, and without any trouble. And now I'm trying to do the same thing in Perl.
The functional PHP is:
$client = new SoapClient("http://thirdpartyurl.com/api.aspx?WSDL");
$info = $client->GetSomeInfo(array('username' => 'myusername', 'password' => 'mypassword'));
Which works great, but I just can't get it working in perl. I tried SOAP::Lite, but didn't make any progress. And I'm now trying SOAP::WSDL:
use SOAP::WSDL;
my $wsdl = SOAP::WSDL->new(wsdl => 'http://thirdpartyurl.com/api.aspx?WSDL');
my $info = $wsdl->call('GetSomeInfo', 'username', 'myusername', 'password', 'mypassword');
Which just doesn't work.
I looked at the raw requests, and the perl version isn't even sending the user/pass parameters through. What am I doing wrong?

For what it's worth, I achieved authentication, and managed to get parameters sent by using the following:
use SOAP::Lite;
my $service = SOAP::Lite->proxy($service_url)->uri($service_url);
sub SOAP::Transport::HTTP::Client::get_basic_credentials {
return 'myusername' => 'mypassword';
}
my $result = $service->insert(
SOAP::Data->name(
'data' => \SOAP::Data->value(
SOAP::Data->name(
'item' => \SOAP::Data->value(
SOAP::Data->name('key' => 'name'),
SOAP::Data->name('value' => 'new_campaign_x')
)
)
)
)->type('Map')
);
Is there a better way to achieve the same results? I realise overwriting 'get_basic_credentials' is a bit hacky.

I've had pretty good luck with SOAP::Lite in my applications. The username/password combo, is that supposed to be authenticating at the HTTP layer or the SOAP layer? Or just regular soap parameters?

When I want to do SOAP, I reach for XML::Compile.

Related

Using Zend Mail with SMTP Authentication gives an error

I'm trying to create a form that sends an email using SMTP authentication, but I keep receiving an error. I've read a bunch of posts online and this is the code I've come up with so far. Does anyone see anything wrong with the code below? Any help would be greatly appreciated.
Thanks
Bob
$configSMTP = array(
'port' => 587,
'auth' => 'login',
'username' => '***',
'password' => '***'
);
$transport = new Zend_Mail_Transport_Smtp('mail.server.com', $configSMTP);
$mail = new Zend_Mail();
$mail->setReplyTo($config['replyto']);
$mail->setBodyText($message);
$mail->setFrom($params[$config['emailID']], $params[$config['nameID']]);
$mail->addTo($config['sendto']);
$mail->setSubject($config['subject']);
try {
$mail->send($transport);
} catch(Exception $ex) {
Mage::getSingleton('core/session')->addError('There was an error submitting your request.');
}
Mandril's SMTP uses TLS.
http://help.mandrill.com/entries/21738477-What-SMTP-ports-can-I-use-
Enable it in your config array.
$configSMTP = array(
'ssl' => 'tls',
'port' => 587,
'auth' => 'login',
'username' => '***',
'password' => '***'
);
Would direct you maybe to section on resource plugins form Zend Mail. Give a better list of the options and shows how to assign them through your app.ini file.
That said, assuming your arguments are valid that looks fine.
What exception are you catching? You must be getting an error message. Can you telnet from this machine to your mail server? Want to eliminate network/auth issues.
It's hard to say without knowing what exception you're getting.
There might be several reasons, can you connect to the SMTP-server.. Is the port 587 really open? Do you have a firewall, and if so, might it be blocking the connection to that port? Are you really sure those credentials are valid? Have you tried manually connecting to the SMTP-server?
If not, see how you can do it with Telnet: How to test an SMTP server using Telnet
You could also try using a transactional email service. That way you wouldn't need to manage an SMTP-server or even think about deliverability, etc. You would just outsource it to someone else.
There are various providers, some of them are:
AlphaMail
Mandrill
PostageApp
If you're using AlphaMail, you could just use the AlphaMail PHP-client and send your emails like the example below:
include_once("comfirm.alphamail.client/emailservice.class.php");
$email_service = AlphaMailEmailService::create()
->setServiceUrl("http://api.amail.io/v1")
->setApiToken("YOUR-ACCOUNT-API-TOKEN-HERE");
$person = new stdClass();
$person->userId = "1234";
$person->firstName = "John";
$person->lastName = "Doe";
$person->dateOfBirth = 1975;
$response = $email_service->queue(EmailMessagePayload::create()
->setProjectId(12345) // You AlphaMail project (determines template, options, etc)
->setSender(new EmailContact("Sender Company Name", "from#example.com"))
->setReceiver(new EmailContact("Joe Doe", "to#example.org"))
->setBodyObject($person) // Any serializable object
);
The templates are constructed in the AlphaMail Dashboard using the Comlang templating language. This means that you can easily edit your emails at any time, without having to dig through code. Templates in Comlang look something like:
<html>
<body>
<b>Name:</b> <# payload.firstName " " payload.lastName #><br>
<b>Date of Birth:</b> <# payload.dateOfBirth #><br>
<# if (payload.userId != null) { #>
Sign Up Free!
<# } else { #>
Sign In
<# } #>
</body>
</html>

SugarCRM SOAP test call fails

I am attempting to test a SugarCRM Soap connection using the following code:
<?
define('sugarEntry', TRUE);
require_once('include/nusoap/nusoap.php');
$sugarclient = new nusoapclient('http://www.mycrmurl.com/soap.php?wsdl',true);
echo $sugarclient->call('test', 'test string');
?>
Unfortunately, the test call returns NULL. Thoughts on how to begin troubleshooting?
I'm not familiar with a SugarCRM SOAP method called test, so unless it's a custom method you made yourself, I'd try with some simple valid calls. (Tested with Sugar CE 6.2).
<?php
require_once('include/nusoap/lib/nusoap.php');
$myWsdl = 'http://www.mycrmurl.com/soap.php?wsdl';
$myAuth = array(
'user_name' => 'will',
'password' => MD5('will'),
'version' => '0.1'
);
$soapClient = new nusoap_client($myWsdl,true);
$loginParams = array('user_auth' => $myAuth, 'application_name' => 'MyApp');
$loginResult = $soapClient->call('login', $loginParams);
$sessionId = $loginResult['id'];
echo $sessionId;
?>
If the above still gives you problems, try the following:
Look in the web server log (Is the call getting through)
Enable the SugarCRM logging and set the level to debug
Either enable PHP error output or make PHP log errors to a log file
Use e.g. SoapUI to test SOAP call
See question 5396302 for a more thorough SOAP example
Check the SugarCRM SOAP documentation
Do this:
$result = $sugarclient->call('test', 'test string');
echo print_r ($result);
It will print the array result, if you just want to see the error description do this:
$result = $sugarclient->call('test', 'test string');
echo $result['error']['description'];
The result is a multidimensional array.

Linkedin OAuth and Zend retrieving Acces Token returns 'Error in HTTP request'

Answer + new question
I found out that the code below works just fine on a LIVE server. LinkedIN blocked all requests from localhost.
That established; Does anybody know how to test an application from localhost with LinkedIN OAuth? Because doing this on a live server sucks!
Old Question
I'm trying to connect with Zend_OAuth to LinkedIN. This code used to work, but now it returns an error in http request while I'm trying to retrieve an access token.
Tried checking the LinkedIN api, but the code still seems valid. Tried several scripts but all with the same result.
The config is setup in the preDispatch of my controller
$this->configLinkedin = array(
'version' => '1.0',
'siteUrl' => 'http://'.$_SERVER['HTTP_HOST'].$this->view->baseUrl(false).'/news/index/connectlinkedin',
'callbackUrl' => 'http://'.$_SERVER['HTTP_HOST'].$this->view->baseUrl(false).'/news/index/connectlinkedin',
'requestTokenUrl' => 'https://api.linkedin.com/uas/oauth/requestToken',
'userAuthorisationUrl' => 'https://api.linkedin.com/uas/oauth/authorize',
'accessTokenUrl' => 'https://api.linkedin.com/uas/oauth/accessToken',
'consumerKey' => 'XXX',
'consumerSecret' => 'XXX'
);
And the code in the action to connect to linkedIN is
$this->consumer = new Zend_Oauth_Consumer($this->configLinkedin);
if(!empty($_GET) && isset($_SESSION['LINKEDIN_REQUEST_TOKEN']))
{
$token = $this->consumer->getAccessToken($_GET, unserialize($_SESSION['LINKEDIN_REQUEST_TOKEN']));
// Use HTTP Client with built-in OAuth request handling
$client = $token->getHttpClient($this->configLinkedin);
// Set LinkedIn URI
$client->setUri('https://api.linkedin.com/v1/people/~:(id,first-name,last-name,picture-url)');
// Set Method (GET, POST or PUT)
$client->setMethod(Zend_Http_Client::GET);
// Get Request Response
$response = $client->request();
$this->NewsService->TokenSocialMedia(
$token,
'linkedin',
serialize($response->getBody())
);
$_SESSION['LINKEDIN_REQUEST_TOKEN'] = null;
$this->_helper->flashMessenger(array('message' => $this->view->translate('The CMS is successfully connected to your linkedin account'), 'status' => 'success'));
$this->_helper->redirector('settings#settingSocial', 'index');
}
else
{
$token = $this->consumer->getRequestToken();
$_SESSION['LINKEDIN_REQUEST_TOKEN'] = serialize($token);
$this->consumer->redirect();
}
What am I missing or doing wrong? I use a similair setup for Twitter and that works fine.
UPDATE 20 September 211
I found out that this rule is returning the error:
$token = $this->consumer->getRequestToken();
I'm still clueless why, and reading the linkedin api doesn't help a bit. Will keep you posted.
I got similar problem and after adding openssl extension it was solved
try adding to php.ini this line:
extension=php_openssl.dll
I got the same issue, try to turn off ssl before asking the new consumer :
$httpConfig = array(
'adapter' => 'Zend\Http\Client\Adapter\Socket',
'sslverifypeer' => false
);
$httpClient = new HTTPClient(null, $httpConfig);
OAuth::setHttpClient($httpClient);

Set Timeout SOAP client (Zend Framework)

I'm requesting a webservice using SOAP for which I need to set a request timeout.
new Zend_Soap_Client(http://www.aaa.com/ws/Estimate.asmx?wsdl",
array('encoding' => 'UTF-8');
I have also tried passing 'connection_timeout'=>100 but it seems like "unknow SOAP client option". Please suggest a way I can set the set timeout.
Thanks
I found a solution to set the timeout with Zend_Framework:
If you have your SoapClient-Object like this:
$client = new Zend_Soap_Client(http://www.aaa.com/ws/Estimate.asmx?wsdl", array('encoding' => 'UTF-8');
You can set the timeout for HTTP-Requests. The default timeout in PHP is 30 seconds. With the following code you can e.g. set it to 1 minute.
$context = stream_context_create(
array(
'http' => array(
'timeout' => 1000
)
)
);
$client->setStreamContext($context);
Found on downlifesroad.com
Connection timeout option is not supported, the code is present in Zend_Soap_Client but commented
// Not used now
// case 'connection_timeout':
// $this->_connection_timeout = $value;
// break;
ini_set('default_socket_timeout',$seconds);
Here is a suggested solution using ZendHttpClient and Zend_Http_Client_Adapter_Curl.
$client = new Zend_Http_Client($location);
$adapter = new Zend_Http_Client_Adapter_Curl();
$client->setAdapter($adapter);
$adapter->setCurlOption(CURLOPT_TIMEOUT, $this->_timeout);
$client->setMethod(Zend_Http_Client::POST);
$client->setHeaders('Content-Type', $version == 2 ?
'application/soap+xml' : 'text/xml');
$client->setHeaders('SOAPAction', $action);
The idea is that you send an http request with the SOAP envelope as string at the request.
Full gist code here
I solved this issue by using native PHP SoapClient class...
$client = new SoapClient($url,
array(
'connection_timeout'=>'30'
));
$response = $client->wsMethod(array
('param'=>'value));
You can define the whole duration limit using
ini_set('default_socket_timeout', '30');
Before calling it.
Works like a charm... ;)

How to implement PayPal in Symfony 1.4 & Docrtrine

I want to use PayPal, Express Checkout, in a Symfony/Doctrine 1.4.8 the current plugins all seem to be in Beta and also somewhat over the top in the way they are implemented. I can follow the logic of the PayPal provided information and code although some items are a bit vague as to how i deal with them in Symfony.
Any class files are ok as i create a lib directory and rename the class and this gets instantiated. However i have some plain procedural PHP files i.e. expresscheckout.php and i am not sure where to put this to load as it doesn't seem to fit in the templates. Perhaps it goes in the actions?
I am not looking for a line by line solution here (but if you have one feel free) but really a few pointers as to where the elements go. As i say i am still suffering form a bit of Symfony blindness.
Finally would i be better to implement a simple (is that possible?) plugin to handle this or group the paypal items in a module on their own?
What I did was write a class, I called it PaypalNvp, name the file PaypalNvp.class.php and put it in your /lib folder and put in functions for the Nvp Ops.
Then you can choose to either call the functions statically (change your class functions as needed) or initialize the class and call the functions...
So something like:
PaypalNvp::doExpressCheckoutPaypment($token, $payer_id, $amount, $currency, $payment_action);
or
$paypal = new PaypalNvp();
$paypal->doExpressCheckoutPaypment($token, $payer_id, $amount, $currency, $payment_action);
I don't think there is a set way of of saying which way is better... I use the latter method myself.
My class has a helper function in it that does the final communication operation with Paypal:
protected function api($data = array())
{
if (empty($data) || !is_array($data)) return false;
// INIT
$data = array_merge($data, array(
'VERSION' => $this->VERSION,
'PWD' => $this->PASSWORD,
'USER' => $this->USERNAME,
'SIGNATURE' => $this->SIGNATURE
));
array_walk($data, array(&$this, 'urlencode_walk'));
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->getUrl() . '/nvp',
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query($data)
));
$response = curl_exec($curl);
if (curl_errno($curl)) {
curl_close($curl);
return false;
} else {
curl_close($curl);
return $this->deformatNVP($response);
}
}
Main things you need to remember is to set the api method, e.g. SetExpressCheckout, and any required fields according to the PaypalNvp API