本文介绍AIMPaaS事件服务的架构、事件参数、事件列表。

简介

AIMPaaS提供了事件通知能力,当事件发生时会产生事件回调。

默认只有AppClient通过IMSDK发起的请求才会有事件,AppServer直接调用AIMPaaS不会产生事件。目前支持的事件请参见事件列表

架构

AIMPaaS的事件服务使用流程如下。

IM回调架构
  1. 业务侧,开发者预先使用控制台登记用于接收回调请求的HTTP URL。
  2. 设置回调URL后,平台会颁发一个用于回调的AppKey和AppSecret。
  3. 平台通过HTTP/HTTPS方式将回调请求发送给AppServer。
  4. AppServer收到请求后应先校验请求合法性,并尽快进行应答。

注册回调

  1. 业务方预先在控制台上登记用于接收回调请求的HTTP URL,平台会颁发一个用于事件回调的AppKey和AppSecret。
  2. 平台通过HTTP/HTTPS方式将回调事件发送给AppServer。

回调参数

请求参数
  • Header
    • method:POST
    • content-type:application/x-www-form-urlencoded
  • Body
    单表解析后如下所示:
    名称 类型 是否必选 示例值 描述
    command String Event.Notification 事件类型,取值请参见事件列表
    data String {"creatorAppUid": "12345", "initMembers": []} 事件内容,具体见每个事件的请求参数。
    ispSignature String 876yvrIsoGSox35bolbXPrs7Gvc=" 加签后的值,开发者通过签名校验,HTTP请求的合法性。
    ispSignatureSecretKey String signkeyname 验证签名的Key,开发者需要维护Key对应的密钥。
返回参数
  • Header

    content-type:JSON

  • Body
    单表解析后如下所示:
    名称 类型 是否必选 示例值 描述
    data String "" 事件应答内容,固定值。

事件列表

名称 Command 描述
消息发送事件 Event.SendMessage 发送的每条单聊和群聊消息都会产生一个消息发送事件。
消息通知事件 Event.Notification 发送的每条单聊和群聊消息都会产生一个消息通知事件,通知主要用于厂商通道的推送,比如APNs推送通道。
用户上下线事件 Event.ChangeStatus 用户连接断开会产生offline事件,登录和断线重连会产生online事件,注销会产生logout事件。
群成员入群事件 Event.AddGroupMember 用户加入群后,会产生该事件。

签名算法


/**
  BodyToSign
    1. 解析HTTP BODY:argsMap = parseForm
    2. 对Form的参数key按照字典序升序排列,sortedArgs;
    3. 遍历sortedArgs:"&" + key + "=" + percentEncode("/")
 */
StringToSign = HTTP-Method + "&" + percentEncode("/") + bodyToSign;

Signature = Base64Encode(hmacSha1(AccessSecret + "&" + stringToSign));

/**
    1. 读取Request中除"IspSignature"参数外的所有参数。
    2. 按照参数名称的字典顺序对参数进行排序。
    3. 对每个请求参数的名称和值进行编码。名称和值要使用UTF-8 字符集进行URL编码,URL编码的编码规则是:
    a. 对于字符 A-Z、a-z、0-9 以及字符“-”、“_”、“.”、“~”不编码;
    b. 对于其他字符编码成 “%XY” 的格式,其中 XY 是字符对应 ASCII 码的 16 进制表示。比如英文的双引号 (”)对应的编码就是 %22
    4. 对于扩展的 UTF-8 字符,编码成 “%XY%ZA...” 的格式。
    5. 需要说明的是英文空格( )要被编码是 %20,而不是加号(+)。
    
    注:一般支持 URL 编码的库(比如 Java 中的 java.net.URLEncoder)都是按照 “application/x- www-form-urlencoded” 的 MIME 类型的规则进行编码的。实现时可以直接使用这类方式进行编 码,把编码后的字符串中加号(+)替换成 %20、星号(*)替换成 %2A、%7E 替换回波浪号 (~),即可得到上述规则描述的编码字符串。
    1. 对编码后的参数名称和值使用英文等号(=)进行连接。
    2. 再把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。
  */
Java版签名实现Demo
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.xml.crypto.dsig.SignatureMethod;
import org.apache.commons.codec.binary.Base64;


  /**
     * RPC签名
     *
     * @return
     * @throws UnsupportedEncodingException
     */
    private String rpcSign(HttpServletRequest request)
            throws Exception {
        List<String> keys = new ArrayList<String>(request.getParameterMap().keySet());
        Collections.sort(keys);
        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            if (key.equals("IspSignature")){
                continue;
            }

            String value = request.getParameter(key);
            sb.append("&").append(percentEncode(key)).append("=").append(percentEncode(value));
        }

        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(percentEncode(request.getMethod()));
        stringToSign.append("&");
        stringToSign.append(percentEncode("/"));
        stringToSign.append("&");
        stringToSign.append(percentEncode(sb.substring(1)));

        SecretKey key = new SecretKeySpec(("YourSecretKey" + "&").getBytes("utf-8"), SignatureMethod.HMAC_SHA1);
        Mac hmacSha1 = Mac.getInstance("HmacSHA1");
        hmacSha1.init(key);

        String sign = new String(new Base64().encode(hmacSha1.doFinal(stringToSign.toString().getBytes("utf-8"))),
                        "utf-8");

        return sign;
    }

 /**
    * 处理特殊字符
    *
    * @param s
    * @return
    * @throws UnsupportedEncodingException
    */
   protected String percentEncode(String s) throws UnsupportedEncodingException {
       if (s == null){
           return null;
       }
       return URLEncoder.encode(s, "utf-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
   }