day[11] Hello Line - 第一个Line讯息

本次铁人赛将通过Line机器人搭建专案,所以没有Line Developers的快去申请吧,会用到的是Messaging API在注册完成後请安装需求套件

pip install line-bot-sdk
pip install pyjwt
pip install jwcrypto
pip install cryptography

产生 Assertion Signing Key(KID)

本次专案以channel access tokens v2.1版本进行实作,依照要求,需要产生Assertion Signing Key

按照官网文件说明,因为只需要进行一次,可以透过浏览器开发工具快速的产生,或者使用Python也可以,这边使用Google浏览器,按下F12开启开发者工具,选择Console页签,将以下程序码贴上,即会产生private key与public key

(async () => {
  const pair = await crypto.subtle.generateKey(
    {
      name: 'RSASSA-PKCS1-v1_5',
      modulusLength: 2048,
      publicExponent: new Uint8Array([1, 0, 1]),
      hash: 'SHA-256'
    },
    true,
    ['sign', 'verify']
  );
   
  console.log('=== private key ===');
  console.log(JSON.stringify(await crypto.subtle.exportKey('jwk', pair.privateKey), null, '  '));
   
  console.log('=== public key ===');
  console.log(JSON.stringify(await crypto.subtle.exportKey('jwk', pair.publicKey), null, '  ')); 
})();

将产生的public key贴到Line Developers Console创建的channels中的Assertion Signing Key栏位,如果看到右侧有一串字串出现代表成功了,这就是KID,存起来等等会用到

实作取得JWT

Line使用JWT,并以此签名Token,详细加密原理请参照网站

此处产生Token的方式需要准备以下参数:

Property 说明
kid 将Public Key填入网站後右侧的字串
iss Channel ID
sub Channel ID
aud https://api.line.me/
exp JWT的有效期限
token_exp 以本JWT签名的Token的有效期限

以Python实作:

import jwt
from jwt.algorithms import RSAAlgorithm
import time

privateKey = {
  "alg": "RS256",
  "d": "dcA-LXLBRecBQbW7a8LKAriFJhnpXzwu2uNoVF_8-QmGVzI5682FWh_CWhl_B6J0fpmA-d7_EP0WCB3AGhxlyTP6ROoYJo7nygb_KMLREM7n64LFGbvNtw4jk7dmISXl_JuEX6CG09BBx4GLh9AGHSaK4v9B-dDvrNZlAo2mIjISHNcAPENbOl_XIOmZpJd56znjjc1gGKaYGbIm8unxHnPhL66IVYGRu8gxKfG6JUP7o370-VDfFOeaAR0HshTycP6M41jcDSjL6z9-J-Sh0zSZXqGS4u82TNtmwtRTzVwd0w30KQ0TTROTiNsz5apVHjpMvmAxRlbvcW41xIq8sQ",
  "dp": "PAWBMzwnwgc-yixarV30gemH6Wk15HfSUYpR4wJZUHemGx_LE5GXdnKoyy8G9DAl6XMpm7YVH8cPXgXYNh-JlAggvzUeH5A7KAV4ZPTNak4CI844GSbYIu_dPBcVAg0O6sxQWugYpPbPnMDpE7qf4KilSSVG3JKqEMxkYySjZZE",
  "dq": "LBA_q2YYnglCL41-1b3BmzCm-hs7Q-N__otDWO01I03VYnzU-vEQmxy6Fzrh2Y4Fgwp6D8iScu42AOyhE-T-qDNbAsCB0iZeFqm84g6VQAfDbknjIUZtcGvQgzy-zlrl253_QdyJvl2b44KT1hfoF0tDNA1rhOy7WlBM__rH0Pc",
  "e": "AQAB",
  "kty": "RSA",
  "n": "x2glWJ7baQV4vdElnAXA5yu8yFk4LpszkHW3Ey-BKGT3kGVLy3Jk3OvkwjBFOglXWeyTWe_rJkMYkBKuon5syZVjrjb24CmViAXGr6d6IvrYWj8IGZ6ElVABfnjGgZMVywmBb7hIh2p8QR0L8UJEuWjBU5nlwkMBpvnY2HXAVhvir8CN7WRj_GBMxxgg7wSuW1tV-7Qf44grMqJ0Je7zjflS4-TpI8Ox3nhamn0d7NIdQ3jNdTP7IZF61IvETgb_6NdFnfsN-aifJC-Ea3ZwhVcEGJ5z3MMoKSoChJmkJMiV9CldqGRnEDWwBugZHeEtn71eGVE3DAXAzrf525YHYQ",
  "p": "7eH8LAzNkITH6t7CWU5tPAmQlGQPkby66Yfq52tSZ43pQRz0CdtDYCQnGoBXvHzAHhzH4MjmNLOSGVimZK_dIRg5lJaPvVe6hgQ3pYud5WzPWsnQTsC7agQ2rfQglyFUtjwd1gWBIY4gwHj4BYG6Up3g0TlX1sf_juZxcLhkOsc",
  "q": "1pf-Pj2ZPL1nGqVcMVH_hfziIOBtjxc5vMGyHwTaLAA9y2xKfe_SRU8kUK2q5ZykJ8wMckR9Pduuyn-vp4q2FANVSN69G01pUKM2ppkgXuil2S3REmzniGdajZjkpWKaZ6z1tJ_xSv9ghx06Dbro8n___KnpBq6afb022anRxJc",
  "qi": "6L6SgH_pkyqq1Tb6QXPAGmtqVZT58Ljf3QTw6Tx5OdZ9NNvDReHHb64MgbUMLhLzGMeXGqDI5j0WLhtXv4ddCKWkF7OeKLUNuRP7yLpyYMazn8TEOjKHsgLAklenxcSgYaoO_wULh1mze1_ZO2PJNgvkIx_Xzr0XDUAqUp4W0jk",
  "use": "sig"
}

