We've Moved! Please visit our new and improved forum over at our new portal: https://portal.plumvoice.com/hc/en-us/community/topics

Soap Webservice.

Questions and answers about Plum Survey

Moderators: admin, support

Post Reply
rob@reposystems.com
Posts: 10
Joined: Fri Oct 10, 2008 12:18 pm
Contact:

Soap Webservice.

Post by rob@reposystems.com »

Hi,

We have created a soap webservice "http://www.reposystems.com/Webservice/testpv.asmx?wsdl"
and added it in the survey, however when we test it, the webservice is accessed but empty values are entered in the database.

When we try to view response in an exel file, then too the responses are not entered in the file.

Please help.

Thanks,
Support@reposystems.com

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

deviations in function signature of sample IVR webservice

Post by support »

We have looked at your WSDL and noticed that there are some deviations in the function signature from our sample IVR webservice at:
http://survey.plumvoice.com/ws/sample-w ... e.php?wsdl

that may be the reason your WSDL is not receiving values.

Your WSDL function "evaluate" needs to be receiving two parameters: the question_texts and the answers. These parameters must each be an array of strings. Your WSDL has two parameters that are just strings, not arrays of strings.

This is the function signature that our SOAP client reads in your WSDL:

Code: Select all

string evaluate(string $Questions, string $Answers)
where it should be something like

Code: Select all

string evaluate(ArrayOfstring $Questions, ArrayOfstring $Answers)
with the WSDL defining ArrayOfstring with something like

Code: Select all

<xsd:complexType name="ArrayOfstring">
  <xsd:complexContent>
    <xsd:restriction base="soapenc:Array">
      <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
    </xsd:restriction>
  </xsd:complexContent>
</xsd:complexType>
where soapenc:Array is a SOAP complexType defined by http://schemas.xmlsoap.org/soap/encoding/.

Please refer to our reference WSDL for the necessary implementation. Once you have made the two parameters into an array type, you can try having your IVR webservice log its input parameters to a file to verify that it is receiving everything correctly.

Hope this helps.
Last edited by support on Thu Mar 04, 2010 5:21 pm, edited 3 times in total.

rob@reposystems.com
Posts: 10
Joined: Fri Oct 10, 2008 12:18 pm
Contact:

Post by rob@reposystems.com »

We have modified our webmethod to receive two arrays of strings, however still no values are received by the webmethod. Could you please provide us the code for the sample webmethod(sample-webservice.php) which receives these two arrays of strings, so that we can modify our webmethod accordingly.

We look forward to your reply.

Thanks and regards,

Support@reposystems.com

rob@reposystems.com
Posts: 10
Joined: Fri Oct 10, 2008 12:18 pm
Contact:

Post by rob@reposystems.com »

We get the error mail with the following error "ERROR: [soap:Server] Server was unable to process request. --> Object
reference not set to an instance of an object.
"

We believe this error happens because the values are not passed to the webmethod.Please let us know why are the values are not passed to the webmethod and also provide us with the code of sample webmethod, which receives these arrays.

Thanks,
support@reposystems.com

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

example of a SOAP request that our IVR application makes

Post by support »

Note: edits made r/t switch from "evaluate" to "plumEval" -- changes noted in bold; see next post for explanation

The mail you are getting is the exception being raised by your IVR code; what happens is our client takes whatever error your IVR code is producing and mails it back to you. If you google your error you will see that you are not instantiating one of your objects properly, it may not necessarily be a problem with passing the parameters. It would be helpful if you had your webservice log the content of the SOAP requests that are being passed to it, so that you could verify that there is indeed data in the request and what format you should be expecting.

When we examine your webservice's evaluate (should be changed to plumEval) method, you still may not have your webservice correctly accepting arrays of strings. The Test section of that page says "The test form is only available for methods with primitive types or arrays of primitive types as parameters." An array of strings is an array of a primitive type (string is a primitive type), so your ASP.NET webservice should be able to generate a test form and it is not.

The following is an example of a SOAP request that our IVR application makes:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:http://survey.plumvoice.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="urn:SampleWebservice" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:plumEval>
      <question_texts SOAP-ENC:arrayType="xsd:string[2]" xsi:type="ns2:ArrayOfstring">
        <item xsi:type="xsd:string">Question 1 Text</item>
        <item xsi:type="xsd:string">Question 2 Text</item>
      </question_texts>
      <answers SOAP-ENC:arrayType="xsd:string[2]" xsi:type="ns2:ArrayOfstring">
        <item xsi:type="xsd:string">yes</item>
        <item xsi:type="xsd:string">no</item>
      </answers>
    </ns1:evaluate>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Your webservice appears to be accepting a slightly different type of request:

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <evaluate xmlns="http://tempuri.org/testservices/testpv">
      <question_texts>
        <string>string</string>
        <string>string</string>
      </question_texts>
      <Answers>
        <string>string</string>
        <string>string</string>
      </Answers>
    </evaluate>
  </soap:Body>
