航天信息精准票据识别服务对接规范接口文档_第1页
航天信息精准票据识别服务对接规范接口文档_第2页
航天信息精准票据识别服务对接规范接口文档_第3页
航天信息精准票据识别服务对接规范接口文档_第4页
航天信息精准票据识别服务对接规范接口文档_第5页
已阅读5页,还剩44页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

新亮僖in

精准票据识别服务对接规范

2020年5月

目录

1.概述4

2.压缩与解压缩4

2.1示例代码4

2.1.1Java开发4

2.1.2C++开发7

2.1.3C#开发11

2.2压缩方法说明13

2.3压缩方法验证13

3.证书加密说明14

3.1加解密使用的密钥说明14

3.1.1演示版密钥使用说明14

3.1.2正式版密钥使用说明14

3.2|AVA开发14

3.2.1Jar包说明14

3.2.2方法说明14

3.2.3加解密流程说明16

3.2.4示例代码16

3.3C++开发17

3.3.1DLL库说明17

3.3.2方法说明17

3.3.3加解密流程说明19

3.3.4小例代码19

3.4C#开发21

3.5力口解密t音误码21

4.对接说明21

4.1获取身份令牌21

4.1.1请求报文示例与数据项说明22

4.1.2返回报文示例与数据项说明23

4.2外层报文说明24

4.2.1公共请求参数24

4.2.2公共返回参数25

4.3票种编码表26

4.4票种返回字段列表26

4.4.1增值税专用/普通/电子发票26

4.4.2增值税卷式发票28

4.4.3机动车销售统一发票29

4.4.4二手车销售统一发票30

4.4.5出租车票32

4.4.6火车票33

4.4.7客运汽车票33

4.4.0机票行程单34

2

4.4.9车辆通行费35

4.4.10定额发票35

4.4.11其他类型35

4.5错误码36

5.服务列表及参数说明37

5.1票据识别服务37

5.1.1精准票据识别请求37

5.1.2精准票据识别结果查询38

6.对接联系人49

3

1.概述

航天信息精准票据识别服务提供财税票据的云端识别服务,对接收到的票据图片进行智能识别,并返问票面文字

信息。可识别票种包含增值税发票、机票行程单、火车票、出租车票、定额发票等。此文档为技术对接规范,请用户

按照此规范进行程序开发。

2.压缩与解压缩

2.1示例代码

2.1.1Java开发

importmons.codec.binary.Base64;

importjava.io.ByteArrayInputstream;

importjava.io.ByteArrayOutputStream;

importjava.io.lOException;

importjava.io.InputStream;

importjava.io.Outputstream;

importjava.util.zip.GZIPInputStream;

importjava.util.zip.GZIPOutputStream;

