接收isv的订阅与调用

联系人 逯浩圻(luhaoqi@glodon.com ) 李东岳(lidy-e@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"
        }	

字段 类型 必填 描述
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})))
    > signKey为第一步获取的密钥
  • Response Body

        {
            "code": "success",
            "message": null,
            "data": "null"
        }

字段 类型 必填 描述
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() {
          	}
           }


        //签名工具类
        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;
          	}
          }

接收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"
    }

如果是用户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"
        }

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

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