用post来进行Soap请求

Posted 破晓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用post来进行Soap请求相关的知识,希望对你有一定的参考价值。

最近调了一个Soap请求C# webservice的项目。网上坑不少。

使用原生的SoapClient库请求也是失败。只好用post来进行模拟了。代码贴出来,给大家参考一下。

 

<?php

namespace App\Services\Proxy;

use Log;

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‘);
    }
    
    /**
     * vipCreate
     */
    public function vipCreate($mobile, $openid, $username, $sex)
    {
        $this->values = [
            ‘vip‘ => [
                ‘surname‘ => $username,
                ‘mobile‘ => $mobile,
                ‘weixin‘ => $openid,
                ‘sex‘ => ($sex == 1) ? ‘M‘ : ‘F‘,
                ‘xf_vipcodeprefix‘ => ‘220‘,
            ]
        ];

        $response = $this->response(‘VipCreate‘, ‘vip.mobile‘);
        if (!empty($response[‘Body‘][‘VipCreateResponse‘][‘VipCreateResult‘][‘DATA‘][‘xf_vipcode‘])) {
            Log::info(‘CRM创建用户:‘ . $response[‘Body‘][‘VipCreateResponse‘][‘VipCreateResult‘][‘DATA‘][‘xf_vipcode‘]);
            return $response[‘Body‘][‘VipCreateResponse‘][‘VipCreateResult‘][‘DATA‘][‘xf_vipcode‘];
        } elseif (isset($response[‘Body‘][‘VipCreateResponse‘][‘VipCreateResult‘][‘Header‘][‘ERRCODE‘])) {
            Log::error(‘CRM创建用户失败,错误代码:‘ 
                        . $response[‘Body‘][‘VipCreateResponse‘][‘VipCreateResult‘][‘Header‘][‘ERRCODE‘]
                        . ‘,错误信息:‘ 
                        . $response[‘Body‘][‘VipCreateResponse‘][‘VipCreateResult‘][‘Header‘][‘ERRMSG‘]);
        }

        return null;
    }

    /**
     * VipModify
     */
    public function vipModify($user)
    {
        $this->values = [
            ‘vip‘ => [
                ‘xf_vipcode‘ => $user[‘crm_vipcode‘],
                ‘surname‘ => $user[‘username‘],
                ‘weixin‘ => $user[‘open_id‘],
                ‘birthday‘ => $user[‘birthday‘],
                ‘idcardno‘ => $user[‘ID_number‘],
                ‘address‘ => $user[‘address‘],
                ‘jointdate‘ => date(‘Y-m-d H:i:s‘, $user[‘created_at‘]),
                ‘sex‘ => ($user[‘sex‘] == 1) ? ‘M‘ : ‘F‘,
                ‘xf_vipcodeprefix‘ => ‘220‘,
            ]
        ];

        $response = $this->response(‘VipModify‘, ‘vip.xf_vipcode‘);

        if (isset($response[‘Body‘][‘VipModifyResponse‘][‘VipModifyResult‘][‘Header‘][‘ERRCODE‘])) {
            if (empty($response[‘Body‘][‘VipModifyResponse‘][‘VipModifyResult‘][‘Header‘][‘ERRCODE‘])) {
                Log::info(‘CRM修改用户:‘ . $user[‘username‘] . ‘成功‘ . json_encode($this->values));
                return true;
            } else {
                Log::error(‘CRM创建用户失败,错误代码:‘
                            . $response[‘Body‘][‘VipModifyResponse‘][‘VipModifyResult‘][‘Header‘][‘ERRCODE‘]
                            . ‘,错误信息:‘ 
                            . $response[‘Body‘][‘VipModifyResponse‘][‘VipModifyResult‘][‘Header‘][‘ERRMSG‘]);
            }
        } 

        return false;
    }

    /**
     * getBasicInfo
     */
    public function getBasicInfo()
    {
        dd($this->response(‘GetBasicInfo‘));
        return $this->response(‘GetBasicInfo‘);
    }

    /**
     * 以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\"?>\r\n";
        
        $soap_xml .= "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:tech=\"{$this->namespace}\">\r\n";
        $soap_xml .= "<soap:Body>\r\n";
        $soap_xml .= "<$action xmlns=\"{$this->namespace}\">\r\n";
        $soap_xml .= "<request>\r\n";

        // header
        $soap_xml .= $this->setHeader($soap_xml, $sign_index);

        // data
        $soap_xml .= "<Data>\r\n";
        $soap_xml .= $this->arrayToXml($this->values);
        $soap_xml .= "</Data>\r\n";
        $soap_xml .= "</request>\r\n";


        $soap_xml .= "</$action>\r\n";

        $soap_xml .= "</soap:Body>\r\n";
        $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>\r\n";
        $xml .= "<SIGN>$sign</SIGN>\r\n";
        $xml .= "<REQDATE>$date</REQDATE>\r\n";
        $xml .= "<REQTIME>$time</REQTIME>\r\n";
        $xml .= "<USER>{$this->username}</USER>\r\n";
        $xml .= "</Header>\r\n";

        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>\r\n";
          } else {
            $xml .= "<$name>$value</$name>\r\n";
          }
        }

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

 

以上是关于用post来进行Soap请求的主要内容,如果未能解决你的问题,请参考以下文章

nodejs post 请求soap 报错.大神求助

SOAP POST 请求 [关闭]

使用 Apache CXF 在 SOAP POST 请求中出错,但 curl 有效

soap协议和普通的post请求有啥区别呢

使用 org.apache.http 发送带有 SOAP 操作的 HTTP Post 请求

WebService Get/Post/Soap 方式请求