# 接收isv的订阅与调用

联系人 逯浩圻(luhaoqi@glodon.com ) 刘大泽(liudz@glodon.com)

# 准备接收isv的订阅

如果您的服务不需要在isv订阅时做初始化的工具,那么可以跳过此步,但如果需要在isv订阅后为isv做一些初始化的工作,怎么办?

AECORE向SP提供了isv订阅事件的通知机制,当isv在AECORE订阅您的服务后,AECORE会向您在注册服务时所留的地址发送通知消息。

# 如何设置接收订阅通知地址

  1. 登录AECORE,进入服务管理,编辑技术服务。
  2. 在API服务信息里配置用于接收ISV订阅通知http url(此地址的接口规则详情参考订阅通知规范)。

# 订阅通知规范

AECORE在向SP发送通知事件时,为安全起见,增加了签名机制,SP通过验签证明通知是由AECORE发出的,下面说明如何找到签名时采用的签名密钥

  1. 在技术服务中详情中查看密钥

  2. 定义回调接口

    • 回调接口URL为: POST https://xxx.glodon.com/isv_subscription,(此地址为用户自定义接口,并配置到技术服务的服务开通通知地址)
    • Reuqest Body为
    {
        "appCode":"appCode",
        "appkey":"appkey",
        "appName":"appName",
        "contactEmail":"contactEmail",
        "contactPhone":"contactPhone",
        "resourceId":"resourceId",
        "timestamp":"timestamp",
        "signature":"signature",
        "userId":"userId"
    }	
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    字段 类型 必填 描述
    appCode String app编码
    appkey String 订阅的appkey
    appName String 应用名称
    contactEmail String 联系邮箱
    contactPhone String 联系手机号
    resourceId String 技术服务的resourceId
    timestamp String 订阅的时间
    userId String 订阅人
    signature String 签名
    • 签名的生成方式为:

      参数按照字母顺序排序,然后经过HMacSha256加密后,生成Base64编码。示例如下:

      Base64(HmacSha256((appCode={appCode}&appKey={appKey}&appName={appName}&contactEmail={contactEmail}&contactPhone={contactPhone}&resourceId={resourceId}&signKey={signKey}&timestamp={timestamp}&userId={userId})))
      
      1

      signKey为第一步获取的密钥

  • Response Body

    {
        "code": "success",
        "message": null,
        "data": "null"
    }
    
    
    1
    2
    3
    4
    5
    6
    字段 类型 必填 描述
    code String 回调成功、失败(success、fail)
  1. 样例程序

    • 签名验证样例
    //验证签名示例
    @PostMapping("/callback")
        public ReSPonseBean<String> callback(@RequestBody CallBackBean callBackBean) {
              String message = SHA256Utils.sha256_HMAC(MessageFormat.format("appCode={0}&appKey={1}&appName={2}&contactEmail={3}&contactPhone={4}&resourceId={5}&signKey={6}×tamp={7}&userId={8}", callBackBean.getAppCode(), callBackBean.getAppkey(), callBackBean.getAppName(),callBackBean.getContactEmail(), callBackBean.getContactPhone(), callBackBean.getResourceId(),
                      signKey, String.valueOf(callBackBean.getTimestamp()), callBackBean.getUserId()), signKey);
              if (StringUtils.equals(callBackBean.getSignature(), message)) {
                  return ReSPonseBean.success();
              } else {
                  return ReSPonseBean.fail("signature not true");
              }
          }
    //CallBackBean定义
    public class CallBackBean {
    	private String appCode;
        	private String appkey;
      	private String appName;
        	private String contactEmail;
      	private String contactPhone;
        	private String resourceId;
      	private Long timestamp;
        	private String userId;
      	private String signature;
        	public CallBackBean() {
      	}
       }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    //签名工具类
    import javax.crypto.Mac;
    import javax.crypto.SPec.SecretKeySpec;
    import java.io.UnsupportedEncodingException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.util.Base64;
    public class SHA256Utils {
     
          public static String sha256_HMAC(String message, String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
    	      Mac hmacSha256 = Mac.getInstance("HmacSHA256");
    	    byte[] keyBytes = secret.getBytes("UTF-8");
          hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
          String sign = Base64.getEncoder().encodeToString(hmacSha256.doFinal(message.getBytes("UTF-8")));
          return sign;
      	}
      }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

# 接收isv调用

当ISV来调用时,我如何知道是哪个ISV调用了我的服务?

因为ISV是带着OAuth2 token通过AECORE网关apigate.glodon.com来调用SP服务的,所以,AECORE能够从token中识别出来ISV的身份,将识别出来的身份信息放入到http header "x-token-info"中发向SP服务。

x-token-info以json格式存储ISV身份信息,如果是应用token,对应的字段说明如下

{
	"scope": [],
	"exp": 1594637537,
	"resource_ids": [],
	"client_authorities": [
		{
			"authority": "ROLE_RESOURCE"
		},
		{
			"authority": "ROLE_CLIENT"
		}
	],
	"client_name": "test-app", //isv应用名称
	"client_id": "YBOiBzRKS2jqkXbYEAhrWYV9qDw0kWw1", //isv的appKey
	"oauth_client_id": "isv-Bhavhi78KT"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

如果是用户token,对应字段说明如下

{
        "user_id": 5889529351866831698,//用户在用户中心的userId
        "scope": [],
        "global_id": "2757867",//用户在用户中心的globalId
        "exp": 1595385280,
        "resource_ids": [],
        "user_authorities": [
            {
                "authority": "ROLE_USER"
            }
        ],
        "client_authorities": [
            {
                "authority": "ROLE_RESOURCE"
            },
            {
                "authority": "ROLE_CLIENT"
            }
        ],
        "client_name": "demo-app-02", //isv应用名称
        "client_id": "CTvOVmGy1JdgLlFx5xXiPc4la0OfPWw4",//isv的appKey
        "oauth_client_id": "isv-7KEleRxGRw"
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

判断用户是够具有相应的操作权限。

同时,为保障x-token-info的安全性,AECORE对其进行了签名,放在http header "x-token-info-sign"中,签名内容即为x-token-info,算法见上面的SHA256Utils。

  • 在线客服

  • 意见反馈