通过 Azure NotificationHub REST 从设备发送推送通知 Api
Send Push Notification from a device via Azure NotificationHub REST Api
我正在尝试通过 Azure NotificationHub REST Api 从 iOS 设备 (iPhone) 发送推送通知。我正在按照我在网上找到的 Azure 文档从 Xamarin.iOS 解决方案尝试此操作。
回复returns以下信息:
Error: '50002: Provider Internal Error'
Status code: 500
用于调用 NotificationHub REST 的代码Api(来自 iOS 客户端应用程序):
var hubUtil = new NotificationHubUtility("Endpoint=sb://company-name.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=00000000000000011111111111111122222222222222");
hubUtil.SendNotificationMessage("This is a TEST Notification!").ConfigureAwait(false);
public class NotificationHubUtility
{
public string Endpoint { get; private set; }
public string SasKeyName { get; private set; }
public string SasKeyValue { get; private set; }
public string HubName { get; private set; }
public string ApiVersion { get; private set; }
public NotificationHubUtility(string connectionString)
{
//Parse Connectionstring
string[] parts = connectionString.Split(new char[] {';'});
for (int i = 0; i < parts.Length; i++)
{
if (parts[i].StartsWith("Endpoint", StringComparison.CurrentCulture))
Endpoint = "https" + parts[i].Substring(11);
if (parts[i].StartsWith("SharedAccessKeyName", StringComparison.CurrentCulture))
SasKeyName = parts[i].Substring(20);
if (parts[i].StartsWith("SharedAccessKey", StringComparison.CurrentCulture))
SasKeyValue = parts[i].Substring(16);
}
HubName = "my-hub";
ApiVersion = "?api-version=2014-09-01";
}
public string GetSaSToken(string uri, int minUntilExpire)
{
string targetUri = Uri.EscapeDataString(uri.ToLower()).ToLower();
// Add an expiration in seconds to it.
long expiresOnDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
expiresOnDate += minUntilExpire * 60 * 1000;
long expires_seconds = expiresOnDate / 1000;
var toSign = targetUri + "\n" + expires_seconds;
// Generate a HMAC-SHA256 hash or the uri and expiration using your secret key.
IMacAlgorithmProvider hasher = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
var messageBuffer = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(toSign, Encoding.UTF8);
var keyBuffer = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(SasKeyValue, Encoding.UTF8);
var hmacKey = hasher.CreateKey(keyBuffer);
var signedMessage = WinRTCrypto.CryptographicEngine.Sign(hmacKey, messageBuffer);
string signature = Uri.EscapeDataString(WinRTCrypto.CryptographicBuffer.EncodeToBase64String(signedMessage));
var token = "SharedAccessSignature sig=" + signature + "&se=" + expires_seconds + "&skn=" + SasKeyName + "&sr=" + targetUri;
return token;
}
public async Task SendNotificationMessage(string message)
{
try
{
// basic http client (if needed)
var httpClient = new HttpClient();
httpClient.MaxResponseContentBufferSize = 1024000;
var notificationPayload = "{\"aps\":{\"alert\":\"" + message + "\"}}";
var notificationHubUrl = $"{Endpoint}{HubName}/messages/{ApiVersion}";
var authToken = GetSaSToken(notificationHubUrl, 10);
var request = new HttpRequestMessage(HttpMethod.Post, notificationHubUrl);
//request.Headers.Add("Content-Type", "application/json;charset=utf-8");
request.Headers.Add("ServiceBusNotification-Format", "apple");
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("YYYY-MM-DDThh:mmTZD"));
request.Headers.Add("Authorization", authToken);
var requestBody = new StringContent(notificationPayload, Encoding.UTF8, "application/json");
request.Content = requestBody;
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead);
}
catch (Exception ex)
{
Console.Error.WriteLine(@"ERROR - Sending Notification {0}", ex.Message);
}
}
}
连接字符串示例:
Endpoint=sb://company-name.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=00000000000000011111111111111122222222222222
环境和假设:
- Xamarin.iOS 使用 C# 的解决方案
- 使用 PCLCrypto 库进行加密
- 我正在尝试重新创建在 Azure 示例 github 存储库中的 Example 中演示的解决方案,但使用的是 Xamarin.iOS
- 连接字符串直接取自 Azure 门户
- 生成SaS令牌的代码改编自Azure NotificationHub REST Api Documentation
- 通知中心工作,我可以通过中心发送测试推送通知UI,我看到它进入设备
我在这里错过了什么?我无法在线找到与此错误相关的很多文档。任何帮助将不胜感激。
修复更新:
对上面的代码进行以下 2 处更改为我解决了这个问题:
已更改
ApiVersion = "?api-version=2014-09-01";
到
ApiVersion = "?api-version=2016-07";
已更改
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("YYYY-MM-DDThh:mmTZD"));
至
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("yyyy-MM-ddTHH:mm:sszzz"));
Api 版本 2014-09-01 不正确。请使用 2016-07 作为 Api 版本,你应该没问题。
谢谢
索拉博
我已经解决了问题:
- +1 Sohrab 指出 Api 版本,我将其更新为
ApiVersion = "?api-version=2016-07";
- ServiceBusNotification-Apns-Expiry header 值格式存在错误,日期未正确格式化为字符串。更正后的格式字符串是
ToString("yyyy-MM-ddTHH:mm:sszzz")
我正在尝试通过 Azure NotificationHub REST Api 从 iOS 设备 (iPhone) 发送推送通知。我正在按照我在网上找到的 Azure 文档从 Xamarin.iOS 解决方案尝试此操作。
回复returns以下信息:
Error: '50002: Provider Internal Error'
Status code: 500
用于调用 NotificationHub REST 的代码Api(来自 iOS 客户端应用程序):
var hubUtil = new NotificationHubUtility("Endpoint=sb://company-name.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=00000000000000011111111111111122222222222222");
hubUtil.SendNotificationMessage("This is a TEST Notification!").ConfigureAwait(false);
public class NotificationHubUtility
{
public string Endpoint { get; private set; }
public string SasKeyName { get; private set; }
public string SasKeyValue { get; private set; }
public string HubName { get; private set; }
public string ApiVersion { get; private set; }
public NotificationHubUtility(string connectionString)
{
//Parse Connectionstring
string[] parts = connectionString.Split(new char[] {';'});
for (int i = 0; i < parts.Length; i++)
{
if (parts[i].StartsWith("Endpoint", StringComparison.CurrentCulture))
Endpoint = "https" + parts[i].Substring(11);
if (parts[i].StartsWith("SharedAccessKeyName", StringComparison.CurrentCulture))
SasKeyName = parts[i].Substring(20);
if (parts[i].StartsWith("SharedAccessKey", StringComparison.CurrentCulture))
SasKeyValue = parts[i].Substring(16);
}
HubName = "my-hub";
ApiVersion = "?api-version=2014-09-01";
}
public string GetSaSToken(string uri, int minUntilExpire)
{
string targetUri = Uri.EscapeDataString(uri.ToLower()).ToLower();
// Add an expiration in seconds to it.
long expiresOnDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
expiresOnDate += minUntilExpire * 60 * 1000;
long expires_seconds = expiresOnDate / 1000;
var toSign = targetUri + "\n" + expires_seconds;
// Generate a HMAC-SHA256 hash or the uri and expiration using your secret key.
IMacAlgorithmProvider hasher = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
var messageBuffer = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(toSign, Encoding.UTF8);
var keyBuffer = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(SasKeyValue, Encoding.UTF8);
var hmacKey = hasher.CreateKey(keyBuffer);
var signedMessage = WinRTCrypto.CryptographicEngine.Sign(hmacKey, messageBuffer);
string signature = Uri.EscapeDataString(WinRTCrypto.CryptographicBuffer.EncodeToBase64String(signedMessage));
var token = "SharedAccessSignature sig=" + signature + "&se=" + expires_seconds + "&skn=" + SasKeyName + "&sr=" + targetUri;
return token;
}
public async Task SendNotificationMessage(string message)
{
try
{
// basic http client (if needed)
var httpClient = new HttpClient();
httpClient.MaxResponseContentBufferSize = 1024000;
var notificationPayload = "{\"aps\":{\"alert\":\"" + message + "\"}}";
var notificationHubUrl = $"{Endpoint}{HubName}/messages/{ApiVersion}";
var authToken = GetSaSToken(notificationHubUrl, 10);
var request = new HttpRequestMessage(HttpMethod.Post, notificationHubUrl);
//request.Headers.Add("Content-Type", "application/json;charset=utf-8");
request.Headers.Add("ServiceBusNotification-Format", "apple");
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("YYYY-MM-DDThh:mmTZD"));
request.Headers.Add("Authorization", authToken);
var requestBody = new StringContent(notificationPayload, Encoding.UTF8, "application/json");
request.Content = requestBody;
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead);
}
catch (Exception ex)
{
Console.Error.WriteLine(@"ERROR - Sending Notification {0}", ex.Message);
}
}
}
连接字符串示例:
Endpoint=sb://company-name.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=00000000000000011111111111111122222222222222
环境和假设:
- Xamarin.iOS 使用 C# 的解决方案
- 使用 PCLCrypto 库进行加密
- 我正在尝试重新创建在 Azure 示例 github 存储库中的 Example 中演示的解决方案,但使用的是 Xamarin.iOS
- 连接字符串直接取自 Azure 门户
- 生成SaS令牌的代码改编自Azure NotificationHub REST Api Documentation
- 通知中心工作,我可以通过中心发送测试推送通知UI,我看到它进入设备
我在这里错过了什么?我无法在线找到与此错误相关的很多文档。任何帮助将不胜感激。
修复更新:
对上面的代码进行以下 2 处更改为我解决了这个问题:
已更改
ApiVersion = "?api-version=2014-09-01";
到
ApiVersion = "?api-version=2016-07";
已更改
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("YYYY-MM-DDThh:mmTZD"));
至
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("yyyy-MM-ddTHH:mm:sszzz"));
Api 版本 2014-09-01 不正确。请使用 2016-07 作为 Api 版本,你应该没问题。
谢谢
索拉博
我已经解决了问题:
- +1 Sohrab 指出 Api 版本,我将其更新为
ApiVersion = "?api-version=2016-07";
- ServiceBusNotification-Apns-Expiry header 值格式存在错误,日期未正确格式化为字符串。更正后的格式字符串是
ToString("yyyy-MM-ddTHH:mm:sszzz")