第三章 模块接口(3) - 开票接口
## 综合服务云平台 - API功能模块接口明细
## 版本更新记录
|修订日期|修订内容|修订人|
|-|-|-|
|2020.09.30|新增 6.1 个体户开票申请、6.2 个体户开票申请确认、6.3 服务费开票申请6.4 服务费开票确认 6.5 证据链上传 6.6 开票结果查询 |彭晓伟|
## 接口时序图

## 6. 开票接口
## 6.1 个体户开票申请
>d 该接口用于个体户开票申请,获取开票的订单号开票金额等信息
开发环境:https://pay-dev.lx-rhino.com
生产环境:https://api.lx-rhino.com
#### 注意
>d 1.在调用开票申请接口前,需要调用 [3.6 个体户状态查询接口](https://easydoc.top/doc/63011222/0klm3Gmk/Cw8Sc3og)查询
返回的taxStatus - 税务状态的状态变更为“已实名”,只有变更后,才能提交该个体户的开票申请;仅限新注册的个体户。
>2. 如果是老的个体户只需调用一次,保存在本地,后续可以不需要再去查询该个体户的税务状态信息。
#### 接口地址:
/open/api/v1/qs/invoice/selfInvoicesApply
#### 请求参数说明:
|参数名称|参数含义|数据类型|是否必填|参数备注|
|-|-|-|-|-|
|idCard|个体户身份证号|String| 是|示例:4104221993XXXX1278|
|invoiceClassification| 开票类型|int| 是|0.普票 1.专票|
|mainstayId|主体id|int| 否|示例:1|
|remark| 备注|String| 否|示例:"XX"|
>d 请求参数示例:
```java
{"idCard":"4104221993XXXX1278","invoiceClassification":1,"phone":"1862687xxxx","remark":"开票"}
```
#### 接口响应参数data字段解密后的参数说明:
>d 注意:该接口响应参数是list集合数据
|参数名称| 参数含义|数据类型| 是否必有| 参数备注|
|-|-|-|-|-|
|invoiceAmount|开票金额|BigDecimal| 是|示例:11.05|
|totalIncomeTaxAmount|个体户已缴纳个税|BigDecimal| 是|示例:1.05|
|totalTaxableAmount|应纳税金额|BigDecimal| 是|示例:11.05|
|totalInvoiceAmount|发放前开票金额|BigDecimal| 是|示例:2.05|
|invoiceStatus|开票状态|Integer| 是|参看[系统编码 - 开票状态码](https://easydoc.top/doc/63011222/0klm3Gmk/lsNgE5QQ)|
|name|个体户姓名|String| 是|示例:"王某某"|
|idCard|个体户身份证号|String| 是|示例:"4104221993XXXX1278"|
|mainstayId|主体id|Integer| 是|示例:1|
|invoiceContent|发票内容|String| 是|示例:"信息技术服务*技术服务费"|
|purchaserInvoiceTitle|购买方发票抬头|String| 是|示例:"xx"|
|purchaserTaxNumber|购买方税号|String| 是|示例:"91990512MA2B6AME1N"|
|purchaserAddressPhone|购买方地址、电话|String| 是|示例:"xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001"|
|purchaserBankAccount|购买方开户行及账号|String| 是|示例:"xx银行xx分行xx部 15000xx8626431"|
|sellerInvoiceTitle|销售方发票抬头|String| 是|示例:"xx"|
|sellerTaxNumber|销售方税号|String| 是|示例:"4104221993XXXX1278"|
|sellerAddressPhone|销售方地址、电话|String| 是|示例:"xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001"|
|sellerBankAccount|销售方开户行及账号|String| 是|示例:"xx银行xx分行xx部 15000xx8626431"|
|allTotalInvoiceAmount|开票金额(汇总)|BigDecimal| 是|此参数与list为同级|
|allShouldInvoiceAmount|应开票金额(汇总)|BigDecimal| 是|此参数与list为同级|
|nonInvoicedAmount|不可开票金额|BigDecimal| 是|此参数与list为同级|
|provisionalInvoiceNo|确认号|String| 是|该参数用于下个确认接口,此参数与list为同级|
>d 响应参数示例:
```json
{
"list": [{
"idCard": "1426271995xxx30615",
"invoiceAmount": 34500.00,
"invoiceContent": "物流辅助服务**运输装卸费",
"invoiceStatus": -2,
"mainstayId": 2,
"name": "赵xx",
"purchaserAddressPhone": "xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001",
"purchaserBankAccount": "xx银行xx分行xx部 15000xx8626431",
"purchaserInvoiceTitle": "xxx",
"purchaserTaxNumber": "4104221993XXXX1278",
"sellerAddressPhone": "xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001",
"sellerBankAccount": "62218816000067xxx39",
"sellerInvoiceTitle": "赵xx",
"sellerTaxNumber": "4104221993XXXX1458",
"totalIncomeTaxAmount": 10.00,
"totalInvoiceAmount": 21.00,
"totalTaxableAmount": 12.05
}],
"allTotalInvoiceAmount": 15000,
"allShouldInvoiceAmount": 9999,
"nonInvoicedAmount": 1000,
"provisionalInvoiceNo": "xxxxxx"
}
```
## 6.2 个体户开票申请确认
>d 该接口用于个体户开票申请后查看信息无误后确认开票
开发环境:https://pay-dev.lx-rhino.com
生产环境:https://api.lx-rhino.com
#### 接口地址:
/open/api/v1/qs/invoice/selfInvoicesApplyConfirm
#### 请求参数说明:
|参数名称|参数含义|数据类型|是否必填|参数备注|
|-|-|-|-|-|
|provisionalInvoiceNo|确认号,上个接口获取|String| 是|示例:"20211515151515151"|
|settlementCertUrl|结算单证明链接|String| 否||
|settlementCertCustomUrl|自定义模板链接|String| 否||
>d注意:
>settlementCertUrl(结算证明):是根据商户后台配置判断的
>直营模式:
>(1)结算前配置:结算时必填,开票申请时就非必填
>(2)开票前配置:开票申请时必填,结算时非必填
>d 请求参数示例:
```java
{"provisionalInvoiceNo":"2020092115145251556097","settlementCertUrl":"xxxx","settlementCertCustomUrl":"xxxx"}
```
#### 接口响应参数data字段解密后的参数说明:
>d 注意:该接口响应参数是list集合数据
|参数名称| 参数含义|数据类型| 是否必有| 参数备注|
|-|-|-|-|-|
|invoiceBillNo|成功开票订单编号|String| 是||
|invoiceStatus|发票状态|Integer| 是|参看[系统编码 - 开票状态码](https://easydoc.top/doc/63011222/0klm3Gmk/lsNgE5QQ),如果是待审核中状态说明已成功提交|
>d 响应参数示例:
```json
{
"invoiceBillNo": "xxxx",
"invoiceStatus": "0"
}
```
## 6.3 服务费开票申请
>d 该接口用于商户服务费开票申请,获取开票的订单号开票金额等信息
开发环境:https://pay-dev.lx-rhino.com
生产环境:https://api.lx-rhino.com
#### 接口地址:
/open/api/v1/qs/invoice/serviceInvoicesApply
#### 请求参数说明:
|参数名称|参数含义|数据类型|是否必填|参数备注|
|-|-|-|-|-|
|mainstayId|主体id|int| 否|该参数在商户合作模式为众包模式的时候为必填选项|
|invoiceCode|发票code|String| 否|该参数在商户合作模式为众包模式的时候为必填选项|
|invoiceClassification| 开票类型|int| 是|0.普票 1.专票|
|remark| 备注|String| 否|示例:"XX"|
>d 请求参数示例:
```java
{"mainstayId":1,"invoiceCode":"发票code"}
```
#### 接口响应参数data字段解密后的参数说明:
|参数名称| 参数含义|数据类型| 是否必有| 参数备注|
|-|-|-|-|-|
|provisionalInvoiceNo|确认单号|String| 是|示例:"2020091720135423517696",下个确认接口需要用到|
|invoiceAmount|开票金额|BigDecimal| 是|示例:11.05|
|mainstayId|主体id|Integer| 是|示例:1|
|invoiceContent|发票内容|String| 是|示例:"信息技术服务*技术服务费"|
|purchaserInvoiceTitle|购买方发票抬头|String| 是|示例:"xx"|
|purchaserTaxNumber|购买方税号|String| 是|示例:"91990512MA2B6AME1N"|
|purchaserAddressPhone|购买方地址、电话|String| 是|示例:"xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001"|
|purchaserBankAccount|购买方开户行及账号|String| 是|示例:"xx银行xx分行xx部 15000xx8626431"|
|sellerInvoiceTitle|销售方发票抬头|String| 是|示例:"xx"|
|sellerTaxNumber|销售方税号|String| 是|示例:"4104221993XXXX1278"|
|sellerAddressPhone|销售方地址、电话|String| 是|示例:"xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001"|
|sellerBankAccount|销售方开户行及账号|String| 是|示例:"xx银行xx分行xx部 15000xx8626431"|
>d 响应参数示例:
```json
{
"provisionalInvoiceNo":"xxxxxx",
"invoiceAmount": 2071.20,
"invoiceBillNo": "2020092115330013906176",
"invoiceContent": "信息技术服务*技术服务费",
"mainstayId": 2,
"purchaserAddressPhone": "xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001",
"purchaserBankAccount": "xx银行xx分行xx部 15000xx8626431",
"purchaserInvoiceTitle": "xxx",
"purchaserTaxNumber": "4104221993XXXX1278",
"sellerAddressPhone": "xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001",
"sellerBankAccount": "62218816000067xxx39",
"sellerInvoiceTitle": "赵xx",
"sellerTaxNumber": "4104221993XXXX1458"
}
```
## 6.4 服务费开票申请确认
>d 该接口用于商户服务费开票申请后查看信息无误后确认开票
开发环境:https://pay-dev.lx-rhino.com
生产环境:https://api.lx-rhino.com
#### 接口地址:
/open/api/v1/qs/invoice/serviceInvoicesApplyConfirm
#### 请求参数说明:
|参数名称|参数含义|数据类型|是否必填|参数备注|
|-|-|-|-|-|
|provisionalInvoiceNo|确认单号|String| 是|示例:"2020092115145251556096"|
|settlementCertUrl|结算单证明链接|String| 否||
|settlementCertCustomUrl|自定义模板链接|String| 否||
>d注意:
>settlementCertUrl(结算证明):是根据商户后台配置判断的
>直营模式:
>(1)结算前配置:结算时必填,开票申请时就非必填
>(2)开票前配置:开票申请时必填,结算时非必填
>众包模式:默认是不需要上传结算证明的
>d 请求参数示例:
```json
{"provisionalInvoiceNo":"2020092115145251556097","settlementCertUrl":"xxxx","settlementCertCustomUrl":"xxxx"}
```
#### 接口响应参数data字段解密后的参数说明:
|参数名称| 参数含义|数据类型| 是否必有| 参数备注|
|-|-|-|-|-|
|invoiceBillNo|发票单号|String| 是||
|invoiceStatus|发票状态|Integer| 是|参看[系统编码 - 开票状态码](https://easydoc.top/doc/63011222/0klm3Gmk/lsNgE5QQ),如果是待审核中状态说明已成功提交,等待审核即可|
>d 响应参数示例:
```json
{
"invoiceBillNo": "xxxx",
"invoiceStatus": "0"
}
``````
## 6.5 开票结果查询
>d 该接口用于个体户开票和服务费开票结果查询
开发环境:https://pay-dev.lx-rhino.com
生产环境:https://api.lx-rhino.com
#### 接口地址:
/open/api/v1/qs/invoice/queryServiceInvoicesResult
#### 请求参数说明:
|参数名称|参数含义|数据类型|是否必填|参数备注|
|-|-|-|-|-|
|invoiceBillNo|开票订单号|String| 是|示例:"2020092115145251556096"|
>d 请求参数示例:
```java
{"invoiceBillNo":"2020092115145251556096"}
```
#### 接口响应参数data字段解密后的参数说明:
|参数名称| 参数含义|数据类型| 是否必有| 参数备注|
|-|-|-|-|-|
|invoiceBillNo|开票订单编号|String| 是|示例:"2020091720135423517696"|
|invoiceClassification| 开票类型|Integer| 是|0.普票 1.专票|
|invoiceStatus|开票状态|Integer| 是|参看[5.开票状态码](https://easydoc.net/doc/63011222/0klm3Gmk/lsNgE5QQ)|
|mainstayId|主体id|Integer| 是|示例:1|
|invoiceAmount|开票金额|BigDecimal| 是|示例:11.05|
|invoiceContent|发票内容|String| 是|示例:"信息技术服务*技术服务费"|
|remark| 备注|String| 否|示例:"XX"|
|purchaserInvoiceTitle|购买方发票抬头|String| 是|示例:"xx"|
|purchaserTaxNumber|购买方税号|String| 是|示例:"91990512MA2B6AME1N"|
|purchaserAddressPhone|购买方地址、电话|String| 是|示例:"xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001"|
|purchaserBankAccount|购买方开户行及账号|String| 是|示例:"xx银行xx分行xx部 15000xx8626431"|
|addressee| 收件人|String| 是|示例:"王某某"|
|phone| 联系电话|String| 是|示例:"1862687xxxx"|
|area| 所在地区|String| 是|所在地区(省市县\区) 示例:"浙江省绍兴市"|
|detailAddress| 详细地址|String| 是|示例:"浙江省绍兴市XX区XX街道XX小区XX单元XX楼"|
|email| 电子邮件|String| 是|示例:"2411XX429@qq.com"|
|sellerInvoiceTitle|销售方发票抬头|String| 是|示例:"xx"|
|sellerTaxNumber|销售方税号|String| 是|示例:"4104221993XXXX1278"|
|sellerAddressPhone|销售方地址、电话|String| 是|示例:"xx省xx市xx县xx区xx路 xx号xx大厦 xx 楼 xx 层 xx 室 17794xx5001"|
|sellerBankAccount|销售方开户行及账号|String| 是|示例:"xx银行xx分行xx部 15000xx8626431"|
|settlementCertUrl|结算单证明|String| 是|示例:"https://xxxx/xxxx.pdf"|
|settlementCertCustomUrl|自定义证明|String| 是|示例:"https://xxxx/xxxx.pdf"|
|expressCompany|快递公司|String| 是|示例:"xx物流有限公司"|
|expressNo|快递单号|String| 是|示例:"2020221993XXXX1278"|
|postStatus|邮寄状态0:未邮寄 1.已邮寄|Integer| 是|示例:1|
|failReason|失败原因|String| 否|示例:"xx"|
|invoiceDetailList|发票明细列表|List<InvoiceDetail>| 否|注意:已发票审核状态变为:(已开票)后的发票订单明细详情为准|
#### InvoiceDetail发票明细列表字段:
|参数名称| 参数含义|数据类型| 是否必有| 参数备注|
|-|-|-|-|-|
|requestNo|明细订单编号|String| 是|示例:"xx"|
|parentRequestNo|关联作废订单的明细编号|String| 否|只有在有已作废订单时才会有|
|invoiceCode|发票代码|String| 否|示例:"xx"|
|invoiceNumber|发票号码|String| 否|示例:"xx"|
|billingTime|开票时间|Date| 是|示例:"yyyy-MM-dd HH:mm:ss"|
|invoiceAmount|汇总开票金额(含税金额)|BigDecimal| 是|示例:101|
|totalAmount|不含税金额|BigDecimal| 是|示例:100|
|taxRate|税率|BigDecimal| 是|示例:0.1|
|taxAmount|税额|BigDecimal| 是|示例:1|
|drawer|开票人|String| 否|示例:"xx"|
|operator|收款人|String| 否|示例:"xx"|
|reviewer|复核人|String| 否|示例:"xx"|
|invoiceStatus|发票状态 -1:已作废 0:未开票 1:已开票|Integer| 是|示例:"xx"|
|invoiceContent|开票内容|String| 是|示例:"xx"|
|purchaserInvoiceTitle|购买方发票抬头|String| 是|示例:"xx"|
|purchaserTaxNumber|购买方税号|String| 是|示例:"xx"|
|purchaserAddressPhone|购买方地址、电话|String| 是|示例:"xx"|
|purchaserBankAccount|购买方开户行及账号|String| 是|示例:"xx"|
|sellerInvoiceTitle|销售方发票抬头|String| 是|示例:"xx"|
|sellerTaxNumber|销售方税号|String| 是|示例:"xx"|
|sellerAddressPhone|销售方地址、电话|String| 是|示例:"xx"|
|sellerBankAccount|销售方开户行及账号|String| 是|示例:"xx"|
>d 响应参数示例:
```java
{
"invoiceBillNo":"2021072915431430296320",
"invoiceClassification":1,
"invoiceStatus":2,
"mainstayId":1,
"invoiceAmount":100000,
"invoiceContent":"现代服务*汽车检测服务费",
"remark":"111111111111111111111111111",
"purchaserInvoiceTitle":"发票抬头(商户名称)cccc",
"purchaserTaxNumber":"纳税人识别号cccc",
"purchaserAddressPhone":"地址、电话ccccccc",
"purchaserBankAccount":"ccccccccccc",
"addressee":"收件人cccc",
"phone":null,
"area":"浙江省杭州市西湖区",
"detailAddress":"详细地址cccc",
"email":"cccc111@qq.com",
"sellerInvoiceTitle":"xx",
"sellerTaxNumber":null,
"sellerAddressPhone":null,
"sellerBankAccount":null,
"settlementCertUrl":"xx",
"settlementCertCustomUrl":"",
"expressCompany":null,
"expressNo":null,
"postStatus":0,
"failReason":null,
"invoiceDetailList":[
{
"requestNo":"2021072915441094972162",
"parentRequestNo":"",
"invoiceCode":"",
"invoiceNumber":"",
"billingTime":null,
"invoiceAmount":100000,
"totalAmount":97087.38,
"taxRate":0.03,
"taxAmount":2912.62,
"drawer":"",
"operator":"",
"reviewer":"",
"invoiceStatus":0,
"invoiceContent":"现代服务*汽车检测服务费",
"purchaserInvoiceTitle":"发票抬头(商户名称)cccc",
"purchaserTaxNumber":"纳税人识别号cccc",
"purchaserAddressPhone":"地址、电话ccccccc",
"purchaserBankAccount":"ccccccccccc",
"sellerInvoiceTitle":"xx",
"sellerTaxNumber":"xxx",
"sellerAddressPhone":"xxx",
"sellerBankAccount":"无"
}
]
}
```
## 6.6.个体工商户完税证明接口
开发环境:https://pay-dev.lx-rhino.com
生产环境:https://api.lx-rhino.com
>d 注意:个体工商户完税是按季度申报的,在获取的时候是在次季度第一个月的20号左右(遇到节假日时间会顺延)才能获取到上一个季度的完税证明
#### 接口地址:/open/api/v1/qs/invoice/queryServiceInvoicesEndResultDetails
#### 请求方式:POST
#### 请求参数说明:
|参数名称|参数含义|数据类型|是否必填|参数备注|
|-|-|-|-|-|
|idCard|个体户身份证号|String|是||
|mainstayId|主体ID|String|是|该参数值由[4.4 查询发票信息与主体信息接口](https://easydoc.net/doc/63011222/0klm3Gmk/cGW1eFKQ)|
#### 接口响应参数说明:
>d 响应的data是一个数组
```json
[
{
"incomeFromProductionAndOperation":"***.jpg",
"selfEmployedId":***,
"taxCycle":"2021.04~2021.06",
"valueAddedTax":"***.jpg"
},
...
]
```
|参数名称|参数含义| 数据类型|是否必有|参数备注|
|-|-|-|-|-|
|selfEmployedId|个体工商户ID|String|是|个体工商户的id是为了区分已注销后又注册的个体工商户的信息|
|taxCycle|报税周期|String|是|例:2021.04~2021.06|
|incomeFromProductionAndOperation|个税URL|String|是|例:***.jpg|
|valueAddedTax|增值税附加税URL|String|是|例:***.jpg|
>d 注意:selfEmployedId(个体工商户ID)是为了区分已注销后又注册的个体工商户的完税信息;
同一个注册地、同一个身份证信息,注销后又注册,这里的个体工商户的id就会有两个;
## 7. 公共接口
## 7.1 上传文件接口
>d 该接口将需要上传的文件上传至发放平台服务器,获取到对应的地址用于其他接口作为入参
开发环境:https://pay-dev.lx-rhino.com
生产环境:https://api.lx-rhino.com
#### 接口地址:
/open/api/v1/common/uploadFile
#### 请求参数说明:
|参数名称|参数含义|是否必填|参数备注|
|-|-|-|-|
|file|文件|是||
#### 响应参数说明:
|参数名称| 参数含义| 是否必有| 参数备注|
|-|-|-|-|
|url|文件地址|是||
java接口代码示例:
```json
@PostMapping(value = "/upload")
@ResponseBody
@NoPermission
public String upload(MultipartFile file) {
String url = baseUrl +"/open/api/v1/invoices/uploadFile";
final byte[] bytes ;
try {
bytes = file.getBytes();
String appKey = "";
String version = "1.0";
String secretkey = "";
String timestamp = String.valueOf(System.currentTimeMillis());
//注意此处签名无 body拼接
String localString = "&Timestamp=" + timestamp + "&AppKey=" + appKey + "&Version=" + version + "&SecretKey" + secretkey;
String sigin = Md5Util.getMd5(localString);
MultipartBody body = new MultipartBody.Builder()
.setType(MediaType.parse("multipart/form-data"))
.addFormDataPart("file", file.getOriginalFilename(), okhttp3.RequestBody.create(MediaType.parse("image/" + "打款凭证"), bytes))
.build();
Request request = new Request.Builder()
.post(body)
.addHeader("AppKey", appKey)
.addHeader("Timestamp", timestamp)
.addHeader("Version", "1.0")
.addHeader("Sign", sigin)
.url(url)
.build();
Call call = HttpUtil.getOkHttpClient().newCall(request);
try {
Response response = call.execute();
String res = response.body().string();
log.info("res====" + res);
return res;
} catch (IOException e) {
log.error("HttpUtil.post网络请求失败:{}", e.getMessage());
return "网络请求失败";
}
} catch (IOException e) {
log.warn("fail to read file", file.getOriginalFilename(), e);
}
return null;
}
```
postman 直接请求示例:
