发票助手PC web端对接文档

# 变更历史
日期 变更描述 变更人 版本 批注
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": "" //请求的返回实际数据
    }

时序图

选择发票时序图

image

发票状态更新时序图

image

js建立连接通道

注意:进入新增或者更新单据界面时,需要建立连接

引入连接库文件

使用库文件地址,建议在线引入


    <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>

创建票无忧socket对象


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();
});

msg的消息格式

消息格式: {"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":"" //发票流水号
        }]
    }
}

java建立连接

注意:当不是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获取数据

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]

获取linkKey

获取路径: /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

获取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

请求格式: https://www.piaozone.com/m4-web/fpzs/index?userKey=d26f60552a440d11a474a6bdcb9e6f98&linkKey=jfyukhhj63n363n3&gridParam=1111 |

编辑分录界面对接

注意打开界面前必须建立好连接通道,参考[4]

获取linkKey

具体参考上述getLinkKey接口

获取userKey

具体参考选择发票获取userKey[5.2] , 注意此时branch_id必须传

缓存单据与发票关系

具体参考缓存单据与发票关系[5.3]

打开编辑分录界面

界面打开路径: /m4-web/fpzs/expense/branch/update?userKey=&linkKey=

请求方式: GET

请求参数:

参数 类型 备注
userKey string 通过getUserKey接口获取到的获取的userKey
linkKey string 通过getLinkKey接口获取到的获取的linkKey

请求格式: https://www.piaozone.com/m4-web/fpzs/expense/branch/update?userKey=d26f60552a440d11a474a6bdcb9e6f98&linkKey=dh7dddd7a8d6f

保存调整后的分录信息

注意:分录调整后,发票云会把当前分录的发票信息通过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

具体参考选择发票获取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

具体参考选择发票获取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

具体参考选择发票获取userKey[5.2]

打开查看单张发票界面

界面打开路径: /m4-web/fpzs/expense/showInvoice?userKey=

请求方式: GET

请求参数: 获取的userKey, 发票流水号serialNo

请求格式: https://api.piaozone.com/m4-web/fpzs/expense/showInvoice?userKey=d26f60552a440d11a474a6bdcb9e6f98&serialNo=78feeff88675676hgngff

保存单据

请求地址: /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;
    }
}

提交单据对接

先调用保存单据,参考[11]

调用更新发票状态接口

注意:当需要驳回和审批通过时,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连接

注意整个页面只需要创建一个socket对象进行通信,通过消息类型进行区分,建立规则和选择发票一致

获取userKey

具体参考选择发票获取userKey[5.2]

打开修改发票界面

请求路径: /m4-web/fpzs/invoice/update?userKey=&serialNo=&linkKey=

请求方式: GET

请求参数:

参数 类型 说明
userKey string 通过getUserKey接口获取的参数
serialNo string 发票流水号
linkKey string 注意如果创建socket连接时使用了linkKey,这里也需要linkKey参数,值为创建连接时的linkKey,否则不需要linkKey

数据更新将会通过socket传递

数据格式如下,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": "操作成功",
}