上海航信电子发票对接

一、配置文件 (config/invoice.php;发票配置数据由开票平台提供,以下配置数据随机修改过不可用于测试)


<?php/**
* Created by PhpStorm. * User: Jason * Date: 2019/7/1 * Time: 10:16 */ return [ 'DSPTBM' => 'sdf11dfd1MsfdFWegesdfIK', //'电商平台编码' 'NSRSBH' => '9670101000000090', //'纳税人识别码' 'NSRMC' => 'XXX官方旗舰店', //'纳税人名称', 'XHFMC' => 'XXX官方旗舰店', //'销货方名称' 'XHF_DZ' => '上海市杨浦区控江路XXX号', //'销货方地址', 'XHF_DH' => '17621251***', //'销货方电话', 'XHF_YHZH' => '', //'销货方银行账号', 'KPY' => '财务一', //'开票员', 'SKY' => '', //'收款员(可选)', 'HSBZ' => '1', 'TERMINALCODE' => '0', 'APPID' => 'ZZS_PT_DZFP', 'TAXPAYWERID' => '9670101000000090', //'税号', 'AUTHORIZATIONCODE' => '56301000000090', //'授权码', 'ENCRYPTCODE' =>'2', //0:不加密 1: 3DES 加密 2:CA 'INTERFACE_FPKJ' => 'ECXML.FPKJ.BC.E_INV', 'INTERFACE_FPXZ' => 'ECXML.FPXZ.CX.E_INV', 'INTERFACE_FPYX' => 'ECXML.EMAILPHONEFPTS.TS.E.INV', 'REQUESTCODE' => 'sdf11dfd1MsfdFWegesdfIK', //'请求码', 'RESPONSECODE' => '211', //'响应码', 'PASSWORD' => '', //'密码', ///'DATAEXCHANGEID' => '交互码', 'KJFP' => 'ECXML.FPKJ.BC.E_INV', 'DOWNLOAD' => 'ECXML.FPXZ.CX.E_INV', 'EMAIL' => 'ECXML.EMAILPHONEFPTS.TS.E.INV', 'REGISTERCODE' => '922588450019', //'注册码', ];

  二、拼装请求数据 (packageinfo.php)

<?php
/**
 * Created by PhpStorm.
 * User: Jason
 * Date: 2019/7/2
 * Time: 10:35
 */

class ome_invoice_packageinfo
{
    private static $_instance = null;

    private $config = [];

    public function __construct()
    {
        $this->config = include ROOT_DIR.'/config/invoice.php';
    }

    /***
     * @param $interface
     * @return string
     */
    public function getXml($interface, $content)
    {
        $rand = rand(1000000000,9999999999);
        $pwd = $rand.base64_encode(md5($rand.$this->config['REGISTERCODE']));
        $terminalcode = $this->config['TERMINALCODE'];
        $appid = $this->config['APPID'];
        $dsptbm = $this->config['DSPTBM'];
        $password = $pwd;
        $date = date('Y-m-d');
        $taxpayerid = $this->config['TAXPAYWERID'];
        $authorizationcode = $this->config['AUTHORIZATIONCODE'];
        $response = $this->config['RESPONSECODE'];
        $dataexchangeid = $this->config['REQUESTCODE'].date('Ymd').substr($rand,0,9);
        $str = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<interface xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.chinatax.gov.cn/tirip/dataspec/interfaces.xsd"
	version="DZFP1.0">
<globalInfo>
		 <terminalCode>{$terminalcode}</terminalCode>
		 <appId>{$appid}</appId>
		 <version>2.0</version>
		 <interfaceCode>{$interface}</interfaceCode>
		 <requestCode>{$dsptbm}</requestCode>
		 <requestTime>{$date}</requestTime>
		 <responseCode>{$response}</responseCode>
		 <dataExchangeId>{$dataexchangeid}</dataExchangeId>
		 <userName>{$dsptbm}</userName>
		 <passWord>{$password}</passWord>
		 <taxpayerId>{$taxpayerid}</taxpayerId>
		 <authorizationCode>{$authorizationcode}</authorizationCode>
</globalInfo>
<returnStateInfo>
<returnCode/>
<returnMessage/>
</returnStateInfo>
<Data>
	<dataDescription>
		  <zipCode>0</zipCode>
		  <encryptCode>0</encryptCode>
		  <codeType>0</codeType>
	</dataDescription>
	<content>
		{$content}	
	</content>
</Data>
</interface>
XML;


        return $str;

    }

    /***
     * @param array $config
     * @param array $arr
     * @return string
     */
    public function getContent(array $arr)
    {
      
        $fpkj = '';
        foreach ($this->content_0($config) as $key => $item){
            if($item['text']!==''){
                $fpkj .= '<'.strtoupper($item['key']).'>'.$item['text'].'</'.$item['key'].'>';
            }else{
                $fpkj .= '<'.strtoupper($item['key']).'>'.$arr[$item['key']].'</'.$item['key'].'>';
            }
        }
        $xm_size = count($arr['items']);
        $fpkj_xm = '';
        foreach ($arr['items'] as $num => $value){
            $fpkj_xm .= '<FPKJXX_XMXX>';
            foreach ($this->content_1($config) as $key=>$item){
                if($item['text']!==''){
                    $fpkj_xm .= '<'.strtoupper($item['key']).'>'.$item['text'].'</'.$item['key'].'>';
                }else{
                    $fpkj_xm .= '<'.strtoupper($item['key']).'>'.$value[$item['key']].'</'.$item['key'].'>';
                }
            }
            $fpkj_xm .= '</FPKJXX_XMXX>';
            //津贴被折扣行
            if(isset($value['discount'])){
                //size对应
                $xm_size++;
                $fpkj_xm .= '<FPKJXX_XMXX>';
                foreach ($this->content_1($config) as $key=>$item){
                    if($item['text']!==''){
                        $fpkj_xm .= '<'.strtoupper($item['key']).'>'.$item['text'].'</'.$item['key'].'>';
                    }else{
                        $fpkj_xm .= '<'.strtoupper($item['key']).'>'.$value['discount'][$item['key']].'</'.$item['key'].'>';
                    }
                }
                $fpkj_xm .= '</FPKJXX_XMXX>';
            }
        }
        $fpkj_dd = '';
        foreach ($this->content_2() as $key=>$item){
            if($item['text']!==''){
                $fpkj_dd .= '<'.strtoupper($item['key']).'>'.$item['text'].'</'.$item['key'].'>';
            }else{
                if($item['text']===null){
                    $fpkj_dd .= '<'.strtoupper($item['key']).'/>';
                    continue;
                }
                $fpkj_dd .= '<'.strtoupper($item['key']).'>'.$arr[$item['key']].'</'.$item['key'].'>';
            }
        }
        $root = <<<ROOT
<REQUEST_FPKJXX class="REQUEST_FPKJXX">
    <FPKJXX_FPTXX class="FPKJXX_FPTXX">
       {$fpkj}
    </FPKJXX_FPTXX>
    <FPKJXX_XMXXS class="FPKJXX_XMXX;" size="{$xm_size}">
    {$fpkj_xm}
    </FPKJXX_XMXXS>
    <FPKJXX_DDXX class="FPKJXX_DDXX">
    {$fpkj_dd}
    </FPKJXX_DDXX>
</REQUEST_FPKJXX>
ROOT;

        return base64_encode($root);
    }

    /***
     * @param string $xml
     * @return mixed|\SimpleXMLElement
     */
    public function XML2array(string $xml)
    {
        $arr = simplexml_load_string($xml);
        $arr = json_decode(json_encode($arr),TRUE);
        return $arr;
    }

    public function getDownload($arr)
    {
        $content = '';

        foreach ($this->download($this->config) as $key => $item){
            if($item['text']!==''){
                $content .= '<'.strtoupper($item['key']).'>'.$item['text'].'</'.$item['key'].'>';
            }else{
                if($item['text']===null){
                    $content .= '<'.strtoupper($item['key']).'/>';
                    continue;
                }
                $content .= '<'.strtoupper($item['key']).'>'.$arr[$item['key']].'</'.$item['key'].'>';
            }
        }

        $root = <<<ROOT
<REQUEST_FPXXXZ_NEW class="REQUEST_FPXXXZ_NEW">
    {$content}
</REQUEST_FPXXXZ_NEW>
ROOT;

        return base64_encode($root);
    }

    /***
     * @param array $arr
     * @return string
     */
    public function getEmail(array $arr)
    {
        $nsrsbh = $this->config['NSRSBH'];

        $root = <<<ROOT
<REQUEST_EMAILPHONEFPTS class="REQUEST_EMAILPHONEFPTS">
    <TSFSXX class="TSFSXX">
        <COMMON_NODES class="COMMON_NODE;" size="4">
            <COMMON_NODE> 
                <NAME>TSFS</NAME> 
                <VALUE>0</VALUE>
            </COMMON_NODE>
            <COMMON_NODE>
                <NAME>SJ</NAME>
                <VALUE></VALUE> 
            </COMMON_NODE>
            <COMMON_NODE>
                <NAME>EMAIL</NAME>
                <VALUE>{$arr['email']}</VALUE> 
            </COMMON_NODE>
            <COMMON_NODE>
                <NAME>扩展字段名称</NAME>
                <VALUE>扩展字段值</VALUE> 
            </COMMON_NODE>
        </COMMON_NODES> 
    </TSFSXX>
    <FPXXS class="FPXX;" size="1">
        <FPXX>
             <COMMON_NODES class="COMMON_NODE;" size="5"> 
                <COMMON_NODE>
                    <NAME>FPQQLSH</NAME>
                    <VALUE>{$arr['FPQQLSH']}</VALUE> 
                </COMMON_NODE>
                <COMMON_NODE>
                    <NAME>NSRSBH</NAME>
                    <VALUE>{$nsrsbh}</VALUE> 
                </COMMON_NODE> 
                <COMMON_NODE>
                    <NAME>FP_DM</NAME>
                    <VALUE>{$arr['fp_dm']}</VALUE> 
                </COMMON_NODE> 
                <COMMON_NODE>
                    <NAME>FP_HM</NAME>
                    <VALUE>{$arr['fp_hm']}</VALUE> 
                </COMMON_NODE> 
                <COMMON_NODE>
                    <NAME>扩展字段名称</NAME>
                    <VALUE>扩展字段值</VALUE>
                </COMMON_NODE>
            </COMMON_NODES> 
        </FPXX>
    </FPXXS>
</REQUEST_EMAILPHONEFPTS>
ROOT;

        return base64_encode($root);
    }

    /***
     * @param $config
     * @return array
     */
    private function content_0($config)
    {
        return  [
            'FPQQLSH'=>[
                'key'=>'FPQQLSH',
                'text'=>'',
                'comment'=>'请求流水号'
            ],
            'DSPTBM'=>[
                'key'=>'DSPTBM',
                'text'=>$config['DSPTBM'],
                'comment'=>'平台编码'
            ],
            'NSRSBH'=>[
                'key'=>'NSRSBH',
                'text'=>$config['NSRSBH'],
                'comment'=>'开票方识别号'
            ],
            'NSRMC'=>[
                'key'=>'NSRMC',
                'text'=>$config['NSRMC'],
                'comment'=>'开票方名称'
            ],
            'DKBZ'=>[
                'key'=>'DKBZ',
                'text'=>'0'
            ],
            'KPXM'=>[
                'key'=>'KPXM',
                'text'=>'',
                'comment'=>'商品信息中第一条'
            ],
            'BMB_BBH'=>[
                'key'=>'BMB_BBH',
                'text'=>'1.0'
            ],
            'XHF_NSRSBH'=>[
                'key'=>'XHF_NSRSBH',
                'text'=>$config['NSRSBH'],
                'comment'=>'销方识别码'
            ],
            'XHFMC'=>[
                'key'=>'XHFMC',
                'text'=>$config['NSRMC'],
                'comment'=>'销方名称'
            ],
            'XHF_DZ'=>[
                'key'=>'XHF_DZ',
                'text'=>$config['XHF_DZ'],
                'comment'=>'销方地址'
            ],
            'XHF_DH'=>[
                'key'=>'XHF_DH',
                'text'=>$config['XHF_DH'],
                'comment'=>'销方电话'
            ],
            'XHF_YHZH'=>[
                'key'=>'XHF_YHZH',
                'text'=>$config['XHF_YHZH'],
                'comment'=>'销方银行账号'
            ],
            'GHFMC'=>[
                'key'=>'GHFMC',
                'text'=>'',
                'comment'=>'购货方名称'
            ],
            'GHF_SJ'=>[
                'key'=>'GHF_SJ',
                'text'=>'',
                'comment'=>'购货方手机'
            ],
            //01-企业 02-机关事业单位 03-个人  04-其他
            'GHFQYLX'=>[
                'key'=>'GHFQYLX',
                'text'=>'',
                'comment'=>'购货方名称'
            ],
            'SKY'=>[
                'key'=>'SKY',
                'text'=>$config['SKY'],
            ],
            'KPY'=>[
                'key'=>'KPY',
                'text'=>$config['KPY'],
            ],
            //1 正票  2 红票
            'KPLX'=>[
                'key'=>'KPLX',
                'text'=>'',
                'comment'=>'开票类型'
            ],
            //10 正票正常开具 11 正票错票重开 20 退货折让红票 21 错票重开红票 22 换票冲红(全冲红电子发票,开具纸质发票)
            'CZDM'=>[
                'key'=>'CZDM',
                'text'=>'',
                'comment'=>'操作代码'
            ],
            'QD_BZ'=>[
                'key'=>'QD_BZ',
                'text'=>'0'
            ],
            //小数点后2位 以元为单位精确到分  double
            'KPHJJE'=>[
                'key'=>'KPHJJE',
                'text'=>'',
                'comment'=>'价税合计金额'
            ],
            //double
            'HJBHSJE'=>[
                'key'=>'HJBHSJE',
                'text'=>'',
                'comment'=>'合计不含税金额'
            ],
            'HJSE'=>[
                'key'=>'HJSE',
                'text'=>'',
                'comment'=>'合计税额'
            ]
        ];
    }


    /***
     * @param array $config
     * @return array
     */
    private function content_1(array $config)
    {
        return [
            'XMMC'=>[
                'key'=>'XMMC',
                'text'=>'',
                'comment'=>'项目名称'
            ],
            'XMSL'=>[
                'key'=>'XMSL',
                'text'=>'',
                'comment'=>'项目数量'
            ],
            'HSBZ'=>[
                'key'=>'HSBZ',
                'text'=>$config['HSBZ']
            ],
            'FPHXZ'=>[
                'key'=>'FPHXZ',
                'text'=>'',
            ],
            //小数点后8位小数
            'XMDJ'=>[
                'key'=>'XMDJ',
                'text'=>''
            ],
            'SPBM'=>[
                'key'=>'SPBM',
                'text'=>''
            ],
            'ZXBM'=>[
                'key'=>'ZXBM',
                'text'=>''
            ],
            'YHZCBS'=>[
                'key'=>'YHZCBS',
                'text'=>'0',
                'comment'=>'优惠政策标识'
            ],
            //小数点后2位
            'XMJE'=>[
                'key'=>'XMJE',
                'text'=>'',
                'comment'=>'项目金额'
            ],
            //税率
            'SL'=>[
                'key'=>'SL',
                'text'=>'0.03'
            ],
        ];
    }

    /***
     * @return array
     */
    private function content_2()
    {
        return [
            'DDH'=>[
                'key'=>'DDH',
                'text'=>''
            ],
            'DDDATE'=>[
                'key'=>'DDDATE',
                'text'=>null,
            ]
        ];
    }

    /***
     * @param array $config
     * @return array
     */
    private function download(array $config)
    {
        return [
            'DDH'=>[
                'key'=>'DDH',
                'text'=>'',
            ],
            'FPQQLSH'=>[
                'key'=>'FPQQLSH',
                'text'=>''
            ],
            'DSPTBM'=>[
                'key'=>'DSPTBM',
                'text'=>$config['DSPTBM'],
            ],
            'NSRSBH'=>[
                'key'=>'NSRSBH',
                'text'=>$config['NSRSBH'],
            ],
            'PDF_XZFS'=>[
                'key'=>'PDF_XZFS',
                'text'=>''  //0-发票状态查询 1-pdf文件
            ]
        ];
    }

    /***
     * @param array $config
     * @return array
     */
    public function email(array $config)
    {
        return [
            'TSFS'=>'',
            'EMAIL'=>'',
            'FPQQLSH'=>'',
            'NSRSBH'=>$config['NSRSBH'],
            'FP_DM'=>'',
            'FP_HM'=>''
        ];
    }

    private function udate($utimestamp = null) {
        if (is_null($utimestamp))
            $utimestamp = microtime(true);

        $timestamp = floor($utimestamp);
        $milliseconds = round(($utimestamp - $timestamp) * 100);
        return $milliseconds;
    }
}

  三、封装SDK(invoicesdk.php)

<?php
/**
 * Created by PhpStorm.
 * User: Jason
 * Date: 2019/7/3
 * Time: 10:20
 */
date_default_timezone_set("Asia/Shanghai");

class ome_invoice_invoicesdk
{
    const KJFP = 'ECXML.FPKJ.BC.E_INV';
    const DOWNLOAD = 'ECXML.FPXZ.CX.E_INV';
    const EMAIL = 'ECXML.EMAILPHONEFPTS.TS.E.INV';

    const HOST = 'http://fw1test.shdzfp.com:9000/sajt-shdzfp-sl-http/SvrServlet';    //test

    public function __construct()
    {
        $this->packageInfoObj = kernel::single("ome_invoice_packageinfo");
    }

    /***
     * @param array $arr
     * @return \SimpleXMLElement
     * 开具发票
     */
    public function create(array $arr)
    {
        $data = [];
        if ($arr['invoice_type'] == 2) {
            $data['ghfmc'] = $arr['invoice_title'];
            $data['ghfqylx'] = '01';
        } else {
            $data['ghfmc'] = '个人';
            $data['ghfqylx'] = '03';
        }
        $items = [];
        //查询子项目
        foreach ($arr['items'] as $key => $item) {
            $show_name = $item['name'];
            $items[$key]['XMMC'] = $show_name;
            $items[$key]['XMSL'] = sprintf('%.8f', $item['quantity']);
            $items[$key]['XMDJ'] = sprintf('%.8f', $item['price']);
            $items[$key]['SPBM'] = $item['spbm'];
            $items[$key]['ZXBM'] = $item['zxbm'];
            $items[$key]['XMJE'] = sprintf('%.2f', $item['price'] * $item['quantity']);


            if ($arr['discount'] && $arr['discount'] != 0.00 && $key == 0) {
                $items[$key]['FPHXZ'] = 2;
                $items[$key]['discount'] = [
                    'XMMC' => $show_name,
                    'XMSL' => '-' . sprintf('%.8f', 1),
                    'FPHXZ' => '1',
                    'XMDJ' => sprintf('%.8f', $arr['discount']),
                    'SPBM' => $item['spbm'],
                    'ZXBM' => $item['id'],
                    'XMJE' => '-' . sprintf('%.2f', $arr['discount'])
                ];
            } else {
                $items[$key]['FPHXZ'] = 0;
            }
            if ($key == 0) {
                $data['KPXM'] = $show_name; //kpxm
            }
        }
        $data['items'] = $items;
        $data['mobile'] = isset($arr['mobile']) ? $arr['mobile'] : '';
        
        $data['KPHJJE'] = sprintf('%.2f', $arr['sum']);
        $data['HJBHSJE'] = sprintf('%.2f', $arr['sum']);
        $data['HJSE'] = sprintf('%.2f', $arr['HJSE']);
        $data['DDH'] = $arr['order_bn'];

        $data['FPQQLSH'] = $arr['FPQQLSH'];
        ///$data['KPXM'] = $arr['KPXM'];
        $data['GHFMC'] = $arr['GHFMC'];
        $data['GHF_SJ'] = $arr['GHF_SJ'];
        $data['GHFQYLX'] = $arr['GHFQYLX'];
        $data['KPLX'] = $arr['KPLX'];
        $data['CZDM'] = $arr['CZDM'];
        
        $content = $this->packageInfoObj->getContent($data);

        $xml = $this->packageInfoObj->getXml(self::KJFP, $content);
        file_put_contents('./request_xml_' . date('YmdHis', time()) . '.xml', $xml);
        
        
        $request_time = microtime(true);
        $response = $this->postCurl(self::HOST, $xml);
        $this->runtime = microtime(true) - $request_time;
        
        //file_put_contents('./invoice_response_' . date('YmdHis', time()) . '.xml', $response);
        
        $content = simplexml_load_string($response);

        //请求日志数据组装
        $log_data = array(
            'api_handler' => 'request',
            'api_name' => 'ECXML.FPKJ.BC.E_INV',
            'api_status' => $content->returnStateInfo->returnCode == '0000' ? 'success' : 'fail',
            'api_request_time' => $request_time,
            'api_check_time' => time(),
            'api_runtime' => $this->get_runtime(),
            'api_method' => 'POST',
            'api_response_status' => empty($content->returnStateInfo->returnCode) ? '-' : (string) $content->returnStateInfo->returnCode,
            'api_url' => self::HOST,
            'api_request_data' => $xml,
            'api_response_data' => $response,
            'sys_error_data' => $content->returnStateInfo->returnCode == '0000' ? 'NULL' : (string) base64_decode($content->returnStateInfo->returnMessage),
        );

        $this->writeLog($log_data);

        if ($content->returnStateInfo->returnCode == '0000') {
            $kaipiaoModel = app::get("ome")->model("invoice_kaipiao");

            $kaipiao_data = [
                'order_bn' => $data['DDH'],
                'fpqqlsh' => $data['FPQQLSH'],
                'user_name' => (string) $content->globalInfo->userName,
                'password' => (string) $content->globalInfo->passWord,
                'add_time' => time()
            ];
            
            $kaipiaoModel->save($kaipiao_data);
        }


        
        return $content;
    }

    /***
     * @param array $arr
     * @return mixed
     */
    public function download(array $arr)
    {
       
        $data['FPQQLSH'] = 'SW_1562151541_1019422043';    //此处FPQQLSH必须是开票成功时请求数据里的FPQQLSH

        $len = strlen($arr['order_bn']);
        $data['lsh'] = str_repeat('0', 20 - $len) . $arr['order_bn'];
        $data['PDF_XZFS'] = 2;
        $data['DDH'] = $arr['order_bn'];
        $content = $this->packageInfoObj->getDownload($data);
        $xml = $this->packageInfoObj->getXml(self::DOWNLOAD, $content);

        //file_put_contents('./download_request_xml_' . date('YmdHis', time()) . '.xml', $xml);

        $request_time = microtime(true);
        $response = $this->postCurl(self::HOST, $xml);
        $this->runtime = microtime(true) - $request_time;

        file_put_contents('./download_invoice_response_' . date('YmdHis', time()) . '.xml', $response);

        $content = simplexml_load_string($response);

        //请求日志数据组装
        $log_data = array(
            'api_handler' => 'request',
            'api_name' => 'ECXML.FPXZ.CX.E_INV',
            'api_status' => $content->returnStateInfo->returnCode == '0000' ? 'success' : 'fail',
            'api_request_time' => $request_time,
            'api_check_time' => time(),
            'api_runtime' => $this->get_runtime(),
            'api_method' => 'POST',
            'api_response_status' => empty($content->returnStateInfo->returnCode) ? '-' : (string) $content->returnStateInfo->returnCode,
            'api_url' => self::HOST,
            'api_request_data' => $xml,
            'api_response_data' => $response,
            'sys_error_data' => $content->returnStateInfo->returnCode == '0000' ? 'NULL' : (string) base64_decode($content->returnStateInfo->returnMessage),
        );

        $this->writeLog($log_data);

        if ($content->returnStateInfo->returnCode == '0000') {
            //PDF_XZFS 1 content内容要先解密再解压
            if ($content->Data->dataDescription->zipCode == 1) {
                $content = gzdecode(base64_decode($return->Data->content));
                $pdf = simplexml_load_string($content);
                return $pdf;
            }
        } elseif ($return->Data->dataDescription->zipCode[0] == 2){
                //PDF_XZFS 2 content内容只要解密不要解压
               $content = base64_decode($return->Data->content);
                $pdf = simplexml_load_string($content);
                return $pdf;
        }
    }

    public function email(array $arr)
    {
        $len = strlen($arr['order_bn']);
        $data['lsh'] = str_repeat('0', 20 - $len) . $arr['order_bn'];
        $data['eamil'] = $arr['email'];
        $data['fp_dm'] = $arr['fp_dm'];
        $data['fp_hm'] = $arr['fp_hm'];
        $content = $this->packageInfoObj->getEmail($data);
        $xml = $this->packageInfoObj->getXml(self::EMAIL, $content);

        $request_time = microtime(true);
        $response = $this->postCurl(self::HOST, $xml);
        $this->runtime = microtime(true) - $request_time;

        $return = simplexml_load_string($response);
        if ($return->returnStateInfo->returnCode == '0000') {
            //修改状态
            return $return;
        }
        //请求日志数据组装
        $log_data = array(
            'api_handler' => 'request',
            'api_name' => 'ECXML.FPXZ.CX.E_INV',
            'api_status' => $return->returnStateInfo->returnCode == '0000' ? 'success' : 'fail',
            'api_request_time' => $request_time,
            'api_check_time' => time(),
            'api_runtime' => $this->get_runtime(),
            'api_method' => 'POST',
            'api_response_status' => empty($return->returnStateInfo->returnCode) ? '-' : (string) $return->returnStateInfo->returnCode,
            'api_url' => self::HOST,
            'api_request_data' => $xml,
            'api_response_data' => $response,
            'sys_error_data' => $return->returnStateInfo->returnCode == '0000' ? 'NULL' : (string) base64_decode($return->returnStateInfo->returnMessage),
        );

        $this->writeLog($log_data);
    }

    public function postCurl($url, $params, $headerArr = '')
    {
        if (!$url) {
            return '请求缺少URL!';
        }

        $headers = array(
            //'content-type:application/json;charset=utf-8',
            'content-type:application/x-www-form-urlencoded;charset=utf-8',

        );

        if (is_array($headerArr) && !empty($headerArr)) {
            $queryHeaders = array();
            foreach ($headerArr as $k => $v) {
                $queryHeaders[] = $k . ':' . $v;
            }
            //print_r($queryHeaders);
            $headers = array_merge($headers, $queryHeaders);
        }

        //$body = json_encode($params);
        $body = $params;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POST, 1);

        //curl_setopt($ch, CURLOPT_HTTPHEADER,array("Content-Type: application/json;charset=utf-8"));

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

        //绕过SSL验证
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if (!empty($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        $return_content = curl_exec($ch);//运行curl
        curl_close($ch);

        return $return_content;

    }

    public function writeLog($log_data)
    {
        app::get('ome')->model('invoice_request_log')->save($log_data);
    }

    /**
     * 获取接口调用执行时间
     * @return string
     */
    protected function get_runtime()
    {
        return sprintf('%.6f', $this->runtime);
    }
}

   四、测试脚本

<?php
/**
 * Created by PhpStorm.
 * User: Jason
 * Date: 2019/7/3
 * Time: 18:59
 */
class ome_ctl_test extends desktop_controller
{
   

    public function invoice()
    {
        $arr = [
            'invoice_type' => '01',
            'invoice_title' => '测试发票单',
            'items' => [
                [
                    'name' => '手表',	//项目名称
                    'quantity' => '1',
                    'price' => '100.00',	//项目单价
                    'spbm' => '1040204020000000000',	//商品编码 填商品名称对应的商品税收分类编码,19位不足补0
                    'zxbm' => '1001',	//自行编码
                    'id' => '1001',		//有折扣时自行编码取值

                ],
            ],
            'discount' => '',
            'mobile' => '17621256***',
            'sum' => '100.00',	//价税合计金额
            'order_bn' => 'order_1000001',	//订单号
            'FPQQLSH' => 'SW_'.time().'_'.rand(1000000000, 9999999999),	//请求流水号
            'KPXM' => 'sfd',	//商品信息中第一条
            'GHFMC' => '张三',	//购货方名称
            'GHF_SJ' => '17621256***',	//购货方手机
            'GHFQYLX' => '01',	//购货方企业类型
            'KPLX' => '1',	//开票类型	1 正票 2 红票
            'CZDM' => '10',	//操作代码
            'HJBHSJE' => '90.00',	//合计不含税金额
            'HJSE' => '100',	//合计税额

            'KPHJJE' => '100',	//价税合计金额

        ];

        $invoiceSdkObj = kernel::single("ome_invoice_invoicesdk");

        //$res = $invoiceSdkObj->create($arr);
        $res = $invoiceSdkObj->download($arr);



    }

}

五、response返回示例:

  1.开票

  

<?xml version="1.0" encoding="UTF-8"?>
<interface xmlns:schemaLocation="http://www.chinatax.gov.cn/tirip/dataspec/interfaces.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="WLFP1.0">
 <globalInfo>
  <terminalCode>0</terminalCode>
  <appId>ZZS_PT_DZFP</appId>
  <version>2.0</version>
  <interfaceCode>ECXML.FPKJ.BC.E_INV</interfaceCode>
  <requestCode>111MFWIK</requestCode>
  <requestTime>2019-07-03</requestTime>
  <responseCode>121</responseCode>
  <dataExchangeId>111MFWIK20190703127514978</dataExchangeId>
  <userName>111MFWIK</userName>
  <passWord>1275149784YTZjMDUxMTcwZGIzYTE4NjU5ODM1NGUxOTA0MzcyMDg=</passWord>
  <taxpayerId>310101000000090</taxpayerId>
  <authorizationCode>3100000090</authorizationCode>
 </globalInfo>
 <returnStateInfo>
  <returnCode>0000</returnCode>
  <returnMessage>5o6l5pS25byA56Wo5pWw5o2u5oiQ5Yqf77yB</returnMessage>
 </returnStateInfo>
 <Data>
  <dataDescription>
   <zipCode>0</zipCode>
   <encryptCode>0</encryptCode>
   <codeType>0</codeType>
  </dataDescription>
  <content />
 </Data>
</interface>

  2.发票下载(含发票 PDF URL)

  

扫描二维码关注公众号,回复: 6722813 查看本文章
<?xml version="1.0" encoding="utf-8" ?>
<interface xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.chinatax.gov.cn/tirip/dataspec/interfaces.xsd"
    version="DZFP1.0">
<globalInfo>
         <terminalCode>0</terminalCode>
         <appId>ZZS_PT_DZFP</appId>
         <version>2.0</version>
         <interfaceCode>ECXML.FPXZ.CX.E_INV</interfaceCode>
         <requestCode>111MFWIK</requestCode>
         <requestTime>2019-07-04</requestTime>
         <responseCode>121</responseCode>
         <dataExchangeId>111MFWIK20190704138486180</dataExchangeId>
         <userName>111MFWIK</userName>
         <passWord>1384861802N2UzZmFhMzg1MTY0M2ZmOGRiNjE3YjJhNjhkMzdjNGI=</passWord>
         <taxpayerId>310101000000090</taxpayerId>
         <authorizationCode>3100000090</authorizationCode>
</globalInfo>
<returnStateInfo>
<returnCode/>
<returnMessage/>
</returnStateInfo>
<Data>
    <dataDescription>
          <zipCode>0</zipCode>
          <encryptCode>0</encryptCode>
          <codeType>0</codeType>
    </dataDescription>
    <content>
        PFJFUVVFU1RfRlBYWFhaX05FVyBjbGFzcz0iUkVRVUVTVF9GUFhYWFpfTkVXIj4KICAgIDxEREg+b3JkZXJfMTAwMDAwMTwvRERIPjxGUFFRTFNIPlNXXzE1NjIxNTE1NDFfMTAxOTQyMjA0MzwvRlBRUUxTSD48RFNQVEJNPjExMU1GV0lLPC9EU1BUQk0+PE5TUlNCSD4zMTAxMDEwMDAwMDAwOTA8L05TUlNCSD48UERGX1haRlM+MjwvUERGX1haRlM+CjwvUkVRVUVTVF9GUFhYWFpfTkVXPg==    
    </content>
</Data>
</interface>

  3.发票下载(含发票 PDF FILE)

  

<?xml version="1.0" encoding="utf-8" ?>
<interface xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.chinatax.gov.cn/tirip/dataspec/interfaces.xsd"
    version="DZFP1.0">
<globalInfo>
         <terminalCode>0</terminalCode>
         <appId>ZZS_PT_DZFP</appId>
         <version>2.0</version>
         <interfaceCode>ECXML.FPXZ.CX.E_INV</interfaceCode>
         <requestCode>111MFWIK</requestCode>
         <requestTime>2019-07-03</requestTime>
         <responseCode>121</responseCode>
         <dataExchangeId>111MFWIK20190703112641847</dataExchangeId>
         <userName>111MFWIK</userName>
         <passWord>1126418479NmNkOTIyN2YzNDQ4MDNjMGU1MWUyNDkzZTc1ZmVkZGI=</passWord>
         <taxpayerId>310101000000090</taxpayerId>
         <authorizationCode>3100000090</authorizationCode>
</globalInfo>
<returnStateInfo>
<returnCode/>
<returnMessage/>
</returnStateInfo>
<Data>
    <dataDescription>
          <zipCode>0</zipCode>
          <encryptCode>0</encryptCode>
          <codeType>0</codeType>
    </dataDescription>
    <content>
        PFJFUVVFU1RfRlBYWFhaX05FVyBjbGFzcz0iUkVRVUVTVF9GUFhYWFpfTkVXIj4KICAgIDxEREg+b3JkZXJfMTAwMDAwMTwvRERIPjxGUFFRTFNIPlNXXzE1NjIxNTE1NDFfMTAxOTQyMjA0MzwvRlBRUUxTSD48RFNQVEJNPjExMU1GV0lLPC9EU1BUQk0+PE5TUlNCSD4zMTAxMDEwMDAwMDAwOTA8L05TUlNCSD48UERGX1haRlM+MTwvUERGX1haRlM+CjwvUkVRVUVTVF9GUFhYWFpfTkVXPg==    
    </content>
</Data>
</interface>

六、发票样式效果

  

  

(注:代码基于商派OMS框架编写,其他同行可以自行修改代码以适用自己公司的框架)

猜你喜欢

转载自www.cnblogs.com/IT-Crowd/p/11131355.html