发票助手移动端-小程序对接
第三方APP调用小程序授权准备
1、进入微信开放平台创建企业自己的移动应用:https://open.weixin.qq.com/
2、填写基本信息,平台信息需要填写android、ios具体信息
3、提交审核通过后,进入该应用进行小程序关联
4、进行微信认证
第三方APP集成拉取小程序SDk
具体打开方式参考微信官方网站**
发票云小程序参数说明:
参数名 | 类型 | 是否必须 | 备注 | 值 |
---|---|---|---|---|
userName | String | 是 | 小程序原始ID | 生产:gh_bfa83b5cd310 测试:gh_cb39a37583e3 |
path | String | 是 | 跳转小程序路径 | "pages/index/index?scene=${userKey}&source=app" userKey由下方接口获取 |
miniprogramType | int | 是 | 小程序模式 | 0 |
Android开发示例
开发前需到微信开发平台下载Android开发工具包(SDK),可在“资源中心-开发资源-资源下载-Android资源下载”按照指引操作。
调用接口:WXLaunchMiniProgram
移动应用跳转到小程序示例:
String appId = "wxd930ea5d5a258f4f"; //微信开发平台创建的应用AppId
IWXAPI api = WXAPIFactory.createWXAPI(context, appId);
WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req();
req.userName = ${userName};
req.path = ${path};
req.miniprogramType = ${miniprogramType};
api.sendReq(req);
回调说明
//WXEntryActivity中
public void onResp(BaseResp resp) {
if (resp.getType() == ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM) {
WXLaunchMiniProgram.Resp launchMiniProResp = (WXLaunchMiniProgram.Resp) resp;
String extraData =launchMiniProResp.extMsg; //对应小程序组件 <button open-type="launchApp"> 中的 app-parameter 属性
}
}
iOS开发示例
开发前需到微信开发平台下载iOS开发工具包(SDK),可在“资源中心-开发资源-资源下载-iOS资源下载”按照指引操作。
移动应用跳转到小程序示例:
WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
launchMiniProgramReq.userName = ${userName};
launchMiniProgramReq.path = ${path};
launchMiniProgramReq.miniProgramType = ${miniProgramType};
return [WXApi sendReq:launchMiniProgramReq];
回调说明
-(void)onResp:(BaseResp *)resp
{
if ([resp isKindOfClass:[WXLaunchMiniProgramResp class]])
{
NSString *string = resp.extMsg;
// 对应JsApi navigateBackApplication中的extraData字段数据
}
}
第三方APP内部是H5页面对接则需要向前端提供js桥方法进行对接,如文档下方“云之家案例”
对接约定
发票云API采用RESTfull的设计方式,客户端通过HTTP协议的GET、POST(目前主要是这两种)方法请求进行调用。
Restful:参考资料
http://www.infoq.com/cn/articles/designing-restful-http-apps-roth
API的调用地址基本上遵循如下约定的方式:
API地址前缀+ 服务 + 资源+ 参数
测试环境: baseUrl = https://api-dev.piaozone.com/test
正式环境: baseUrl = https://api.piaozone.com
对接过程中需要: 发票云授权标识(client_id)、授权密钥(client_secret)、加密密钥(encrypt_key)进行授权,每个环境的授权不同,获取方式可以找实施人员协助提供
接口返回约定: 若无特别说明,接口返回如下
{
"errcode": "0000", ///成功时为0000, 失败时为非0000
"description": "操作成功", //描述,失败时可以根据这个字段进行提示
"data": "" //请求的返回实际数据
}
调用小程序前,需要先获取userKey
获取userKey接口地址: baseUrl/m4/bill/wmp/get/user/key?access_token=${access_token}
请求方式: POST
请求content-type格式: application/json
请求的全部参数:
token的获取方式和其它接口一致
参数名 | 是否必须 | 备注 |
---|---|---|
bxd_key | 是 | 报销单ID,如果需要同步附件信息,则必传 |
timestamp | 是 | 用于签名验证 |
clientId | 是 | 发票云分配的应用clientId |
ghf_mc | 是 | 购货方名称(校验发票抬头是否一致时使用) |
tin | 是 | 企业税号 |
cid | 是 | 接入企业的用户ID |
sign | 是 | 签名, 签名规则见对接约定, clientSecret和clientId由发票云分配 |
encType | 否 | 签名加密类型 0:MD5、1:SHA256、2:HMAC SHA256,不传默认MD5加密 |
random | 是 | 随机码 |
ticketParam | 是 | 过滤规则,格式如:1101 |
salerName | 否 | 单据限制销方名称 |
salerTaxNo | 否 | 单据限制销方税号 |
billType | 否 | 单据类型 |
assembleByBillType | 否 | 是否按单据类型(billType)组装推送给APP的数据。 1:组装; 其他不组装 |
optMode | 否 | 非必须,操作模式 ,0正常(默认) 1仅附件上传 |
ticketParam 参数规则顺序: 0 不允许 1 允许
第1位:已报销过的发票是否允许导入
第2位:发票抬头与企业名称不一致的发票是否允许导入
第3位:发票抬头与税号不一致发票是否允许导入
第4位:发票查验不通过的发票是否允许导入
billType参数规则:
参数值 | 备注 |
---|---|
Tra | 智能差旅行程单 |
Pur | 智能物品采购报销单 |
BizOut | 智能对公报销单 |
"" | 费用报销单传空字符串 |
请求的返回值:
{
"errcode": "0000", ///成功时为0000, 失败时为非0000
"description": "操作成功", //描述,失败时可以根据这个字段进行提示
"data": {
"userKey": "" //获取到的userKey
}
}
导入发票跳转回App或小程序后,再次导发票请重新获取userkey避免失效
获取授权access_token
API地址前缀:基本不变的API访问URL地址,如下:
流程图:
接口请求说明:
http请求方式:POST
获取token接口地址: baseUrl/base/oauth/token
请求数据结构
{
"client_id":"vc0c6hjlgnKCic",
"sign":"8b9c78fccedbb72eff1106c57505b8f6",
"encType": 0,
"timestamp":1463468225650
}
**返回数据结构:**
{
"access_token":"7ffe2cced2a0e3615a24705ee39f53d09a243911c0e932991570ffa1d86abbf4",
"token_type":"bearer",
"expires_in":43200,
"errcode":"0000",
"description":"操作成功"
}
请求参数描述:
参数 | 类型 | 是否必须 | 描述 |
---|---|---|---|
client_id | string | 是 | 发票云授权标识 |
sign | String | 是 | 签名,签名规则见对接约定 |
encType | Int | 否 | 签名加密类型 0:MD5、1:SHA256、2:HMAC SHA256,不传默认MD5加密 |
timestamp | long | 是 | 时间戳 |
返回参数描述:
参数 | 类型 | 描述 |
---|---|---|
access_token | string | 字符串, 最长255,用于后续访问的令牌,随机字符串 |
token_type | String | 字符串,令牌类型,可以不用关注, 目前固定bearer |
expires_in | string | 长整型,令牌在多少秒内有效,单位为秒 |
errcode | String | 操作结果码 |
description | string | 操作描述 |
失败信息:
{
"error":"invalid_client",
"error_description":"Bad client credentials"
}
案例 云之家轻应用
接口调用代码(js需客户方自己提供....)
xuntongJSBridge.call(
'launchMiniprogram',{
'userName':'xxx',
'path':'yyyyy',
'miniprogramType': 'zzz',
....
},
function(result){
}
);
参数说明
参数 | 类型 | 描述 |
---|---|---|
userName | String | 小程序原始ID ("gh_bfa83b5cd310") 注意:每个环境对应的小程序不同,则原始ID要注意更换 |
path | String | "pages/index/index?scene=${userkey}&source=app";拉起小程序页面路径(app为固定值) |
miniprogramType | Int | 0 小程序的版本 |
回调说明
{
success : true or false 是否成功(String),
error:错误信息(String),
errorCode:错误码(int)//
data:{
extraData:’xxx' //小程序返回的发票、附件信息
}
}
常见的对接问题
提示二维码失效
注:出现上述图1,图2问题,解决流程如下。
1:先通过图3(我的--新手指导)检查当前环境是什么小程序。
2:检查客户配置(如下图: 苍穹费用报销)的发票云小程序id和小程序模式是否跟图3匹配。
参数说明
名称 | userName | miniprogramType | 对应环境 | 小程序版本名称 |
---|---|---|---|---|
金蝶发票云 | gh_bfa83b5cd310 | 0 | 生产 api.piaozone.com | pwy-release x.x.x |
票无忧100 | gh_cb39a37583e3 | 0 | 测试 api-dev.piaozome.com/test | pwy-test x.x.x |
注:
1: 云之家客户仅绑定了一个小程序,因此,切换环境调试时,只需要修改对应的 miniprogramType 值,userName 不变; 对接测试环境时跳转小程序后可能需要给用户添加访问权限
2: 其他App客户如果同时绑定 金蝶发票云 和 票无忧100 了,则只需要调整userName即可切换调试环境
小程序返回App并传递发票,附件数据
数据接收方式请参考上面android和ios示例中的回调部分
发票云返回的数据格式如下
消息格式: {"type":"selectedInvoices", data: {}}
type为saveBill时为导入时的发票数据
费用单据的数据格式:billType为空字符串
{
type: "selectedInvoices", //选择的发票信息
data: { //发票信息
invoicesAmount: 1000, //价税合计总额
invoicesTaxAmount: 200, //总税额
serialNos: "044031600113,044031600113", //发票流水号,逗号分隔
},
attachData: [{ //附件信息
"attachmentName": "附件984775", //附件名称
"gatherTime": "2019-01-30", //附件采集时间
"serialNo": "b115345688f64c519b047943bb2d11b38", //附件流水号
"snapshotUrl": "http://api.kingdee.com/kdrive/user/file/thumbnail?client_id=200242&file_id=54947544&quality=100&scode=WXZRZnl2dl9MMWZJVi9MSUhlXzcx&sign=1c2e361c97aa438f6ae9c409107d2e2f9472c44f&width=800", //附件快照地址
"remark": "- -" //附件备注
}]
}
//如果需要或发票的完整信息, 请通过接口(如下)传入发票流水号获取发票完整数据
智能差旅行程单的数据数据格式, billType为:Tra
{
"type": "selectedInvoices",
"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": "selectedInvoices",
"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": "selectedInvoices",
"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":"" //发票流水号
}]
}
}
以上操作为移动端界面通过小程序采集发票流程
报销单据与发票关系处理(重点)
请查看接口文档11.0: 发票助手PC web端对接
报销单据上查看关联发票(重点)
1.1 通过报销单ID查询
接口地址:baseUrl/m4/fpzs/bxdInvoices?bxd_key={报销单ID}&client_id={创建当前报销单的发票云授权标识}×tamp={时间戳}&sign={签名}
请求方式: GET
参数说明
参数 | 类型 | 描述 |
---|---|---|
bxd_key | String | 报销单ID |
client_id | String | 创建当前报销单的发票云授权标识 |
timestamp | String | 时间戳 |
sign | String | 签名规则见对接约定, clientSecret和clientId由发票云分配 |
encType | Int | 签名加密类型 0:MD5、1:SHA256、2:HMAC SHA256,不传默认MD5加密 |
请求接口参数示例
{
"client_id": "创建当前报销单的发票云授权标识",
"sign": "签名:见对接约定",
"encType": 0,
"timestamp": "时间戳",
"bxd_key": "weqasdaqweqweqe"
}
1.2 单据分录上通过事件代码查询
接口地址:baseUrl/m4/fpzs/expense/invoices/certifacate/query?event_code=${eventCode}
请求方式: GET
参数说明
参数 | 类型 | 描述 |
---|---|---|
envent_code | String | 事件代码(如下接口获取) |
1.2.1获取事件代码eventCode=f2adb2cb45a3ac1b129c581102a0d266
接口地址: baseUrl/base/oauth/eventCode
请求方式: POST
请求content-type格式: application/json
参数说明
参数 | 类型 | 描述 |
---|---|---|
client_id | String | 创建当前报销单的发票云授权标识 |
timestamp | String | 时间戳 |
sign | String | 签名规则见对接约定, clientSecret和clientId由发票云分配 |
encType | Int | 签名加密类型 0:MD5、1:SHA256、2:HMAC SHA256,不传默认MD5加密 |
type | String | EXPENSE_SERIALNO_QUERY //固定值 |
buyerName | String | 购方抬头 |
buyerTaxNo | String | 购方税号 |
ticketParam | String | 发票校验过滤规则,格式如:1101 |
certifacateSerialNos | Array | 附件流水号 |
invoiceSerialNos | Array | 发票流水号 |
expenseId | String | 报销单ID |
请求接口参数示例
{
"client_id": "创建当前报销单的发票云授权标识",
"data": {
"buyerName": "校验发票抬头企业名称不一致提示",
"buyerTaxNo": "校验发票抬头税号不一致提示",
"certifacateSerialNos": [
"附件流水号1",
"附件流水号1"
],
"invoiceSerialNos": [
"发票流水号1",
"发票流水号2"
],
"ticketParam": "发票校验过滤规则,格式如:1101",
"expenseId":"报销单ID"
},
"sign": "签名:见对接约定",
"encType": 0,
"timestamp": "时间戳",
"type": "EXPENSE_SERIALNO_QUERY"
}
小程序跳转小程序对接收票流程
客户小程序跳转
wx.navigateToMiniProgram({
appId: '${appId}',
path: 'pages/index/index?scene=${userKey}'+'&source=mini',
envVersion: 'release',
success(res) {
// 打开成功
}
})
参数说明
参数 | 类型 | 描述 |
---|---|---|
appId | String | 目标小程序应用ID(测试环境:wxb5de26c7f5dc89c6 ,生产环境:wxa3a3844ae7205f76 ) |
userKey | String | 由上诉接口获取 |
客户小程序接收
//app.js
onShow: function (options) {
if (options.referrerInfo){
const { extraData } = options.referrerInfo
const { miniData } = extraData; //数据说明如下
}
}
数据说明
{
"type":"selectedInvoices", //固定值
"data":{
"invoicesAmount":3540, //发票总金额
"invoicesTaxAmount":102.39, //发票总税额
"serialNos":"0e9db98b85aa4aec9d6d340be1e199db0,aa43d7084afe4ca690c371d7e5b5498e0," //发票流水号集合
},
"attachData":[ //附件流水号集合
"c395e1d0236c483b8fc3a4ae0f3dd52b1",
"590a6a40e3b740d597c0b044a819a6580"
]
}
通过流水号获取发票,附件详情
查看文档:发票助手PC web端对接