什么是数电票、全电发票? 

      全面数字化的电子发票(简称全电发票、数电票)是与纸质发票具有同等法律效力的全新发票,不以纸质形式存在、不用介质支撑、无须申请领用、发票验旧及申请增版增量。纸质发票的票面信息全面数字化,多个票种集成归并为电子发票单一票种,全国统一赋码、开具金额总额度管理、自动流转交付。以下简称为全电发票。

  1. 所有接口通用的求格式

HTTP请求URL

https://fpkj.market.alicloudapi.com/kpgl/fpkj

请求方式

POST

接口请求头部信息ContentType

application/x-www-form-urlencoded;charset=UTF-8

HTTP请求参数格式

DATA

HTTP返回参数格式

JSON

2、全电发票开具接口 

接口地址:

https://fpkj.market.alicloudapi.com/kpgl/fpkj

参数

token=&data=[发票报文json的base64]&spid=

明:(注意:data有[])下面

字段

描述

data

发票报文json的base64,同时需要对base64用[]括号起来

spid

税盘id

发票报文JSON如下(注意:报文节点全大写):

[{
    "XTLSH": "单据号",
    "KHMC": "客户名称",
    "KHSH": "税号",
    "KHDZ": "地址",
    "KHKHYHZH": "客户银行账号",
    "FPZL": "发票种类",
    "BZ": "备注",
    "KPR": "开票人",
    "SKR": "收款人",
    "FHR": "复核人",
    "QYKHYHZH": "企业开户银行账号",
    "QYDZDH": "企业地址电话",
    "YFPHM": "红冲原发票号",
    "XXBBH": "信息表编号",
    "QDBZ": "清单标志",
    "KHYJ": "客户邮件",
    "KHSJ": "客户手机号",
"JDC": "机动车标识",
"DBTS": "代办退税标识",
    "ITEM": [{
        "CPMC": "产品名称1",
        "CPXH": "产品型号",
        "CPDW": "产品单位",
        "SL": "税率",
        "CPSL": "数量",
        "BHSJE": "不含税金额",
        "SE": "税额",
        "FLBM": "分类编码",
        "XSYH": "税率优惠",
        "LSLBZ": "零税率标识",
"YHSM": "优惠说明",
        "KCJE":"0"
    }, {
        "CPMC": "产品名称2",
        "CPXH": "产品型号",
        "CPDW": "产品单位",
        "SL": "税率",
        "CPSL": "数量",
        "BHSJE": "不含税金额",
        "SE": "税额",
        "FLBM": "分类编码",
        "XSYH": "税率优惠",
"LSLBZ": "零税率标识",
"YHSM": "优惠说明",
        "KCJE":"0"
    }]
}]

字段

是否必需(否的节点,可以不带此节点)

描述

说明

XTLSH

单据号(相当于订单号)

唯一字段

KHMC

客户名称

KHSH

客户税号

KHDZ

客户地址

KHKHYHZH

开户银行账号

FPZL

发票种类

 020 全电专票 021 全电普票

BZ

备注

KPR

开票人

SKR

收款人

FHR

复核人

QYKHYHZH

销方银行账号

QYDZDH

销方地址电话

YFPHM

条件是

原发票号(原发票代码+原发票号码)

红字发票必传,普票和电票必有,注意:含(代码)总共18位或20位。

XXBBH

条件是

信息表编号

红字专票必传,普票电票不需要传。

QDBZ

清单标志

默认为0

KHYJ

客户邮件

自动发邮件

KHSJ

客户手机

JDC

机动车标识

1为开具机动车专票

DBTS

代办退税标识

1为开具代办退税发票

ITEM信息

CPMC

产品名称

如果是折扣行,必需与正数行一致的名称

CPXH

产品型号

如果是折扣行,此值为空

CPDW

产品单位

如果是折扣行,此值为空

SL

税率

CPSL

产品数量

红冲时为负,红冲时,不能有正数金额。

BHSJE

不含税金额

红冲时为负

SE

税额

红冲时为负

FLBM

分类编码

必需到未级编码

XSYH

税收优惠

有优惠1 无优惠0

LSLBZ

零税率标识

SL=0时需要设置

1、免税(同时XSYH需设置成1),2、不征税(同时XSYH需设置成1),3、其它或0税率

Sl<>0时,值为空

YHSM

优惠政策说明

KCJE

扣除金额

差额开票时有用

{

"Reulst": "1",

"Message": "",

"SucessList": [{

"xtlsh": "001",

"fpzl": "",

"fpdm": "1233456789012",

"fphm": "12345678",

"kprq": "2023-01-12T11:20:33",

"skm": "税控码",

"jym": "校验码",

"ewm": "二维码",

"url": "",

"kpjg": "",

"kpfk": ""

}],

"ErrList": [{

"XTLSH": "",

"ErrMsg": ""

}]

}

