苹果推送通知无法接收外文重音字符

3

我正在发送推送通知,当消息包含外国字符(在我的情况下为土耳其语)如İ、ş、ç、ğ时...消息无法到达设备。

以下是我的代码:

$message = 'THİS is push';
$passphrase = 'mypass';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'MyPemFile.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

// Open a connection to the APNS server
$fp = stream_socket_client(
    'ssl://gateway.push.apple.com:2195', $err,
    $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
    exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to Apple service. ' . PHP_EOL;

// Encode the payload as JSON
$body['aps'] = array(
    'alert' => $message,
    'sound' => 'default'
    );
$payload = json_encode($body);

$result = 'Start'.PHP_EOL;
$tokenArray = array('mytoken');
foreach ($tokenArray as $item)
{
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $item) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
    echo 'Failed message'.PHP_EOL;
else
    echo 'Successful message'.PHP_EOL;
}

// Close the connection to the server
fclose($fp);

我尝试使用 utf8_encode() 对 $message 变量进行编码,但接收到的消息是 "THÝS is push"。而其他方法,如 iconv() 则无法正常工作,有些会截断土耳其字符,有些则完全无法接收。

我还有:

header('content-type: text/html; charset: utf-8');

并且

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

在我的页面中,我认为问题不是出现在设置值时,而可能是与pack()函数相关。有什么办法可以解决这个问题而不用将字符替换为英文吗?


var_dump($payload) - 你试图发送什么?猜测:该字符串不是UTF-8编码。进一步猜测:你的源代码不是UTF-8编码。请阅读《每个程序员绝对需要了解的有关编码和字符集以处理文本的知识》(http://kunststube.net/encoding/)。 - deceze
当消息中包含土耳其字符时,var_dump($payload)返回"bool(false)"。但是当不包含土耳其字符时,它返回例如 "{"aps":{"alert":"This is push","sound":"default"}}"。当我使用utf8_encode()进行编码时,字符串难道不会被编码吗?另外,我不应该在echo中看到损坏的字符吗?当我将消息写到屏幕上时,一切看起来都很正常。 - kubilay
阅读我的链接文章,了解utf8_encode实际上是做什么的。 - deceze
我尝试了“将ISO-8859-1字符串编码为UTF-8”,但感到困惑,于是尝试使用utf8_decode()代替...但肯定行不通。所以,你的猜测看起来是正确的。我怎么知道它是用什么编码的? - kubilay
阅读文章的其余部分。 - deceze
2个回答

3
我只需要用以下脚本替换土耳其字符即可:

function tr_to_utf($text) {   
    $text = trim($text);    
    $search = array('Ü','Ş','Ğ','Ç','İ','Ö','ü','ş','ğ','ç','ı','ö');  
    $replace = array('Ãœ','Å','&#286;','Ç','Ä°','Ö','ü','ÅŸ','ÄŸ','ç','ı','ö');
    $new_text = str_replace($search,$replace,$text);    
    return $new_text;  
}

现在它正常工作没有问题。

这是源代码链接


@kubilay,你是怎么做到让它工作的?对我来说不起作用。 - gilsaints88
@gilsaints88 你是什么意思?你确定这个函数工作正常吗?记得你需要将返回的字符串转换为变量,例如 $text = tr_to_utf($text); | 或许你只是使用了 tr_to_utf($text);? - kubilay
@kubilay 是的,我正在使用像 $text = tr_to_utf($text); 这样的代码,但它没有被推送。请问您是否在您的 PHP 中添加了任何头文件?谢谢。 - gilsaints88
@gilsaints88 很抱歉回复晚了,我花了一些时间在档案中找到这段代码。距离我上次使用它已经超过2年了。你可以在我的博客中找到这段代码:http://www.kubilayerdogan.net/?p=450 - kubilay
@kubilay 非常感谢。上周我找到了一种解决办法,把 iOS 代码中的土耳其字符转换了一下,虽然不太优雅,但是暂时先用一下吧 ;) 。再次感谢!当我下次重构代码时,我会尝试你的方法。 - gilsaints88
显示剩余4条评论

0

参数“n”的意思是使用无符号短整型打包(始终为16位,大端字节顺序)。我不确定苹果CPU硬件如何处理指令以及如何转换它们,但肯定与PC不同。尝试切换字节顺序,使用“v”无符号短整型(始终为16位,小端字节顺序)。


好的,我尝试了 {$msg = chr(0).pack('v', 16).pack('H*', $item).pack('v', strlen($payload)).$payload;} 这个,这是你想要的吗?但是它没有接收到任何东西,我可能实际上并没有按照你说的去做。 - kubilay
尝试在这里阅读函数手册http://bg2.php.net/manual/en/function.pack.php,并尝试使用不同的pack()格式字符进行实验。如果问题出现在pack()函数中,那么最终你会找到解决方案。 - Bud Damyanov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接