</soap:Envelope>
Note that your service does not utilize http://schemas.xmlsoap.org/soap/encoding/ which contains the standard SOAP encoding for arrays. Our service is using it and declaring for each parameter an attribute arrayType="xsd:string[$length]", and each parameter contains <item xsi:type="xsd:string"></item>. Your service seems to be defining its own complexType with <string></string>, although we are not sure exactly what you have set up.

As you have requested, we are posting the source code for our own service. Note that our implementation is in PHP, not ASP.NET. This IVR code is explained in detail in our IVR site documentation.

sample-webservice.php:

Code: Select all

<?php
/*************
* PLUM SURVEY SAMPLE WEBSERVICE
* This webservice demonstrates how to make a SOAP service for use with a 
* 'SOAP webservice' question in a survey.
* (c) 2008 Plum Voice
*************/
$NAMESPACE = "http://survey.plumvoice.com";
$DEBUG = true;

include_once('../lib/WSDL_Gen.php');
$WS_DOC_CSS = "css/ws_doc.css";
$DESCRIPTION = "An example of a webservice that could be used by a \"SOAP webservice\" question in a survey.";

$LOGFILE = fopen("/var/tmp/surveysamplewebservice.log", "a+");
function debuglog($str) {
  global $LOGFILE, $DEBUG;
  if ($LOGFILE && $DEBUG) {
    fwrite($LOGFILE, $str);
  }
}

class SampleWebservice extends Services_Webservice {

  /**
   * The WSDL that you use should specify only one function named "evaluate".
   * This function will receive two arrays of strings: one with the text 
   * of each question, and the other with all the answers received on the 
   * current page.  These arrays will be indexed in the same fashion, e.g., 
   * each array's elements will be ordered so that the questions correspond 
   * with the answers.  This function should return a string, which will be 
   * saved as the response for the question calling this webservice.  If 
   * there is a choice with skip logic that corresponds to this answer, 
   * it will be followed. ...
   * 
   * This sample webservice returns "accepted" if any of the submitted 
   * answers were "yes", and "rejected" otherwise.
   *
   * @param string[] $question_texts
   * @param string[] $answers
   * @return string
   **/
  function plumEval($question_texts, $answers) {
    ob_start("debuglog");
    $ret = 'rejected';
    foreach ($answers as $answer) {
      if ($answer == 'yes') { $ret = 'accepted'; break; }
    }
    ob_end_flush();
    return $ret;
  }

}

$myService = new SampleWebservice($NAMESPACE, $DESCRIPTION, array('uri'=>$NAMESPACE, 'encoding'=>SOAP_ENCODED));

$myService->handle();

if ($LOGFILE) {
  fclose($LOGFILE);
}
?>
../lib/WSDL_Gen.php: (this is a standard library from PEAR)

Code: Select all

<?php

ini_set('error_reporting',E_ALL);
ini_set('error_log','/var/www/error.log');

/* vim: set expandtab tabstop=4 shiftwidth=4: */

/**
 * Easy Web Service (SOAP) creation
 *
 * PHP 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   Services
 * @package    Webservice
 * @author     Manfred Weber <weber@mayflower.de>
 * @copyright  2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id: WSDL_Gen.php,v 1.2 2008/10/03 16:59:45 ted Exp $
 * @link       http://dschini.org/Services/
 */

// {{{ abstract class Services_WebService

/**
 * PEAR::Services_Webservice
 *
 * The PEAR::Services_WebService class creates web services from your classes
 *
 * @author  Manfred Weber <weber@mayflower.de>
 * @package Webservices
 * @version
 */
abstract class Services_Webservice
{
    /**
     * Namespace of the webservice
     *
     * @var    string
     * @access public
     */
    public $namespace;

    /**
     * Description of the webservice
     *
     * @var    string
     * @access public
     */
    public $description;

    /**
     * Protocol of the webservice
     *
     * @var    string
     * @access public
     */
    public $protocol;


    /**
     * SOAP-server options of the webservice
     *
     * @var    array
     * @access public
     */
    public $soapServerOptions = array();

    /**
     * SOAP schema related URIs
     *
     * @access private
     */
    const SOAP_XML_SCHEMA_VERSION  = 'http://www.w3.org/2001/XMLSchema';
    const SOAP_XML_SCHEMA_INSTANCE = 'http://www.w3.org/2001/XMLSchema-instance';
    const SOAP_SCHEMA_ENCODING   = 'http://schemas.xmlsoap.org/soap/encoding/';
    const SOAP_XML_SCHEMA_MIME   = 'http://schemas.xmlsoap.org/wsdl/mime/';
    const SOAP_ENVELOP           = 'http://schemas.xmlsoap.org/soap/envelope/';
    const SCHEMA_SOAP_HTTP       = 'http://schemas.xmlsoap.org/soap/http';
    const SCHEMA_SOAP            = 'http://schemas.xmlsoap.org/wsdl/soap/';
    const SCHEMA_WSDL            = 'http://schemas.xmlsoap.org/wsdl/';
    const SCHEMA_WSDL_HTTP       = 'http://schemas.xmlsoap.org/wsdl/http/';
    const SCHEMA_DISCO           = 'http://schemas.xmlsoap.org/disco/';
    const SCHEMA_DISCO_SCL       = 'http://schemas.xmlsoap.org/disco/scl/';
    const SCHEMA_DISCO_SOAP      = 'http://schemas.xmlsoap.org/disco/soap/';