注意:

Result=0时,说明数据肯定是有异常或流程有异常,此时需要关注下Message这个值。

Result=1时,不代表一定是开票成功,当离线开票或税盘不在线时可能代表接收成功,如果是批量开票时,还需要关注下ErrList这个值,此时有可能是部份成功,部份不成功。

唯一能确定开票成功开票的情况: SucessList列表并且发票号不是为空的情况,如果Result=1并且SucessList列表中返回的发票号码是空的,需要用异步获取开票结果进行获取开票状态。

--------------以上是全电接口--------------分割线--------------以下是乐企开票接口--------------


3.1 乐企录入发票信息接口的字段说明与校验规则
    依据发票开具的要求,录入发票信息,并依据发票开具规则对发票信息进行业务逻辑校验,主要包括合规性校验、数值校验。 
    合规性校验主要对输入参数的类型、长度、是否必填、码值进行校验。以下任意一项不满足要
求时,阻断发票开具。校验规则如下:
● 发票号码,必填,长度20位,由数字组成,前2位为年份后2位。
● 蓝字发票标志,必填,取值范围为“0”、“1”.
● 平台编号,必填,最大长度20位。
● 服务器地址,必填,长度20位。
● mac地址,必填,长度20位。
● CPU序列号,选填,长度20位。
● 主板序列号,选填,长度20位。
● 发票票种,必填,取值范围为“01”、“02”。
● 购买方自然人标志,选填,取值范围为“Y”、“N”。
● 特定要素,选填,必须为空。
● 区域代码,必填,最大长度20位。
● 收购发票类型代码,选填,必须为空。
● 差额征税类型代码,选填,取值范围为“空”、“01”、“02”。
● 出口业务适用政策代码,选填,取值范围为“空”、“01”、“02”、“03”。
● 增值税即征即退代码,选填,取值范围为“空”、“01”、“02”、“03”、“04”、
“05”、“06”、“07”、“08”、“09”、“10”、“11”、“12”。
● 销售方纳税人识别号,必填,最大长度20位,由数字和大写字母组成。
● 销售方名称,必填,最大长度300位。
● 销售方地址,选填,最大长度300位。
● 销售方电话,选填,最大长度60位。
● 销售方开户行,选填,最大长度120位。
● 销售方账号,选填,最大长度50位。
● 购买方纳税人识别号,选填,最大长度 20位(开具数电专票时,必填)。
● 购买方名称,必填,最大长度300位。
● 购买方地址,选填,最大长度300位。
● 购买方电话,选填,最大长度60位。
● 购买方开户行名称,选填,最大长度120位。
● 购买方开户行银行账号,选填,最大长度100位。
● 经办人,选填,最大长度150位。
● 经办人身份证件号码,选填,最大长度 30位。
● 经办人联系电话,选填,最大长度60位。
● 合计金额,必填,最大长度18位,最多2位小数。
● 合计税额,必填,最大长度18位,最多2位小数。
● 价税合计,必填,最大长度18位,最多2位小数。
● 收款银行名称,选填,最大长度120位。
● 收款银行账号,选填,最大长度100位。
● 结算方式,选填,取值范围为“01”、“02”、“03”、“04”、“05”、“99”。
● 应税行为发生地,选填,最大长度11位。
● 开票人,必填,最大长度300位,必须与申请接入时配置的开票员一致。
● 开票人证件号码,必填,最大长度30位,必须是开票人证件类型对应的证件号码,并且与平台
维护的信息一致。
● 开票人证件类型,必填,最大长度4位,取值范围为“100”,“ 101”,“ 102”,“
103”,“ 199”,“ 200”,“ 201”,“ 202”,“ 203”,“ 204”,“ 205”,“ 206”,“
207”,“ 208”,“ 209”,“ 210”,“ 211”,“ 212”,“ 213”,“ 214”,“ 215”,“
216”,“ 217”,“ 218”,“ 219”,“ 220”,“ 221”,“ 222”,“ 223”,“ 224”,“
225”,“ 220”,“ 227”,“ 228”,“ 229”,“ 230”,“ 231”,“ 232”,“ 233”,“
234”,“ 235”,“ 236”,“ 237”,“ 238”,“ 239”,“ 240”,“ 241”,“ 291”,“
299”。
● 对应蓝字发票号码,选填,长度20位。
● 红字确认信息单编号,选填,最大长度20位。
● 红字确认单uuid,选填,最大长度32位。
● 备注,选填,最大长度450位。
● 开票日期,必填,格式必须是“yyyy-MM-dd HH:mm:ss”。
● 是否展示销售方银行账号标签,选填,最大长度1位。
● 是否展示购买方银行账号标签,选填,最大长度1位。
● 收款人姓名,选填,最大长度150位。
● 复核人姓名,选填,最大程度75位。
● 明细序号,必填,最大长度8位。
● 对应蓝字发票明细序号,选填,最大长度8位。
● 货物或应税劳务、服务名称,必填,最大长度300位。
● 商品服务简称,必填,最大长度120位。
● 项目名称,必填,最大长度600位。
● 规格型号,选填,最大长度150位。
● 单位,选填,最大长度300位。
● 数量,选填(如“单价”非空,则必填),最大长度25位。
● 单价,选填(如“数量”非空,则必填),最大长度25位。
● 金额,必填,最大长度18位,最多2位小数。
● 增值税税率/征收率,必填,最大长度16位,最多6位小数。必须在可用税率信息中存在。
● 税额,必填,最大长度18位,最多2位小数。
● 含税金额,必填,最大长度18位,最多2位小数。
● 扣除额,选填,最大长度18位,最多2位小数。
● 商品和服务税收分类合并编码,必填,最大长度19位。必须在商品编码信息中存在。
● 发票行性质,必填,取值范围为“00”、“01”、“02”。
● 优惠政策标识,选填,不为空时取值范围为“01”、“02”、“03”、“04”、“05”、
“06”、“07”、“08”、“09”、“10”、“11”、“12”、“13”、“14”、“15”、“16”、
“17”、“18”。
● 附加要素名称,选填,最大长度200位。
● 附加要素类型,选填,最大长度200位。
● 附加要素值,选填,最大长度200位

 
3.2 数电票上传接口说明
   给企业提供上传开具的数电预发票功能,上传成功后给企业返回信息。
