最近调了一个Soap请求C# webservice的项目。网上坑不少。
使用原生的SoapClient库请求也是失败。只好用post来进行模拟了。代码贴出来,给大家参考一下。
<?php namespace AppServicesProxy; use Log; use Cache; class Crm { private $host; private $namespace; private $app_secret; private $username; private $values; public function __construct() { $this->host = config('crm.host'); $this->namespace = config('crm.namespace'); $this->app_secret = config('crm.app_secret'); $this->username = config('crm.username'); $this->values = []; } /** * 通过mobile和open_id获取用户信息 */ public function getVipInfoByMobileOpenID($mobile, $openid) { $this->values = [ 'mobile' => $mobile, 'openid' => $openid, ]; return $this->response('GetVipInfoByMobileOpenID'); } /** * 以post方式提交xml到对应的接口url */ private function postXml($action, $sign_index = null) { $body = $this->toCRMXml($action, $sign_index); // Get cURL resource $ch = curl_init(); // Set url curl_setopt($ch, CURLOPT_URL, $this->host); // Set method curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); // Set options curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Set headers curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: text/xml"]); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); // Send the request & save response to $resp $resp = curl_exec($ch); if ($resp === false) { $error = curl_error($ch); curl_close($ch); Log::info('CRM请求错误:' . json_encode($error)); return false; } curl_close($ch); return $resp; } /** * 输出CRM soap xml字符 */ private function toCRMXml($action, $sign_index = null) { $soap_xml = "<?xml version="1.0" encoding="utf-8"?> "; $soap_xml .= "<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tech="{$this->namespace}"> "; $soap_xml .= "<soap:Body> "; $soap_xml .= "<$action xmlns="{$this->namespace}"> "; $soap_xml .= "<request> "; // header $soap_xml .= $this->setHeader($soap_xml, $sign_index); // data $soap_xml .= "<Data> "; $soap_xml .= $this->arrayToXml($this->values); $soap_xml .= "</Data> "; $soap_xml .= "</request> "; $soap_xml .= "</$action> "; $soap_xml .= "</soap:Body> "; $soap_xml .= "</soap:Envelope>"; return $soap_xml; } /** * 生成Header */ private function setHeader($xml, $sign_index= null) { list($date, $time) = explode(' ', date('Ymd His')); $sign = $this->setSign($date, $time, $sign_index); $xml = ""; $xml .= "<Header> "; $xml .= "<SIGN>$sign</SIGN> "; $xml .= "<REQDATE>$date</REQDATE> "; $xml .= "<REQTIME>$time</REQTIME> "; $xml .= "<USER>{$this->username}</USER> "; $xml .= "</Header> "; return $xml; } /** * 生成sign */ private function setSign($date, $time, $sign_index= null) { if ($sign_index) { if (strpos($sign_index, '.')) { list($stuct_index, $index) = explode('.', $sign_index); $seeder = $date . $time . $this->values[$stuct_index][$index] . $this->app_secret; } else { $seeder = $date . $time . $this->values[$sign_index] . $this->app_secret; } } else { $seeder = $date . $time . $this->app_secret; } return md5($seeder); } /** * 数组转换成xml */ private function arrayToXml($params) { $xml = ""; foreach ($params as $name => $value) { if (is_array($value)) { $xml .= "<$name>" . $this->arrayToXml($value) . "</$name> "; } else { $xml .= "<$name>$value</$name> "; } } return $xml; } /** * 将xml结果转化为对象 */ public function response($action, $sign_index = null) { $result = str_ireplace('soap:', '', $this->postXml($action, $sign_index)); return $this->objectToArray(simplexml_load_string($result, 'SimpleXMLIterator', LIBXML_NOCDATA)); } /** * 将对象转化为数组 */ public function objectToArray($obj) { $_arr = is_object($obj) ? get_object_vars($obj) : $obj; $arr = []; foreach ($_arr as $key => $val) { $val = (is_array($val) || is_object($val)) ? $this->objectToArray($val) : $val; $arr[$key] = $val; } return $arr; } }