项目介绍:
项目是Unity项目,然后导出uwp平台(c++),项目之前接的是亚马逊aws sdk,实现ios和android的推送服务。但是由于unity导出是c++/cx项目,亚马逊sdk没有提供对其支持。
通过几天的摸索,找到aws web api, 能拿到SNS的end point,但是无法推送(不太清楚原因)。
解决方案:重新接微软wns sdk 。
后端代码(erlang):
%%%-------------------------------------------------------------------
%%% @author lee
%%% @copyright (C) 2017, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 31. Jul 2017 10:50 AM
%%%-------------------------------------------------------------------
-module(lib_wns_push).
-author("lee").
-include("common.hrl").
%% API
-export([
dispatch_test/0,
dispatch/2,
authenticate/0
]).
-define(ACCESS_BASEURL, "https://login.live.com/accesstoken.srf").
-define(SCOPE, "notify.windows.com").
-define(IBROWSE_OPTIONS(ContentType), [ % Ibrowse options ContentType = "text/html"
{max_sessions, 1000},
{max_pipeline_size, 500},
{connect_timeout, 2000},
{inactivity_timeout, 4000},
{content_type, ContentType}]).
-define(WNS_DATA, <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<toast>
<visual>
<binding template=\"ToastGeneric\">
<text>~s</text>
<image placement=\"appLogoOverride\" hint-crop=\"circle\" src=\"ms-appx:///Assets/Square44x44Logo.scale-200.png\"/>
</binding>
</visual>
</toast>">>).
dispatch_test() ->
XMLData = <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<toast>
<visual>
<binding template=\"ToastGeneric\">
<text>\"Hello World\"</text>
<image placement=\"appLogoOverride\" hint-crop=\"circle\" src=\"ms-appx:///Assets/Square44x44Logo.scale-200.png\"/>
</binding>
</visual>
</toast>">>,
dispatch("https://hk2.notify.windows.com/?token=AwYAAAB6hF5%2bwn01WJmmIumQf%2buOCFmvxqXjnzIp6xQpjaQIszPg8eNEtDoXWcl1SosSSc%2blzF7LOC%2fPsoA%2fmqr1%2bvyEuWZuVl2lUg5iI%2bGiDnFIvDSqmElAcBAEGoe8hkksQn4%3d", XMLData).
dispatch(ChannelURI, Notice) ->
XMLBody = lists:flatten(io_lib:format(?WNS_DATA, [Notice])),
case authenticate() of
{ok, Token} ->
Options = ?IBROWSE_OPTIONS("text/xml"),
Headers = [
{"Authorization", Token},
{"Content-Type", "text/xml"},
{"X-WNS-Type", "wns/toast"}, % X-WNS-Type: wns/toast | wns/badge | wns/tile | wns/raw
{"X-WNS-RequestForStatus", "true"}],
try
case ibrowse:send_req(binary_to_list(ChannelURI), Headers, post, XMLBody, Options, 10000) of
{ok, "200", _RetHeaders, BodyData} ->
ok;
Else ->
?ERR("microsoft err request ~p~n", [Else])
end
catch
_E:_R ->
?ERR("microsoft crash request ~p~n", [Token])
end;
{err, Reason} -> erlang:error(Reason)
end.
authenticate() ->
Options = ?IBROWSE_OPTIONS("application/x-www-form-urlencoded"),
Bodys = lists:append([
"grant_type=", "client_credentials",
"&client_id=", http_uri:encode("xxxxxx"),
"&client_secret=", http_uri:encode("xxxxxxx"),
"&scope=", http_uri:encode(?SCOPE)]),
Headers = [{"Content-Type", "application/x-www-form-urlencoded"}],
case ibrowse:send_req(?ACCESS_BASEURL, Headers, post, Bodys, Options, 10000) of
{ok, "200", Head, Body} ->
Json = jsx:decode(list_to_binary(Body)),
{_AccessType, AccessToken} = {
proplists:get_value(<<"token_type">>, Json),
proplists:get_value(<<"access_token">>, Json)},
AuthValue = binary_to_list(<<"Bearer ", AccessToken/binary>>),
{ok, AuthValue};
Else ->
io:format("~w:~w microsoft err response ~p~n", [?MODULE, ?LINE, Else]),
{err, Else}
end.
客户端代码:
void MainPage::RegisterWNS()
{
try
{
auto authTask = Concurrency::create_task(PushNotificationChannelManager::CreatePushNotificationChannelForApplicationAsync());
authTask.then([=](PushNotificationChannel^ channel)
{
channel->PushNotificationReceived += ref new TypedEventHandler<PushNotificationChannel ^, PushNotificationReceivedEventArgs ^>(this, &MainPage::OnPushNotificationReceived);
SendMessageToU3D(11, channel->Uri);
});
}
catch (const std::exception&)
{
m_retryCount++;
if (m_retryCount > 3) {
return;
}
RegisterWNS();
}
}
void MainPage::OnPushNotificationReceived(PushNotificationChannel ^sender, PushNotificationReceivedEventArgs ^args)
{
switch (args->NotificationType)
{
case PushNotificationType::Toast:
ToastNotificationManager::CreateToastNotifier()->Show(args->ToastNotification);
break;
case PushNotificationType::Badge:
BadgeUpdateManager::CreateBadgeUpdaterForApplication()->Update(args->BadgeNotification);
break;
case PushNotificationType::Tile:
TileUpdateManager::CreateTileUpdaterForApplication()->Update(args->TileNotification);
break;
case PushNotificationType::Raw:
break;
default:
break;
}
//args->Cancel = true;
}