税务局端接收到企业上传的数电票后,依次校验企业是具备开票条件、发票信息是否合规、是
否超过发票额度、数电票号码是否合法、发票是否属于直连单位,当校验不通过时,不接收企业上
传的数电票,返回具体错误信息。每次上传最大票量为100张数电票。

请求参数说明:

序号 数据项标识 数据项名称 字段类型 长度 必须 说明
1 fphm 发票号码 varchar 20
2 lzfpbz 蓝字发票标志 varchar 1 0:蓝字发票
1:红字发票
3 ptbh 平台编号 varchar 20 直连单位ID
4 fppz 发票票种 varchar 2 01:数电专
02:数电普
5 gmfzrrbz 购买方自然人标志 varchar 1 Y:购买方是自
然人
N:购买方非自
然人
6 tdys 特定要素 varchar 2 空:非特定要素
01:成品油发票
02:稀土发票
0 3 : 建 筑 服 务 发

0 4 : 货 物 运 输 服
务发票
5 gmfzrrbz 购买方自然人标志 varchar 1 否
Y:购买方是自
然人
N:购买方非自
然人
6 tdys 特定要素 varchar 2 否
空:非特定要素
01:成品油发票
02:稀土发票
0 3 : 建 筑 服 务 发

0 4 : 货 物 运 输 服
务发票
7 qyDm 区域代码 varchar 20
8 cezslxDm 差额征税类型代码 varchar 2 空:非差额发票
01:全额开票
02:差额开票
9 sgfplxDm 收购发票类型代码 varchar 2 空:非收购发票
01:农产品收购
发票
02:光伏收购发