    /**
     * Simple WSDL types
     *
     * @var    array
     * @access private
     */
    private $simpleTypes = array(
        'string', 'int', 'float', 'bool', 'double', 'integer', 'boolean',
        'varstring', 'varint', 'varfloat', 'varbool', 'vardouble',
        'varinteger', 'varboolean');

    /**
     * classes are parsed into struct
     *
     * @var    array
     * @access private
     */
    private $wsdlStruct;

    /**
     * disco dom root node
     * the disco dom object
     *
     * @var    object
     * @access private
     */
    private $disco;

    /**
     * wsdl dom root node
     * the wsdl dom object
     *
     * @var    object
     * @access private
     */
    private $wsdl;

    /**
     * wsdl-definitions dom node
     *
     * @var    object
     * @access private
     */
    private $wsdl_definitions;

    /**
     * Name of the class from which to create a webservice from
     *
     * @var    string
     * @access private
     */
    private $classname;

    /**
     * exclude these methods from webservice
     *
     * @var    array
     * @access private
     */
    private $preventMethods;

    /**
     * error namespace
     *
     * @var    bool
     * @access private
     */
    private $warningNamespace;

    /**
     * error description
     *
     * @var    bool
     * @access private
     */
    private $errorDescription;

    /**
     * constructor
     *
     * @var    string
     * @var    string
     * @var    array
     * @access public
     */
    public function __construct($namespace, $description, $options)
    {
        if (isset($namespace) && $namespace != '') {
            $this->warningNamespace   = false;
            $this->errorDescription = false;
            //$namespace .= (substr($namespace, -1) == '/') ? '' : '/';
        } else {
            $this->warningNamespace   = true;
            $this->errorDescription = true;
            $namespace = 'http://example.org/';
        }
        $this->namespace   = $namespace;
        $this->description = ($description != '') ? $description : 'my example service description';
        $this->soapServerOptions = (isset($options) && count($options) > 0) ? $options : array(
            'uri' => $this->namespace,
            'encoding' => SOAP_ENCODED);
        $this->wsdlStruct = array();
        $this->preventMethods = array(
            '__construct',
            '__destruct',
            'handle');
        $this->protocol = 'http';
    }

    // }}}
    // {{{ handle()
    /**
     * handle
     *
     * @access public
     */
    public function handle()
    {
        switch (strtolower($_SERVER['QUERY_STRING'])){
            case 'wsdl':
                $this->intoStruct();
                $this->handleWSDL();
                break;
            case 'disco':
                $this->intoStruct();
                $this->handleDISCO();
                break;
            default:
                $this->intoStruct();
                if (isset($_SERVER['HTTP_SOAPACTION'])) {
                    $this->createServer();
                } else {
                    $this->handleINFO();
                }
                break;
        }
    }

    // }}}
    // {{{ createServer()
    /**
     * create the soap-server
     *
     * @access private
     */
    private function createServer()
    {
        $server = new SoapServer(null, $this->soapServerOptions);
        $server->SetClass($this->classname);
        $server->handle();
    }

    // }}}
    // {{{ handleWSDL()
    /**
     * handle wsdl
     *
     * @access private
     */
    private function handleWSDL()
    {
        header('Content-Type: text/xml');
        $this->wsdl = new DOMDocument('1.0' ,'utf-8');
        $this->createWSDL_definitions();
        $this->createWSDL_types();
        $this->createWSDL_messages();
        $this->createWSDL_portType();
        $this->createWSDL_binding();
        $this->createWSDL_service();
        echo $this->wsdl->saveXML();
    }

    // }}}
    // {{{ createDISCO()
    /**
     * handle disco
     *
     * @access private
     */
    private function handleDISCO()
    {
        header('Content-Type: text/xml');
        $this->disco = new DOMDocument('1.0' ,'utf-8');
        $disco_discovery = $this->disco->createElement('discovery');
        $disco_discovery->setAttribute('xmlns:xsi', self::SOAP_XML_SCHEMA_INSTANCE);
        $disco_discovery->setAttribute('xmlns:xsd', self::SOAP_XML_SCHEMA_VERSION);
        $disco_discovery->setAttribute('xmlns', self::SCHEMA_DISCO );
        $disco_contractref = $this->disco->createElement('contractRef');
        $urlBase = $this->protocol . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
        $disco_contractref->setAttribute('ref', $urlBase . '?wsdl');
        $disco_contractref->setAttribute('docRef', $urlBase);
        $disco_contractref->setAttribute('xmlns', self::SCHEMA_DISCO_SCL);
        $disco_soap = $this->disco->createElement('soap');
        $disco_soap->setAttribute('address', $urlBase);
        $disco_soap->setAttribute('xmlns:q1', $this->namespace);
        $disco_soap->setAttribute('binding', 'q1:' . $this->classname);
        $disco_soap->setAttribute('xmlns', self::SCHEMA_DISCO_SCL);
        $disco_contractref->appendChild($disco_soap);
        $disco_discovery->appendChild($disco_contractref);
        $this->disco->appendChild($disco_discovery);
        echo $this->disco->saveXML();
    }

