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

什么是电子签章

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

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

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

对接流程

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签宝的对接案例和流程方法,敬请关注!

关于明道云

明道云是一个创新的超级应用平台,可以帮助用户零代码构建企业应用,用户不需要代码开发就能够搭建出用户体验上佳的销售、运营、人事、采购等核心业务应用,打通企业内部数据。明道云还具备超自动化引擎,可以全面自动化复杂和重复的业务流程。运用明道云的集成中心与完整的API对接能力,用户可以轻松地将明道云与外部系统集成。除此之外,明道云超级应用平台还具备很高的可组合性,国际化支持,并支持云原生架构,实现了多云部署能力。通过插件架构,明道云正在逐步建立起繁荣的实施与开发生态。

明道云可以帮助企业大大节省软件费用、降低定制开发的成本和时间,拥有一个极度灵活和易用的数字化平台,是企业数字化建设的重要工具。目前已有上百万用户使用,付费企业超过4000家,包括可口可乐、复星集团、中国移动、中国联通、中国电信、中铁集团、北京地铁、佛山铁路、华夏银行、民生银行、迪卡侬、艾默生电气、泰科电子、四川航空、东方证券、万豪酒店、洲际酒店等知名客户。

2021年5月,明道云获得海纳亚洲近亿元投资。公司目前有超过130名员工,产品研发团队过半,总部位于上海漕河泾开发区,在北京、广州、深圳、成都、郑州、武汉、西安和宁波设有分支机构。公司为高新技术企业,上海市专新特精认定企业。