0 3 : 二 手 车 收 购
发票
10 ckywsyzcDm 出口业务适用政策代 码 varchar 2 空:非出口业务
01:退税政策
02:免税政策
03:征税政策
11 zzsjzjtDm 增值税即征即退代码 varchar 2 空:非增
01:软件产品发票
02:资源综合利用产品发票
03:管道运输服务发票
04:有形动产融资租赁服务
05:有形动产融资性售后回租服务发票
06:新型墙体材料发票
07:风力发电产品发票
08:光伏发电产品发票
09:动漫软件产品发票
10:飞机维修劳务发票
11:黄金发票
12:铂金发票
12 xsfnsrsbh (销售方)统一社
会信用代码/纳税人
识别号/身份证件号
varchar 20
13 xsfmc (销售方)名称 varchar 300
14 xsfdz 销售方地址 varchar 300
15 xsfdh 销售方电话 varchar 60
16 xsfkhh 销售方开户行 varchar 120
17 xsfzh 销售方账号 varchar 50
18 gmfnsrsbh (购买方)统一社
会信用代码/纳税人
识别号/身份证件号
varchar 20 开具数电专票时
,必填
19 gmfmc (购买方)名称 varchar 300
20 gmfdz 购买方地址 varchar 300
21 gmfdh 购买方电话 varchar 60
22 gmfkhh 购买方开户行 varchar 120
23 gmfzh 购买方账号 varchar 50
24 gmfjbr 购买方经办人姓名 varchar 150
25 jbrsfzjhm 购买方经办人证件 号码 varchar 30
26 gmfjbrlxdh 购买方经办人联系 电话 varchar 60
27 hjje 合计金额 number 18,2
28 hjse 合计税额 number 18,2
29 jshj 价税合计 number 18,2
30 skyhmc 收款银行名称 varchar 120
31 skyhzh 收款银行账号 varchar 100
32 jsfs 结算方式 varchar 2 01:现金
02:银行转账
03:票据
04:第三方支付
05:预付卡
99:其他
33 ysxwfsd 应税行为发生地 varchar 11
34 kpr 开票人 varchar 300
35 kprzjhm 开票人证件号码 varchar 30
32 jsfs 结算方式 varchar 2 01:现金
02:银行转账
03:票据
04:第三方支付
05:预付卡
99:其他
33 ysxwfsd 应税行为发生地 varchar 11
34 kpr 开票人 varchar 300
35 kprzjhm 开票人证件号码 varchar 30
36 kprzjlx 开票人证件类型 varchar 4 201:居民身份证
202:军官证
203:武警警官证
204:士兵证205:军队离退休干部证
206:残疾人证
207:残疾军人证(1-8级)
208:外国护照
209:港澳同胞回乡证
210:港澳居民来往内地通行证
211:台胞证
212:中华人民共和国往来港澳通行证
213:台湾居民来往大陆通行证
214:大陆居民往来台湾通行证
215:外国人居留证
216:外交官证
217:使(领事)馆证
218:海员证
219:香港永久性居民身份证
220:台湾身份证
221:澳门特别行政区永久性居民身份证
222:外国人身份证件
223:高校毕业生自主创业证
224:就业失业登记证
225:退休证
220:离休证
227:中国护照
37 dylzfphm 对应蓝字发票号码 varchar 20 是否蓝字发票标
志为1时,此节点
有内容
红 票 开 具 时 必 传

如 果 红 冲 的 是 税
控 发 票 , 对 应 蓝
字 发 票 号 码 的 填
写 规 则 为 税 控 发
票的发票代码+发
票号码。
38 hzqrxxdbh 红字确认信息单编 号 varchar 20 是否蓝字发票标
志为1时,此节点
有内容
红票开具时必传
39 hzqrduuid 红字确认单uuid varchar 32 是否蓝字发票标
志为1时,此节点
有内容红票开具
时必传
40 bz 备注 varchar 450
41 ip 服务器地址 varchar 20 需 自 行 采 集 开 票 申请设备
42 macdz mac地址 char 20 需 自 行 采 集 开 票
申请设备
43 cpuid CPU序列号 char 20
44 zbxlh 主板序列号 varchar 20
45 kprq 开票日期 datetime 格式:
y y y y - M M - d d
HH:mm:ss
46 sfzsxsfyhzhbq 是否展示销售方银 行账号标签 varchar 1 Y:展示 N:不展示
47 sfzsgmfyhzhbq 是否展示购买方银 行账号标签 varchar 1 Y:展示 N:不展示
48 skrxm 收款人姓名 varchar 150
49 fhrxm 复核人姓名 varchar 75
50 mxxh 明细序号 Number 8
51 dylzfpmxxh 对应蓝字发票明细 序号 Number 8 红票必传
52 xmmc 项目名称 varchar 600
53 hwhyslwfwmc 货物或应税劳务、服 务名称 varchar 300 拼 装 规 则 : “* 商 品 服 务简 称
(spfwjc)*”+
“ 项 目 名 称
(xmmc)”
54 spfwjc 商品服务简称 varchar 120
55 ggxh 规格型号 varchar 150
56 dw 单位 varchar 300
57 sl 数量 varchar 25 如“单价”栏次
非空,则本栏次
必须非空
58 dj 单价 varchar 25 如“数量”栏次
非空,则本栏次
必须非空
59 je 金额 number 18,2
60 slv 增值税税率/征收率 number 16,6
61 se 税额 number 18,2
62 hsje 含税金额 number 18,2
63 kce 扣除额 number 18,2
64 sphfwssflhbbm 商品和服务税收分类 合并编码 varchar 19
65 fphxz 发票行性质 varchar 2 00:正常行
01:折扣行
02:被折扣行
66 yhzcbs 优惠政策标识 varchar 2 01:简易征收
02:稀土产品
03:免税
04:不征税
05:先征后退
0 6 : 1 0 0 % 先 征
后退
07:50%先征后
退
0 8 : 按 3 % 简 易
征收
0 9 : 按 5 % 简 易
征收
1 0 : 按 5 % 简
67 fjysmc 附加要素名称 String 200
68 fjyslx 附加要素类型 String 200
69 fjysz 附加要素值 String 200


