日期 | 变更描述 | 变更人 | 版本 | 批注 |
---|---|---|---|---|
2019/06/13 | 编写发票助手web对接初稿 | 毕红波 | V1.0 | |
2020/02/14 | 新增发票助手java端建立连接 | 毕红波 | V1.1 | |
2020/02/25 | 新增通过单据号查询全部发票列表 | 毕红波 | V1.2 |
测试环境: https://api-dev.piaozone.com/test
正式环境: https://api.piaozone.com
对接过程中需要:client_id和client_secret进行授权,每个环境的授权不同,获取方式可以找实施人员协助提供
接口返回约定: 若无特别说明,接口返回如下
{
"errcode": "0000", ///成功时为0000, 失败时为非0000
"description": "操作成功", //描述,失败时可以根据这个字段进行提示
"data": "" //请求的返回实际数据
}
注意:进入新增或者更新单据界面时,需要建立连接
使用库文件地址,建议在线引入:
<script type="text/javascript" src="https://img-expense.piaozone.com/static/gallery/socket.io.js"></script>
<script type="text/javascript" src="https://img-expense.piaozone.com/static/public/js/pwy-socketio-v2.js"></script>
var pwyWebsocket = new PwyWebSocket({
env: 'prod', //正式环境: prod, 测试环境: test
tin: tin, ///tin为获取userKey时的税号
eid: eid, //eid为获取userKey时的用户eid
client_id: client_id, // 发票云分配的client_id
sign: sign, // 签名规则:MD5(client_id + client_secret + timestamp)
timestamp: timestamp, // 签名时的时间戳
name: linkKey, // 连接名称,选择发票前获取的linkKey
sourceType: 'socket', // 默认socekt, 对于不支持socket的端请设置为polling,java端的轮询参考5
onOpen: function(){ // 连接成功的回调
//console.log("连接成功"+ this.name);
},
onMessage: function(msg){
//msg为接收到的消息, 消息格式:{"type":"saveBill", data: {}}
//当type为saveBill时, data的数据为导入的发票数据,具体格式参考4.3
//当type为saveEntrys时, data的数据为分录调整后的数据,具体格式参考6.4
//当type为updateInvoice, data的数据为修改的发票基本信息,具体格式参考14.3
//接收到消息后,企业处理好自己业务, 如果要调用查看发票界面(调用6.3接口进行缓存),处理完成关闭窗口即可
},
onError: function(errText, errCode){ //失败时的回调
}
// 关闭连接, 接受到消息之后需要先关闭连接,需要再次使用需要重新创建socket对象
pwyWebsocket.close();
});
消息格式: {"type":"saveBill", data: {}}
type为saveBill时为导入时的发票数据
费用报销单的数据格式:billType为空字符串
//type为消息类型,saveBill为发票数据,saveEntrys为分录数据
{
"type": "saveBill",
"data": {
"billnumber": "2018-11-28-00001898", //单据编号
"bxd_key": "Ik2TrOC5RSCOND0pE9J8=", //单据全球唯一key
"data": [{
"serialNo": 1125866, //发票流水号
"invoiceType": "1", //发票种类,1.普通电子发票2.电子发票专票3.普通纸质发票4.专用纸质发票5.普通纸质卷票7.通用机打8.的士票9.火车票10.飞机票11.其他 12.机动车 13.二手车14.定额发票15.通行费16.客运票17.过路过桥发票19.完税证明20.轮船票23通用机打电子发票
"invoiceCode": "044031600113", //发票代码
"invoiceNo": "30819002", //发票号码
"invoiceDate":"2020-01-01",//发票日期
"checkStatus": 1, //1查验通过,2查验不通过
"expenseStatus": 1, //报销状态,1为未使用,30为使用中,60为已使用
"amount": 383.76, //合计不含税金额
"totalAmount": 449, //价税合计
"taxAmount": 66.24, //开票合计税额
"taxRate":"0.09",//税率,针对多税率的情况下传99
"goodsCood": "1010115010000000000", //商品编码,取明细第一条
"sallerName": "新华书店总店", //购货方名称
"sallerTaxNo": "440301999999980", //购货方纳税人识别号
"buyerName": "新华书店总店", //销货方名称
"buyerTaxNo": "440301999999980" //销货方纳税人识别号
}],
"invoiceSerialNos":"e7601aa2a677467bbf0271fbde682d910,e7fde3adddbe46328aa3405085854c250",//当前报销单导入的发票流水号集合
"invoicesAmount": 178860,//发票金额总和
"invoicesTaxAmount": 0,//发票税额总和
"isElectronicInvoice": false,//当前报销单导入的发票是否全是电票,true为是,false为否
"userid": "eid-1544414642579" //对应用户的eid
}
}
智能差旅行程单的数据数据格式, billType为:Tra
{
"type": "saveBill",
"data": {
"billnumber": "2018-11-28-00001898", //单据编号
"bxd_key": "Ik2TrOC5RSCOND0pE9J8=", //单据全球唯一key
"data": [{
"invoiceData": [{
"salerAccount": "中国银行5218666111888", //销方银行名称和账号
"stationGeton": "", //
"classify": "other", //分类
"amount": 50.91, //不含税金额,飞机票则采用票价
"salerName": "航信培训企业", //销方名称
"invoiceDate": "2018-09-29", //开票日期
"invoiceCode": "", //发票代码
"serialNo": "", //发票流水号
"totalAmount": 56, //价税合计
"taxRate": "0.099980", //税率
"seatGrade": "",
"salerAddressPhone": "广东省深圳市南山区 xxxx", //销方地址电话
"stationGetoff": "",
"salerTaxNo": "", //销方税号
"invoiceType": "1", //发票种类,1.普通电子发票2.电子发票专票3.普通纸质发票4.专用纸质发票5.普通纸质卷票7.通用机打8.的士票9.火车票10.飞机票11.其他 12.机动车 13.二手车14.定额发票15.通行费16.客运票17.过路过桥发票19.完税证明20.轮船票23通用机打电子发票
"goodsCode": "3079900000000000000", //商品编码
"taxAmount": 5.09, //总税额
"invoiceNo": "", //发票号码
"airItemsArr": [], //如果是机票,可能有多条行程
"goodsName": "*水果*苹果", //商品名称
"classifyName": "其他费用" //分类中文名
}],
"totalAmount": 60.3,
"amount": 54.97,
"costName": "其他费用",
"size": 2,
"costType": "other",
"taxAmount": 6.33,
"invoiceDate": "2018-09-29"
}],
"invoicesTotalAmount": 76.98,//发票金额总和
"invoicesTaxAmount": 5.82,//发票税额总和
"allSize": 3,//导入该单据的发票总数量
"invoiceSerialNos":"e7601aa2a677467bbf0271fbde682d910,e7fde3adddbe46328aa3405085854c250",//当前报销单导入的发票流水号集合
"isElectronicInvoice": false,//当前报销单导入的发票是否全是电票,true为是,false为否
"userid": "eid-1544420896749"//对应用户的eid
}
}
智能物品采购报销单-数据数据格式, billType为:Pur
{
"type": "saveBill",
"data": {
"billnumber":"", //对应传入的billnumber
"bxd_key":"", //对应传入的bxd_key
"type":"", //前端约定交互方式识别
"userid":"", //对应传入的eid
"isElectronicInvoice": false,//当前报销单导入的发票是否全是电票,true为是,false为否
"invoiceSerialNos":"e7601aa2a677467bbf0271fbde682d910,e7fde3adddbe46328aa3405085854c250",//当前报销单导入的发票流水号集合
"data":
{
//收款方信息集合
"buyerInfo":[
{
"buyerName":"", //收款方企业名称
"buyerTaxNo":"", //收款方企业税号
"buyerAddressPhone":"", //收款方地址电话
"buyerAccount":"", //收款方银行帐号
}
],
//采购列表信息,按供应商、品名划分
"purchaseInfo":[
{
"salerName":"", //销方名称,即供应商名称
"salerTaxNo":"", //销方税号,即供应商税号
"goodsName":"", //品名
"goodsCode":"", //品名对应的商品编码
"invoiceDate":"", //日期,默认取第一个
"unit":"", //单位,默认取第一个
"num":"", //数量,数量总和
"unitPrice":"", //单价,平均单价
"detailAmount":"", //报销金额
"taxAmount":"", //合计税额
"size":"", //品名条数
"invoiceData":[] //发票流水号集合
}
]
}
}
}
智能对公报销单-数据数据格式, billType为:BizOut
{
"type": "saveBill",
"data": {
"billnumber": "RH-365-20181117-1054", //报销单号
"bxd_key": "iCFJ7WdQTrxjJTCkx2fAmKk7FTnPXj=", //报销单ID
"type": "savebill",
"userid": "", //用户eid
"invoicesTotalAmount": 1000, //总价税合计总额
"invoicesTaxAmount": 200, //总税额
"data": [ //按税号、银行帐号划分
{
"salerTaxNo":"", //开票方税号
"salerName":"", //开票方名称
"salerAddressPhone":"", //开票方地址、帐号
"salerAccount":"", //开票方银行开户行、帐号
"amount": 1000, //总金额(不含税)
"taxAmount": 200, //总税额
"totalAmount":"", //价税合计总额
"invoiceType":"", //发票类型
"invoiceNo":"", //发票号码
"invoiceCode":"",//发票代码
"goodsCode":"", //税收分类编码,发票数据中取第一条信息为准
"goodsName":"", //货物名称,发票数据中取第一条信息为准
"taxRate":"", //税率 ,发票数据中取第一条信息为准
"serialNo":"" //发票流水号
}]
}
}
注意:当不是web打开发票助手时,可以采用java方式建立长连接
// 请求示例
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import com.alibaba.fastjson.JSONObject;
/**
* 描述:长轮询调用工具
* @author chuang_li date:<2019年3月14日> <p>
*
* @version <TODO EAS***>
*/
public class PwyHttpURLConnection {
private static final String CHARSET = "utf-8"; // 编码格式
public String doPost(String urlStr, String param) {
// 从连接中读取响应信息
String msg = "";
try {
// 1. 获取访问地址URL
URL url = new URL(urlStr);
// 2. 创建HttpURLConnection对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
/* 3. 设置请求参数等 */
// 请求方式
connection.setRequestMethod("POST");
// 超时时间
// connection.setReadTimeout(TIME_OUT);
// 超时时间
// connection.setConnectTimeout(TIME_OUT);
// 设置是否输出
connection.setDoOutput(true);
// 设置是否读入
connection.setDoInput(true);
// 设置是否使用缓存
connection.setUseCaches(false);
// 设置此 HttpURLConnection 实例是否应该自动执行 HTTP 重定向
connection.setInstanceFollowRedirects(false);
// 设置使用标准编码格式编码参数的名-值对
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Charset", "UTF-8");
// 连接
connection.connect();
// 上传参数
DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
// 请求结束标志
dos.write(param.getBytes("UTF-8"));
dos.flush();
dos.close();
int code = connection.getResponseCode();
if (code == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), CHARSET));
String line;
while ((line = reader.readLine()) != null) {
msg += line + "\n";
}
reader.close();
}
// 5. 断开连接
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
public String doHttpsGet(String urlStr) {
// 从连接中读取响应信息
String msg = "";
try {
// 1. 获取访问地址URL
URL url = new URL(urlStr);
// 2. 创建HttpURLConnection对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int code = connection.getResponseCode();
if (code == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), CHARSET));
String line;
while ((line = reader.readLine()) != null) {
msg += line + "\n";
}
reader.close();
}
// 5. 断开连接
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
public static void main(String[] args) {
String client_id = "";
String client_secret = "";
PwyHttpURLConnection test = new PwyHttpURLConnection();
String baseUrl = "https://api-dev.piaozone.com/test/";//针对发票云环境需要动态修改
//1、获取token
long times = System.currentTimeMillis();
JSONObject jsonObject = new JSONObject();
jsonObject.put("client_id", client_id);
jsonObject.put("sign", MD5.md5crypt(client_id + client_secret + times));//此处需要md5加密
jsonObject.put("timestamp", times);
String tokenUrl = baseUrl + "base/oauth/token";
String tokenResult = test.doPost(tokenUrl, jsonObject.toJSONString());
System.out.println("获取到的token:" + tokenResult);
JSONObject tokenJson = JSONObject.parseObject(tokenResult);
if("0000".equals(tokenJson.getString("errcode"))){
String access_token = tokenJson.getString("access_token");
//2、获取对应key的数据,该处根据业务处理。。如果获取到一次之后就不需要获取,可自行处理(示例中的是无限循环一直取数)
while(true){
//需要获取的消息key
String key = "bxd_test1";
String result = test.doHttpsGet(baseUrl + "polling/fpzs/invoice/data/v2?access_token="+access_token+"&key="+key);
System.out.println("接收到的消息:"+result);
if(result.contains("0000")){
JSONObject resultJson = JSONObject.parseObject(result);
//3、获取到消息时,需要调用确认回执,不然后面该消息会再次返回
String callBack = test.doHttpsGet(baseUrl + "polling/fpzs/portal/receipt?access_token="+access_token+"&key="+key+"&msgId="+resultJson.getJSONObject("data").getString("msgId"));
System.out.println("确认回执结果:"+callBack);
}
}
}else{
//token获取失败,有可能是请求环境和clientid未匹配上,请联系金蝶管理员
}
}
}
socket正式环境连接地址:https://link.piaozone.com
socket测试环境连接地址:https://link-test.piaozone.com
// java模拟socket连接, 请求示例:
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
public class TestSocketIO {
private Socket socket;
public String doHttpsGet(String urlStr) {
// 从连接中读取响应信息
String msg = "";
try {
// 1. 获取访问地址URL
URL url = new URL(urlStr);
// 2. 创建HttpURLConnection对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int code = connection.getResponseCode();
if (code == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), CHARSET));
String line;
while ((line = reader.readLine()) != null) {
msg += line + "\n";
}
reader.close();
}
// 5. 断开连接
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
public void send(String userId) {
try {
IO.Options options = new IO.Options();
options.query = "userId="+userId;
socket = IO.socket("https://link.piaozone.com", options);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
System.out.println("连接中...");
System.out.println(args);
}
});
socket.on(userId+"", new Emitter.Listener() {
@Override
public void call(Object... args) {
if(null != args) {
String baseUrl = "https://api-dev.piaozone.com/test/";//针对发票云环境需要动态修改
System.out.println("接收到的消息:"+args[0]);
JSONObject resultJson = JSONObject.parseObject(args[0].toString());
//获取到消息时,需要调用确认回执,不然后面该消息会再次返回
String callBack = doHttpsGet(baseUrl+"polling/fpzs/portal/receipt?access_token="+access_token+"&key="+key+"&msgId="+resultJson.getJSONObject("data").getString("msgId"));
System.out.println("确认回执结果:"+callBack);
}
}
});
socket.on(Socket.EVENT_CONNECT_TIMEOUT, new Emitter.Listener() {
@Override
public void call(Object... args) {
System.out.println("EVENT_CONNECT_TIMEOUT");
}
}).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
@Override
public void call(Object... args) {
System.out.println("EVENT_CONNECT_ERROR");
}
});
socket.io().on(io.socket.engineio.client.Socket.EVENT_OPEN, new Emitter.Listener() {
@Override
public void call(Object... args) {
}
});
socket.io().on(io.socket.engineio.client.Socket.EVENT_PACKET, new Emitter.Listener() {
@Override
public void call(Object... args) {
System.out.println("EVENT_PACKET");
}
});
socket.io().on(io.socket.engineio.client.Socket.EVENT_DATA, new Emitter.Listener() {
@Override
public void call(Object... args) {
System.out.println("EVENT_DATA");
}
});
socket.open();
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
TestSocketIO t = new TestSocketIO();
t.send("lctest1");
}
}
// 消息返回结果:
// {"data":{"data": "接收到的消息","from": "发送端key","key": "接收端key","msgId": "消息ID唯一"},"description": "成功","errcode": "0000"}
注意打开界面前必须建立好连接通道,参考[4]
获取路径: /m4/fpzs/getLinkKey
请求方式: POST
请求参数:无
返回结果:
参数 | 类型 | 说明 |
---|---|---|
errcode | varchar | 状态码,0000表示成功 |
description | varchar | 描述 |
data | varchar | linkKey |
请求示例:
package com.kingdee.apitest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.net.URI;
public class LinkKeyDemo {
//测试环境: https://www.piaozone.com/test
//正式环境: https://www.piaozone.com
private static final String HOST = "www.piaozone.com/test";
private static final String API_PATH = "/m4/fpzs/getLinkKey";
private static final String CONTENT_TYPE = "application/json";
public static void main(String[] args) throws Exception {
String result = getLinkKey();
System.out.println(result);
}
/**
* 获取linkkey
* @return
* @throws Exception
*/
public static String getLinkKey() throws Exception {
HttpClient client = HttpClients.createDefault();
URIBuilder builder = new URIBuilder();
// 创建Post请求
URI uri = builder.setScheme("http")
.setHost(HOST)
.setPath(API_PATH)
.build();
HttpPost post = new HttpPost(uri);
//设置请求头
post.setHeader("Content-Type", CONTENT_TYPE);
//获取返回信息
HttpResponse response = client.execute(post);
HttpEntity resp = response.getEntity();
String result = EntityUtils.toString(resp,"UTF-8");
return result;
}
}
获取userKey路径: /m4/fpzs/getUserKey
请求方式: POST
请求content-type格式: application/json
请求的全部参数:
参数名 | 是否必须 | 备注 |
---|---|---|
timestamp | 是 | 用于签名验证 |
client_id | 是 | 发票云分配的应用client_id |
tin | 是 | 企业税号 |
ghf_mc | 是 | 企业名称 |
eid | 是 | 接入企业用户ID, |
sign | 是 | 签名, 签名规则:MD5(client_id + client_secret + timestamp) |
billNumber | 是 | 企业单据编号,可以为空,已经保存的单据传入可以方便查询出已经存在的票据 |
bxd_key | 是 | 单据号, 全球唯一算法生成的ID |
random | 是 | 随机数,用户导入发票时建立socket通讯 |
ticketParam | 是 | 过滤规则,格式如:1101 |
billType | 是 | 单据类型 |
branch_id | 否 | 指定查看分录的ID,用于分录编辑和查看时必须传入 |
invoiceSerialNos | 否 | 已采集的发票流水号集合字符串,英文逗号分隔 |
attachmentSerialNos | 否 | 已采集的附件流水号集合字符串,英文逗号分隔 |
buyerAccount | 否 | 专票开户行账号,用于校验专票开户行账号是否一致 |
buyerAddressPhone | 否 | 专票地址电话,用于校验专票地址电话是否一致 |
billType 参数:
参数值 | 备注 |
---|---|
Tra | 智能差旅行程单 |
Pur | 智能物品采购报销单 |
BizOut | 智能对公报销单 |
"" | 费用报销单传空字符串 |
ticketParam 参数规则顺序: 0 不允许 1 允许
第1位:已报销过的发票是否允许导入
第2位:发票抬头与企业名称不一致的发票是否允许导入
第3位:发票抬头与税号不一致发票是否允许导入
第4位:发票查验不通过的发票是否允许导入
第5位: 个人发票是否允许导入
请求的返回值:
{
"errcode": "0000", ///成功时为0000, 失败时为非0000
"description": "操作成功", //描述,失败时可以根据这个字段进行提示
"data": {
"userKey": "" //获取到的userKey
}
}
返回值说明:
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
errcode | String | 4 | 响应 |
description | String | N | 描述 |
userKey | String | 32 | 后续接口需要使用的用户身份认证key |
请求示例:
package com.kingdee.apitest;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.net.URI;
public class GetUserKeyDemo {
//测试环境: https://www.piaozone.com/test
//正式环境: https://www.piaozone.com
private static final String HOST = "localhost:9409";
private static final String API_PATH = "/m4/fpzs/getUserKey";
private static final String CONTENT_TYPE = "application/json";
public static void main(String[] args) throws Exception {
String client_id = "";
String eid = "=";
String bxd_key = "";
String random = "";
String ticketParam = "";
String tin = "";
String secret = "";
String result = getUserKey(client_id, secret, tin, eid, bxd_key, ticketParam, random);
System.out.println(result);
}
/**
* 获取userKey
* @param client_id 发票云分配的应用client_id
* @param secret 发票云分配的应用secret
* @param tin 企业税号
* @param eid erp系统的用户ID
* @param bxd_key 单据号, 全球唯一算法生成的ID
* @param ticketParam 过滤规则,格式如:1101
* @param random 随机数,用户导入发票时建立socket通讯
* @return
* @throws Exception
*/
public static String getUserKey(String client_id, String secret, String tin, String eid, String bxd_key, String ticketParam, String random) throws Exception {
HttpClient client = HttpClients.createDefault();
URIBuilder builder = new URIBuilder();
// 创建Post请求
URI uri = builder.setScheme("http")
.setHost(HOST)
.setPath(API_PATH)
.build();
HttpPost post = new HttpPost(uri);
//设置请求头
post.setHeader("Content-Type", CONTENT_TYPE);
//组装参数
JSONObject params = new JSONObject();
long currentTimeMillis = System.currentTimeMillis();
params.put("timestamp", currentTimeMillis);
params.put("client_id", client_id);
params.put("eid", eid);
params.put("bxd_key", bxd_key);
params.put("random", random);
params.put("ticketParam", ticketParam);
params.put("tin", tin);
String sign = client_id + secret + currentTimeMillis;
String md5Hex = DigestUtils.md5Hex(sign);
params.put("sign", md5Hex);
post.setEntity(new StringEntity(params.toJSONString()));
//获取返回信息
HttpResponse response = client.execute(post);
HttpEntity resp = response.getEntity();
String result = EntityUtils.toString(resp,"UTF-8");
return result;
}
}
把目前界面最新的单据和发票关系缓存到发票云
请求地址: /m4/fpzs/expense/entry/cache
请求方式: POST
请求格式: application/json
参数格式如下:
//如没有特殊说明,参数不能为空
{
"userKey":"",//打开首页时获取的userKey(可以为空)
"eid":"",//erp系统的用户id
"billTypeId":"",//单据类型, 用于区分是哪种单据
"billnumber": "", //保存时的报销单号
"bxd_key": "", //保存时的报销单ID全球唯一id,如果没有这个字段,与billnumber一致即可
"client_id": "", //发票云分配的授权ID
"tin": "", //企业税号
"timestamp": "", //签名的时间戳
"sign": "", //签名规则:MD5(client_id + client_secret + timestamp)
"data": [{
"entryid": "", //单据的分录id,如果没有分录功能,可以传空
"fid": [
"流水号1",
"流水号2"
] //发票流水号, 数组格式
}]
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
userKey | String | 32 | 后续接口需要使用的用户身份认证key |
eid | String | 80 | erp系统的用户id |
billTypeId | String | 80 | 单据类型 |
billnumber | String | N | 保存时的报销单号 |
bxd_key | String | 50 | 保存时的报销单ID |
client_id | String | 20 | 发票云分配的授权ID |
tin | String | 20 | 企业税号 |
timestamp | String | 13 | 签名的时间戳 |
sign | String | 32 | 签名规则:MD5(client_id + client_secret + timestamp) |
entryid | String | N | 单据的分录id |
fid | String | 33 | 流水号 |
参数格式如下:
//成功时的返回
{
"errcode":"0000",
"description": "操作成功"
}
//请求失败时的返回
{
"errcode":"3000",
"description": "错误描述"
}
请求示例:
package com.kingdee.apitest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.net.URI;
public class ExpenseEntryCacheDemo {
//测试环境: https://www.piaozone.com/test
//正式环境: https://www.piaozone.com
private static final String HOST = "localhost:9409";
private static final String API_PATH = " /m4/fpzs/expense/entry/cache";
private static final String CONTENT_TYPE = "application/json";
public static void main(String[] args) throws Exception {
String client_id = "";
String eid = "=";
String bxd_key = "";
String billTypeId = "";
String billnumber = "";
String tin = "";
String secret = "";
JSONArray data = new JSONArray();
String result = executeEntryCache(client_id, secret, tin, eid, billTypeId, billnumber, bxd_key, data);
System.out.println(result);
}
/**
* 执行-将界面上最新的单据和发票关系缓存到发票云
* @param client_id 发票云分配的授权ID
* @param secret 发票云分配的授权secret
* @param tin 企业税号
* @param eid erp系统的用户id
* @param billTypeId 单据类型,用于区分是哪种单据
* @param billnumber 保存时的报销单号
* @param bxd_key 保存时的报销单ID全球唯一id,如果没有这个字段,与billnumber一致即可
* @param data "data": [{
* "entryid": "", //单据的分录id,如果没有分录功能,可以传空
* "fid": [
* "流水号1",
* "流水号2"
* ] //发票流水号, 数组格式
* }]
* @return
* @throws Exception
*/
public static String executeEntryCache(String client_id, String secret, String tin, String eid, String billTypeId, String billnumber, String bxd_key, JSONArray data) throws Exception {
HttpClient client = HttpClients.createDefault();
URIBuilder builder = new URIBuilder();
// 创建Post请求
URI uri = builder.setScheme("http")
.setHost(HOST)
.setPath(API_PATH)
.build();
HttpPost post = new HttpPost(uri);
//设置请求头
post.setHeader("Content-Type", CONTENT_TYPE);
//组装参数
JSONObject params = new JSONObject();
long currentTimeMillis = System.currentTimeMillis();
params.put("timestamp", currentTimeMillis);
params.put("client_id", client_id);
params.put("eid", eid);
params.put("bxd_key", bxd_key);
params.put("billTypeId", billTypeId);
params.put("billnumber", billnumber);
params.put("tin", tin);
params.put("data", data);
String sign = client_id + secret + currentTimeMillis;
String md5Hex = DigestUtils.md5Hex(sign);
params.put("sign", md5Hex);
post.setEntity(new StringEntity(params.toJSONString()));
//获取返回信息
HttpResponse response = client.execute(post);
HttpEntity resp = response.getEntity();
String result = EntityUtils.toString(resp,"UTF-8");
return result;
}
}
界面打开路径: /m4-web/fpzs/index?userKey=&linkKey=&gridParam=&sourceType=socket
请求方式: GET
请求参数:
参数 | 类型 | 备注 |
---|---|---|
userKey | string | 通过getUserKey接口获取到的获取的userKey |
linkKey | string | 通过getLinkKey接口获取到的获取的linkKey |
gridParam | string | 选择发票格子控制,支持(1111: 默认四个格子,1100:显示PC上传和手机端推送,0011:显示扫码枪和扫描仪) |
sourceType | string | 非必须,作用为指定推送的连接模式,默认为socket,如果gui或者不支持socket的端请设置为polling |
注意打开界面前必须建立好连接通道,参考[4]
具体参考上述getLinkKey接口
具体参考选择发票获取userKey[5.2] , 注意此时branch_id必须传
具体参考缓存单据与发票关系[5.3]
界面打开路径: /m4-web/fpzs/expense/branch/update?userKey=&linkKey=
请求方式: GET
请求参数:
参数 | 类型 | 备注 |
---|---|---|
userKey | string | 通过getUserKey接口获取到的获取的userKey |
linkKey | string | 通过getLinkKey接口获取到的获取的linkKey |
注意:分录调整后,发票云会把当前分录的发票信息通过socket传入,msg的消息类型为saveEntrys, 接收到新的分录信息后,只需要自身界面调整当前分录信息,如发票张数,金额,税额,等等
//具体格式如下
{
"type": "saveEntrys", //消息类型
"data": {
"bxd_key": "", //报销单id
"branch_id": "", //分路id
"list": {
"fplx": "", //发票种类,1.普通电子发票2.电子发票专票3.普通纸质发票4.专用纸质发票5.普通纸质卷票7.通用机打8.的士票9.火车票10.飞机票11.其他 12.机动车 13.二手车14.定额发票15.通行费16.客运票17.过路过桥发票19.完税证明20.轮船票23通用机打电子发票
"spbm": "", //税收分类编码
"fpdm": "", //发票代码
"fphm": "", //发票号码
"jshj": 0, //价税合计金额
"kprq": "", //开票日期,"YYYY-MM-DD"
"se": 0, //税额
"fid": "" //发票流水号
},
"traList": [ //冗余字段,需要对接的可以使用
{
"invoiceData": [{
"fid": "", //发票流水号
"spbm": "", //商品编码
"fpdm": "", //发票代码
"fphm": "", //发票号码
"jshj": "", //价税合计
"kprq": "", //发票日期
"se": "", //税额
"fplx": "" //发票类型
}],
"costType": "", //报销类型
"amount": "", //金额合计
"costName": "", //报销类型名称
"size": "", //发票份数
"invoiceDate": "", //发票日期
"taxAmount": "", //税额
"totalAmount": "" //价税合计
}]
}
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
type | String | N | saveBill/saveEntrys/updateInvoice |
bxd_key | String | 50 | 保存时的报销单ID |
branch_id | String | N | 分路id |
fplx | String | 1 | 发票种类,1.普通电子发票2.电子发票专票3.普通纸质发票4.专用纸质发票5.普通纸质卷票7.通用机打8.的士票9.火车票10.飞机票11.其他 12.机动车 13.二手车14.定额发票15.通行费16.客运票17.过路过桥发票19.完税证明20.轮船票23通用机打电子发票 |
spbm | String | N | 税收分类编码 |
fpdm | String | 12 | 发票代码 |
fphm | String | 8 | 发票号码 |
jshj | String | 23 | 价税合计金额 |
kprq | String | 10 | 开票日期,"YYYY-MM-DD" |
se | String | 13 | 税额 |
fid | String | 33 | 流水号 |
costType | String | N | 报销类型 |
costName | String | N | 报销类型名称 |
size | Number | N | 发票份数 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
taxAmount | String | 13 | 税额 |
totalAmount | String | 23 | 价税合计金额 |
具体参考选择发票获取userKey[5.2], 注意此时branch_id必须传
界面打开路径: /m4-web/fpzs/expense/branch/info?userKey=
请求方式: GET
请求参数: 获取的userKey
请求格式: https://api.piaozone.com/m4-web/fpzs/expense/branch/info?userKey=d26f60552a440d11a474a6bdcb9e6f98
具体参考选择发票获取userKey[5.2]
具体参考缓存单据与发票关系[5.3]
界面打开路径: /m4-web/fpzs/expense/invoice/list?userKey=
请求方式: GET
请求参数: 获取的userKey
请求格式: https://api.piaozone.com/m4-web/fpzs/expense/invoice/list?userKey=d26f60552a440d11a474a6bdcb9e6f98
具体参考选择发票获取userKey[5.2]
界面打开路径: /m4-web/fpzs/expense/showInvoice?userKey=
请求方式: GET
请求参数: 获取的userKey, 发票流水号serialNo
请求地址: /m4/fpzs/expense/entry/save
请求方式: POST
请求格式: application/json
参数格式如下:
//如没有特殊说明,参数不能为空
{
"userKey": "",//打开首页时获取的userKey(可以为空)
"eid": "",//eas用户id eas系统用户id
"billTypeId": "", //单据类型, 用于区分是哪种单据
"billnumber": "", //报销单号
"bxd_key": "", //报销单ID全球唯一id,如果没有这个字段,与billnumber一致即可
"client_id": "", //发票云分配的授权ID
"tin": "", //企业税号
"timestamp": "", //签名的时间戳
"sign": "", //签名规则:MD5(client_id + client_secret + timestamp)
"coverBase64": "",//封面的base64
"coverFileType": "",//封面的文件类型:pdf、jpg、png等
"coverNumber": "",//影像/封面编号
"data": [{
"entryid": "", //单据的分录id,如果没有分录功能(可以传空)
"fid": [ //发票流水号, 数组格式
"流水号1",
"流水号2"
],
"costTypeId":"",//费用类型id(如获取不到可以为空)
"costTypeName":"业务招待费",//费用类型名称(如获取不到可以为空)
}]
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
userKey | String | 32 | 后续接口需要使用的用户身份认证key |
eid | String | 80 | eas系统用户id |
billTypeId | String | 80 | 单据类型 |
billnumber | String | N | 保存时的报销单号 |
bxd_key | String | 50 | 保存时的报销单ID |
client_id | String | 20 | 发票云分配的授权ID |
tin | String | 20 | 企业税号 |
timestamp | String | 13 | 签名的时间戳 |
sign | String | 32 | 签名规则:MD5(client_id + client_secret + timestamp) |
entryid | String | N | 单据的分录id |
fid | String | 33 | 流水号 |
costType | String | N | 报销类型 |
costName | String | N | 报销类型名称 |
coverBase64 | String | N | 封面的base64(非必填) |
coverFileType | String | N | 封面的文件类型:pdf、jpg、png等(如果传封面,必填文件类型) |
coverNumber | String | N | 影像/封面编号(如果传封面,必填编号) |
参数格式如下:
//成功时的返回
{
"errcode":"0000",
"description": "操作成功"
}
//请求失败时的返回
{
"errcode":"3000",
"description": "错误描述"
}
请求示例:
package com.kingdee.apitest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class ExpenseEntrySaveDemo {
//测试环境: https://www.piaozone.com/test
//正式环境: https://www.piaozone.com
private static final String HOST = "www.piaozone.com/test";
private static final String API_PATH = "/m4/fpzs/expense/entry/save";
private static final String CONTENT_TYPE = "application/json";
public static void main(String[] args) throws Exception {
String userKey = "";
String client_id = "";
String secret = "";
String eid = "";
String bxd_key = "";
String billTypeId = "";
String billnumber = "";
String tin = "";
JSONArray data = new JSONArray();
String result = saveExpenseEntry(userKey, client_id, secret, tin, eid, bxd_key, billTypeId, billnumber, data);
System.out.println(result);
}
/**
* 保存单据
* @param userKey getUserKey接口获取的参数
* @param client_id 发票云分配的应用client_id
* @param secret 发票云分配的应用secret
* @param tin 企业税号
* @param eid erp系统的用户ID
* @param bxd_key 单据号, 全球唯一算法生成的ID 如果没有这个字段,与billnumber一致即可
* @param billTypeId 单据类型
* @param billnumber 报销单号
* @param data [{
* "entryid": "", //单据的分录id,如果没有分录功能(可以传空)
* "fid": [ //发票流水号, 数组格式
* "流水号1",
* "流水号2"
* ],
* "costTypeId":"",//费用类型id(如获取不到可以为空)
* "costTypeName":"业务招待费",//费用类型名称(如获取不到可以为空)
* }]
* @return
*/
public static String saveExpenseEntry(String userKey, String client_id, String secret, String tin, String eid, String bxd_key, String billTypeId, String billnumber, JSONArray data) throws URISyntaxException, IOException {
HttpClient client = HttpClients.createDefault();
URIBuilder builder = new URIBuilder();
// 创建Post请求
URI uri = builder.setScheme("http")
.setHost(HOST)
.setPath(API_PATH)
.build();
HttpPost post = new HttpPost(uri);
//设置请求头
post.setHeader("Content-Type", CONTENT_TYPE);
//组装参数
JSONObject params = new JSONObject();
long currentTimeMillis = System.currentTimeMillis();
params.put("timestamp", currentTimeMillis);
params.put("client_id", client_id);
params.put("eid", eid);
params.put("bxd_key", bxd_key);
params.put("userKey", userKey);
params.put("billTypeId", billTypeId);
params.put("tin", tin);
String sign = client_id + secret + currentTimeMillis;
String md5Hex = DigestUtils.md5Hex(sign);
params.put("sign", md5Hex);
params.put("billnumber", billnumber);
params.put("data", data);
post.setEntity(new StringEntity(params.toJSONString()));
//获取返回信息
HttpResponse response = client.execute(post);
HttpEntity resp = response.getEntity();
String result = EntityUtils.toString(resp,"UTF-8");
return result;
}
}
注意:当需要驳回和审批通过时,expenseStatus传对应的值即可
请求地址: /m4/fpzs/expense/invoice/status/update
请求方式: POST
请求格式: application/json
参数格式如下:
{
"userKey":"", //打开首页时获取的userKey(可以为空)
"timestamp": "", //签名的时间戳
"tin": "", //税号
"sign": "", // 签名规则:MD5(client_id + client_secret + timestamp)
"client_id": "",//发票云分配的授权ID
"expenseStatus":"", //报销单状态: 1,未报销(未用),30审批中(在用)、60审批通过(已用)、65已入账
"ticketParam":"" //过滤规则,默认不允许重复报销
"billnumber": "", //保存时的报销单号
"bxd_key": "", //保存时的报销单ID全球唯一id,如果没有这个字段,与billnumber一致即可
"eid":"nT4HWQn0R+6dR0nHjzp7vxO33n8=",//erp系统的用户id
"billTypeId":"",// 单据类型, 用于区分是哪种单据, 最长80位
"invoiceData":[{
"serialNo":"",//流水号
"canBeDeduction":"",//是否可抵扣,0不可 1 可以
"entryAmount":"",//入账税额
"outputReason":""//转出原因
}]
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
userKey | String | 32 | 后续接口需要使用的用户身份认证key |
eid | String | 80 | erp系统的用户id |
billTypeId | String | 80 | 单据类型 |
billnumber | String | N | 保存时的报销单号 |
bxd_key | String | 50 | 保存时的报销单ID |
client_id | String | 20 | 发票云分配的授权ID |
tin | String | 20 | 企业税号 |
timestamp | String | 13 | 签名的时间戳 |
sign | String | 32 | 签名规则:MD5(client_id + client_secret + timestamp) |
ticketParam | String | 4 | 过滤规则,格式如:1101 |
invoiceData | JSON数组 | N | 回写发票信息{"serialNo":"流水号","canBeDeduction":"是否可抵扣","entryAmount":"入账税额","outputReason":"转出原因"} |
expenseStatus | int | 2 | 报销单状态 :1,未报销(未用),30审批中(在用)、60审批通过(已用)、65已入账 |
返回值如下:
操作成功:
{
"errcode":"0000",
"description":"成功",
"data":null
}
操作失败:
{
"errcode":"0000",
"description":"错误描述",
"data":null
}
请求示例:
package com.kingdee.apitest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class InvoiceStatusDemo {
//测试环境: https://www.piaozone.com/test
//正式环境: https://www.piaozone.com
private static final String HOST = "www.piaozone.com/test";
private static final String API_PATH = "/m4/fpzs/expense/invoice/status/update";
private static final String CONTENT_TYPE = "application/json";
public static void main(String[] args) throws Exception {
String userKey = "";
String secret = "";
String client_id = "";
String eid = "";
String bxd_key = "";
String billTypeId = "";
String billnumber = "";
String ticketParam = "";
String tin = "";
String expenseStatus = "1";
String result = updateInvoiceStatus(userKey, client_id, secret, tin, eid, bxd_key, billTypeId, billnumber, ticketParam, expenseStatus);
System.out.println(result);
}
/**
* 修改发票状态
* @param userKey 通过getUserKey获取的参数
* @param client_id 发票云分配的应用client_id
* @param secret 发票云分配的应用secret
* @param tin 企业税号
* @param eid erp系统的用户ID
* @param bxd_key 单据号, 全球唯一算法生成的ID 如果没有这个字段,与billnumber一致即可
* @param billTypeId 单据类型
* @param billnumber 报销单号
* @param ticketParam 过滤规则,格式如:1101
* @param expenseStatus 报销单状态:1-未报销,30-已提交(报销中),60-已报销
* @return
* @throws URISyntaxException
* @throws IOException
*/
public static String updateInvoiceStatus(String userKey, String client_id, String secret, String tin, String eid, String bxd_key, String billTypeId, String billnumber, String ticketParam, String expenseStatus) throws URISyntaxException, IOException {
HttpClient client = HttpClients.createDefault();
URIBuilder builder = new URIBuilder();
// 创建Post请求
URI uri = builder.setScheme("http")
.setHost(HOST)
.setPath(API_PATH)
.build();
HttpPost post = new HttpPost(uri);
//设置请求头
post.setHeader("Content-Type", CONTENT_TYPE);
//组装参数
JSONObject params = new JSONObject();
long currentTimeMillis = System.currentTimeMillis();
params.put("timestamp", currentTimeMillis);
params.put("client_id", client_id);
params.put("eid", eid);
params.put("bxd_key", bxd_key);
params.put("userKey", userKey);
params.put("tin", tin);
String sign = client_id + secret + currentTimeMillis;
String md5Hex = DigestUtils.md5Hex(sign);
params.put("sign", md5Hex);
params.put("billTypeId", billTypeId);
params.put("billnumber", billnumber);
params.put("ticketParam", ticketParam);
params.put("expenseStatus", expenseStatus);
post.setEntity(new StringEntity(params.toJSONString()));
//获取返回信息
HttpResponse response = client.execute(post);
HttpEntity resp = response.getEntity();
String result = EntityUtils.toString(resp,"UTF-8");
return result;
}
}
请求地址: /m4/fpzs/expense/invoice/del/entry
请求方式: POST
请求格式: application/json
参数格式如下:
{
"userKey":"", //打开选择发票时获取的userKey(可以为空)
"timestamp": "", //签名的时间戳
"sign": "", //签名规则:MD5(client_id + client_secret + timestamp)
"client_id": "",//发票云分配的授权ID
"billnumber": "", //保存时的报销单号
"bxd_key": "", //保存时的报销单ID全球唯一id,如果没有这个字段,与billnumber一致即可
"tin": "", //税号
"branch_id": "", //单据的分录id
"ticketParam":"", //过滤规则,默认不允许重复报销
"eid":"nT4HWQn0R+6dR0nHjzp7vxO33n8=", //erp系统的用户id
"billTypeId":"",// 单据类型,用于区分是哪种单据, 最长80位
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
userKey | String | 32 | 后续接口需要使用的用户身份认证key |
eid | String | 80 | erp系统的用户id |
billTypeId | String | 80 | 单据类型 |
billnumber | String | N | 保存时的报销单号 |
bxd_key | String | 50 | 保存时的报销单ID |
client_id | String | 20 | 发票云分配的授权ID |
tin | String | 20 | 企业税号 |
timestamp | String | 13 | 签名的时间戳 |
sign | String | 32 | 签名规则:MD5(client_id + client_secret + timestamp) |
entryid | String | N | 单据的分录id |
ticketParam | String | 4 | 过滤规则,格式如:1101 |
返回值如下:
操作成功:
{
"errcode":"0000",
"description":"成功",
"data":null
}
操作失败:
{
"errcode":"0000",
"description":"错误描述",
"data":null
}
请求示例:
package com.kingdee.apitest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
public class InvoiceDelEntryDemo {
//测试环境: https://www.piaozone.com/test
//正式环境: https://www.piaozone.com
private static final String HOST = "www.piaozone.com/test";
private static final String API_PATH = "/m4/fpzs/expense/invoice/del/entry";
private static final String CONTENT_TYPE = "application/json";
public static void main(String[] args) throws Exception {
String userKey = "";
String client_id = "";
String secret = "";
String eid = "";
String bxd_key = "";
String billTypeId = "";
String billnumber = "";
String tin = "";
String branch_id = "";
String result = delInvoiceEntry(userKey, client_id, secret, tin, eid, bxd_key, billTypeId, billnumber, branch_id);
System.out.println(result);
}
/**
* 删除发票分录
* @param userKey getUserKey接口获取的参数
* @param client_id 发票云分配的应用client_id
* @param secret 发票云分配的应用secret
* @param tin 企业税号
* @param eid erp系统的用户ID
* @param bxd_key 单据号, 全球唯一算法生成的ID 如果没有这个字段,与billnumber一致即可
* @param billTypeId 单据类型
* @param billnumber 报销单号
* @param branch_id 分录id
* @return
*/
public static String delInvoiceEntry(String userKey, String client_id, String secret, String tin, String eid, String bxd_key, String billTypeId, String billnumber, String branch_id) throws IOException, URISyntaxException {
HttpClient client = HttpClients.createDefault();
URIBuilder builder = new URIBuilder();
// 创建Post请求
URI uri = builder.setScheme("http")
.setHost(HOST)
.setPath(API_PATH)
.build();
HttpPost post = new HttpPost(uri);
//设置请求头
post.setHeader("Content-Type", CONTENT_TYPE);
//组装参数
JSONObject params = new JSONObject();
long currentTimeMillis = System.currentTimeMillis();
params.put("timestamp", currentTimeMillis);
params.put("client_id", client_id);
params.put("eid", eid);
params.put("bxd_key", bxd_key);
params.put("userKey", userKey);
params.put("billTypeId", billTypeId);
params.put("tin", tin);
String sign = client_id + secret + currentTimeMillis;
String md5Hex = DigestUtils.md5Hex(sign);
params.put("sign", md5Hex);
params.put("billnumber", billnumber);
params.put("branch_id", branch_id);
post.setEntity(new StringEntity(params.toJSONString()));
//获取返回信息
HttpResponse response = client.execute(post);
HttpEntity resp = response.getEntity();
String result = EntityUtils.toString(resp,"UTF-8");
return result;
}
}
请求地址: /m4/fpzs/expense/invoice/del
请求方式: POST
请求格式: application/json
参数格式如下:
{
"userKey":"", //选择发票时获取的userKey(可以为空)
"timestamp": "", //签名的时间戳
"sign": "", //签名规则:MD5(client_id + client_secret + timestamp)
"client_id": "", //发票云分配的授权ID
"billnumber": "", //保存时的报销单号
"bxd_key": "", //保存时的报销单ID全球唯一id,如果没有这个字段,与billnumber一致即可
"tin": "", //税号
"ticketParam":"" //过滤规则,默认不允许重复报销
"eid":"", //erp系统的用户id
"billTypeId":"",// 单据类型, 用于区分是哪种单据, 最长80位
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
userKey | String | 32 | 后续接口需要使用的用户身份认证key |
eid | String | 80 | erp系统的用户id |
billTypeId | String | 80 | 单据类型 |
billnumber | String | N | 保存时的报销单号 |
bxd_key | String | 50 | 保存时的报销单ID |
client_id | String | 20 | 发票云分配的授权ID |
tin | String | 20 | 企业税号 |
timestamp | String | 13 | 签名的时间戳 |
sign | String | 32 | 签名规则:MD5(client_id + client_secret + timestamp) |
fid | String | 33 | 流水号 |
返回值如下:
操作成功:
{
"errcode":"0000",
"description":"成功",
"data":null
}
操作失败:
{
"errcode":"0000",
"description":"错误描述",
"data":null
}
注意整个页面只需要创建一个socket对象进行通信,通过消息类型进行区分,建立规则和选择发票一致
具体参考选择发票获取userKey[5.2]
请求路径: /m4-web/fpzs/invoice/update?userKey=&serialNo=&linkKey=
请求方式: GET
请求参数:
参数 | 类型 | 说明 |
---|---|---|
userKey | string | 通过getUserKey接口获取的参数 |
serialNo | string | 发票流水号 |
linkKey | string | 注意如果创建socket连接时使用了linkKey,这里也需要linkKey参数,值为创建连接时的linkKey,否则不需要linkKey |
数据格式如下,msg类型为updateInvoice
{
"type": "updateInvoice",
"data": {
"data": {
"goodsCode": "1010115010000000000", //商品编码
"checkStatus": 1, //1查验通过,2查验不通过
"expenseStatus": 1, //使用状态,1为未使用,30为使用中,60为已使用
"serialNo": 1125866, //发票流水号, 注意如果发票的关键字段发生变化,发票流水号号将会变化,更新时以这里的流水号为准
"invoiceType": "1", //发票种类,1.普通电子发票2.电子发票专票3.普通纸质发票4.专用纸质发票5.普通纸质卷票7.通用机打8.的士票9.火车票10.飞机票11.其他 12.机动车 13.二手车14.定额发票15.通行费16.客运票17.过路过桥发票19.完税证明20.轮船票23通用机打电子发票
"invoiceCode": "044031600113", //发票代码
"invoiceNo": "30819002", //发票号码
"amount": 383.76, //合计不含税金额
"totalAmount": 449, //价税合计
"taxAmount": 66.24, //开票合计税额
"sallerName": "新华书店总店", //销货方名称
"sallerTaxNo": "440301999999980" //销货方纳税人识别号
},
"billnumber": "2018-11-28-00001898", //单据编号
"bxd_key": "Ik2TrOC5RSCOND0pE9J8=", //单据全球唯一key
"userid": "eid-1544414642579" //对应用户的eid
}
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
type | String | N | saveBill/saveEntrys/updateInvoice |
goodsCode | String | 20 | 商品编码 |
checkStatus | Number | 1 | 查验状态 1查验通过,2查验不通过 |
expenseStatus | Number | 1 | 使用状态,1为未使用,30为使用中,60为已使用 |
serialNo | String | 33 | 流水号 |
invoiceType | String | 1 | 发票种类,1.普通电子发票2.电子发票专票3.普通纸质发票4.专用纸质发票5.普通纸质卷票7.通用机打8.的士票9.火车票10.飞机票11.其他 12.机动车 13.二手车14.定额发票15.通行费16.客运票17.过路过桥发票19.完税证明20.轮船票23通用机打电子发票 |
invoiceCode | String | 12 | 发票代码 |
invoiceNo | String | 8 | 发票号码 |
totalAmount | String | 23 | 价税合计金额 |
taxAmount | String | 13 | 税额 |
sallerName | String | 80 | 销货方名称 |
sallerTaxNo | String | 20 | 销货方纳税人识别号 |
billTypeId | String | 80 | 单据类型 |
billnumber | String | N | 保存时的报销单号 |
userid | String | 80 | erp系统的用户id |
注意:接收到更新的发票数据后,如果需要更新该发票的完整信息,需要通过获取发票详情接口[16]获取
请求地址: /m4/fpzs/expense/invoice/detail/query
请求方式: POST
请求格式: application/json
{
"userKey":"", //打开首页时获取的userKey(可以为空)
"timestamp": "", //签名的时间戳
"sign": "", // 签名规则:MD5(client_id + client_secret + timestamp)
"client_id": "",//发票云分配的授权ID
"fid": "" //逗号分隔的发票流水号
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
userKey | String | 32 | 后续接口需要使用的用户身份认证key |
timestamp | String | 13 | 签名的时间戳 |
sign | String | 32 | 签名规则:MD5(client_id + client_secret + timestamp) |
client_id | String | 20 | 发票云分配的授权ID |
fid | String | 33 | 流水号 |
返回格式:
{
"data": [],
"description": "操作成功",
"errcode": "0000"
}
data详细数据格式请参考: 增值税发票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkCode": "校验码",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"downloadUrl": "发票文件下载地址",
"drawer": "开票人",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceCode": "发票代码",
"invoiceDate": "发票日期YYYY-MM-DD",
"invoiceMoney": "不含税金额",
"invoiceNo": "发票号码",
"invoiceStatus": "发票状态:0正常;1失控;2作废;3红冲;4异常",
"invoiceType": "发票种类,1.普通电子发票2.电子发票专票3.普通纸质发票4.专用纸质发票5.普通纸质卷票12.机动车 13.二手车15.通行费",
"isRevise": "发票是否被修改:1未修改;2已修改",
"items": [
{
"detailAmount": "明细金额",
"discountType": "",
"goodsCode": "商品代码",
"goodsName": "商品名称",
"num": "数量",
"specModel": "规格",
"taxAmount": "税额",
"taxRate": "税率",
"unit": "单位",
"unitPrice": "单价"
}
],
"originalGraphUrl": "发票原图地址",
"payee": "付款人",
"pixel": "像素大小",
"proxyMark": "是否代开:空字符串表示非代开;1则表示代开",
"region": "单张发票区域",
"remark": "备注",
"reviewer": "复核人",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"taxAmount": "税额",
"totalAmount": "价税合计"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 yyyy:MM:dd HH:mm:ss |
buyerAccount | String | 150 | 购方银行账号 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerName | String | 80 | 购货方名称 |
buyerTaxNo | String | 20 | 购方税号 |
checkCode | String | 50 | 校验码 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 yyyy:MM:dd HH:mm:ss |
downloadUrl | String | 255 | pdf下载地址 |
drawer | String | 8 | 开票人 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceType | String | 1 | 发票种类,1.普通电子发票2.电子发票专票3.普通纸质发票4.专用纸质发票5.普通纸质卷票12.机动车 13.二手车15.通行费 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceMoney | String | 20 | 不含税金额 |
invoiceNo | String | 8 | 发票号码 |
invoiceStatus | String | 1 | 发票状态0:正常、1:失控、2:作废、3:红冲、4:异常 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
detailAmount | String | 16 | 明细金额 |
discountType | String | 1 | 折扣行 |
goodsCode | String | 20 | 商品编码 |
goodsName | String | 120 | 商品名称 |
num | String | 35 | 数量 |
specModel | String | 50 | 规格 |
taxAmount | String | 20 | 税额 |
taxRate | String | 10 | 税率 |
unit | String | 20 | 单位 |
unitPrice | String | 35 | 单价 |
originalGraphUrl | String | 255 | 发票原图地址 |
payee | String | 30 | 收款人 |
pixel | String | 30 | 像素大小 |
proxyMark | String | 1 | 是否代开:空字符串表示非代开;1则表示代开 |
region | String | 30 | 单张发票区域 |
remark | String | 200 | 备注 |
reviewer | String | 8 | 复核人 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
totalAmount | String | 23 | 价税合计金额 |
taxAmount | String | 13 | 税额 |
通用机打发票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"downloadUrl": "发票文件下载地址",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceCode": "发票代码",
"invoiceDate": "开票日期YYYY-MM-DD",
"invoiceNo": "发票号码",
"invoiceType": "发票类型:7通用机打23通用机打电子发票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"originalGraphUrl": "发票原图地址",
"pixel": "像素大小",
"region": "单张发票区域",
"remark": "备注",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"taxAmount": "税额",
"totalAmount": "合计总金额",
"trip": "行程"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 yyyy:MM:dd HH:mm:ss |
buyerAccount | String | 150 | 购方银行账号 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerName | String | 80 | 购货方名称 |
buyerTaxNo | String | 20 | 购方税号 |
checkCode | String | 50 | 校验码 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 yyyy:MM:dd HH:mm:ss |
downloadUrl | String | 255 | pdf下载地址 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,7.通用机打23.通用机打电子发票 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
detailAmount | String | 16 | 明细金额 |
discountType | String | 1 | 折扣行 |
originalGraphUrl | String | 255 | 发票原图地址 |
pixel | String | 30 | 像素大小 |
proxyMark | String | 1 | 是否代开:空字符串表示非代开;1则表示代开 |
region | String | 30 | 单张发票区域 |
remark | String | 200 | 备注 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
totalAmount | String | 23 | 价税合计金额 |
taxAmount | String | 13 | 税额 |
trip | String | 30 | 行程 |
出租车票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"downloadUrl": "发票文件下载地址",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceCode": "发票代码 ",
"invoiceDate": "开票日期YYYY-MM-DD",
"invoiceNo": "发票号码",
"invoiceType": "发票类型:8出租车票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"licenseNumber": "车牌号",
"mileage": "里程",
"originalGraphUrl": "发票原图地址",
"pixel": "像素大小",
"place": "乘车地地名",
"price": "单价",
"region": "单张发票区域",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"taxAmount": "税额",
"timeGetOff": "下车时间",
"timeGetOn": "上车时间",
"totalAmount": "合计总金额",
"trip": "无行程"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 |
buyerAccount | String | 150 | 购方银行账号 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerName | String | 80 | 购货方名称 |
buyerTaxNo | String | 20 | 购方税号 |
checkCode | String | 50 | 校验码 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkTime | String | 19 | 认证时间 |
downloadUrl | String | 255 | pdf下载地址 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,8.的士票 |
火车票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"downloadUrl": "发票文件下载地址",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceCode": "乘车日期8位YYYYMMDD",
"invoiceDate": "开票日期YYYY-MM-DD",
"invoiceNo": "印刷序列号",
"invoiceType": "发票类型:9火车票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"originalGraphUrl": "发票原图地址",
"passengerName": "乘客姓名",
"pixel": "像素大小",
"printingSequenceNo": "印刷序列号",
"region": "单张发票区域",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"seatGrade": "座位等级",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"stationGetOff": "终点",
"stationGetOn": "起点",
"taxAmount": "税额",
"taxRate": "税率",
"totalAmount": "合计总金额",
"trainNum": "车次",
"trainTime": "乘车时间 时分秒",
"trip": "无行程"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 |
buyerAccount | String | 150 | 购方银行账号 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerName | String | 80 | 购货方名称 |
buyerTaxNo | String | 20 | 购方税号 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 |
downloadUrl | String | 255 | pdf下载地址 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,9.火车票 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
originalGraphUrl | String | 255 | 发票原图地址 |
passengerName | String | 20 | 乘客姓名 |
pixel | String | 30 | 像素大小 |
printingSequenceNo | String | 32 | 印刷序列号 |
region | String | 30 | 单张发票区域 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
seatGrade | String | 10 | 座位等级 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
stationGetOff | String | 32 | 终点 |
stationGetOn | String | 32 | 起点 |
taxAmount | String | 13 | 税额 |
taxRate | String | 10 | 税率 |
totalAmount | String | 23 | 价税合计金额 |
trainNum | String | 10 | 车次 |
trainTime | String | 10 | 乘车时间 |
trip | String | 10 | 无行程 |
飞机票返回格式:
{
"airTime": "乘机时间",
"airportConstructionFee": "机场建设费/民航发展基金",
"amount": "票价",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"customerIdentityNum": "身份证号码",
"destination": "终点",
"downloadUrl": "发票文件下载地址",
"electronicTicketNum": "电子行程单号",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"fillingUnit": "填开单位",
"flightNum": "航班号",
"fuelSurcharge": "燃油附加费",
"insurancePremium": "保险费",
"invoiceCode": "乘机日期8位YYYYMMDD",
"invoiceDate": "开票日期YYYY-MM-DD",
"invoiceNo": "电子客票号",
"invoiceType": "发票类型:10飞机票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"originalGraphUrl": "发票原图地址",
"otherTotalTaxAmount": "其他税费",
"passengerName": "顾客姓名",
"pixel": "像素大小",
"placeOfDeparture": "起点",
"region": "单张发票区域",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"salesUnitCode": "销售单位代码",
"seatGrade": "舱位等级",
"seatGradeName": "舱位等级名称",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"taxAmount": "税额",
"taxRate": "税率",
"totalAmount": "合计总金额",
"trip": "起点-终点"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
airTime | String | 10 | 乘机时间 |
airportConstructionFee | String | 10 | 机场建设费/民航发展基金 |
amount | String | 23 | 票价 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 |
buyerAccount | String | 150 | 购方银行账号 |
buyerName | String | 80 | 购货方名称 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerTaxNo | String | 20 | 购方税号 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 |
customerIdentityNum | String | 32 | 身份证号码 |
destination | String | 32 | 终点 |
downloadUrl | String | 255 | pdf下载地址 |
electronicTicketNum | String | 32 | 电子行程单号 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
fillingUnit | String | 100 | 填开单位 |
flightNum | String | 32 | 航班号 |
fuelSurcharge | String | 32 | 燃油附加费 |
insurancePremium | String | 32 | 保险费 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,10.飞机票 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
originalGraphUrl | String | 255 | 发票原图地址 |
otherTotalTaxAmount | String | 32 | 其他税费 |
passengerName | String | 20 | 乘客姓名 |
pixel | String | 30 | 像素大小 |
placeOfDeparture | String | 30 | 起点 |
region | String | 30 | 单张发票区域 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
salesUnitCode | String | 20 | 销售单位代码 |
seatGrade | String | 10 | 座位等级 |
seatGradeName | String | 32 | 舱位等级名称 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
taxAmount | String | 13 | 税额 |
taxRate | String | 10 | 税率 |
totalAmount | String | 23 | 价税合计金额 |
trip | String | 10 | 起点-终点 |
定额发票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"consumptionType": "发票消费类型:定额发票进一步确定消费类型:长途suburb;市内city;住宿hotel;其他other;餐饮dining;话费telephoneCharge",
"downloadUrl": "发票文件下载地址",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceCode": "发票代码 ",
"invoiceDate": "入库日期YYYY-MM-DD",
"invoiceNo": "发票号码",
"invoiceType": "发票类型:14定额发票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"originalGraphUrl": "发票原图地址",
"pixel": "像素大小",
"place": "发票所在地",
"region": "单张发票区域",
"remark": "备注",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"taxAmount": "税额",
"totalAmount": "合计总金额",
"trip": "无行程"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 |
buyerAccount | String | 150 | 购方银行账号 |
buyerName | String | 80 | 购货方名称 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerTaxNo | String | 20 | 购方税号 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 |
consumptionType | String | 32 | 发票消费类型:定额发票进一步确定消费类型:长途suburb;市内city;住宿hotel;其他other;餐饮dining;话费telephoneCharge |
downloadUrl | String | 255 | pdf下载地址 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,14.定额发票 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
originalGraphUrl | String | 255 | 发票原图地址 |
otherTotalTaxAmount | String | 32 | 其他税费 |
passengerName | String | 20 | 乘客姓名 |
pixel | String | 30 | 像素大小 |
place | String | 30 | 发票所在地 |
region | String | 30 | 单张发票区域 |
remark | String | 30 | 备注 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
taxAmount | String | 13 | 税额 |
taxRate | String | 10 | 税率 |
totalAmount | String | 23 | 价税合计金额 |
trip | String | 10 | 无行程 |
客运票/轮船票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"currencyType": "币种",
"downloadUrl": "发票文件下载地址",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceCode": "发票代码",
"invoiceDate": "开票日期YYYY-MM-DD",
"invoiceNo": "发票号码",
"invoiceType": "发票类型:16客运票;20轮船票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"originalGraphUrl": "发票原图地址",
"passengerName": "乘客姓名",
"pixel": "像素大小",
"region": "单张发票区域",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"stationGetOff": "终点",
"stationGetOn": "起点",
"taxAmount": "税额",
"taxRate": "税率 默认值是0",
"time": "时间 时分秒",
"totalAmount": "合计总金额",
"trip": "起点-终点"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 |
buyerAccount | String | 150 | 购方银行账号 |
buyerName | String | 80 | 购货方名称 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerTaxNo | String | 20 | 购方税号 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 |
currencyType | String | 32 | 币种 |
downloadUrl | String | 255 | pdf下载地址 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,16.客运票20.轮船票 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
originalGraphUrl | String | 255 | 发票原图地址 |
passengerName | String | 20 | 乘客姓名 |
pixel | String | 30 | 像素大小 |
region | String | 30 | 单张发票区域 |
remark | String | 30 | 备注 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
stationGetOff | String | 32 | 终点 |
stationGetOn | String | 32 | 起点 |
taxAmount | String | 13 | 税额 |
taxRate | String | 10 | 税率 |
time | String | 10 | 时间 时分秒 |
totalAmount | String | 23 | 价税合计金额 |
trip | String | 32 | 起点-终点 |
过路过桥票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"downloadUrl": "发票文件下载地址",
"entrance": "入口",
"exit": "出口",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceCode": "发票代码",
"invoiceDate": "开票日期YYYY-MM-DD",
"invoiceNo": "发票号码",
"invoiceType": "发票类型:17过路过桥票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"originalGraphUrl": "发票原图地址",
"pixel": "像素大小",
"place": "发票所在地",
"region": "单张发票区域",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"taxAmount": "税额",
"time": "过路过桥发票时间 格式:时分秒",
"totalAmount": "合计总金额",
"trip": "无行程"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 |
buyerAccount | String | 150 | 购方银行账号 |
buyerName | String | 80 | 购货方名称 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerTaxNo | String | 20 | 购方税号 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 |
downloadUrl | String | 255 | pdf下载地址 |
entrance | String | 32 | 入口 |
exit | String | 32 | 出口 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,17.过路过桥发票 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
originalGraphUrl | String | 255 | 发票原图地址 |
pixel | String | 30 | 像素大小 |
place | String | 30 | 发票所在地 |
region | String | 30 | 单张发票区域 |
remark | String | 30 | 备注 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
taxAmount | String | 13 | 税额 |
taxRate | String | 10 | 税率 |
time | String | 10 | 过路过桥发票时间 格式:时分秒 |
totalAmount | String | 23 | 价税合计金额 |
trip | String | 32 | 起点-终点 |
完税证明发票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"downloadUrl": "发票文件下载地址",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceDate": "开票日期YYYY-MM-DD",
"invoiceType": "发票类型:19完税证明发票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"originalGraphUrl": "发票原图地址",
"pixel": "像素大小",
"region": "单张发票区域",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"taxAmount": "税额",
"taxAuthorityName": "税务机关",
"taxPaidProofNo": "完税证明号码(发票号码)",
"totalAmount": "合计总金额",
"trip": "无行程"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 |
buyerAccount | String | 150 | 购方银行账号 |
buyerName | String | 80 | 购货方名称 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerTaxNo | String | 20 | 购方税号 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 |
downloadUrl | String | 255 | pdf下载地址 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,19.完税证明 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
originalGraphUrl | String | 255 | 发票原图地址 |
pixel | String | 30 | 像素大小 |
region | String | 30 | 单张发票区域 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
taxAmount | String | 13 | 税额 |
taxAuthorityName | String | 32 | 税务机关 |
taxPaidProofNo | String | 32 | 完税证明号码(发票号码) |
totalAmount | String | 23 | 价税合计金额 |
trip | String | 32 | 无行程 |
其他发票返回格式:
{
"amount": "不含税金额",
"authenticateFlag": "认证标志:1未任何认证及勾选;2勾选认证;3扫描认证",
"authenticateTime": "认证时间",
"buyerAccount": "购方银行账号",
"buyerAddressPhone": "购方地址手机",
"buyerName": "购方名称",
"buyerTaxNo": "购方税号",
"checkFlag": "勾选标志:1未勾选;2已勾选",
"checkStatus": "查验状态:1通过;2不通过;3未查验",
"checkTime": "勾选时间",
"downloadUrl": "发票文件下载地址",
"expenseStatus": "报销状态:1未用;30在用;60已用",
"invoiceCode": "发票代码",
"invoiceDate": "入库日期YYYY-MM-DD",
"invoiceNo": "发票号码",
"invoiceType": "发票类型:11其他发票",
"isRevise": "发票是否被修改:1未修改;2已修改",
"originalGraphUrl": "发票原图地址",
"pixel": "像素大小",
"region": "单张发票区域",
"remark": "备注",
"rotationAngle": "发票原图旋转角度",
"salerAccount": "销方银行账号",
"salerAddressPhone": "销方地址电话",
"salerName": "销方名称",
"salerTaxNo": "销方税号",
"serialNo": "发票流水号",
"snapshotUrl": "发票快照地址",
"taxAmount": "税额",
"totalAmount": "合计总金额",
"trip": "无行程"
}
参数值 | 类型 | 长度 | 备注 |
---|---|---|---|
amount | String | 23 | 不含税金额 |
authenticateFlag | String | 1 | 认证标志:1未任何认证及勾选;2勾选认证;3扫描认证 |
authenticateTime | String | 19 | 认证时间 |
buyerAccount | String | 150 | 购方银行账号 |
buyerName | String | 80 | 购货方名称 |
buyerAddressPhone | String | 100 | 购方地址手机 |
buyerTaxNo | String | 20 | 购方税号 |
checkFlag | String | 1 | 勾选标志:1未勾选;2已勾选 |
checkStatus | String | 1 | 查验状态1:通过,2,不通过,3:未查验 |
checkTime | String | 19 | 认证时间 |
downloadUrl | String | 255 | pdf下载地址 |
expenseStatus | String | 1 | 单据状态 :1,未报销,2.已打包 25.已提交、30审批中、60审批通过、65等待付款/70已付款、27已废弃、40审核不通过、80已关闭 |
invoiceCode | String | 12 | 发票代码 |
invoiceDate | String | 10 | 开票日期,"YYYY-MM-DD" |
invoiceNo | String | 8 | 发票号码 |
invoiceType | String | 1 | 发票种类,11.其他 |
isRevise | String | 1 | 发票是否被修改:1未修改;2已修改 |
originalGraphUrl | String | 255 | 发票原图地址 |
pixel | String | 30 | 像素大小 |
region | String | 30 | 单张发票区域 |
remark | String | 30 | 备注 |
rotationAngle | String | 30 | 发票原图旋转角度 |
salerAccount | String | 150 | 销方银行账号 |
salerAddressPhone | String | 100 | 销方地址电话 |
salerName | String | 80 | 销货方名称 |
salerTaxNo | String | 20 | 销货方识别号 |
serialNo | String | 33 | 发票流水号 |
snapshotUrl | String | 255 | 发票快照地址 |
taxAmount | String | 13 | 税额 |
totalAmount | String | 23 | 价税合计金额 |
trip | String | 32 | 无行程 |
请求地址: /m4/fpzs/expense/invoices/query
请求方式: POST
请求格式: application/json
{
"userKey":"", // userKey不能为空
"billNumber": "" // 单据号, 不能为空
}
返回格式:
详细数据格式请参考:进项发票数据格式
{
"errcode": "0000",
"description": "操作成功",
"data": []
}
请求地址: /m4/bill/expense/additionalInformation/collect
请求方式: POST
请求格式: application/json
{
"accountInfo": {
"accountId": "账套ID(唯一)",
"system": "核算体系",
"type": "账套类型",
"subject": "科目表",
"baseCurrency": "本位币",
"exchangeRate": "汇率表"
},
"voucherInfo": {
"vouchId": "凭证ID", //必填
"vouchNo": "凭证号", //必填
"businessDate": "业务日期yyyy_MM_dd", //必填
"accountDate": "记账日期yyyy_MM_dd", //必填
"period": "所属账期yyyyMM", //必填
"voucherAccountId": "凭证所属账套ID(唯一)",
"voucherCompanyId": "凭证所属企业ID(唯一)",
"type": "凭证类型",
"resource": "凭证来源:1发票云、2EAS、3Cloud、4苍穹、5星空",
"supInformation": "补充资料",
"supInformationAmount": "补充资料金额",
"creator": "制单人",
"examiner": "审核人",
"reviewer": "复核人",
"attachmentsCount": "附件数",
"item": "主表项目",
"accountItem": "主表核算项目",
"accountItemAmount": "主表项目金额",
"entries": [
{
"unit": "计量单位",
"amount": "原币金额",
"exchangeRate": "汇率",
"subject": "科目",
"price": "单价",
"accountDimension": "核算维度",
"dueDate": "到期日yyyy_MM_dd",
"num": "数量",
"currency": "币别",
"abstract": "摘要",
"creditAmount": "贷方合计",
"debitsAmount": "借方合计"
}
]
},
"companyInfo": {
"companyId": "企业ID(唯一)",
"number": "企业编码",
"name": "企业名称"
},
"expenseIdArray": [
"报销单ID1",
"报销单ID2",
"报销单ID3"
],
"serialNoArray": [
"发票流水号1",
"发票流水号2",
"发票流水号3"
],
"invoiceData": [
{
"serialNo": "发票流水号",
"deductionFlag": ,//是否能抵扣,0不可,1可以
"deductionTaxAmount": "",//入账税额
"remark": ""//转出原因
}
]
}
返回格式:
{
"errcode": "0000",
"description": "操作成功",
}
请求地址: /m4/bill/expense/voucher/del
请求方式: POST
请求格式: application/json
{
"vouchNo":"凭证号",//必填
"vouchId":"凭证ID"//必填
}
返回格式:
{
"errcode": "0000",
"description": "操作成功",
}