diff --git a/apps/dimension_apn/src/dimension_apn.app.src b/apps/dimension_apn/src/dimension_apn.app.src index c73953b..e12a4f4 100644 --- a/apps/dimension_apn/src/dimension_apn.app.src +++ b/apps/dimension_apn/src/dimension_apn.app.src @@ -9,6 +9,8 @@ cowboy, lager, sync, + ssl, + jiffy, apns, kernel, stdlib diff --git a/apps/dimension_apn/src/dimension_apn_pusher.erl b/apps/dimension_apn/src/dimension_apn_pusher.erl index c82af5b..9783703 100644 --- a/apps/dimension_apn/src/dimension_apn_pusher.erl +++ b/apps/dimension_apn/src/dimension_apn_pusher.erl @@ -13,6 +13,8 @@ %% API -export([start_link/0]). +-export([push/4]). +-export([test/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -20,13 +22,22 @@ -define(SERVER, ?MODULE). -record(state, { - + apns_pid :: pid() }). %%%=================================================================== %%% API %%%=================================================================== +test(DeviceToken) -> + Title = <<"这是一个消息通知"/utf8>>, + Body = jiffy:encode(#{<<"id">> => 1234, <<"name">> => <<"英雄第二季"/utf8>>}, [force_utf8]), + gen_server:cast(?SERVER, {push, DeviceToken, Title, Body}). + +-spec push(Pid :: pid(), DeviceToken :: binary(), Title :: binary(), Body :: binary()) -> no_return(). +push(Pid, DeviceToken, Title, Body) when is_pid(Pid), is_binary(DeviceToken), is_binary(Title), is_binary(Body) -> + gen_server:cast(Pid, {push, DeviceToken, Title, Body}). + %% @doc Spawns the server and registers the local name (unique) -spec(start_link() -> {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). @@ -43,16 +54,24 @@ start_link() -> {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {stop, Reason :: term()} | ignore). init([]) -> - {ok, Pid} = apns:connect(#{ + {ok, ApnsPid} = apns:connect(#{ name => my_first_conn, apple_host => "api.sandbox.push.apple.com", apple_port => 443, - certfile => "priv/aps_development.pem", - keyfile => "priv/priv_key.pem", - type => cert + certfile => "/usr/local/code/erl/dimension_apn/apps/dimension_apn/priv/aps_development.pem", + keyfile => "/usr/local/code/erl/dimension_apn/apps/dimension_apn/priv/priv_key.pem", + type => cert, + timeout => 5000, + ssl_opts => [ + {verify, verify_peer}, + {log_level, debug} + ] }), - lager:debug("connect get pid: ~p", [Pid]), - {ok, #state{}}. + ok = apns:wait_for_connection_up(ApnsPid), + + lager:debug("connect get pid: ~p", [ApnsPid]), + + {ok, #state{apns_pid = ApnsPid}}. %% @private %% @doc Handling call messages @@ -73,7 +92,43 @@ handle_call(_Request, _From, State = #state{}) -> {noreply, NewState :: #state{}} | {noreply, NewState :: #state{}, timeout() | hibernate} | {stop, Reason :: term(), NewState :: #state{}}). -handle_cast(_Request, State = #state{}) -> +handle_cast({push, DeviceToken, Title, Body}, State = #state{apns_pid = ApnsPid}) -> + Notification = #{ + aps => #{ + alert => #{ + title => Title, + body => Body + }, + % 播放默认声音 + sound => <<"default">>, + % App 图标角标 + badge => 1 + } + }, + + lager:debug("call me here"), + + Headers = #{ + %apns_id => undefined, + apns_expiration => "0", + apns_priority => "10", + apns_topic => "com.jihe.dimensionhub", + %apns_collapse_id => undefined, + apns_push_type => "alert" + }, + + PushResult = apns:push_notification(ApnsPid, DeviceToken, Notification, Headers), + lager:debug("[] push result is: ~p", [PushResult]), + + Config = #{ host => "feedback.push.apple.com", + port => 2195, + certfile => "/usr/local/code/erl/dimension_apn/apps/dimension_apn/priv/aps_development.pem", + keyfile => "/usr/local/code/erl/dimension_apn/apps/dimension_apn/priv/priv_key.pem", + timeout => 5000 + }, + FeedResult = apns:get_feedback(Config), + lager:debug("[] feed_result result is: ~p", [FeedResult]), + {noreply, State}. %% @private diff --git a/apps/dimension_apn/src/dimension_apn_sup.erl b/apps/dimension_apn/src/dimension_apn_sup.erl index 64e48f7..9d7f3bb 100644 --- a/apps/dimension_apn/src/dimension_apn_sup.erl +++ b/apps/dimension_apn/src/dimension_apn_sup.erl @@ -26,10 +26,19 @@ start_link() -> %% type => worker(), % optional %% modules => modules()} % optional init([]) -> - SupFlags = #{strategy => one_for_all, - intensity => 0, - period => 1}, - ChildSpecs = [], + SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600}, + + ChildSpecs = [ + #{ + id => dimension_apn_pusher, + start => {'dimension_apn_pusher', start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => ['dimension_apn_pusher'] + } + ], + {ok, {SupFlags, ChildSpecs}}. %% internal functions