为什么我不能将 WNS toast 通知从 C# 发送到 windows phone 8.1
why can't I send WNS toast notification from c# to windows phone 8.1
我遵循了这两个指南:
https://msdn.microsoft.com/en-us/library/windows/apps/hh202945(v=vs.105).aspx
https://msdn.microsoft.com/library/windows/apps/xaml/hh868252
生成的代码如下。尽管看起来一切正常,但它 returns 是一个 404 错误。怎么会这样?任何帮助都会延迟我的自杀。
public static void PushToWindows2()
{
try
{
var accessToken = GetAccessToken("Nhz******************XkwX", "ms-app://s-1-15-2-***************-2150981501");
byte[] contentInBytes = Encoding.UTF8.GetBytes("<toast launch=\"\"><visual lang=\"en-US\"><binding template=\"ToastImageAndText01\"><image id=\"1\" src=\"World\" /><text id=\"1\">Hello</text></binding></visual></toast>");
HttpWebRequest request = HttpWebRequest.Create("https://db5.notify.windows.com/?token=awyaaaborhlhub%2bfxeytzjnz****************pftroh5l18sgorvgrkq%3d") as HttpWebRequest;
request.Method = "POST";
request.ContentLength = contentInBytes.Length;
request.ContentType= "text/xml";
request.Headers.Add("X-WindowsPhone-Target", "token");
request.Headers.Add("X-NotificationClass", "1"); ;
request.Headers.Add("X-WNS-Type", "wns/toast");
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken.ToString()));
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string notificationStatus = response.Headers["X-NotificationStatus"];
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
}
catch (Exception ex)
{
Console.Write("EXCEPTION: " + ex.Message);
}
}
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
}
public static OAuthToken GetOAuthTokenFromJson(string jsonString)
{
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
var ser = new DataContractJsonSerializer(typeof(OAuthToken));
var oAuthToken = (OAuthToken)ser.ReadObject(ms);
return oAuthToken;
}
}
public static OAuthToken GetAccessToken(string secret, string sid)
{
var urlEncodedSecret = HttpUtility.UrlEncode(secret);
var urlEncodedSid = HttpUtility.UrlEncode(sid);
var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com",
urlEncodedSid,
urlEncodedSecret);
string response;
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
response = client.UploadString("https://login.live.com/accesstoken.srf", body);
}
return GetOAuthTokenFromJson(response);
}
我也尝试过 PushSharp 路线,在这种情况下,我收到 "Device subscription has expired" 错误。这里是:
var config = new WnsConfiguration("424****.*******nts", "ms-app://s-1-15-2-***************1501", "Nhz************XkwX");
// Create a new broker
var wnsBroker = new WnsServiceBroker (config);
wnsBroker.QueueNotification(new WnsToastNotification {
ChannelUri = deviceId,
Payload = XElement.Parse (@"
<toast>
<visual>
<binding template=""ToastText01"">
<text id=""1"">WNS_Send_Single</text>
</binding>
</visual>
</toast>")
});
}
更新:
也与编码无关。我同时使用了带有 = 和 + 符号的未编码令牌和编码令牌。还是404
WNS 的 HTTP 404 错误意味着通道 URI 本身已被篡改,因此 WNS 无法理解它。从您的代码看来,频道 URI 在某处被降低了()- 通常令牌以 "AwYAAAD" 之类的内容开头。尝试删除小写频道 URI 的任何内容。
此外,当您需要 WNS 时,您似乎在混合使用 WNS 和 MSDN 文档(尽管这不会导致您的 404 错误)。 This is WNS, but this 是 MPNS 文档。具体来说,这些 headers 用于 MPNS,将被 WNS 忽略或失败:
- X-WindowsPhone-Target
- X-NotificationClass
- X-NotificationStatus
- X-SubscriptionStatus
- X-DeviceConnectionStatus
您想改用 these WNS headers。
我遵循了这两个指南: https://msdn.microsoft.com/en-us/library/windows/apps/hh202945(v=vs.105).aspx https://msdn.microsoft.com/library/windows/apps/xaml/hh868252
生成的代码如下。尽管看起来一切正常,但它 returns 是一个 404 错误。怎么会这样?任何帮助都会延迟我的自杀。
public static void PushToWindows2()
{
try
{
var accessToken = GetAccessToken("Nhz******************XkwX", "ms-app://s-1-15-2-***************-2150981501");
byte[] contentInBytes = Encoding.UTF8.GetBytes("<toast launch=\"\"><visual lang=\"en-US\"><binding template=\"ToastImageAndText01\"><image id=\"1\" src=\"World\" /><text id=\"1\">Hello</text></binding></visual></toast>");
HttpWebRequest request = HttpWebRequest.Create("https://db5.notify.windows.com/?token=awyaaaborhlhub%2bfxeytzjnz****************pftroh5l18sgorvgrkq%3d") as HttpWebRequest;
request.Method = "POST";
request.ContentLength = contentInBytes.Length;
request.ContentType= "text/xml";
request.Headers.Add("X-WindowsPhone-Target", "token");
request.Headers.Add("X-NotificationClass", "1"); ;
request.Headers.Add("X-WNS-Type", "wns/toast");
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken.ToString()));
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string notificationStatus = response.Headers["X-NotificationStatus"];
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
}
catch (Exception ex)
{
Console.Write("EXCEPTION: " + ex.Message);
}
}
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
}
public static OAuthToken GetOAuthTokenFromJson(string jsonString)
{
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
var ser = new DataContractJsonSerializer(typeof(OAuthToken));
var oAuthToken = (OAuthToken)ser.ReadObject(ms);
return oAuthToken;
}
}
public static OAuthToken GetAccessToken(string secret, string sid)
{
var urlEncodedSecret = HttpUtility.UrlEncode(secret);
var urlEncodedSid = HttpUtility.UrlEncode(sid);
var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com",
urlEncodedSid,
urlEncodedSecret);
string response;
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
response = client.UploadString("https://login.live.com/accesstoken.srf", body);
}
return GetOAuthTokenFromJson(response);
}
我也尝试过 PushSharp 路线,在这种情况下,我收到 "Device subscription has expired" 错误。这里是:
var config = new WnsConfiguration("424****.*******nts", "ms-app://s-1-15-2-***************1501", "Nhz************XkwX");
// Create a new broker
var wnsBroker = new WnsServiceBroker (config);
wnsBroker.QueueNotification(new WnsToastNotification {
ChannelUri = deviceId,
Payload = XElement.Parse (@"
<toast>
<visual>
<binding template=""ToastText01"">
<text id=""1"">WNS_Send_Single</text>
</binding>
</visual>
</toast>")
});
}
更新:
也与编码无关。我同时使用了带有 = 和 + 符号的未编码令牌和编码令牌。还是404
WNS 的 HTTP 404 错误意味着通道 URI 本身已被篡改,因此 WNS 无法理解它。从您的代码看来,频道 URI 在某处被降低了()- 通常令牌以 "AwYAAAD" 之类的内容开头。尝试删除小写频道 URI 的任何内容。
此外,当您需要 WNS 时,您似乎在混合使用 WNS 和 MSDN 文档(尽管这不会导致您的 404 错误)。 This is WNS, but this 是 MPNS 文档。具体来说,这些 headers 用于 MPNS,将被 WNS 忽略或失败:
- X-WindowsPhone-Target
- X-NotificationClass
- X-NotificationStatus
- X-SubscriptionStatus
- X-DeviceConnectionStatus
您想改用 these WNS headers。