一、配置文件 (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)
<?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框架编写,其他同行可以自行修改代码以适用自己公司的框架)