publicclassGZipUtils{

publicstaticintBUFFER=1024;

publicstaticStringEXT='*.gz";

/*★

*对数据压缩,封装了参数为byte□的方法

*Qparamdata

*^return

*^throwsException

*/

publicstaticbooleancompress(byte[]data,ByteArrayOutputStreambaos)throws

lOException{

ByteArrayInputstreambais=newByteArraylnputStream(data);

〃压缩

try(

compress(bais,baos);

4

returntrue;

}catch(Exceptione;{

e.printStackTrace();

returnfalse;

}finally{

bais.close();

}

)

/★★

*数据压缩

*©paramis

*@paramos

*@throwsException

*/

publicstaticvoidcompress(Inputstreamis,Outputstreamos)throwsException{

GZIPOutputStreamgos=newGZIPOutputStream(os);

intcount;

bytedata[]=newbyte[BUFFER];

while((count=is.read(data,0,BUFFER))!=-1){

gos.write(data,0fcount);

}

gos.finish();

gos・flush();

gos.close();

)

/★

*对数据解压缩,封装了参数为byte□的方法

*@paramdata

*^return

*©throwsException

*/

publicstaticbooleandecompress(byte[]data,ByteArrayOutputStreambaos)throws

lOException{

ByteArrayInputStreambais=newByteArrayInputstream(data);

//解压缩

try(

decompress(bais,baos);

returntrue;

}catch(Exceptione:{

e.printStackTrace();

returnfalse;

}finally{

bais.close();

}

)

5

*数据解压缩

*@paramis

*@paramos

*@throwsException

*/

publicstaticvoiddecompress(Inputstreamis,Outputstreamos)throwsException{

GZIPInputStreamgis=newGZIPInputStream(is);

intcount;

bytedata[]=newbyte(BUFFER];

while((count=gis.read(data,0,BUFFER))!=-1){

os.write(data,0,count);

)

gis.close();

)

publicstaticvoidmain(String[]args)throwslOException{

//压缩示例代码

Stringstr=

for(inti=0;i<ICO;i++){

str+='*51云税中台compressanddecompresstest;";

)

System.out.printin("压缩前长度:"+str.length());

ByteArrayOutputStreambaos=newByteArrayOutputStream();

BooleanstrZipReturn=compress(str.getBytes(),baos);

if(false—strZipReturn){

System.out.printIn("压缩失败,,);

}

byte[]output=baos.toByteArray();

baos.flush();

baos.close();

〃压缩后的内容用base64编码

Stringoutputstr=Base64.encodeBase64String(output);

System.cut.println(',乐缩后的内容为:"+outpnt.Str);

System.out.printin("压缩后的长度为:"+outputstr.length());

〃解压缩示例代码

ByteArrayOutputStreambaos2=newByteArrayOutputStream();

〃先用base64解码

byte[]strZipByte=Base64.decodeBase64(outputStr);

BooleanstrReturn=decompress(strZipByte,baos2);

if(false==strReturn){

System.out.printIn("解压缩失败”);

6

)

byte[]data=baos2.toByteArray();

baos2.flush();

baos2.close();

StringstrMessage=rewString(data);

System.out.printin("解压缩后的内容为:”+strMessage);

)

)

2.1.2C++开发

#include"zlib.h"//使用到zlib库

boolCompressData(INconststringSsSrcData,OUTstring&sDstData,string&sErr)

(

intiOrgLen=sSrcData.size();

/*计算缓冲区大小,并为其分配内存*/

uLongfiDataCnt=compressBound(iOrgLen+1);//压缩后的最长长度,需要把字符

串的结束符10,也一并处理

Bytef*pDstData=nullptr;

YQAutoPtr<Bytef>PtrDstData(SpDstData,iDataCnt);

if(nullptr==pDstData)

|

sErr="压缩:内存error”;

returnfalse;

)

memset(pDstData,0,iDataCnt);

Bytef*plnpuData=(Bytef*)sSrcData.c_str();

intiRlt=compress(pDstData,&iDataCnt,plnpuEata,iOrgLen);

//错误处理

boolbRlt=false;

stringsTmp="压缩错误代码:”;

switch(iRlt)

{

caseZ_OK:

caseZ_STREAM_END:

caseZ_NEED_DICT:

bRlt=true;

break;

caseZ_ERRNO:

sErr=sTmp+to_string(iRlt)+",Z_ERRNO";

bRlt=false;

7

break;

caseZ_STREAM_ERROR:

sErr=sTmp+to_string(iRlt)+”,Z_STREAM_ERRORn;

bRlt=false;

break;

caseZ_DATA_ERROR:

sErr=sTmp+to_string(iRlt)+”,Z_DATA_ERRORn;

bRlt=false;

break;

caseZ_MEM_ERROR:

sErr=sTmp+to_string(iRlt)+“,Z_MEM_ERRORn;

bRlt=false;

break;

caseZ_BUF_ERROR:

sErr=sTmp+to_string(iRlt)+“,Z_BUF_ERRORn;

bRlt=false;

break;

caseZ_VERSION_ERROR:

sErr=sTmp+to_string(iRlt)+”,Z_VERSION_ERROR";

bRlt=false;

break;

default:

sErr=sTmp+”未知”;

bRlt=false;

break;

}

if(bRlt)

(

//Base64

intmLen=iDataCnt;

intiBase64Len=iDataCnt*4/3+32;

unsignedchar*pBase64Data=nullptr;

YQAutoPtr<unsignedchar>AutoPtr(&pBase64Data,iBase64Len);

if(nullptr==pBase64Data)

{

sErr="压缩:内存error”;

returnfalse;

}

memset(pBase64Data,0,iBase64Len);

memcpy(pBase64Data,pDstData,iDataCnt);

Base64_Encode_2(pBase64Data,mLen);

sDstData.assign((char*)pBase64Data);

)

returnbRlt;

8

boolUnCompressData(INstring&sSrcDatazintSiOrgnLen,OUTstring&sDstData,string

SsErr)

if((sSrcData.empty())||(iOrgnLen<=0))

(

sDstData='*";

sErr=”压缩报文不能为空/原文长度不正确,

returnfalse;

)

//Base64解码

intiDcdDataLen=0;

char*pDcdData=nullptr;

intiSrcDataLen=sSrcData.length()+1;

YQAutoPtr<char>PtrDcdData(&pDcdUata,iSrcDataLen);

if(nullptr==pDcdData)

(

sErr="解压缩:内存error”;

returnfalse;

)

memset(pDcdData,0,iSrcDataLen);

memcpy(pDcdData,sSrcData.c_str(),iSrcDataLen);

Base64_Decode_2(pDcdData,&iDcdDataLen);

intiDeBs64Len=strlen(pDcdData)+1;

//endBase64解码

//为解压缩做准备

Bytef*pBSrcData=(Bytef*)pDcdData;

Bytef*pDstData=nullptr;

YQAutoPtr<Bytef>PtrDstData(spDstData,iOrgnLen+1);

if(nullptr==pDstData)

(

sErr="解压缩内存错误,

returnfalse;

}

memset(pDstData,0,iOrgnLen+1);

uLongfiDstLen=iOrgnLen+1;

intiRlt=uncompress(pDstData,SiDstLen,pBSrcData,iDcdDataLen);

9

〃错误处理

boolbRlt=false;

stringsTmp="解压缩错误代码:,,

switch(iRlt)

(

caseZ_OK:

caseZ_STREAM_END:

caseZ_NEED_DICT:

sDstData.assign((char*)pDstData);

bRlt=true;

break;

caseZ_ERRNO:

sErr=sTmp+to_string(iRlt)+”,Z_ERRNO”;

bRlt=false;

break;

caseZ_STREAM_ERROR:

sErr=sTmp+to_string(iRlt)+”,Z_STREAM_ERRORU;

bRlt=false;

break;

caseZ_DATA_ERROR:

sErr=sTmp+to_string(iRlt)+”,Z_DATA_ERRORn;

bRlt=false;

break;

caseZ_MEM_ERROR:

sErr=sTmp+to_string(iRlt)+”,Z_MEM_ERRORH;

bRlt=false;

break;

caseZ_BUF_ERROR;

sErr=sTmp+to_string(iRlt)+",Z_BUF_ERRORH;

bRlt=false;

break;

caseZ_VERSION_ERROR:

sErr=sTmp+to_string(iRlt)+",Z_VERSION_ERROR";

bRlt=false;

break;

default:

sErr=sTmp+”未知”;

bRlt=false;

break;

}

returnbRlt;

}

10

2.1.3C#开发

namespaceCAencrypt

(

classzlibCompress

(

internalconststringNameZlib32=nzlib32.dll*';

internalconststringNameZlib64=nzlib64.dll";

internalstaticboolIs64-(IntPtr.Size--8);

[Dlllmport(NameZlib32,EntryPoint='*compress*',ExactSpelling=true,CharSet=

CharSet.Ansi)]

privatestaticexternintcompress_32(byte[]dest,refSystem.UInt32destLen,

byte[]source,System.UInt32sourceLen);

[Dlllmport(NameZlib32,EntryPoint="uncompress",ExactSpelling=true,CharSet

=CharSet.Ansi)]

publicstaticexternintuncompress_32(Byte[]dest,refSystem.UInt32destLen,

Byte[]source,System.UInt32sourceLen);

[Dlllmport(NameZlib64zEntryPoint="compress*',ExactSpelling=trae,CharSet=

CharSet.Ansi)]

privatestaticexternintcompress_64(byte[]dest,refSystem.UInt32destLen,

byte[]source,System.UInt32sourceLen);

[Dlllmport(NameZlib64,EntryPoint="uncompress",ExactSpelling=true,CharSet

=CharSet.Ansi)]

publicstaticexternintuncompress_64(Bytefldest,refSystem.UInt32destLen,

Byte[]source,System.UInt32sourceLen);

[Dlllmport(NameZlib32,EntryPoint=ncompressBound**,ExactSpelling=true,

CharSet=CharSet.Ansi,CalLingConvention=Callingconvention.StdCall)]

publicstaticexternSystem.UInt32compressBound_32(System.UInt32ILength);

[Dlllmport(NameZlib64,EntryPoint="compressBound',,ExactSpelling=true,

CharSet=CharSet.Ansi,CalLingConvention=Callingconvention.StdCall)]

publicstaticexternSystem.UInt32compressBound_64(System.UInt32ILength);

publicstaticstringzlibZip(stringvalue)//zlib压缩

(

byte[]arrBufSrc=Encoding.UTF8.GetBytes(value);

System.UInt32nBufSrc=(System.UInt32)arrBufSrc.Length+1;

System.UInt32nBufDst;

intiRtn;

if(Is64)

nButDst=compressBound_64(nButSrc);

11

else

nBufDst=compressBound_32(nBufSrc);

}

byte[]arrBufDst=newbyte[nBufDst];

if(Is64){

iRtn=compress_64(arrBufDst,refnBufDst,arrBufSrc,nBufSrc);

)

else

iRtn=compress_32(arrBufDst,refnBufDst,arrBufSrc,nBufSrc);

//Compress(byteArray,byteArray.Length,reftmpArray,refaa);

if(iRtn==0)

(

byte[]arrDstAct=newbyte[nBufDst];

Array.Copy(arrBufDst,arrDstAct,nBufDst);

returnConvert.ToBase64String(arrDstAct);

}

else

return”压缩失败,

)

publicstaticstringzlibDecompress(stringstrSource)

(

try

(

byte[]Buffersource=Convert.FromBase64String(strSource);//解base64

System.UInt32sourceLen=(System.UInt32)BufferSource.Length;

System.UInt32des二Len=1024*1024*100;

12

byte[]BufferByteDest=newbyte[destLen];

intiRtn=0;

if(Is64)

iRtn=uncompress_64(BufferByteDest,refdestLen,BufferSource,

sourceLen);

else

iRtn=uncompress_32(BufferByteDest,refdestLen,BufferSource,

sourceLen);

if(iRtn--0)

|

byte[]arrDstAct=newbyte[destLen];

Array.Copy(BufferByteDest,arrDstAct,destLen);

stringstrRe=System.Text.Encoding.UTF8.GetString(BufferByteDest,0z

BufferByteDest.Length);

returnstrRe.Trim({1\01));

)

else

return”解压缩失败”+iRtn;

}//zlib解压缩

catch

(

return”解压缩失败,请确认字符串是否为压缩后的内容”;

)

)//zlib解压缩

)

2.2压缩方法说明

无论使用何种语言开发压缩、解压缩功能,与51云税中台对接时,均需要注意以下几点:

(1)压缩与解压缩的函数需要配对使用:

(2)加解密过程中,是否需要压缩与CA加解密,参照zipCode与encryptCode字段;

(3)请求报文处理顺序:内层报文(明文,UTF-8格式)—CA加密—压缩-Base64编码;

(4)返回报文处理顺序:Base64解码一解压缩-CA解密―内层报文(明文,UTF-8格式)。

2.3压缩方法验证

为方便用户验证自己的压缩、解压缩功能是否正确,下面提供了51云税中台压缩前后的报文供测试验证对比:

(1)压缩前报文(UTF-8格式):

13

51云税中台compressanddecompresstest

(2)压缩后报文(经过Base64编码)

H4sIAAAAAAAAADMlfLJr4vMVfU92rH3avOEhOT+3oCiluFghMS9FISUVzilJLS4BAKG4N+OrAAAA

用户可以用上面压缩前、压缩后的报文在自己的压缩、解压缩函数上进行测试,如果结果与上面的一致,则说明

用户自己的压缩、解压缩函数与51云税中台对接没问题。

3.证书加密说明

3.1加解密使用的密钥说明

3.1.1演示版密钥使用说明

演示版联调时,通过线下的方式可获取到以下四项,调用方在云端配置时需注意,应使用对应的演示版调用方公

钥和私铁:

(1)演示版调用方公钥:CLIENT_DECRYPTCER=YS01TEST.cer

(2)演示版调用方私钥:CLIENT_3ECRYPTPFX=YS01TEST.pfx

(3)演示版调用方私钥密码:CLIENT_D演RYPTPF用KEY=szeNe6kEb5

(4)演示版51云税中台公钥:PLATF0RM_DECRYPTCER=51fapiao_20180523.cer

3.1.2正式版密钥使用说明

在正式环境中,平台商注册成功后,会通过邮件方式获取到正式版调用方公钥、正式版调用方私钥和正式版调用

方私钥密码,正式版51云税中台公钥(PLATF()RM_DECRYPTCER=51fapiao.cer)需自行通过平台商系统下载。调用方在

云端配置时需注意,应使用对应的正式版调用方公钥和私钥。

3.2Java开发

3.2.1Jar包说明

ca.api-version.jar是负责CA加解密的工具包,需要集成到业务系统的程序里,集成方式可自行选择。

Jar包中的核心类是CaApi,封装了加解密的算法实现。

3.2.2方法说明

加密并签名方法

方法名:CaApi.encrypt7sign

调用参数:

序号参数名参数描述类型长度必须说明

14

1.cer加密公钥证书Varchar是

2.pfx签名私钥证书byte口是

3.password签名私钥密码Varchar是

4.plaintext明文Varchar是

传true为生产,要使

用生产证书;rflag传

5.rflag证书类型boolean是

false为测试,要使用测

试证书

返叵值:

序号参数名参数描述类型长度必须说明

1.密文字节流byte[]是

解密并验签方法

方法名:CaApi.decrypt7check

调用参数:

序号参数名参数描述类型长度必须说明

1.cer验签公钥证书Varchar是

2.p仅解密私钥证书byte[]是

3.password解密私钥密码Varchar是

4.ciphertext密文字节流byte[]是

传true为生产,要使

用生产证书;rflag传

5.rflag证书类型boolean是

false为测试,要使用测

试证书

返叵值:

序号参数名参数描述类型长度必须说明

1.明文Varchar是

15

323加解密流程说明

设定一个场景,A对明文加密,发给B,B解密得出明文。

B对明文加密,发给A,A解密得出明文。

A使用B的公钥加密,用A的私钥签名,调用encrypt7sign方法,得出密文发给B。

B拿到密文使用B的私钥解密,用A的公钥验签,调用decrypt7check方法,得出明文。

B使用A的公钥加密,用B的私叙签名,调用encrypt7sign方法,得出密文发给A。

A拿到密文使用A的私钥解密,用B的公钥验签,调用decrypt7check方法,得出明文。

3.2.4示例代码

由于java版本已封装jar包,所以只提供如何在java工程中编写弋码调用jar包的示例代码。

ca.test是ca加解密的demo,演示程序,demo里,调用jar包方法,传参的证书均从工程中ca目录读取,文件路

径通过perties读取。

测试,直接执行demo中CaTest里的main方法即可,加解密的结果会输出在控制台上。

main方法中代码如图所示:分别模拟了客户端加密得到密文a,服务端解密得到明文b,服务端加密得到密文c,

客户端解密得到明文do

publicstaticvoidmain(String[]args)

(

for(inti=0;i<1;i++)

(

try{

byte[]clientPfx=FileUtils.readFileToByteArray(new

File(getPropertyAddress("CLIENT_DECRYPTPFXn)));

byte[]clientCer=FileUtils.readFileToByteArray(new

File(getPropertyAddress(,'CLIENT_DECRYPTCERH)));

StringclientPsw=getProperty(HCLIENT_DECRYPTPFX_KEYn);

byfA[]SArvArCAr=Fi1al汁i1s.raadFi1ATnRytpArray(nAw

File(getPropertyAddress("PLATFORM_DECRYPTCER")));

byte[]serverPfx=FileUtils.readFileToByteArray(new

File(getPropertyAddress("PLATFORM_DECRYPTPFX")));

StringserverPsw=getProperty(•,PLATFORM_DECRYPTPFX_KEYH);

//客户端加密用客户端私钥签名、用服务器端的公铜加密一

byte[]a=CaApi.encrypt7sign(newString(serverCer),clientPfx,

clientPsw,"51云税",false);

System.out.println("密文:'1+newString(newBase64().encode(a)));

//服务器端解密用服务器端的私钥解密、用客户端的公钥验签

Stringb=CaApi.decrypt7check(newString(clientCer),serverPfx,

serverPsw,a,false);

System.out.printIn(“明文:"+b);

//服务器端加密用服务器的私钥签名、用客户端的公钥加密

byte[]c=CaApi.encrypt7sign(newString(clientCer),serverPfx,

serverPsw,"云税51”,false);

System.out.printin(“密文:*'+newString(newBase64().encode(c)));

//客户端解密用客户端私钥解密、用服务器端公钥验签

16

Stringd=CaApi.decrypt7check(newString(serverCer),clientPfx,

clientPsw,c,false);

System.out.printin("明文:"+d);

}

catch(Exceptione)

(

e.printStackTrace();

}

}

}

3.3C++开发

3.3.1DLL库说明

SOFCdll是负责CA加解密的动态库,需要集成到业务系统的程序里,集成方式可自行选择。

共提供windows下32位和64位两个版本。

3.3.2方法说明

加密并签名方法

方法名:aisino_PKCS7_signedAndEnvelopedMulti

调用参数:

序号参数名参数描述类型长度必须说明

1.pRMTrusts信仟链文件内容Char*是

2.pEncB64Cert加密证书内容Char*是PEM格式

3.pSigPfx签名证书内容Char*是pfx格式

4.iSigPfxLen签名证书长度Int是

签名证书的保护

5.pPasswdChar*是

密钥

6.plnData原文数据Char*是

7.ilnDataLen原文数据长度Int是

返叵值:

序号参数名参数描述类型长度必须说明

1.pOutData密文Char*是

2.plOutDataLen密文长度Int*是

17

解密并验签方法

方法名:aisino_PKCS7_unpackMulti

调用参数:

序号参数名参数描述类型长度必须说明

1.pB64Trusts信任链文件内容Char*是

2.pDccPfx解密证书内容Char*是pfx格式

3.iDecPfxLen解密证书长度Int是

解密证书的保护

4.pPasswdChar*是

密钥

5.plnData密文数据Char*是

6.ilnDataLen密文数据长度Int是

返叵值:

注意:同一时刻pSigCert>pOutData>pSubject、pSerial只能有一个为NULL,来获取对应项的长度

序号参数名参数描述类型长度必须说明

PEM格式,此参数如果

传入NULL,则

1.pSigCert签名证书内容Char*是

plSigCertLen输出为需要

分配的签名证书长度

2.plSigCertLen签名证书长度Int*

此参数如果传入NULL,

3.pOutData解密后的明文Char*则plOutDataLen输出为

需要分配的明文长度

解密后的明文长

4.plOutDataLenInt*

此参数如果传入NULL,

则plSubjectLen输出为

5.pSubject签名证书主题Char*

需要分配的签名证书.主

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论