php - 使用 PHP 的 Azure 通知中心 REST API

标签 php azure push-notification

我正在尝试使用 PHP 为 Azure 通知中心 API 创建 SharedAccessSignature。

我不断收到错误“授权 token 签名无效”。

有人有在 PHP 5.4+ 中创建 SAS 的示例吗? 有一些 API 文档:http://msdn.microsoft.com/en-us/library/dn170477.aspx ,但有人说实现与文档不同。

这是我失败的实现:

private static function get_authentication_header()
    {
        $uri = "https://x.servicebus.windows.net/x";
        $expiry = time() + (60*60);
        $string = utf8_encode(urlencode($uri) . "\n" . $expiry);
        $keyname = "DefaultFullSharedAccessSignature";
        $key = base64_decode(static::HUB_KEY);
        $signature = base64_encode(hash_hmac('sha256', $string,  $key));
        $sas = 'SharedAccessSignature sig=' . $signature . '&se=' . $expiry . '&skn=' .      $keyname . '&sr=' . urlencode($uri);
        return $sas;
 }

最佳答案

这是一个简单的包装器,用于使用 PHP 将通知发送到通知中心。

<?php

include 'Notification.php';

class NotificationHub {

    const API_VERSION = "?api-version=2013-10";

    private $endpoint;
    private $hubPath;
    private $sasKeyName;
    private $sasKeyValue;

    function __construct($connectionString, $hubPath) {
        $this->hubPath = $hubPath;

        $this->parseConnectionString($connectionString);
    }

    private function parseConnectionString($connectionString) {
        $parts = explode(";", $connectionString);
        if (sizeof($parts) != 3) {
            throw new Exception("Error parsing connection string: " . $connectionString);
        }

        foreach ($parts as $part) {
            if (strpos($part, "Endpoint") === 0) {
                $this->endpoint = "https" . substr($part, 11);
            } else if (strpos($part, "SharedAccessKeyName") === 0) {
                $this->sasKeyName = substr($part, 20);
            } else if (strpos($part, "SharedAccessKey") === 0) {
                $this->sasKeyValue = substr($part, 16);
            }
        }
    }

    private function generateSasToken($uri) {
        $targetUri = strtolower(rawurlencode(strtolower($uri)));

        $expires = time();
        $expiresInMins = 60;
        $expires = $expires + $expiresInMins * 60;
        $toSign = $targetUri . "\n" . $expires;

        $signature = rawurlencode(base64_encode(hash_hmac('sha256', $toSign, $this->sasKeyValue, TRUE)));

        $token = "SharedAccessSignature sr=" . $targetUri . "&sig="
                    . $signature . "&se=" . $expires . "&skn=" . $this->sasKeyName;

        return $token;
    }

    public function broadcastNotification($notification) {
        $this->sendNotification($notification, "");
    }

    public function sendNotification($notification, $tagsOrTagExpression) {
        echo $tagsOrTagExpression."<p>";

        if (is_array($tagsOrTagExpression)) {
            $tagExpression = implode(" || ", $tagsOrTagExpression);
        } else {
            $tagExpression = $tagsOrTagExpression;
        }

        # build uri
        $uri = $this->endpoint . $this->hubPath . "/messages" . NotificationHub::API_VERSION;

        echo $uri."<p>";

        $ch = curl_init($uri);

        if (in_array($notification->format, ["template", "apple", "gcm"])) {
            $contentType = "application/json";
        } else {
            $contentType = "application/xml";
        }

        $token = $this->generateSasToken($uri);

        $headers = [
            'Authorization: '.$token,
            'Content-Type: '.$contentType,
            'ServiceBusNotification-Format: '.$notification->format
        ];

        if ("" !== $tagExpression) {
            $headers[] = 'ServiceBusNotification-Tags: '.$tagExpression;
        }

        # add headers for other platforms
        if (is_array($notification->headers)) {
            $headers = array_merge($headers, $notification->headers);
        }

        curl_setopt_array($ch, array(
            CURLOPT_POST => TRUE,
            CURLOPT_RETURNTRANSFER => TRUE,
            CURLOPT_SSL_VERIFYPEER => FALSE,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_POSTFIELDS => $notification->payload
        ));

        // Send the request
        $response = curl_exec($ch);

        // Check for errors
        if($response === FALSE){
            throw new Exception(curl_error($ch));
        }

        $info = curl_getinfo($ch);

        if ($info['http_code'] <> 201) {
            throw new Exception('Error sending notificaiton: '. $info['http_code'] . ' msg: ' . $response);
        }

        //print_r($info);

        //echo $response;
    } 
}

?>

不知道你是想发推送还是做注册管理。修改上面的内容来进行注册管理并不难,如 NH REST API 所示(记住 xml 文档中的顺序很重要!):http://msdn.microsoft.com/en-us/library/dn223264.aspx .

如果您仍然遇到问题,请告诉我。

埃利奥

关于php - 使用 PHP 的 Azure 通知中心 REST API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23360832/

相关文章:

php - 如何阻止 MySQL 错误输出到浏览器以包含数据库密码?

OMS 门户中的 Azure SQL Analytics 磁贴未立即显示最新数据库?

ruby-on-rails - ROR 推送通知引擎

ios - 推送通知不适用于生产

php mysql 在连接表上搜索部分匹配的数据

php - ajax自定义 header 提交两次

javascript - PHP - file_get_contents 使用正则表达式获取 JSON,但无法解码 JSON(获取 JSON_ERROR_SYNTAX)

azure - 尝试从 ACR 构建容器应用程序引发未经授权的错误

c# - DateTime.Now 给出的时间不正确

android - 如何在android中设置一次闹钟