如何使用Erlang发送推送通知?

如何使用Erlang发送推送通知?,erlang,binary,push,apple-push-notifications,Erlang,Binary,Push,Apple Push Notifications,我正在尝试使用Erlang向APN发送推送通知。 这是我到目前为止提出的代码: -module(apnstest2). -export([connect/0]). connect() -> application:start(ssl), ssl:seed("someseedstring"), Address = "gateway.sandbox.push.apple.com", Port = 2195, Cert = "/path/to/Certi

我正在尝试使用Erlang向APN发送推送通知。 这是我到目前为止提出的代码:

-module(apnstest2).
-export([connect/0]).

connect() ->
    application:start(ssl),
    ssl:seed("someseedstring"),
    Address = "gateway.sandbox.push.apple.com",
    Port = 2195,
    Cert = "/path/to/Certificate.pem",
    Key = "/path/to/Key.unenc.pem",
    Options = [{certfile, Cert}, {keyfile, Key}, {mode, binary}],
    Timeout = 1000,
    {ok, Socket} = ssl:connect(Address, Port, Options, Timeout),

    Token = "195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03",
    Payload = "{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}",
    TokenLength = length(Token),
    PayloadLength = length(Payload),

    Packet = [<<0:8, TokenLength, Token, PayloadLength, Payload>>],

    ssl:send(Socket, list_to_binary(Packet)),
    ssl:close(Socket).
-模块(apnstest2)。
-导出([connect/0])。
连接()->
应用:启动(ssl),
ssl:seed(“someseedstring”),
Address=“gateway.sandbox.push.apple.com”,
端口=2195,
Cert=“/path/to/Certificate.pem”,
Key=“/path/to/Key.unenc.pem”,
选项=[{certfile,Cert},{keyfile,Key},{mode,binary}],
超时=1000,
{ok,Socket}=ssl:connect(地址、端口、选项、超时),
令牌=“195EC05A962B24954693C0B638B6216579A0D1D74B3E1C6F534CF8FD0D50D03”,
有效载荷=“{\'aps\':{\'alert\':\'Just testing.\',\'sound\':\'chime\',\'badge\':10}}”,
令牌长度=长度(令牌),
有效载荷长度=长度(有效载荷),
数据包=[],
ssl:send(套接字、列表到二进制(数据包)),
ssl:关闭(套接字)。
该代码没有利用Erlang的并发性,只是一个原型。我只想测试我是否能以最简单的方式发送推送

我认为问题在于发送给APN的数据包。 这是推送通知的二进制格式:

我应该如何在Erlang中创建这样的数据包? 有人能看一下我的代码并告诉我问题出在哪里吗?
我还使用Erlang的SSL应用程序创建连接并发送数据,我不知道这是问题还是数据包。

谢谢

首先,不需要创建单个二进制文件的列表,然后在其上调用
list\u To\u binary/1
。你可以直接发送二进制文件

此外,确保字段长度和值符合协议:

TokenLength = 32 = length(Token),
Packet = <<0:8, TokenLength:16/big, Token, PayloadLength:16/big, Payload>>,
ssl:send(Socket, Packet),
TokenLength=32=长度(令牌),
数据包=,
ssl:发送(套接字、数据包),
至此,我们将看到长度(标记)实际上是64,而不是32: 您忘记将令牌的十六进制字符串转换为二进制,因此您发送的是64字节的十六进制字符串,而不是32个二进制字节

所以。。。从一开始就将有效负载设置为二进制,并将令牌设置为数字常量,您可以执行以下操作:

Payload = <<"{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}">>,
PayloadLength = size(Payload),
Packet = <<0:8, 32:16/big,
          16#195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03:256/big,
          PayloadLength:16/big, Payload/binary>>,
ssl:send(Socket, Packet),
Payload=,
有效载荷长度=尺寸(有效载荷),
数据包=,
ssl:发送(套接字、数据包),
感谢您指出本答案之前修订版中的一些错误。

我看到两个错误:

  • 令牌应以二进制而不是十六进制ascii传递
  • 不能使用二进制语法将列表转换为二进制文件
要将十六进制解析为整数,然后再解析为二进制,请使用以下内容:

Token = "dead",
TokenNum = erlang:list_to_integer(Token, 16),
TokenBin = <<TokenNum:32/integer-unit:8>>,
TokenBin = ...,
Payload = <<"Payload">>,
PayloadSize = byte_size(Payload),
Packet = <<0:8, 32:16, TokenBin/binary, PayloadSize:16, Payload/binary>>,
Token=“dead”,
TokenNum=erlang:list_to_integer(Token,16),
TokenBin=,
使用如下内容构建协议包:

Token = "dead",
TokenNum = erlang:list_to_integer(Token, 16),
TokenBin = <<TokenNum:32/integer-unit:8>>,
TokenBin = ...,
Payload = <<"Payload">>,
PayloadSize = byte_size(Payload),
Packet = <<0:8, 32:16, TokenBin/binary, PayloadSize:16, Payload/binary>>,
TokenBin=。。。,
有效载荷=,
PayloadSize=字节大小(有效负载),
数据包=,
尝试使用一个简单的库

该库可以通过Erlang端以APN和FCM的形式发送推送通知。如何使用epns(Erlang推送通知)库-您可以在README.md中阅读。此库可以用作项目中的第三方,也可以在本地运行,以了解此库的工作原理:

$ git clone https://github.com/vkatsuba/epns.git
$ cd epns
$ make
在Erlang 20~21上重新测试