webservice的一种常用实现方式就是soap了。我们后端的JAVA也是用soap的原理实现的。那么我显然首先要上网上搜搜关于soap的文章。最早进入实现的是PHP写的nusoap类。这个nusoap.php文件是完全用PHP写法来实现的soap方法。优点是不用给php装动态模块,也不用重新编译PHP。我当时像找到了新大陆一样,一头就载进去了。

先构建一个soap_server.php的文件,主要就是负责把给TokenString解密的getMsgSoap函数。具体解密算法我肯定是封装在自己写的类里了。

<?php

define('IFENG_LOG_LEVEL_DEBUG', 8);
require('./include/nusoap.php');
include "./include/class.IFengSystem.php";
include "./include/class.IFengHttp.php";
include "./include/class.IFengPay.php";

//创建soap服务类
$server = new soap_server;
$server->register('getMsgSoap');

//$pay = new
IFengPay();   
//创建支付类
$pay =
IFengPay::getInstance();   
//单态创建一个类
//$token =
$pay->des->decrypt('C445FFDB6DE7093E58E0D60F9249B54DBEE2719EAD036262BCAABD5C234155B98229C4F8283B643FF2A454B22CED20F1C53C75F6C578EC30F597F656B125997CF0121F184989D32CFA1D40E74ECA4FBE93212FF5FC839625EE459294FF052A9FBC1F1961DBA8FAB6DBFB6E3C1A53FFBEA91B0C95E370588C44C9B1A5786A49D6BC67D79894A65664');   
//调用des解密算法

function getMsgSoap($token)
{
    global
$pay;
    $token =
$pay->des->decrypt($token);   
//调用des解密算法
    return
$token;
}
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ?
$HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

然后再写一个soap_client.php,实际上就是调用soap_server.php上封装好的方法。
代码如下:
<?php
//引用numsoap包。
require('./include/nusoap.php');

//soap的服务端
$server_url =
'http://app.finance.ifeng.com/Sso/soap_server.php';

//创建一个实例
$client = new soapclient($server_url);
//调用的soap端的函数协议
$soap_method_name = 'getMsgSoap';
//TokenString是返回的加密串的参数名
$data = array('token' =>
$_GET['TokenString']);
$result = $client->call($soap_method_name,
$data);
// Display the result
print_r($result);
?>

测试完了,我一测试,OK了。高兴,兴奋,原来这么简单。结果没过多久,我们技术部的同事yetao就找我来了,你这个WEBSERVICE我那边调用不了。

其实我当时还没有害怕,看看怎么回事儿呗。结果yetao说我这个nusoap自动生成的wsdl和他JAVA,还有C#生成的wsdl不统一。也就是说我这个不是标准的。晕,不是吧。心里凉了半截。

这里需要给大家说一下什么是WSDL,基本上这就是XML的一种标准变形,类似于SVG和XSL那种,又自己的命名规则。剩下的知识大家搜索一下吧。

没办法了。换别的方法吧。于是继续在网上寻觅着。突然有篇帖子说nusoap已经过时了,而且通用性不好,最好还是用PHP5中自带的soap函数。切,最后还是躲不过要安装动态模块的老路。结果就看看手册上的安装帮助呗。手册上的安装需求部分会提示This
extension makes use of the »
GNOME xml library
. Download and install this library. You will
need at least libxml-2.5.4.
于是我开始在网上找libxml的package,这个还挺好找了,用了和上次mcrypt一样的安装方法,详见http://blog.sina.com.cn/s/blog_582246d20100dej9.html

装完了libxml我说继续找soap的安装包吧,结果满互联网找竟然都没找到一个安装的文件,无论是php.net,还是pecl网站都没找到,也可能是我笨吧。问问合作方用的PHP是什么版本,发现和我的一样,我想同样的版本说不定直接把soap.so文件要过来就成了(这绝对是用多了windows系统人的弊病,别以为这是php_soap.dll那样的,因为只要是在windows环境下,dll文件就通用)但是在linux下可就不同了,果不其然,对方的系统是centos,和我这边的不同。这条路也断了。

问了问技术部同事sunli,他建议我只能重新编译php了,然后在编译是加上--enable-soap。于是我写个phpinfo()把Configure
Command 对应的代码都拷贝下来,然后再加上我新要加上的这个模块。
代码如下:
'./configure' '--prefix=/usr/local/php5'
'--with-libxml-dir=/usr/lib' '--with-zlib'
'--with-gd=/usr/local/gdlibforphp/gd' '--with-zlib-dir=/usr'
'--with-mysql=/data/mysql' '--enable-sockets' '--enable-mbstring'
'--enable-soap' '--with-apxs2=/data/apache/bin/apxs'
'--enable-safe-mode' '--enable-ftp' '--with-png-dir=/usr/local'
'--with-freetype-dir=/usr'
'--with-jpeg-dir=/usr/local/gdlibforphp/jpeg'
'--with-sqlite=shared'

