在AWS的Lambda上部署kintone

cybozu发表于:2019年07月18日 17:47:22更新于:2021年04月01日 17:57:00

Index

Serverless简介

Serverless最近非常流行,无服务器应用也让我们可以简单快速上线一些功能,而无需关心底层的基础架构。

那么今天也让我们来利用Serverless的思想在亚马逊云(AWS)上部署我们的程序吧。

课题

在AWS上部署一个钉钉和kintone的整合应用。可以让kintone随时同步钉钉的打卡数据。(钉钉上已有打卡记录)

流程

创建npm项目,编写代码 => 建立钉钉的应用 => 建立AWS的IAM账户 => 建立AWS的vpc => 建立AWS的API Gateway网关 => 建立Lambda =>kintone自定义开发

0015d318ac820398d07f70cfd27e428

kintone设置

首先我们创建一个kintone app,在app里添加一个单行文本框字段以保存钉钉传过来的打卡地址。并且开启“API令牌”,设置访问权限,让这个应用可以通过API来添加数据。

0015d3016dfd9c6b8d9fed11139d7cd

0015d2e89cdaed260214bf1fe75e718

服务端开发

创建一个npm项目,导入kintone的js sdk依赖包。

npm init
npm install --save @kintone/kintone-js-sdk  request request-promise

kintone/kintone-js-sdk是kintone的js sdk。具体的用法可以参见文档 https://github.com/kintone-labs/kintone-js-sdk/

关于钉钉的开发请参见另一篇文章 https://cybozudev.kf5.com/hc/kb/article/1295078

下面是具体的同步钉钉数据的代码,我们命名为index.js

const request = require('request-promise');
const kintone = require('@kintone/kintone-js-sdk');
const DOMAIN = 'https://oapi.dingtalk.com/gettoken?appkey=';
const APP_KEY = 'xxxxxxxxxx';
const API_SECRET = 'xxxxxxxxxxxxx';
const KINTONE_DOMAIN = "xxxxx.cybozu.cn";
const MY_TOKEN = "xxxxxxxxxxxx";
const URL = DOMAIN + APP_KEY + '&appsecret=' + API_SECRET;
exports.handler = async (event) => {
    let getAccessToken = function () {
        let options = {
            url: URL,
            method: 'GET'
        };
        return request(options);
    };
    let getCard = function (result) {
        let ppp = JSON.parse(result);
        var token = ppp.access_token;
        let options = {
            url: "https://oapi.dingtalk.com/attendance/listRecord?access_token=" + token,
            method: 'POST',
            body: {
                userIds: ["282306481325123890"],
                checkDateFrom: "2019-07-05 09:00:00",
                checkDateTo: "2019-07-05 12:00:00",
                isI18n: "false"
            },
            json: true
        };
        return request(options);
    };
    let insertKintone = async (ding) => {
        let data = ding.recordresult[0].userAddress;
        let kintoneAuthWithAPIToken = (new kintone.Auth()).setApiToken(MY_TOKEN);
        let kintoneConnection = new kintone.Connection(KINTONE_DOMAIN, kintoneAuthWithAPIToken);
        let kintoneRecord = new kintone.Record(kintoneConnection);
        let appID = 1;
        let record = {
            ding: {
                value: data
            }
        };
        try {
            let recordResult = await kintoneRecord.addRecord(appID, record);
            return recordResult;
        } catch (error) {
            return error;
        }
    };
    return getAccessToken().then(getCard).then(insertKintone);
};

请按照实际情况,设置APP_KEY,API_SECRET,KINTONE_DOMAIN,MY_TOKEN变量的值。

再建立一个test.js

const r =  require("./index");
r.handler();

我们可以测试运行下node test.js,看下结果是否在kintone上已经同步了钉钉的打卡数据。

以下是kintone上同步钉钉的记录。

0015d3017a7e5b04ea68b2c77531128

测试成功后,我们就可以把它部署到我们的AWS云上了。