数电票上传接口报文如下:
[
    {
        "fphm": "发票号码",
        "lzfpbz": "蓝字发票标志",
        "ptbh": "平台编号",
        "fppz": "发票票种",
        "gmfzrrbz": "购买方自然人标志",
        "tdys": "特定要素",
        "qyDm": "区域代码",
        "cezslxDm": "差额征税类型代码",
        "sgfplxDm": "收购发票类型代码",
        "ckywsyzcDm": "出口业务适用政策代码",
        "zzsjzjtDm": "增值税即征即退代码",
        "xsfnsrsbh": "(销售方)统一社会信用代码/纳税人识别号/身份证件号码",
        "xsfmc": "(销售方)名称",
        "xsfdz": "销售方地址",
        "xsfdh": "销售方电话",
        "xsfkhh": "销售方开户行",
        "xsfzh": "销售方账号",
        "gmfnsrsbh": "(购买方)统一社会信用代码/纳税人识别号/身份证件号码",
        "gmfmc": "(购买方)名称",
        "gmfdz": "购买方地址",
        "gmfdh": "购买方电话",
        "gmfkhh": "购买方开户行名称",
        "gmfzh": "购买方开户行银行账号",
        "gmfjbr": "经办人",
        "jbrsfzjhm": "经办人身份证件号码",
        "gmfjbrlxdh": "经办人联系电话",
        "hjje": "合计金额",
        "hjse": "合计税额",
        "jshj": "价税合计",
        "skyhmc": "收款银行名称",
        "skyhzh": "收款银行账号",
        "jsfs": "结算方式",
        "ysxwfsd": "应税行为发生地",
        "kpr": "开票人",
        "kprzjhm": "开票人证件号码",
        "kprzjlx": "开票人证件类型",
        "dylzfphm": "对应蓝字发票号码",
        "hzqrxxdbh": "红字确认信息单编号",
        "hzqrduuid": "红字确认单uuid",
        "bz": "备注",
        "ip": "服务器地址",
        "macdz": "mac地址",
        "cpuid": "CPU序列号",
        "zbxlh": "主板序列号",
        "kprq": "开票日期",
        "sfzsxsfyhzhbq": "是否展示销售方银行账号标签",
        "sfzsgmfyhzhbq": "是否展示购买方银行账号标签",
        "skrxm": "收款人姓名",
        "fhrxm": "复核人姓名",
        "fpmxList": [
            {
                "mxxh": "明细序号",
                "dylzfpmxxh": "对应蓝字发票明细序号",
                "hwhyslwfwmc": "货物或应税劳务、服务名称",
                "spfwjc": "商品服务简称",
                "xmmc": "项目名称",
                "ggxh": "规格型号",
                "dw": "单位",
                "sl": "数量",
                "dj": "单价",
                "je": "金额",
                "slv": "增值税税率/征收率",
                "se": "税额",
                "hsje": "含税金额",
                "kce": "扣除额",
                "sphfwssflhbbm": "商品和服务税收分类合并编码",
                "fphxz": "发票行性质",
                "yhzcbs": "优惠政策标识"
            }
        ],
        "fjysList": [
            {
                "fjysmc": "附加要素名称",
                "fjyslx": "附加要素类型",
                "fjysz": "附加要素值"
            }
        ]
    }
]

以下是c#代码示例 ,和报文的SM4加解密算法

