全部产品
弹性计算 会员服务 网络 安全 移动云 数加·大数据分析及展现 数加·大数据应用 管理与监控 云通信 阿里云办公 培训与认证 智能硬件
存储与CDN 数据库 域名与网站(万网) 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 更多

CRM Demo介绍

更新时间:2018-05-09 18:27:48

CRMDemo 是一个集阿里云单点登录系统(基于Oauth2,以下简称Oauth2)和云呼叫中心坐席工作台(软电话)为一体的CRM示例,如果把Oauth2和软电话集成到用户自有系统中,可以实现和自有系统的联动,使其能够在自有系统中通过Oauth2获取阿里云的AccessToken,从而使用云呼叫中心的资源!

1.CRMDemo的登录

CRMDemo登录页面登录的uri:https://127.0.0.1:8443如果是通过公网登录端口号务必修改为HTTPS默认端口:443!CRM提供了自有的认证系统,该userName和passWord是CRM在初始化的时候写进数据库的,默认提供两组测试账号,User Name和Password分别是<Edward,1234>和<sissi,5678>。

  • 点击”Click here to see a customer list.”获取用户列表;
  • 点击“Retrieval Aliyun Token”会跳转至阿里云认证页面;请注意:云呼叫中心使用HTTPS协议,所以务必使用HTTPS协议。

2.Oauth2认证

登录CRM之后,如需请求呼叫中心资源,请点击“Retrieval Aliyun Token”,跳转至阿里云系统认证页面,通过阿里云主账号或者子账号都可以完成认证授权。

Oauth2流程

第一步:获取授权码(authorization code)

获取访问令牌的第一步是要获取用户授权码。应用需要通过浏览器将用户重定向到阿里云OAuth 2.0服务,认证成功之后,阿里云服务端会携带授权码(code)和state重定向至注册的回调地址。

请求样例:https://signin.aliyun.com/oauth2/v1/auth?response_type=code&response_mode=form_post&redirect_uri=https://127.0.0.1:8443/aliyun/auth/callback&client_id=120171021&state=75fb39a2-8b9f-49d6-9888-57a20ce8d7e5&codeChallenge=NTZ4wOaGVacs3oIk1sLfh8QWsF7CBfqTOEt3Sm1QJtzP3

  1. 换行列出是为了更好的展示:
  2. https://signin.aliyun.com/oauth2/v1/auth?
  3. response_type=code&
  4. response_mode=form_post&
  5. redirect_uri=https://127.0.0.1:8443/aliyun/auth/callback&
  6. client_id=120171021&state=75fb39a2-8b9f-49d6-9888-57a20ce8d7e5&
  7. codeChallenge=NTZ4wOaGVacs3oIk1sLfh8QWsF7CBfqTOEt3Sm1QJtzP3&access_type=offline
  8. 其中state设置为任意字符串,Auth Server会将请求中的state参数及取值放到重定向的request中。应用通过state参数可以实现各种目的,比如状态保持,发送nonce从而减少CSRF威胁等。

返回样例:https://127.0.0.1:8443/aliyun/auth/callback?code=NTZ4wOaGVacs3oIk1sLfh8QWsF7CBfqTOEt3Sm1QJtzP3&state=75fb39a2-8b9f-49d6-9888-57a20ce8d7e5

  1. 换行列出是为了更好的展示:
  2. GET HTTP/1.1 302 Found
  3. https://127.0.0.1:8443/aliyun/auth/callback?
  4. code=NTZ4wOaGVacs3oIk1sLfh8QWsF7CBfqTOEt3Sm1QJtzP3&
  5. state=75fb39a2-8b9f-49d6-9888-57a20ce8d7e5

第二步:用授权码换取访问令牌