记住,编译之前要把那个生成的文件夹删除,从新用tar命令解压,然后执行这编译命令,再make
&& make
install来安装。完毕后重启apache,再看phpinfo。发现soap包终于有了。看来有的时候想躲一些事情是躲不掉的。但是这样有一个问题,就是现在这个只是在测试机上编译安装。如果在产品机上安装,那肯定得找个浏览人数少的时候,所以未来这一两天,我看那天晚上方便,给产品机重新编译一下。

然后重新构造这两个soap文件,准确的说是三个,因为还要自己构造一个wsdl文件。
soap_server.php程序代码如下:
<?php

define('IFENG_LOG_LEVEL_DEBUG', 8);
include "./include/class.IFengSystem.php";
include "./include/class.IFengHttp.php";
include "./include/class.IFengPay.php";

class msg
{
    public
function getMsgSoap($token = '')
    {
   
    $pay =
IFengPay::getInstance();   
//单态创建一个类
   
    $token =
$pay->des->decrypt($token);   
//调用des解密算法
   
    return
$token;
    }
}
$server = new SoapServer('msg.wsdl', array('soap_version'
=> SOAP_1_2,
'encoding'=>'UTF-8'));

$server->setClass("msg");

$server->handle();

?>

编码强制转化为了UTF-8,然后声明一个webservice类msg,这里也可以声明function的。

soap_client.php代码如下:
<?php
//$client = new
SoapClient('http://app.finance.ifeng.com/Sso/msg.wsdl');

$client = new
SoapClient("http://app.finance.ifeng.com/Sso/soap_server.php?WSDL",array('cache_wsdl'
=> 0));
$TokenString = $_GET['TokenString'];
try {
    $result =
$client->getMsgSoap($TokenString);

} catch(SoapFault $e) {  
    print "Sorry
an error was caught executing your request:
{$e->getMessage()}";

}

print_r($result);
?>
   
其中第一行注释的就是wsdl的位置,因为nusoap是自动生成wsdl的,所以我们之前一直没有考虑这个东西。这个wsdl是可以通过zend自动生成的。当你写好一个soap_server.php的时候,在zend中执行“工具”->“WSDL生成器”,然后选定一个wsdl文件,这个文件不同于JAVA和C#中,需要我们事先建立好这个文件,然后选中这个文件后点击下一步,选择绑定的文件(也就是我们这个soap_server.php),于是就会自动显示这个文件中的方法了。选中你想填入到wsdl中的方法,然后complete就可以了。生成的这个wsdl是标准的可以被JAVA中soap方法识别的。

最后就当我以为已经成功的时候,程序上又输出了一行错误。“Unable to parse
URL”也就是$e->getMessage()这行生效了。我在百度上搜索数条误解后,开始求助google了。于是在一篇英文的文章中找到了解决方法,不得否认,还是老外牛啊。

该文链接:http://www.electrictoolbox.com/php-soapclient-unable-parse-url/

根据这篇文章,我把大家需要改动的部分罗列出来吧,方便看英文不方便的同学。
1、首先你要在生成的wsdl文件中找到<soap:address
location=""/>,然后改为<soap:address
location="http://app.finance.ifeng.com/Sso/soap_server.php"/>也就是换成你那个soap_server.php所在的位置。

2、修改php.ini,加入下面这几行,是控制WSDL的缓存的。

[soap]

; Enables or disables WSDL caching feature.

soap.wsdl_cache_enabled=1

; Sets the directory name where SOAP extension will put cache files.
soap.wsdl_cache_dir="/tmp"

; (time to live) Sets the number of second while cached file will be used

; instead of original one.

soap.wsdl_cache_ttl=86400 3、最后就是网上关于Soap类调用的例子都是直接
$client = new SoapClient('http://host/path/file.php?wsdl');
但是后面还要加上一个参数的,改为下面这句。
$client = new SoapClient('http://host/path/file.php?wsdl',
array('cache_wsdl' => WSDL_CACHE_NONE));
try{}catch(SOAPFAULT $e){}

这三步都修改完毕后,重启apache,再看你的页面,发现终于成功了!OH,终于成功了!

最近在开发上用到了soap,同时还碰到了一个怪问题。

当我修改了服务端的调用方法后,更新了wsdl,客户端的参数老是丢失(不是全丢失,而是部分),让人很郁闷。

第二天我索性增加了一个服务端的新方法,更新了wsdl,但是客户端请求却报错说没有定义该方法。

最后发现是因为php对soap的wsdl进行了缓存。

解决方法是,修改php.ini中的soap.wsdl_cache_enabled=1(改为0),soap.wsdl_cache_ttl=86400(改为0)两项。

特别注意的是,客户端和服务端的机器都要改。