using System;
using System.Text;
using System.Text.RegularExpressions;
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;


  static void Main()
        {       
         //https://lq.chinatax.gov.cn:84/access/sandbox/v2/invoke/能力编码/服务编码/  
          string url = "https://lq.chinatax.gov.cn:84/access/sandbox/v2/invoke/" + "202007" + "/QDFPSC";
            string nsrsbh = "91440101MA59LCK170";
            string key = "a95826561dfd68992ec1e6e43fce4737";//乐企秘钥
            string jrdybm = "5d2cff003e37f7ef28d1";//接入单位id
            string sydwbm = "5d2cff003e37f7ef28d1";//使用单位id
            string ylbm = "102301";//用例编码 
			string param=[
	{
		"fphm": "发票号码",
		"lzfpbz": "蓝字发票标志",
		"ptbh": "平台编号",
		"fppz": "发票票种",
		"gmfzrrbz": "购买方自然人标志",
		"tdys": "特定要素",
		"qyDm": "区域代码",
		"cezslxDm": "差额征税类型代码",
		"sgfplxDm": "收购发票类型代码",
		"ckywsyzcDm": "出口业务适用政策代码",
		"zzsjzjtDm": "增值税即征即退代码",
		"xsfnsrsbh": "(销售方)统一社会信用代码/纳税人识别号/身份证件号码",
		"xsfmc": "(销售方)名称",
		"xsfdz": "销售方地址",
		"xsfdh": "销售方电话",
		"xsfkhh": "销售方开户行",
		"xsfzh": "销售方账号",
		"gmfnsrsbh": "(购买方)统一社会信用代码/纳税人识别号/身份证件号码",
		"gmfmc": "(购买方)名称",
		"gmfdz": "购买方地址",
		"gmfdh": "购买方电话",
		"gmfkhh": "购买方开户行名称",
		"gmfzh": "购买方开户行银行账号",
		"gmfjbr": "经办人",
		"jbrsfzjhm": "经办人身份证件号码",
		"gmfjbrlxdh": "经办人联系电话",
		"hjje": "合计金额",
		"hjse": "合计税额",
		"jshj": "价税合计",
		"skyhmc": "收款银行名称",
		"skyhzh": "收款银行账号",
		"jsfs": "结算方式",
		"ysxwfsd": "应税行为发生地",
		"kpr": "开票人",
		"kprzjhm": "开票人证件号码",
		"kprzjlx": "开票人证件类型",
		"dylzfphm": "对应蓝字发票号码",
		"hzqrxxdbh": "红字确认信息单编号",
		"hzqrduuid": "红字确认单uuid",
		"bz": "备注",
		"ip": "服务器地址",
		"macdz": "mac地址",
		"cpuid": "CPU序列号",
		"zbxlh": "主板序列号",
		"kprq": "开票日期",
		"sfzsxsfyhzhbq": "是否展示销售方银行账号标签",
		"sfzsgmfyhzhbq": "是否展示购买方银行账号标签",
		"skrxm": "收款人姓名",
		"fhrxm": "复核人姓名",
		"fpmxList": [
			{
				"mxxh": "明细序号",
				"dylzfpmxxh": "对应蓝字发票明细序号",
				"hwhyslwfwmc": "货物或应税劳务、服务名称",
				"spfwjc": "商品服务简称",
				"xmmc": "项目名称",
				"ggxh": "规格型号",
				"dw": "单位",
				"sl": "数量",
				"dj": "单价",
				"je": "金额",
				"slv": "增值税税率/征收率",
				"se": "税额",
				"hsje": "含税金额",
				"kce": "扣除额",
				"sphfwssflhbbm": "商品和服务税收分类合并编码",
				"fphxz": "发票行性质",
				"yhzcbs": "优惠政策标识"
			}
		],
		"fjysList": [
			{
				"fjysmc": "附加要素名称",
				"fjyslx": "附加要素类型",
				"fjysz": "附加要素值"
			}
		]
	}
]   ;
          string bodySm4 = Sm4Encrypt(param, key);
          string jg = HttpPostByJsonStringLqApi(url, jrdybm, sydwbm,"", ylbm, "application/json;charset=UTF-8", bodySm4);
		  JObject Api_jg = JObject.Parse(jg);
            if ((Api_jg == null) || (Api_jg["httpStatusCode"] == null) || (Api_jg["httpStatusCode"].ToString() != "200"))
            {
                TextBox1.AppendText("失败=" + message + "\r\n");
            }
            if (Api_jg["body"] == null)
            {
                TextBox1.AppendText("失败,body is null=" + message + "\r\n");
            }  
            JObject body_jg = JObject.Parse(Api_jg["body"].ToString());
            if ((body_jg == null) || (body_jg["Response"] == null))
            {
                TextBox1.AppendText("失败,Data is null=" + message + "\r\n");
                return;
            }
            if ((body_jg["Response"]["Data"] == null) && (body_jg["Response"]["Error"] != null))
            {
                TextBox1.AppendText("失败:" + body_jg["Response"]["Error"].ToString() + "\r\n");
                return;

            } 
            string Datasm4 = body_jg["Response"]["Data"].ToString(); 
            bodySm4 = Sm4Decrypt(Datasm4, key);
            TextBox1.AppendText("响应乐企解密报文=" + bodySm4 + "\r\n");
        } 
       /// <summary>
        /// SM4加密 采用SM4/ECB/PKCS5Padding
        /// </summary>
        /// <param name="plaintext">字符串内容</param>
        /// <param name="sm4Key">sm4秘钥</param>
        /// <returns></returns>
        public static string Sm4Encrypt(string plaintext, string sm4Key)
        {
            byte[] sourceData = Encoding.UTF8.GetBytes(plaintext);
            byte[] keyBytes = Hex.Decode(sm4Key);// Encoding.UTF8.GetBytes(sm4Key);
            return Sm4Encrypt(sourceData, keyBytes);
        }

        /// <summary>
        /// SM4加密 采用SM4/ECB/PKCS5Padding
        /// </summary>
        /// <param name="sourceData">源数据</param>  
        /// <param name="keyBytes">sm4秘钥</param>
        /// <returns>Base64字符串</returns>
        public static string Sm4Encrypt(byte[] sourceData, byte[] keyBytes)
        {
            KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
            IBufferedCipher inCipher = CipherUtilities.GetCipher("SM4/ECB/PKCS5Padding");
            inCipher.Init(true, key);
            byte[] cipher = inCipher.DoFinal(sourceData);
            string str = Convert.ToBase64String(cipher);
            return str;
        }

   


      public string HttpPostLqApi(string Url, string JsonStrSm4, string jrdwptbh, string sydwptbh, string ylbm)
        {

            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;// 解决,未能创建 SSL/TLS 安全通道
            ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidate;//验证服务器证书回调自动验证
            HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(Url);
            byte[] bytes = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(JsonStrSm4);
            webrequest.ContentType = "application/json;charset=UTF-8";
            webrequest.Headers.Add("jrdwptbh", jrdwptbh);
            webrequest.Headers.Add("sydwptbh", sydwptbh);
            webrequest.Accept = "application/json";
            webrequest.Headers.Add("sxcsbz", "1");//沙箱测试标志 ,仅适用于能力开通后 或能力审核中时进行 沙箱调用,能力未提交 审核前不要加上此参 数
            //if (ylbm != "") webrequest.Headers.Add("ylbm", ylbm);
            webrequest.Headers.Add("ylbm", ylbm);
            webrequest.Referer = Url;
            webrequest.Method = "POST";
            webrequest.ContentLength = bytes.Length;
            webrequest.Timeout = 60 * 1000;
            using (Stream requestStream = webrequest.GetRequestStream())
            {
                requestStream.Write(bytes, 0, bytes.Length);
                requestStream.Close();
            }
            HttpWebResponse webreponse = null;
            try
            {
                webreponse = (HttpWebResponse)webrequest.GetResponse();
            }
            catch (WebException ex)
            {
                webreponse = (HttpWebResponse)ex.Response;
            };
            Stream responseStream = webreponse.GetResponseStream();
            string resp = string.Empty;
            using (StreamReader reader = new StreamReader(responseStream))
            {
                resp = reader.ReadToEnd();
            }
            return resp;
        }

