明道云对接案例之法大大电子签章

什么是电子签章

电子签章是电子签名的一种表现形式,利用图像处理技术将电子签名操作转化为与纸质文件盖章操作相同的可视效果,同时利用电子签名技术保障电子信息的真实性和完整性以及签名人的不可否认性。

电子合同是企业用途最广的一种合同形式,受《合同法》认可。但由于电子合同以数据电文为载体,涉及到一系列的技术标准,其中最核心、也最重要的是电子签名技术。根据国家法律规定,只有使用可靠电子签名签订的电子合同才具有法律效力。

明道云也十分重视电子签章的功能集成方案。技术顾问经过一段时间的产品调研、测试,以及为客户对接实践,终于形成了较为成熟的电子签章集成对接方案。那么今天,明道云的技术顾问就在这里介绍明道云与法大大的集成对接流程,并简单评价法大大集成的优缺点

对接流程

1.申请密钥

  • 官网联系客服
  • 操作开通申请
  • 在指定邮箱里收到密钥信息及API对接文档

2.注册账号、证书申请、印章上传

接口名称解释

  • 为用户注册法⼤大账号:account_register.api
  • 根据账号类型调用对应的接口
    • miget_person_verify_url.api 个⼈实名认证⻚面接
    • get_company_verify_url.api 企业实名认证⻚⾯接⼝
  • 申请实名证书:apply_cert.api

代码块示例

1.账号注册参数加密
var account_type = input.account_type=='个人'?'1':'2';
var v = input.v;
var app_secret = input.app_secret;
var app_id = input.app_id;
var crypto = require('crypto');
function pad2(n) { return n < 10 ? '0' + n : n }
function generateTimeReqestNumber() {
            var datee = new Date();
var localTime = datee .getTime();
var localOffset=datee .getTimezoneOffset()*60000; //获得当地时间偏移的毫秒数
var utc = localTime + localOffset; //utc即GMT时间
var offset =8; //以北京时间为例,东8区
var hawaii = utc + (3600000*offset); 
	var date = new Date(hawaii);
	date.setHours(date.getHours());
	return date.getFullYear().toString() + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds());
}
function sha1(s) {
	var hash = crypto.createHash('sha1');
	hash.update(s);
	return hash.digest('hex').toUpperCase();
}
function md5(s) {
	var hash = crypto.createHash('md5');
	hash.update(s);
	return hash.digest('hex').toUpperCase();
}
function base64(s) {
	var b = new Buffer.from(s);
	return b.toString('base64');
}
function ast(s) {
	return s.split('').sort().join('');
}


var timestamp = generateTimeReqestNumber();	
var msg_digest = base64( sha1( app_id + md5(timestamp) + sha1(app_secret + account_type + input.openid)));
return {ts: timestamp, sign: msg_digest, appid: app_id, v: v, openid: input.open_id, accounttype: account_type};


1.2 调用注册方法
var url=input.url+'/api/account_register.api';
const fetch = require('node-fetch'); 
const FormData= require('form-data');
var result={};
let data= new FormData();
data.append("app_id",input.appid)
data.append("v",input.v)
data.append("timestamp",input.ts)
data.append("msg_digest",input.sign)
data.append("open_id",input.openid)
data.append("account_type",input.accounttype)
async function getAll(data){
    const res = await   fetch(url,{
    method:"post",
    body:data
}).then(function(response){
    if(response.ok){
 return  response.json();   
    }else{
  return   {"error":"无数据"};
}
}).catch(function(err){
   return   {"error":"Fetch错误:"+err};
});
    const result = await   res;
    return result;
}
result=await  getAll(data);
output={result:result}


2申请实名认证参数加密
var v = input.v;
var app_secret = input.appsecret;
var aid = input.aid;
var crypto = require('crypto');
var data={"customer_id":input.customerid,
"verified_way":3,
"page_modify":1,
"option":"add",
"lang":"zh",
"organization_type":0,
"notify_url":"换为你的接受地址"}