当Auth Server重定向至回调地址后,首先对返回的state参数做校验,然后获得授权码(code)以及初始请求中设置的redirect_uri参数值和nonce参数值(Auth Server用来判断是否是同一个站点的请求),应用直接调用如下Endpoint(https://oauth.aliyun.com/v1/token)换取访问令牌 access_token,其包含了accessToken,refresh_token,credentials,idToken,userInfo等字段.

请求样例:http://oauth.aliyun.com/v1/token?client_id=120171021&grant_type=authorization_code&client_secret=E1QGQUDMSqRNcOO/WTt83vQ25Bdtb0LJYSm0fFdF0eY=&code=NTZ4wOaGVacs3oIk1sLfh8QWsF7CBfqTOEt3Sm1QJtzP3&redirect_uri=https://127.0.0.1:8443/aliyun/auth/callback&code_verifier=yuhT7azLRG2ZVTp5BEFWtVV5WzXWGswH2ZW0VwWrfOMoV

  1. 换行列出是为了更好的展示:
  2. http://oauth.aliyun.com/v1/token?
  3. client_id=120171021&
  4. grant_type=authorization_code&
  5. client_secret=E1QGQUDMSqRNcOO/WTt83vQ25Bdtb0LJYSm0fFdF0eY=&code=NTZ4wOaGVacs3oIk1sLfh8QWsF7CBfqTOEt3Sm1QJtzP3&
  6. redirect_uri=https://127.0.0.1:8443/aliyun/auth/callback&
  7. code_verifier=yuhT7azLRG2ZVTp5BEFWtVV5WzXWGswH2ZW0VwWrfOMoV
  1. 返回样例:
  2. {
  3. "request_id":"231863ac-21eb-4927-9214-853eca0fa9b8",
  4. "access_token":"eyJBY2Nlc3NLZXlJZCI6IlNUUy5DVUR6ckpGa3UxZmNUM1IyNFF1U25kTjd4IiwiQWNjZXNzS2V5U2VjcmV0IjoiQmlXcHBqVE5BcllQQUtQZDJmU0hVMnhWZmdqZWF2eldIV3lKaTU3alFraXQiLCJTZWN1cml0eVRva2VuIjoiQ0FJU2l3SjFxNkZ0NUIyeWZTaklvcGJ4TWNqK3E3UlVocVNJVmhYajFqUUVlZHhDaTR1Y21qejNJWHhLZVhkc0Flc2VzZmswbEdwWTd2c2VpWU1TR3NVZEhCT2ROWkFwdGl6dVFvcFlKOWl2Z2RlOHlKQlpvcERIY0RIaEEzeVc5Y3ZXWlBxRFA3RzVVL3l4YWxmQ3V6WnV5TC9oRDF1TFZFQ2tOcHY3NHZ3T0xLNUZQRytDWUNGQkdjMWRLeVo3dGNZZUxnR3hEL3UyTlFQd2lXZWllaWdjc3dGbjIyaDA0dmI5a0pURXRVZU8xQUtua2JGUCtkdXFlTVgyTGVzVVpjOGdEb2Z0ZzdFdEtQQ2ZqM1VLdGlJbnJ2a20wUFoyZ1JiQ3B0eUhHRjVYNmdtTFA5ZlAvOGRuUkEwQ1BQUmtSdkFZOUtPa3lxQWo2cmFEejltcmxnd2dMT2hUVnluUGtWTW5HMVpoa0lrYWdBRSswZDlmRUYxMlJOKzVPY2U2bGx3bnVQRjYweTdadStMbU5oRENrL2U5Yi9UZFYwTkRQZ0hxamd4ald6cTZsSThheWhXOGYzWDZtcHRZcmlHaVpuczBFUWpmOHpDMTRybXZWR2NkK284enVNYk1SdUZRblM5NDVsVUZEVmRIRmlvSzFlelNpci91T1Q1Si90KzhZYjhmZS9PR0ZjUkxqRE50cW1BVkdaNGVVUT09In0",
  5. "token_type":"AliyunSTS",
  6. "refresh_token":"1vpn8NKWBK2lLvhf",
  7. "id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IkpDOXd4enJocUowZ3RhQ0V0MlFMVWZldkVVSXdsdEZodWk0TzFiaDY3dFUifQ.eyJleHAiOjE1MTY1OTY4MTYsInN1YiI6IjI0NjU2NDAzMDc1MzgyODA1NDUiLCJuYW1lIjoieWFubGVAcHJlLm9uYWxpeXVuLmNvbSIsInVwbiI6InlhbmxlQHByZS5vbmFsaXl1bi5jb20iLCJhdWQiOiI5MjAxNzEwMzEiLCJpc3MiOiJodHRwczpcL1wvb2F1dGguYWxpeXVuLmNvbSIsImRpZCI6IiIsImFpZCI6IjEwNzU4MDc1MzYyNjczMjUiLCJiaWQiOiIyNjg0MiIsImlhdCI6MTUxNjU5MzIxNn0.eIQfAXswTrGD8db7VOO2XBS4g16aQRPQxhG2qC4cse3_Av6JmAeKjZWYGrJF7vSix8Pw7pPA6Je4tg53Xx2fhksaQXehsRnFDjAga1RkmL5v9fYJ1ksAQS3lZ6I_8WZ5grx186pc2hjwKlo8LRqLJMg76MjsHSnuCLyYKLTouR1f1Iv4QFfSrR5UzWQhG0jBWaGjGIGKSBv1ouxjeD8ouQxn-EsIRkrEa8wQclOQuYny-IdjEzeUrIrbvlRAxoZJRigc7_sdyB6dmYCM6aZgEp1n2lugIN_lWyfipW8VecczNyfc2bZeqtb6kzwitS7_23-mTCFUFlmwIMqTurDbPw",
  8. "additional_information":{"refresh_token_id":9718},
  9. "expires_in":"3599"
  10. }
  11. 返回的参数中access_token是一个对象,其包含了accessToken,refresh_token,idToken等字段.
  12. * accessToken:有效时间为3000秒,是一个base64-url encoded字符串,将其解析之后设置为credentials字段的值,也就是真正的访问令牌;
  13. * refresh_token:有效时间为3年,可以用来换取令牌;
  14. * idToken:是一个经过JWT加密的字符串,将其解析之后就是userInfo,同时将其赋值给userInfo字段;

第三步:刷新访问令牌

由于access_token默认有效时间为一小时,所以每隔一小时需要点击从而刷新令牌,就是使用refresh_token换取了一个新的access_token.请求样例:http://oauth.aliyun.com/v1/token?client_id=120171021&grant_type=refresh_token&client_secret=E1QGQUDMSqRNcOO/WTt83vQ25Bdtb0LJYSm0fFdF0eY=&refresh_token=1vpn8NKWBK2lLvhf&redirect_uri=/aliyun/refresh

  1. 换行列出是为了更好的展示:
  2. POST /v1/token HTTP/1.1
  3. Host: oauth.aliyun.com
  4. Content-Type: application/x-www-form-urlencoded
  5. http://oauth.aliyun.com/v1/token?
  6. client_id=120171021&
  7. grant_type=refresh_token&
  8. client_secret=E1QGQUDMSqRNcOO/WTt83vQ25Bdtb0LJYSm0fFdF0eY=&
  9. refresh_token=1vpn8NKWBK2lLvhf&
  10. redirect_uri=/aliyun/refresh
  11. 请求的返回值与用授权码换取访问令牌的返回值一致,但不包含refresh_tokenid_token。所以获取newToken之后需要把oldToken中的refresh_tokenid_token设置进newToken中,以便下次刷新访问令牌;

第四步:撤销令牌

如果您已经不打算再次调用呼叫中心的资源,点击“Revoke Aliyun Token”则会使您已经获取的阿里云AccessToken立即失效,如需再次请求呼叫中心资源只需要再次点击“Retrieval Aliyun Token”即可!请求实例:https://oauth.aliyun.com/v1/revoke?client_id=120171021&client_secret=E1QGQUDMSqRNcOO/WTt83vQ25Bdtb0LJYSm0fFdF0eY=&token=eyJBY2Nlc3NLZXlJZCI6IlNUUy5NTmpWbU1LVmNGajN6RGdXNjFGbmtXUUZaIiwiQWNjZXNzS2V5U2VjcmV0IjoiN0VFVEttb1pMWXZneGpaRUVHVGd2WFdUUFh4UG5hN1NTTFBuc3QyMkt6ZFMiLCJTZWN1cml0eVRva2VuIjoiQ0FJU2l3SjFxNkZ0NUIyeWZTaklySTNmSGRmNXBvbEM4YWpZZUdMV3N6WmtTdUZIdUpUdHVEejNJWHhLZVhkc0Flc2VzZmswbEdwWTd2c2VpWU1TR3NVZEhCT2ROWkFwdGk2ZWJZdFlKOWl2Z2RlOHlKQlpvcERIY0RIaEEzeVc5Y3ZXWlBxRFA3RzVVL3l4YWxmQ3V6WnV5TC9oRDF1TFZFQ2tOcHY3NHZ3T0xLNUZQRytDWUNGQkdjMWRLeVo3dGNZZUxnR3hEL3UyTlFQd2lXZWllaWdjc3dGbjIyaDA0dmI5a0pURXRVZU8xQUtua2JGUCtkdXFlTVgyTGVzVVpjOGdEb2Z0ZzdFdEtQQ2ZqM1VLdGlJbnJ2a20wUFoyZ1JiQ3B0eUhHRjVYNmdtTFA5ZlAvOGRuUkEwQ1BQUmtSdkFZOUtPa3lxQWo2cmFEejltcmxnd2dMT2hUVnluUGtWTW5HMVpoa0lrYWdBR1Y5bS9tR0FOcWgwTnhmWHJaeUxmSkxZSkVYRHkwQjhtYUlKV0hGY0htNHc2bTI0dFlLczlBV1VBbXpWQndFVlFyS1d5RFB4alFVSUR4SlJWSmthZ3JsRDRKbitrZjBVNEVWaFVITFRLVmRGTFBObWpCWWJhUjFzTDd5d1VhSE51bVNTdTA4OERmVkYzSldKVThHRnVtRDJzL2hTRjNpRHRPcENneXc5Sk1Vdz09In0&redirect_uri=/aliyun/revoke

  1. 换行列出是为了更好的展示:
  2. https://oauth.aliyun.com/v1/revoke?
  3. client_id=120171021&
  4. client_secret=E1QGQUDMSqRNcOO/WTt83vQ25Bdtb0LJYSm0fFdF0eY=&
  5. token=eyJBY2Nlc3NLZXlJZCI6IlNUUy5NTmpWbU1LVmNGajN6RGdXNjFGbmtXUUZaIiwiQWNjZXNzS2V5U2VjcmV0IjoiN0VFVEttb1pMWXZneGpaRUVHVGd2WFdUUFh4UG5hN1NTTFBuc3QyMkt6ZFMiLCJTZWN1cml0eVRva2VuIjoiQ0FJU2l3SjFxNkZ0NUIyeWZTaklySTNmSGRmNXBvbEM4YWpZZUdMV3N6WmtTdUZIdUpUdHVEejNJWHhLZVhkc0Flc2VzZmswbEdwWTd2c2VpWU1TR3NVZEhCT2ROWkFwdGk2ZWJZdFlKOWl2Z2RlOHlKQlpvcERIY0RIaEEzeVc5Y3ZXWlBxRFA3RzVVL3l4YWxmQ3V6WnV5TC9oRDF1TFZFQ2tOcHY3NHZ3T0xLNUZQRytDWUNGQkdjMWRLeVo3dGNZZUxnR3hEL3UyTlFQd2lXZWllaWdjc3dGbjIyaDA0dmI5a0pURXRVZU8xQUtua2JGUCtkdXFlTVgyTGVzVVpjOGdEb2Z0ZzdFdEtQQ2ZqM1VLdGlJbnJ2a20wUFoyZ1JiQ3B0eUhHRjVYNmdtTFA5ZlAvOGRuUkEwQ1BQUmtSdkFZOUtPa3lxQWo2cmFEejltcmxnd2dMT2hUVnluUGtWTW5HMVpoa0lrYWdBR1Y5bS9tR0FOcWgwTnhmWHJaeUxmSkxZSkVYRHkwQjhtYUlKV0hGY0htNHc2bTI0dFlLczlBV1VBbXpWQndFVlFyS1d5RFB4alFVSUR4SlJWSmthZ3JsRDRKbitrZjBVNEVWaFVITFRLVmRGTFBObWpCWWJhUjFzTDd5d1VhSE51bVNTdTA4OERmVkYzSldKVThHRnVtRDJzL2hTRjNpRHRPcENneXc5Sk1Vdz09In0&
  6. redirect_uri=/aliyun/revoke
  1. 在集成测之前请先参考 https://help.aliyun.com/document_detail/70950.html 注册应用, 以便获取Client ID 和 Client Secret(二者唯一的标示了您的应用,请注意保密)。
  2. 注册的时候需要提供您的阿里云账号名称,阿里云账号idUID)以及通过OAuth2获取授权码的回调地址列表(可同时注册多个),比如https://crm.company.com/aliyun/auth/callback。
  3. 注册请发送邮件至yonghong.lyh@alibaba-inc.com或者wb-zt354936@alibaba-inc.com(请在邮件中注明您的注册信息:阿里云账号,UIDcallbackURl列表)。 后期我们会提供自助注册功能,敬请期待!
  4. 当您获取到了Client ID Client Secret那说明您的应用已经注册成功,接下来您需要用您自己的Client ID Client Secret替换掉应用的属性文件中的对应值,同时您还需要跟您的客户经理获取您在呼叫中心创建的InstanceId,然后用它替换home.html文件中的对应值!
  5. 关于instanceId的获取,后期我们会在控制台页面展示出来,用户就可以自助获取拉!