以下Java的调用示例,和报文的SM4加解密算法


import static channel.Channel.*;

public class JDKPMain {

    static String key = "乐企";//乐企秘钥
    static String jrdybm = "";//接入单位id
    static String sydwbm = "";//使用单位id
    static String ylbm ="" ;//用例编码


    static String nsrsbh = "";//纳税人识别号

    public static void main(String[] args) {
        CXNSRJBXX();
    }


    /**
     * 查询纳税人基本信息
     */
    private static void CXNSRJBXX() {
        String url = "https://lq.chinatax.gov.cn:84/access/v2/invoke/202007/CXNSRJBXX";
        String param = "{\"nsrsbh\":\""+nsrsbh+"\"}";
        request(url, param, key, jrdybm, sydwbm, ylbm);
    }


}



package channel;

import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Map;

public class Channel {

    public static String request(String url, String param, String key, String jrdybm, String sydwbm) {
        return request(url,param,key,jrdybm,sydwbm,null);
    }


    public static String request(String url, String param, String key, String jrdybm, String sydwbm, String ylbm) {
        param = param.replace("\n","");
        param = param.replace("{  ","{");
        param = param.replace(",  ",",");
        param = param.replace(",  ",",");
        param = param.replace("[  ","[");
        param = param.replace("{  ","{");
//        System.out.println("\n请求乐企服务地址:" + url);
        System.out.println("\n");
        System.out.println("请求乐企原始报文:" + param);
        String encParam = SM4Util.encryptEcb(key, param);
        System.out.println("请求乐企加密报文:" + encParam);
        String result = postLeqi(url, encParam, jrdybm, sydwbm, ylbm);
        System.out.println("响应乐企原始报文:" + result);
        Map<String, Object> resultDTO = JSON.parseObject(result, Map.class);
        Map<String, Object> body = JSON.parseObject((String) resultDTO.get("body"), Map.class);
        Map<String, Object> response = (Map<String, Object>) body.get("Response");
        String data = (String) response.get("Data");
        String resultMsg = SM4Util.decryptEcb(key, data);
        System.out.println("响应乐企解密报文:" + resultMsg);
        return resultMsg;
    }