    // }}}
    // {{{ handleINFO()
    /**
     * handle info-site
     *
     * @access private
     */
    private function handleINFO()
    {
        global $WS_DOC_CSS;
        header('Content-Type: text/html');

        echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>' . $this->classname . ' WebService</title>
<meta name="generator" content="PEAR::Services_Webservice" />
<style type="text/css">'
. file_get_contents($WS_DOC_CSS) .
'</style>
</head>
<body>
<div id="header">
<h1>' . $this->classname . '</h1>
<p>' . htmlspecialchars($this->description) . '</p>
</div>
<p>The following operations are supported. For a formal definition, please review the <a href="' . htmlentities($_SERVER['PHP_SELF']) . '?WSDL">Web Services Description Language</a>.</p>
<ul>';

        foreach ($this->wsdlStruct[$this->classname]['method'] as $methodName => $method) {
            $paramValue = array();
            foreach ($method['var'] AS $methodVars) {
                if (isset($methodVars['param'])) {
                    $paramValue[] = "<var class=\"parameter\">" . $methodVars['type']
                                     . str_repeat('[]', $methodVars['length']) . "</var> " . $methodVars['name'];
                }
            }
            $returnValue = array();
            foreach ($method['var'] AS $methodVars) {
                if (isset($methodVars['return'])) {
                    $returnValue[] = $methodVars['type']
                                     . str_repeat('[]', $methodVars['length']);
                }
            }
            echo sprintf('<li><samp><var class="returnedValue">%s</var> <b class="functionName">%s</b>( %s )</samp>%s</li>'
                    , implode(',', $returnValue)
                    , $methodName
                    , implode(', ', $paramValue)
                    , ((empty($method['description'])) ? '' : ('<br /><span class="description">' . htmlspecialchars($method['description']) . '</span>')));
        }
/*
        echo '</ul>
<p><a href="' . htmlentities($_SERVER['PHP_SELF']) . '?DISCO">DISCO</a> makes it possible for clients to reflect against endpoints to discover services and their associated <acronym title="Web Service Description Language">WSDL</acronym> documents.</p>';
*/
        if ($this->warningNamespace == true
            || $this->namespace == 'http://example.org/') {
            echo '
<p class="warning"><strong>This web service is using http://example.org/ as its default namespace.<br />
Recommendation: Change the default namespace before the <acronym title="eXtensible Markup Language">XML</acronym> Web service is made public.</strong></p>

<p>Each XML Web service needs a unique namespace in order for client applications to distinguish it from other services on the Web. http://example.org/ is available for XML Web services that are under development, but published XML Web services should use a more permanent namespace.<br />
Your XML Web service should be identified by a namespace that you control. For example, you can use your company`s Internet domain name as part of the namespace. Although many XML Web service namespaces look like <acronym title="Uniform Resource Locators">URLs</acronym>, they need not point to actual resources on the Web. (XML Web service namespaces are <acronym title="Uniform Resouce Identifiers">URIs</acronym>.)</p>

<p>For more details on XML namespaces, see the <acronym title="World Wide Web Consortium">W3C</acronym> recommendation on <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a>.<br />
For more details on <acronym title="Web Service Description Language">WSDL</acronym>, see the <a href="http://www.w3.org/TR/wsdl">WSDL Specification</a>.<br />
For more details on URIs, see <a href="http://www.ietf.org/rfc/rfc2396.txt"><acronym title="Request For Comment">RFC</acronym> 2396</a>.</p>
<p><small>Powered by PEAR <a href="http://pear.php.net/">http://pear.php.net</a></small></p>
</body>
</html>';

        }
    }

    // }}}
    // {{{ intoStruct()
    /**
     * parse classes into struct
     *
     * @access private
     */
    protected function intoStruct()
    {
        $class = new ReflectionObject($this);
        $this->classname = $class->getName();
        $this->classMethodsIntoStruct();
        $this->classStructDispatch();
    }

    // }}}
    // {{{ classStructDispatch()
    /**
     * dispatch types
     *
     * @access private
     */
    protected function classStructDispatch()
    {
        foreach ($this->wsdlStruct[$this->classname]['method'] as $method) {
            foreach ($method['var'] as $var){
                if (($var['class'] == 1 && $var['length'] == 0)
                    || ($var['class'] == 1 && $var['length'] > 0)) {
                    $this->classPropertiesIntoStruct($var['type']);
                }
                if (($var['array'] == 1 && $var['length'] > 0)
                    || ($var['class'] == 1 && $var['length'] > 0)) {
                    $_typensSource = '';
                    for ($i = $var['length']; $i > 0; --$i) {
                        $_typensSource .= 'ArrayOf';
                        $this->wsdlStruct['array'][$_typensSource . $var['type']] = substr($_typensSource, 0, strlen($_typensSource) - 7) . $var['type'];
                    }
                }
            }
        }
    }

    // }}}
    // {{{ classPropertiesIntoStruct()
    /**
     * parse classes properties into struct
     *
     * @var    string
     * @access private
     */
    protected function classPropertiesIntoStruct($className)
    {
        if (!isset($this->wsdlStruct[$className])) {
            $class = new ReflectionClass($className);
            $properties = $class->getProperties();
            $this->wsdlStruct['class'][$className]['property'] = array();
            for ($i = 0; $i < count($properties); ++$i) {
                if ($properties[$i]->isPublic()) {
                    preg_match_all('~@var\s(\S+)~', $properties[$i]->getDocComment(), $var);

                    $_cleanType = str_replace('[]', '', $var[1][0], $_length);
                    $_typens    = str_repeat('ArrayOf', $_length);

                    $this->wsdlStruct['class'][$className]['property'][$properties[$i]->getName()]['type'] =
                            $_cleanType;
                    $this->wsdlStruct['class'][$className]['property'][$properties[$i]->getName()]['wsdltype'] =
                            $_typens.$_cleanType;
                    $this->wsdlStruct['class'][$className]['property'][$properties[$i]->getName()]['length'] =
                            $_length;
                    $this->wsdlStruct['class'][$className]['property'][$properties[$i]->getName()]['array'] =
                            ($_length > 0 && in_array($_cleanType, $this->simpleTypes))
                            ? true : false;
                    $isObject = (!in_array($_cleanType, $this->simpleTypes) && new ReflectionClass($_cleanType))
                            ? true : false;
                    $this->wsdlStruct['class'][$className]['property'][$properties[$i]->getName()]['class'] =
                            $isObject;
                    if ($isObject == true) {
                        $this->classPropertiesIntoStruct($_cleanType);
                    }
                    if ($_length > 0) {
                        $_typensSource = '';
                        for ($j = $_length; $j > 0;  --$j) {
                            $_typensSource .= 'ArrayOf';
                            $this->wsdlStruct['array'][$_typensSource.$_cleanType] =
                                    substr($_typensSource, 0, strlen($_typensSource) - 7) . $_cleanType;
                        }
                    }
                }
            }
        }
    }

    // }}}
    // {{{ classMethodsIntoStruct()
    /**
     * parse classes methods into struct
     *
     * @access private
     */
    protected function classMethodsIntoStruct()
    {
        $class = new ReflectionClass($this->classname);
        $methods = $class->getMethods();
        // params
        foreach ($methods AS $method) {
            if ($method->isPublic()
                && !in_array($method->getName(), $this->preventMethods)) {
                $docComments = $method->getDocComment();
                $_docComments_Description = trim(str_replace('/**', '', substr($docComments, 0, strpos($docComments, '@'))));
                $docComments_Description = preg_replace('/(\\s+|^)\\*\\s*|\\s*\\*(\\s+|$)/', ' ', $_docComments_Description);
                $this->wsdlStruct[$this->classname]['method'][$method->getName()]['description'] = $docComments_Description;
                preg_match_all('~@param\s(\S+)~', $docComments, $param);
                preg_match_all('~@return\s(\S+)~', $method->getDocComment(), $return);
                $params = $method->getParameters();
                for ($i = 0; $i < count($params); ++$i) {
                    $_class = $params[$i]->getClass();
                    $_type  = ($_class) ? $_class->getName() : $param[1][$i];

                    $_cleanType = str_replace('[]', '', $_type, $_length);
                    $_typens    = str_repeat('ArrayOf', $_length);

                    $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['name'] =
                            $params[$i]->getName();
                    $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['wsdltype'] =
                            $_typens . $_cleanType;
                    $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['type'] =
                            $_cleanType;
                    $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['length'] =
                            $_length;
                    $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['array'] =
                            ($_length > 0 && in_array($_cleanType, $this->simpleTypes))
                            ? true : false;
                    $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['class'] =
                            (!in_array($_cleanType, $this->simpleTypes) && new ReflectionClass($_cleanType))
                            ? true : false;
                    $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['param'] = true;
                }
                // return
                if (isset($return[1][0])) {
                    $_cleanType = str_replace('[]', '', $return[1][0], $_length);
                } else {
                    $_cleanType = 'void';
                    $_length = 0;
                }
                $_typens = str_repeat('ArrayOf', $_length);

                $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['wsdltype'] =
                        $_typens.$_cleanType;
                $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['type'] = $_cleanType;
                $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['length'] = $_length;
                $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['array'] =
                        ($_length > 0 && $_cleanType != 'void' && in_array($_cleanType, $this->simpleTypes)) ? true : false;
                $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['class'] =
                        ($_cleanType != 'void' && !in_array($_cleanType, $this->simpleTypes) && new ReflectionClass($_cleanType))
                        ? true : false;
                $this->wsdlStruct[$this->classname]['method'][$method->getName()]['var'][$i]['return'] = true;
            }
        }
    }

    // }}}
    // {{{ createWSDL_definitions()
    /**
     * Create the definition node
     *
     * @return void
     */
    protected function createWSDL_definitions()
    {
		/*
		<definitions name="myService"
		    targetNamespace="urn:myService"
		    xmlns:typens="urn:myService"
		    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
		    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
		    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
		    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
		    xmlns="http://schemas.xmlsoap.org/wsdl/">
		*/
		
        $this->wsdl_definitions = $this->wsdl->createElement('definitions');
        $this->wsdl_definitions->setAttribute('name', $this->classname);
        $this->wsdl_definitions->setAttribute('targetNamespace', 'urn:'.$this->classname);
        $this->wsdl_definitions->setAttribute('xmlns:typens', 'urn:'.$this->classname);
        $this->wsdl_definitions->setAttribute('xmlns:xsd', self::SOAP_XML_SCHEMA_VERSION);
        $this->wsdl_definitions->setAttribute('xmlns:soap', self::SCHEMA_SOAP);
        $this->wsdl_definitions->setAttribute('xmlns:soapenc', self::SOAP_SCHEMA_ENCODING);
        $this->wsdl_definitions->setAttribute('xmlns:wsdl', self::SCHEMA_WSDL);
        $this->wsdl_definitions->setAttribute('xmlns', self::SCHEMA_WSDL);
        
        //$this->wsdl_definitions->setAttribute('xmlns:mime', self::SOAP_XML_SCHEMA_MIME);
        //$this->wsdl_definitions->setAttribute('xmlns:tns', $this->namespace);
        //$this->wsdl_definitions->setAttribute('xmlns:http', self::SCHEMA_WSDL_HTTP);
        
        $this->wsdl->appendChild($this->wsdl_definitions);
    }

    // }}}
    // {{{ createWSDL_types()
    /**
     * Create the types node
     *
     * @return void
     */
    protected function createWSDL_types()
    {
    	/*
		<types>
        	<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:myService"/>
        </types>
    	*/
        $types  = $this->wsdl->createElement('types');
        $schema = $this->wsdl->createElement('xsd:schema');
        $schema->setAttribute('xmlns', self::SOAP_XML_SCHEMA_VERSION );
        $schema->setAttribute('targetNamespace', 'urn:'.$this->classname);
        $types->appendChild($schema);

        // array
        /*
        <xsd:complexType name="ArrayOfclassC">
            <xsd:complexContent>
                <xsd:restriction base="soapenc:Array">
                    <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="typens:classC[]"/>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
        */
        if (isset($this->wsdlStruct['array'])) {

	        foreach ($this->wsdlStruct['array'] as $source => $target) {
	        	
	        	//<s:complexType name="ArrayOfArrayOfInt">
				//<s:sequence>
				//<s:element minOccurs="0" maxOccurs="unbounded" name="ArrayOfInt" nillable="true" type="tns:ArrayOfInt"/>
				//</s:sequence>
	        	
	            $complexType 	= $this->wsdl->createElement('xsd:complexType');
	            $complexContent = $this->wsdl->createElement('xsd:complexContent');
	            $restriction 	= $this->wsdl->createElement('xsd:restriction');
	            $attribute 		= $this->wsdl->createElement('xsd:attribute');
	            $restriction->appendChild($attribute);
	            $complexContent->appendChild($restriction);
	            $complexType->appendChild($complexContent);
	            $schema->appendChild($complexType);
	            
	            $complexType->setAttribute('name', $source);
	            $restriction->setAttribute('base', 'soapenc:Array');
	            $attribute->setAttribute('ref', 'soapenc:arrayType');

	            try {
	            	$class = new ReflectionClass($target);
	            }catch (Exception $e){}
	            
	            if(in_array($target, $this->simpleTypes)){
		            $attribute->setAttribute('wsdl:arrayType', 'xsd:'.$target.'[]');
	            }elseif(isset($class)){
		            $attribute->setAttribute('wsdl:arrayType', 'typens:'.$target.'[]');
	            }else{
		            $attribute->setAttribute('wsdl:arrayType', 'typens:'.$target.'[]');
	            }
	            unset($class);
	            
	        }
        }
        
        // class
        /*
        <xsd:complexType name="classB">
            <xsd:all>
                <xsd:element name="classCArray" type="typens:ArrayOfclassC" />
            </xsd:all>
        </xsd:complexType>
        */
        if (isset($this->wsdlStruct['class'])) {
            foreach ($this->wsdlStruct['class'] as $className=>$classProperty) {
                $complextype = $this->wsdl->createElement('xsd:complexType');
                $complextype->setAttribute('name', $className);
                $sequence = $this->wsdl->createElement('xsd:all');
                $complextype->appendChild($sequence);
                $schema->appendChild($complextype);
                foreach ($classProperty['property'] as $classPropertyName => $classPropertyValue) {
                    $element = $this->wsdl->createElement('xsd:element');
                    $element->setAttribute('name', $classPropertyName);
                    $element->setAttribute('type', ((in_array($classPropertyValue['wsdltype'], $this->simpleTypes)) 
                    										? 'xsd:' 
                    										: 'typens:') . $classPropertyValue['wsdltype']);
                    $sequence->appendChild($element);
                }
            }
        }

        $this->wsdl_definitions->appendChild($types);
    }

    // }}}
    // {{{ createWSDL_messages()
    /**
     * Create the messages node
     *
     * @return void
     */
    protected function createWSDL_messages()
    {
    	/*
	    <message name="hello">
	        <part name="i" type="xsd:int"/>
	        <part name="j" type="xsd:string"/>
	    </message>
	    <message name="helloResponse">
	        <part name="helloResponse" type="xsd:string"/>
	    </message>
	    */
        foreach ($this->wsdlStruct[$this->classname]['method'] AS $methodName => $method){
            $messageInput = $this->wsdl->createElement('message');
            $messageInput->setAttribute('name', $methodName);
            $messageOutput = $this->wsdl->createElement('message');
            $messageOutput->setAttribute('name', $methodName . 'Response');
            $this->wsdl_definitions->appendChild($messageInput);
            $this->wsdl_definitions->appendChild($messageOutput);

            foreach ($method['var'] as $methodVars) {            	
                if (isset($methodVars['param'])) {
                    $part = $this->wsdl->createElement('part');
                    $part->setAttribute('name', $methodVars['name']);
                    $part->setAttribute('type', (($methodVars['array'] != 1 && $methodVars['class'] != 1)
                        ? 'xsd:' : 'typens:') . $methodVars['wsdltype']);
            		$messageInput->appendChild($part);
                }
                if (isset($methodVars['return'])) {
                    $part = $this->wsdl->createElement('part');
                    $part->setAttribute('name', $methodName.'Response'); //$methodVars['wsdltype']);
                    $part->setAttribute('type', (($methodVars['array'] != 1 && $methodVars['class'] != 1)
                        ? 'xsd:' : 'typens:') . $methodVars['wsdltype']);
            		$messageOutput->appendChild($part);
                }
            }
        }
    }

	// }}}
    // {{{ createWSDL_binding()
    /**
     * Create the binding node
     *
     * @return void
     */
    protected function createWSDL_binding()
    {
    	/*
	    <binding name="myServiceBinding" type="typens:myServicePort">    
	        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
	            <operation name="hello">
	                <soap:operation soapAction="urn:myServiceAction"/>
					<input>
					    <soap:body use="encoded" namespace="urn:myService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
	                </input>
	                <output>
	                    <soap:body use="encoded" namespace="urn:myService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
	                </output>
	        </operation>
	    </binding>
	    */
		$binding = $this->wsdl->createElement('binding');
        $binding->setAttribute('name', $this->classname . 'Binding');
        $binding->setAttribute('type', 'typens:' . $this->classname . 'Port');
        $soap_binding = $this->wsdl->createElement('soap:binding');
        $soap_binding->setAttribute('style', 'rpc');
        $soap_binding->setAttribute('transport', self::SCHEMA_SOAP_HTTP);
        $binding->appendChild($soap_binding);
        foreach ($this->wsdlStruct[$this->classname]['method'] AS $methodName => $methodVars) {
            $operation = $this->wsdl->createElement('operation');
            $operation->setAttribute('name', $methodName);
            $binding->appendChild($operation);
            $soap_operation = $this->wsdl->createElement('soap:operation');
            $soap_operation->setAttribute('soapAction', 'urn:'.$this->classname.'Action');
            $operation->appendChild($soap_operation);            
            $input  = $this->wsdl->createElement('input');
            $output = $this->wsdl->createElement('output');
            $operation->appendChild($input);
            $operation->appendChild($output);
            $soap_body = $this->wsdl->createElement('soap:body');
            $soap_body->setAttribute('use', 'encoded');
            $soap_body->setAttribute('namespace', 'urn:'.$this->namespace);
            $soap_body->setAttribute('encodingStyle', self::SOAP_SCHEMA_ENCODING );
            $input->appendChild($soap_body);
            $soap_body = $this->wsdl->createElement('soap:body');
            $soap_body->setAttribute('use', 'encoded');
            $soap_body->setAttribute('namespace', 'urn:'.$this->namespace);
            $soap_body->setAttribute('encodingStyle', self::SOAP_SCHEMA_ENCODING );
            $output->appendChild($soap_body);
        }
        $this->wsdl_definitions->appendChild($binding);
    }

    // }}}
    // {{{ createWSDL_portType()
    /**
     * Create the portType node
     *
     * @return void
     */
    protected function createWSDL_portType()
    {
    	/*
	    <portType name="myServicePort">
	        <operation name="hello">
	            <input message="typens:hello"/>
	            <output message="typens:helloResponse"/>
	        </operation>
	    </portType>
	    */
        $portType = $this->wsdl->createElement('portType');
        $portType->setAttribute('name', $this->classname.'Port');
        foreach ($this->wsdlStruct[$this->classname]['method'] AS $methodName => $methodVars) {
            $operation = $this->wsdl->createElement('operation');
            $operation->setAttribute('name', $methodName);
            $portType->appendChild($operation);

            $documentation = $this->wsdl->createElement('documentation');
            $documentation->appendChild($this->wsdl->createTextNode($methodVars['description']));
            $operation->appendChild($documentation);

            $input  = $this->wsdl->createElement('input');
            $output = $this->wsdl->createElement('output');
            $input->setAttribute('message', 'typens:' . $methodName );
            $output->setAttribute('message', 'typens:' . $methodName . 'Response');
            $operation->appendChild($input);
            $operation->appendChild($output);
        }
        $this->wsdl_definitions->appendChild($portType);
    }

    // }}}
    // {{{ createWSDL_service()
    /**
     * Create the service node
     *
     * @return void
     */
    protected function createWSDL_service()
    {
    	/*
	    <service name="myService">
	        <port name="myServicePort" binding="typens:myServiceBinding">
	            <soap:address location="http://dschini.org/test1.php"/>
	        </port>
	    </service>
        */
        $service = $this->wsdl->createElement('service');
        $service->setAttribute('name', $this->classname);
        $port = $this->wsdl->createElement('port');
        $port->setAttribute('name', $this->classname . 'Port');
        $port->setAttribute('binding', 'typens:' . $this->classname . 'Binding');
        $adress = $this->wsdl->createElement('soap:address');
        $adress->setAttribute('location', $this->protocol . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
        $port->appendChild($adress);
        $service->appendChild($port);
        $this->wsdl_definitions->appendChild($service);
    }
}

?>
Last edited by support on Thu Mar 04, 2010 5:24 pm, edited 11 times in total.

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

IVR Note: new changes

Post by support »

Attention - the name of the IVR function that we would prefer our users to have in their WSDL has changed. The reason we are making this change is that in some languages/architectures (e.g., ColdFusion) the word "evaluate" is reserved for the language, making it difficult to create a method for an IVR webservice with this name. The new name of the IVR function in your WSDL should be "plumEval". This is reflected in the newly released IVR documentation and info text on the IVR site, and is also edited into the post above.

However, we are not forcing this change on you immediately; if you have one properly-typed function in your WSDL called "evaluate" our SOAP client will adjust accordingly and it should still work without any changes.

rvafadar
Posts: 4
Joined: Thu Nov 04, 2010 9:32 am

Re: Soap Webservice.

Post by rvafadar »

Hi,

We have created a soap webservice and added it in the survey, however when we test it, the webservice is accessed but empty values are entered in the database.


Please help.

Thanks,
Rita Vafdar from (rvafadar@wisintl.com)

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

Re: Soap Webservice.

Post by support »

Hi Rita,

For SOAP webservice assistance, I would advise you to first read the following documentation:

http://www.plumvoice.com/docs/surveys/a ... _Questions

http://www.plumvoice.com/docs/surveys/s ... ervice.htm

You may find why your webservice is returning empty values from the documentation.

If you need further assistance, could you please provide us with a link to your WSDL?

Regards,
Plum Support

rvafadar
Posts: 4
Joined: Thu Nov 04, 2010 9:32 am

Re: Soap Webservice.

Post by rvafadar »

Hi,

I have created a Survey "Rep Arrival" and used the "SOAP Web service" at the end of Survey quesions.

"http://wwwtest.wisusa.com/PlumWebServic ... .asmx?WSDL".

Till yesterday, I was able to test the survey and see my web service got called and plumEval functioned just fine, but starting yesterday Dec 14, 2010, for some unknown reasons, whenever I test my survey,using Web or Phone, it stays in the questions and does not call the web service.

FYI, I have tested my web service using Client Web service and it works just fine.
Please let me know if you could

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

Re: Soap Webservice.

Post by support »

Hi,

We have tested this using the WSDL you provided within a test survey that we created, and it called on your webservice as expected (we received an answer of, 'rejected'). Are you able to reproduce this issue? If so, if you can tell us what question types you are using, it might help us to attempt to replicate the problem.

Regards,
Plum Support

rvafadar
Posts: 4
Joined: Thu Nov 04, 2010 9:32 am

Re: Soap Webservice.

Post by rvafadar »

You could test the survey with the following data and I expect to get an "accepted" message from Web service call.

"What is your Employee Number?" 10065
"What is the workorder number you are working on?" 273394
"At what time did you arrive at location?" 12:00 PM
"Did the Proper number of crew members show up with all required items to work, if No contact your Branch Manager immediately after this call?" yes

So far, nothing being saved in your Summery Report. When I go to "View Responsese" it says "This survey has no response data. "

I appriciate if you could forward me with the message from my web service?
Thanks,
rita

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

Re: Soap Webservice.

Post by support »

Hi Rita,

We cloned your survey (our copy is called: Rep Arrival PLUM copy) and placed a few test calls in an effort to replicate this issue. If you look at the responses for our cloned survey, you'll notice that all responses were saved correctly, including cases for 'accepted' and 'rejected'. At this point, we've been unable to reproduce this issue.

Regards,
Plum Support

Post Reply