headers = {
    "alg": "RS256",
    "typ": "JWT",
    "kid": "9869e446-3489-4516-a83f-ec9214ad94d0"
}

payload = {
  "iss": "1234567890",
  "sub": "1234567890",
  "aud": "https://api.line.me/",
  "exp":int(time.time())+(60 * 30),
  "token_exp": 60 * 60 * 24 * 30
}

key = RSAAlgorithm.from_jwk(privateKey)

JWT = jwt.encode(payload, key, algorithm="RS256", headers=headers, json_encoder=None)
print(JWT)

实作取得channel_access_token

在这边,要向Line官方取得token,在产生JWT後,需要在JWT的有效期限内进行token的产生,详细的错误说明与栏位解释可以参照官方文件,会使用到的参数如下:

Property 说明
JWT JWT,JSON格式

以Python实作:

def Issue_channel_access_token(JWT):
  #https://developers.line.biz/en/reference/messaging-api/#issue-channel-access-token-v2-1
  url = "https://api.line.me/oauth2/v2.1/token"
  headers = APIPm.xwwwformurlencodedheaders
  data = {
      "grant_type":"client_credentials",
      "client_assertion_type":"urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
      "client_assertion": JWT
  }
  resp = APIPm.sendreq(url=url, headers=headers, data=data)
  # resp = json.loads(resp.text)
  return jsonresphandler(resp)

Hello Line,发送讯息

有了Token,就可以进行API的使用了,这边先跳到Line Developers,请在自己的机器人的Basic setting中最下方找到Your user ID存起来备用,要发讯息罗

以Python实作:

def Send_push_message(token, IDs):
  access_token = token['access_token']
  url = "https://api.line.me/v2/bot/message/push"
  headers = APIPm.jsonheaders.copy()
  headers['Authorization'] = f"Bearer {access_token}"
  data = {
      "to": IDs,
      "messages":[
          {
              "type":"text",
              "text":"Hello, world"
          },
          {
              "type":"text",
              "text":"Hello, ITironman"
          }
      ]
  }
  resp = APIPm.sendreq(url=url, headers=headers, data=json.dumps(data, indent=4))
  return jsonresphandler(resp)

现在应该可以在手机上找到发给自己的讯息了,明天开始把接收功能做出来


<<:  Day 22 - Ajax

>>:  JavaScript 函数 | 一级函数

Professional Writer

I am professional blogger and has keen interest in...

[DAY 16]用bot打出色色柴犬counter牌

最近很夯的色色柴犬大家应该有听过吧 没错就是这一系列牌组 然後某一天晚上不知道我发什麽神经突然有个念...

30天程序语言研究

今天是30天程序语言研究的第六天,研究的语言一样是python,今天主要学习的是建立一个计算机和字典...

RDS备份还原与地端的差异

在使用面板成功备份还原後, 再使用SSMS实作的可行性, 是否跟地端的一样? 先使用UI方式备份, ...

Day 26 : 插件篇 05 — 做好笔记备份,使用 Obsidian Git自动备份笔记到 Github

前言 我在《操作基础篇 04 — 做好笔记备份 ,使用 iCloud 和 Google Drive ...