关于阿里云三年内免登陆策略:由于access_token默认有效时间为一小时,refreshToken有效期为三年,所以需要先获取refreshToken,然后将其保存,以后每次就可以不用去阿里云认证就可以用refreshToken换取AccessToken.那如何获取refreshToken呢?就是在上面的第二步,Auth Server重定向至回调地址的时候,其access_token字段中就包含了refreshToken.请注意云呼叫中心使用WebRTC协议进行语音传输,因此务必使用HTTPS协议。

3. 坐席工作台

系统集成了坐席工作台,我们通过阿里云Oauth2授权之后,就可以基于CRM使用坐席的功能,比如呼入呼出,来电弹屏,上下线以及小休等!

在CRM中对于坐席工作台的所有功能使用都是通过引入的workbenchSdk.js(坐席工作台的web组件)加载的时候发出请求,在CccController中调用OpenAPI来访问呼叫中心的资源。请求示例:https://127.0.0.1:8443/aliyun/ccc/api?action=ListSkillGroupsOfUser

  1. CccController中的示例代码
  2. DefaultProfile profileBear = DefaultProfile.getProfile(REGION);
  3. profileBear.addEndpoint(ENDPOINT, REGION, PRODUCT, DOMAIN);
  4. BearerTokenCredentials bearerTokenCredentials =
  5. new BearerTokenCredentials(accessToken);
  6. DefaultAcsClient accessTokenClient = new DefaultAcsClient(profileBear, bearerTokenCredentials);
  7. accessTokenClient.setAutoRetry(false);
  8. /**
  9. * 使用CommonAPI调用POP API时,和使用传统产品SDK相比,请求和返回参数的格式都有所不同,因此需要进行一定的格式转换。
  10. */
  11. CommonRequest commonRequest = new CommonRequest();
  12. commonRequest.setDomain(DOMAIN);
  13. commonRequest.setVersion(VERSION);
  14. commonRequest.setAction(action);
  15. JSONObject jsonObject = JSONObject.parseObject(request);
  16. for (Entry<String, Object> entry : jsonObject.entrySet()) {
  17. String key = entry.getKey().trim();
  18. if (key.length() > 1) {
  19. key = key.substring(0, 1).toUpperCase() + key.substring(1);
  20. } else if (key.length() == 1) {
  21. key = key.toUpperCase();
  22. } else {
  23. continue;
  24. }
  25. commonRequest.putQueryParameter(key, entry.getValue().toString());
  26. }
  27. commonRequest.putQueryParameter("accessToken", accessToken);
  28. CommonResponse response = null;
  29. try {
  30. response = accessTokenClient.getCommonResponse(commonRequest);
  31. System.out.println(JSONObject.toJSONString(response.getData()));
  32. } catch (ClientException e) {
  33. logger.error("Failed to invoke open API, request=" + JSON.toJSONString(commonRequest), e);
  34. throw new CallCenterServiceException(e.getRequestId(), e.getErrCode(), e.getMessage());
  35. }
本文导读目录