在最后的最后,yetao说他那边虽然能看见我这个方法了,但是一传参数还是会报错,由于时间紧,我们就改http的传送方式来解决这个问题了。不过这个问题的源头可能是这句话。在网上看到的。“特别注意:我发现调用php
webserver的方法和调用.net web服务的方法不一样。 调用.net service方法必须传入命名参数;而调用php
web服务方法,一定不能传入命名参数,只能按顺序传入,为什么?这一点尤其要注意
”。有时间再研究吧,这个已经占用我很多时间了。

简单对象访问协议(Simple Object Access Protocol),PHP调用SOAP过程中的种种问题;php的soap无故出错的真凶:wsdl缓存的更多相关文章

  1. 一、SOAP简单对象访问协议讲解

    一.SOAP简单对象访问协议讲解 今天给大家讲讲SOAP的基本知识.下节给大家演示创建基于SOAP的Web Service. 更多SOA文章请查看我的个人博客. 首先,让我来简单一下入门SOAP所需的 ...

  2. SOAP(简单对象访问协议)

    ylbtech-Miscellaneos:SOAP(简单对象访问协议) A,返回顶部 1, 简单对象访问协议是交换数据的一种协议规范,是一种轻量的.简单的.基于XML(标准通用标记语言下的一个子集)的 ...

  3. SOAP 简单对象访问协议

    webService三要素 SOAP.WSDL(WebServicesDescriptionLanguage).UDDI(UniversalDescriptionDiscovery andIntegr ...

  4. 轻型目录访问协议 ldap 公司内部网站的登录 单点登录

    https://zh.wikipedia.org/wiki/轻型目录访问协议 轻型目录访问协议(英文:Lightweight Directory Access Protocol,缩写:LDAP,/ˈɛ ...

  5. IMAP(Internet Mail Access Protocol,Internet邮件访问协议)以前称作交互邮件访问协议(Interactive Mail Access Protocol)。

    IMAP(Internet Mail Access Protocol,Internet邮件访问协议)以前称作交互邮件访问协议(Interactive Mail Access Protocol).IMA ...

  6. LADP(Lightweight Directory Access Protocol)轻量目录访问协议~小知识

    What is LDAP and how does it work(implementation)? LDAP stands for “Lightweight Directory Access Pro ...

  7. 介质访问控制子层-Medium Access Control Sublayer:多路访问协议、以太网、无线局域网

    第四章 介质访问控制子层-Medium Access Control Sub-layer 4.1介质访问控制子层概述 MAC子层不属于之前提到的OSI或TCP/IP架构的任何一层,这也是为什么这一层被 ...

  8. Internet Message Access Protocol --- IMAP协议

    https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol   Internet Message Access Protocol

  9. Simple Mail Transfer Protocol --- SMTP协议

    https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol   Simple Mail Transfer Protocol

随机推荐

  1. Python内置函数(9)——callable--转载

    英文文档: callable(object) Return True if the object argument appears callable, False if not. If this re ...

  2. CentOS6.4_x86_120g__20160306.rar

    安装的镜像包: CentOS-6.4-i386-bin-DVD1to2(CentOS-6.4-i386-bin-DVD1.iso / CentOS-6.4-i386-bin-DVD2.iso) 1. ...

  3. C#对象初始或器-Chapter3 P38

    protected string GetMessage() { //如何构造和初始化泛型集合库中的一个数组和两个类. Product myProduct = ,Name="Kayak&quo ...

  4. [vuex]——使用vuex解决模块间传值问题

    二月的第四个周末,在家.受寒流的影响,深圳天气持续冰冻了好几天,天冷人就变得懒动,迷迷糊糊睡到了快十点,终于在饥饿的催促下起床. 和妹子吃完粥后,百无聊赖.透过窗户,发现太阳依旧没有露头的打算,我们也 ...

  5. 加密算法中涉及C/C++总结

    学习网站:http://www.runoob.com/cplusplus/cpp-functions.html char在VC(c++)中占1字节(byte),8位(bit). int在VC(c++) ...

  6. ArcGIS 10 Raster Calculator 在哪儿

    ArcGIS 10 Raster Calculator 在哪儿? 现在大家用的最多的是ArcGIS9.3,所以大家都知道Raster Calculator在ArcToolbox->Spatial ...

  7. android中自定义view构造函数ContentItemView(Context context, AttributeSet paramAttributeSet)的用处

    自己定义一个view <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:a ...

  8. C++设计模式之备忘录模式

    备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态[DP].举个简单的例子,我们玩游戏时都会保存进度,所保存的进度以文件的 ...

  9. strtol 笔记

    今天看了一下网上关于这个函数的解释,根据文章大意记录一下 strtol 是将字符串转换为long int的一个函数 strtol(const char* nptr, char **endptr, in ...

  10. 使用nginx反向代理处理前后端跨域访问

    本文主要解决:使用nginx反向代理处理前后端跨域访问的问题 1.何为跨域访问? 以下类型为跨域访问 1)不同域名间访问 www.zuiyoujie.com和www.baidu.com 2)同域名不同 ...