function pad2(n) { return n < 10 ? '0' + n : n }
function generateTimeReqestNumber() {
            var datee = new Date();
var localTime = datee .getTime();
var localOffset=datee .getTimezoneOffset()*60000; //获得当地时间偏移的毫秒数
var utc = localTime + localOffset; //utc即GMT时间
var offset =8; //以北京时间为例,东8区
var hawaii = utc + (3600000*offset); 
	var date = new Date(hawaii);
	date.setHours(date.getHours());
	return date.getFullYear().toString() + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds());
}
function sha1(s) {
	var hash = crypto.createHash('sha1');
	hash.update(s);
	return hash.digest('hex').toUpperCase();
}
function md5(s) {
	var hash = crypto.createHash('md5');
	hash.update(s);
	return hash.digest('hex').toUpperCase();
}
function base64(s) {
	var b = new Buffer.from(s);
	return b.toString('base64');
}
function ast(s) {
	return s.split('').sort().join('');
}
var newData = {},params='';
Object.keys(data).sort().map(key => {
  newData[key]=data[key]
  params=params+=data[key];
})
var timestamp = generateTimeReqestNumber();	
var msg_digest = base64( sha1(aid + md5(timestamp) + sha1(app_secret+params)));
newData["app_id"]=aid ;
newData["m_verified_way"]=4;
newData.timestamp=timestamp;
newData.v=v;
newData["msg_digest"]=msg_digest;
output={ts:timestamp,sign:msg_digest,'app_id':aid, v: v, params:params,newData:JSON.stringify(newData )};


2.2调用实名认证接口难道链接
var indata=JSON.parse(input.data);
var url=input.url+'/api/get_company_verify_url.api';
const fetch = require('node-fetch'); 
const FormData= require('form-data');
var result={};
let data= new FormData();


Object.keys(indata).forEach((key) => {
 data.append(key,indata[key]);
})
async function getAll(data){
    const res = await   fetch(url,{
    method:"post",
    body:data
}).then(function(response){
    if(response.ok){
 return  response.json();   
    }else{
  return   {"error":"无数据"};
}
}).catch(function(err){
   return   {"error":"Fetch错误:"+err};
});
    const result = await   res;
    return result;
}
result=await  getAll(data);
output={result:re

拿到接口返回的链接,使用打开界面节点来打开新连接。认证成功后,在你的信息接受地址中调用申请证书接口。

3.配置“上传合同及单个签署”的流程

接口名称解释

  • uploaddocs.api 合同上传接⼝
  • extsign_auto.api 自动签接⼝

代码块示例

1.合同上传参数加密
var crypto = require('crypto');
var doc_title='', doc_type='';
var v = input.v;
var app_secret = input.appsecret;
var aid = input.aid;
var contractid=input.contractid+'-'+parseInt(input.ind).toString();
var imgurl=input.imgurl
var types=['.doc','.docx','.pdf','.jpg','.jpeg','.png','.bmp']
//法大大不支持图片签章,e签宝支持.这里是为了后面方法公共
function getfiletype(f){
  var obj={'ftype':'','fname':''};
  for(var i=0;i<types.length;i++){
   var find=f.indexOf(types[i])
   var temp=f;
   if(find>-1){
      obj.ftype=types[i];
      temp=temp.substring(0,find);
      obj.fname=getfilename(find,temp);
      break;
    }
  }
  return obj;
}
function getfilename(find,f){
    var fname=''
    f=f.substring(0,find);
    var nind=f.lastIndexOf('/');
    if(nind>-1){
      fname=f.substring(nind+1,f.length);
    }else{
       nind=f.lastIndexOf('=');
       if(nind>-1){
       fname=f.substring(nind+1,f.length);
      }
    }
    return fname;
}
var obj=getfiletype(imgurl);
doc_type=obj.ftype;
doc_title=obj.fname;
var data={
"contract_id":contractid,
"doc_title":doc_title,
"doc_type":doc_type,
'doc_url':imgurl}


function pad2(n) { return n < 10 ? '0' + n : n }
function generateTimeReqestNumber() {
            var datee = new Date();
var localTime = datee .getTime();
var localOffset=datee .getTimezoneOffset()*60000; //获得当地时间偏移的毫秒数
var utc = localTime + localOffset; //utc即GMT时间
var offset =8; //以北京时间为例,东8区
var hawaii = utc + (3600000*offset); 
	var date = new Date(hawaii);
	date.setHours(date.getHours());
	return date.getFullYear().toString() + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds());
}
function sha1(s) {
	var hash = crypto.createHash('sha1');
	hash.update(s);
	return hash.digest('hex').toUpperCase();
}
function md5(s) {
	var hash = crypto.createHash('md5');
	hash.update(s);
	return hash.digest('hex').toUpperCase();
}
function base64(s) {
	var b = new Buffer.from(s);
	return b.toString('base64');
}
function ast(s) {
	return s.split('').sort().join('');
}
var newData = {},params='';
Object.keys(data).sort().map(key => {
  newData[key]=data[key]
  params=params+=data[key];
})
var timestamp = generateTimeReqestNumber();	
var msg_digest = base64( sha1(aid + md5(timestamp) + sha1(app_secret+data.contract_id)));
newData["app_id"]=aid ;
newData.timestamp=timestamp;
newData.v=v;
newData["msg_digest"]=msg_digest;
output={ts:timestamp,sign:msg_digest,'app_id':aid, v: v, params:params,newData:JSON.stringify(newData),contractid:contractid,doc_title:doc_title};


