1

我从以前的开发人员那里接管了一个应用程序,并且有一些代码使用 Nusoap 完成了一半,我收到了错误:

Call to register_donation() web service failed due to an exception: 
Function ("register_donation") is not a valid method for this service   

该应用程序建立在:CakePHP 1.2.10& 使用nuSoap 0.9.5.

我已经ini_set('soap.wsdl_cache_enabled', 0);(这没有帮助。)

我的代码在下面(为了便于阅读,我缩短了它),我是否正确处理了这个响应?(代码是我自己从以前的开发人员那里接手的)。

Pastebin(完整代码)在这里:PasteBin Link

下面是一个简短的版本供您浏览,完整版本在上面的 pastebin 链接中。

<?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
}
}

?>

如果我可以提供更多信息,请告诉我。

总结:如何处理来自外部来源的 nusoap 响应。
任何调试想法、提示和技巧或解决方案都将得到奖励(+1!)。

4

1 回答 1

4

在发布的代码中有一个registerDonation名为ServicesController. 在该函数内部还有另一个函数被调用register_donation(这显然没有意义 [旧代码])。

从方法中删除命名的函数register_donation并将registerDonation其作为方法放在ServicesContoller.

然后更改以下行(在其中注册要公开的函数)。

从:$server->register('register_donation',
到:     $server->register('ServicesController.register_donation',

所以你class.method只调用方法而不是方法(这将在 PHP4 过程编程中工作,但在 OOP 中,你需要controller.method在公开函数时指定)。


还有其他问题吗?

问:CakePHP & nuSOAP 没有命中我的控制器/方法,而是重定向到 app/webroot 答:使用 CakePHP 1.2,我发现当它没有服务模型时(因为它在技术上不是必需的),请求没有命中控制器。因此,如果您遇到此问题,请为您的控制器创建一个模型,即使您没有使用它。供您参考,这里有一个模态示例:

<?php // You may not need this modal, but cakephp requires it to be there.
class Services extends AppModel {
   public $name = 'Services';
   public $useTable = false;
}
?>

问:我应该收到哪个 URL 的回复? 答:您设置的响应命中的 URL 必须包含?wsdl.
所以.. 例如:你有一个名为的控制器和名为的SOAPController方法process
在 CakePHP 中,您的 URL 看起来像这样:mydomain.com/SOAP/process.
所以你WSDL位于mydomain.com/SOAP/process?wsdl. 确保您的回调 URL 设置为此(包括wsdl)。

问:如何使用 CakePHP 调试 SOAP 请求/响应?
答: CakePHP 有一个日志记录功能,它在调试中被证明是无价的SOAP。在您的控制器(或模态)中,您可以使用:

$this->log('your message or variable', 'name_of_file_to_save_to);

您可以通过您的SOAP请求或响应使用它来查看哪些部分被点击/调用和调试变量(例如:)$HTTP_RAW_POST_DATA

问:当我访问 SOAP 页面时,我的 WSDL 位置显示为“domain.com/app/webroot”。

答:我认为这是导致所有问题的问题,查看用于获取当前脚本的源代码NusoapPHP_SELF在 cakePHP 中是app/webroot/index.php),不用担心,您可以wsdl通过在 URL 中附加来?wsdl访问向您展示您生成的WSDL文件,您无需担心修复此问题。它不会干扰您的SOAP请求,只是为了您的方便。

问:我的 SOAP 地址位置显示“domain.com/app/webroot/index.php”

答:这是我通过$endpointconfigureWSDL().

//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
于 2012-10-30T19:30:34.043 回答