TokenGetterForAlicom.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. use Aliyun\Api\Msg\Request\V20170525\QueryTokenForMnsQueueRequest;
  3. use Aliyun\Core\Config;
  4. use AliyunMNS\Client;
  5. use Aliyun\Core\Profile\DefaultProfile;
  6. use Aliyun\Core\DefaultAcsClient;
  7. use Aliyun\Core\Exception\ClientException;
  8. use Aliyun\Core\Exception\ServerException;
  9. // 加载区域结点配置
  10. Config::load();
  11. /**
  12. * 接收云通信消息的临时token
  13. *
  14. * @property array tokenMap
  15. * @property int bufferTime 过期时间小于2分钟则重新获取,防止服务器时间误差
  16. * @property string mnsAccountEndpoint
  17. * @property \Aliyun\Core\DefaultAcsClient acsClient
  18. */
  19. class TokenGetterForAlicom
  20. {
  21. /**
  22. * TokenGetterForAlicom constructor.
  23. *
  24. * @param string $accountId AccountId
  25. * @param string $accessKeyId AccessKeyId
  26. * @param string $accessKeySecret AccessKeySecret
  27. */
  28. public function __construct($accountId, $accessKeyId, $accessKeySecret)
  29. {
  30. $endpointName = "cn-hangzhou";
  31. $regionId = "cn-hangzhou";
  32. $productName = "Dybaseapi";
  33. $domain = "dybaseapi.aliyuncs.com";
  34. $this->tokenMap = [];
  35. $this->bufferTime = 2 * 60;
  36. DefaultProfile::addEndpoint($endpointName, $regionId, $productName, $domain);
  37. $profile = DefaultProfile::getProfile($regionId, $accessKeyId, $accessKeySecret);
  38. $this->acsClient = new DefaultAcsClient($profile);
  39. $this->mnsAccountEndpoint = $this->getAccountEndpoint($accountId, $regionId);
  40. }
  41. /**
  42. * 配置获取AccountEndPoint
  43. *
  44. * @param string $accountId AccountId
  45. * @param string $region Region
  46. * @param bool $secure 是否启用https
  47. * @param bool $internal
  48. * @param bool $vpc
  49. * @return string <ul>
  50. * <li>http(s)://{AccountId}.mns.cn-beijing.aliyuncs.com</li>
  51. * <li>http(s)://{AccountId}.mns.cn-beijing-internal.aliyuncs.com</li>
  52. * <li>http(s)://{AccountId}.mns.cn-beijing-internal-vpc.aliyuncs.com</li>
  53. * </ul>
  54. */
  55. private function getAccountEndpoint($accountId, $region, $secure=false, $internal=false, $vpc=false)
  56. {
  57. $protocol = $secure ? 'https' : 'http';
  58. $realRegion = $region;
  59. if ($internal) {
  60. $realRegion .= '-internal';
  61. }
  62. if ($vpc) {
  63. $realRegion .= '-vpc';
  64. }
  65. return "$protocol://$accountId.mns.$realRegion.aliyuncs.com";
  66. }
  67. /**
  68. * 远程取Token
  69. *
  70. * @param string $messageType 消息订阅类型 SmsReport | SmsUp
  71. * @return TokenForAlicom|bool
  72. */
  73. public function getTokenFromRemote($messageType, $queueName)
  74. {
  75. $request = new QueryTokenForMnsQueueRequest();
  76. $request->setMessageType($messageType);
  77. $request->setQueueName($queueName);
  78. try {
  79. $response = $this->acsClient->getAcsResponse($request);
  80. // print_r($response);
  81. $tokenForAlicom = new TokenForAlicom();
  82. $tokenForAlicom->setMessageType($messageType);
  83. $tokenForAlicom->setToken($response->MessageTokenDTO->SecurityToken);
  84. $tokenForAlicom->setTempAccessKey($response->MessageTokenDTO->AccessKeyId);
  85. $tokenForAlicom->setTempSecret($response->MessageTokenDTO->AccessKeySecret);
  86. $tokenForAlicom->setExpireTime($response->MessageTokenDTO->ExpireTime);
  87. // print_r($tokenForAlicom);
  88. return $tokenForAlicom;
  89. }
  90. catch (ServerException $e) {
  91. print_r($e->getErrorCode());
  92. print_r($e->getErrorMessage());
  93. }
  94. catch (ClientException $e) {
  95. print_r($e->getErrorCode());
  96. print_r($e->getErrorMessage());
  97. }
  98. return false;
  99. }
  100. /**
  101. * 先从tokenMap中取,如果不存在则远程取Token并存入tokenMap
  102. *
  103. * @param string $messageType 消息订阅类型 SmsReport | SmsUp
  104. * @param string $queueName 在云通信页面开通相应业务消息后,就能在页面上获得对应的queueName<br/>(e.g. Alicom-Queue-xxxxxx-SmsReport)
  105. * @return TokenForAlicom|bool
  106. */
  107. public function getTokenByMessageType($messageType, $queueName)
  108. {
  109. $tokenForAlicom = null;
  110. if(isset($this->tokenMap[$messageType])) {
  111. $tokenForAlicom = $this->tokenMap[$messageType];
  112. }
  113. if(null == $tokenForAlicom || strtotime($tokenForAlicom->getExpireTime()) - time() > $this->bufferTime)
  114. {
  115. $tokenForAlicom =$this->getTokenFromRemote($messageType, $queueName);
  116. $client = new Client(
  117. $this->mnsAccountEndpoint,
  118. $tokenForAlicom->getTempAccessKey(),
  119. $tokenForAlicom->getTempSecret(),
  120. $tokenForAlicom->getToken()
  121. );
  122. $tokenForAlicom->setClient($client);
  123. $tokenForAlicom->setQueue($queueName);
  124. $this->tokenMap[$messageType] = $tokenForAlicom;
  125. }
  126. return $tokenForAlicom;
  127. }
  128. }