AWS云服务器的部署

创建IAM账户

我们先建立一个AWS的IAM用户, 它能够安全地管理对AWS 服务和资源的访问。具体可参见AWS官方的介绍。我这边就不多做阐述了。

以下是我们建立的IAM账户,并赋予了它一定的权限。

0015d2fdf774efec448dba162024f8a

建立VPC

为什么要建立vpc?

为了调用的安全性,很多的API调用是需要一个白名单的IP地址,只有这些IP可以调用它的API服务,但是如果你用一些云服务器,包括AWS的Lambda的时候,它并不会提供你一个固定的IP。这时候你可以使用aws的vpc服务,来解决这个问题。

详情请查看 如何解决Lambda里需要连接限制IP访问的应用

通过vpc获取到一个弹性IP后,这个IP就可以作为“服务器公网出口IP名单”填写到钉钉后台了。

AWS弹性IP:

b946(1).png


钉钉应用小程序后台:

0015d2c0dc43ba85ac53b331d2b0d81

Lambda函数

Lambda是AWS提供的无服务器计算服务。

这边就以钉钉和kintone的整合作为例子。以Node.js作为语言来做一个demo。

创建函数

首先是创建函数,在Lambda画面,然后选择创建函数。输入函数名字,选好运行语言Node.js,然后选好角色权限。

0015d2fe1186dadcd74af9f4ef39cab

设置参数

我们调整好基本设置的超时时间,设置好vpc网络的访问。

0015d30365b6c5f66b506490fc58f34


上传代码

我们可以将整个项目打成zip包,然后通过上传来部署到Lambda。

0015d31681c7507ef592b1926e72d42

触发器API Gateway

API gateway一般用来作为多个微服务的路由,这里我们也可以简单的将它作为我们 Lambda函数运行的触发器。

新建一个API Gateway,选择REST。

0015d30239eb5c873c010e4ed2c6fd9

点击“操作” > “创建方法”,创建一个GET方法,集成环境选择Lambda函数,然后选择我们之前创建的Lambda函数。

0015d30324189a8af2dd87b87194fe8


最后点击“部署 API”,设置部署的阶段名称。这样我们的API部署就完成了

0015d31511e0be85aac21c826a11012


此时点击“阶段”,点击GET方法,会显示 “调用URL”,访问该url就会触发之前我们创建的Lambda函数

0015d3033025fa0d77137161685a4cf

kintone自定义开发

最后我们在kintone上自定义一段js代码,以便我们只要点击一下按钮即可同步钉钉的数据。

kintone_cum.js

(function () {
    "use strict";
    kintone.events.on('app.record.index.show', function (event) {
        if (document.getElementById('my_index_button') !== null) {
            return;
        }
        var myIndexButton = document.createElement('button');
        myIndexButton.id = 'my_index_button';
        myIndexButton.innerText = '同步钉钉';
        var url = "xxxxxxxxx"; //aws的api gateway的调用url
        myIndexButton.addEventListener('click', (e) => {
            $.ajax({
                url: url,
                method: 'get'
            }).always(
                function () {
                    window.location.reload();
                }
            )
        })
        kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);
    });
})();

将上面的代码如下图上传到刚才创建的应用中。

0015d313aea794f1ebf770b8eb9ec26

点击同步钉钉后,程序会自动拉取钉钉的打卡记录,并刷新页面

0015d3192d6bb7912eb5fb1de0db7fc

后记

通过Lambda可以不用关心服务器的基础架构的部署,直接关注我们业务逻辑代码的开发就可以了,它提供很多开发语言,java,python,ruby等等。

vpc的建立也很好的解决了安全方面的一些问题,我们的kintone也可以放心的开通“IP地址限制”,这样从AWS过来的访问也可以安全的加入到白名单了。

注意事项

  • 本示例代码不保证其运行。

  • 我们不为本示例代码提供技术支持。

相关链接