    public static String postLeqi(String url, String reqDTO, String jrdybm,
                                  String sydwbm, String ylbm) {

        try {
            SSLContext ctx = null;
            try {
                ctx = SSLContext.getInstance("SSL");
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }
            X509TrustManager tm = new X509TrustManager() {

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] arg0,
                                               String arg1) {
                }
            };
            ctx.init(null, new TrustManager[]{tm}, null);
            SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
            HttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(ssf).disableCookieManagement().build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("jrdwptbh", jrdybm);
            httpPost.addHeader("sydwptbh", sydwbm);
            if (ylbm != null) {
                httpPost.addHeader("ylbm", ylbm);
            }
            StringEntity stringEntity = new StringEntity(reqDTO, StandardCharsets.UTF_8);
            httpPost.setEntity(stringEntity);
            CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            return EntityUtils.toString(responseEntity);
        } catch (KeyManagementException | IOException e) {
            throw new RuntimeException(e);
        }
    }
}



package channel;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

public class SM4Util {

    private SM4Util() {
    }

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    private static final Charset ENCODING = StandardCharsets.UTF_8;
    public static final String ALGORITHM_NAME = "SM4";
    // 加密算法/分组加密模式/分组填充方式
    // PKCS5Padding-以8个字节为一组进行分组加密
    // 定义分组加密模式使用:PKCS5Padding
    public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
    // 128-32位16进制;256-64位16进制
    public static final int DEFAULT_KEY_SIZE = 128;

    /**
     * 自动生成密钥(16进制字符串,长度32)
     */
    public static String generateKey() {
        return Hex.toHexString(generateKey(DEFAULT_KEY_SIZE));
    }

    /**
     * @param keySize 密钥长度
     */
    public static byte[] generateKey(int keySize) {
        try {
            KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
            kg.init(keySize, new SecureRandom());
            return kg.generateKey().getEncoded();
        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成ECB暗号
     *
     * @param algorithmName 算法名称
     * @param mode          模式
     * @param key           密码
     */
    private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) {
        try {
            Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
            Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
            cipher.init(mode, sm4Key);
            return cipher;
        } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | NoSuchProviderException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * sm4加密 ,加密模式:ECB
     *
     * @param hexKey   16进制密钥(忽略大小写)
     * @param paramStr 待加密字符串
     * @return 返回Base64后加密字符串
     */
    public static String encryptEcb(String hexKey, String paramStr) {
        try {
            // 16进制字符串-->byte[]
            @SuppressWarnings("deprecation")
            byte[] keyData = ByteUtils.fromHexString(hexKey);
            // String-->byte[]
            byte[] srcData = paramStr.getBytes(ENCODING);
            // 加密后的数组
            byte[] cipherArray = encryptEcbPadding(keyData, srcData);
            // byte[]-->hexString
            return Base64.getEncoder().encodeToString(cipherArray);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 加密模式为ECB
     *
     * @param key  2进制密钥
     * @param data 2进制原文
     * @return 二进制密文
     */
    public static byte[] encryptEcbPadding(byte[] key, byte[] data) {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
        try {
            return cipher.doFinal(data);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * sm4解密 ,解密模式:采用ECB
     *
     * @param hexKey     16进制密钥
     * @param cipherText 16进制的加密字符串(忽略大小写)
     * @return 解密后的字符串
     */
    public static String decryptEcb(String hexKey, String cipherText) {
        try {
            // hexString-->byte[]
            @SuppressWarnings("deprecation")
            byte[] keyData = ByteUtils.fromHexString(hexKey);
            // hexString-->byte[]
            byte[] cipherData = Base64.getDecoder().decode(cipherText);
            // 解密
            byte[] srcData = decryptEcbPadding(keyData, cipherData);
            // 接收解密后的字符串 byte[]-->String
            return new String(srcData, ENCODING);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * sm4解密
     *
     * @param key        2进制密钥
     * @param cipherText 2进制密文
     * @return 解密后的2进制原文
     */
    public static byte[] decryptEcbPadding(byte[] key, byte[] cipherText) {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
        try {
            return cipher.doFinal(cipherText);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new RuntimeException(e);
        }
    }


}

// 

 使用乐企接口需要邀请,申请,审核等审批的流程。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