1.1 合同上传
const fetch = require('node-fetch'); 
const FormData= require('form-data');


var indata=JSON.parse(input.data);
var url=input.url+'/api/uploaddocs.api';
var result={};
var tempparams='';
let data= new FormData();


Object.keys(indata).forEach((key) => {
 data.append(key,indata[key]);
})
async function getAll(data){
    const res = await   fetch(url,{
    method:"post",
    body:data
}).then(function(response){
    if(response.ok){
 return  response.json();   
    }else{
  return   {"error":"无数据"};
}
}).catch(function(err){
   return   {"error":"Fetch错误:"+err};
});
    const result = await   res;
    return result;
}
result=await  getAll(data);


output={result:res

剩下的接口调用方法几乎一样,请查看 API 接口来调用。

特别注意几点:

  • 每个接口的签名规则都需要细看。
  • 最后自动签署的流程,需要设置异步通知的地址,因为存在“签署中”的状态。
  • 根据异步通知中的接受到的数据,在工作流设置签署后的文件。

结语

务实的明道云,在技术领域不断取得创新突破。每次更新迭代、集成方案,都带给您最美的期待。下一篇文章里,我们将介绍明道云和e签宝的对接案例和流程方法,敬请关注!

0

关于明道云

明道云(www.mingdao.com)成立于2013年,位于上海,创始人为互联网知名人士任向晖先生。明道云是一个APaaS平台,帮助企业快速搭建个性化业务应用。用户不需要代码开发就能够搭建出用户体验上佳的销售、运营、人事、采购等核心业务应用,打通企业内部数据,也能够通过API和Webhook和其他系统对接。

明道云的自动化工作流还可以实现审批、填写等控制流程和业务自动化。如果用户企业使用钉钉或企业微信,也可以将明道云搭建的应用直接对接到工作台上。

明道云可以帮助企业大大节省软件费用、降低定制开发的成本和时间,拥有一个极度灵活和易用的数据中台,并提高整体数字化和智能化水平。目前已有上百万用户使用,付费企业超过4000家,典型客户包括:中铁三局、佛山地铁、普华永道、艾瑞咨询、迪卡侬、北京大学、四川航空、上海静安区街道、艾默生电子、西门子、杭州建筑设计研究院、七天四季酒店、希尔顿、凯宾斯基酒店、可口可乐等知名机构。

点击了解更多