web-dev-qa-db-ja.com

APNSプッシュ通知が本番環境で機能しない

Webサーバーからリモート通知を送信するアプリを作成しました。アプリを開発モードでテストしたところ、すべての通知が電話に正しく届きました。AppStoreのリリース後、アプリは通知を受信しなくなりました。

ここで私がやったことです:

  1. 本番用と開発用の秘密鍵を作成しました。
  2. 前の生成されたCertFileを渡すことにより、私のアプリIDで2つのSSL証明書を生成しました。 AppIDの下でDev CenterからSSL証明書をダウンロードするために、2つのキーが正しく生成されて正しく渡されたことが100%確信しています。
  3. 開発用と本番用に.pemファイルを作成しました(KeyChainなどから抽出した.p12ファイルを変換することにより)。
  4. 手順1のAppIDに接続された、開発用と本番用の2つの異なるプロビジョニングプロファイルを作成しました。
  5. 手順4で作成した正しいプロビジョニングプロファイルを使用して、ビルド設定でアプリに署名しました。
  6. ユーザーのトークンをキャッチして保存するWebアプリを作成しました。
  7. プッシュ通知の送信をテストするためのphpページを作成しました。

ここで私がテストしたものです:

  1. サンドボックスリンクでtelnetを使用して、開発で生成された.pemファイルをテストし、成功した回答を示しました。
  2. 本番環境で生成された.pemファイルを本番環境のリンクでtelnetを使用してテストし、成功した回答を示しました。
  3. 私は自分のiPhoneの開発トークンをWebアプリケーションに100%確実に保存しました。
  4. 私は自分のiPhoneのプロダクショントークンをWebアプリケーションサーバーに100%確実に保存しました。
  5. 私は100%確実に私のphpページで正しいメッセージをAppleサーバー(開発とプロダクションの両方で)に渡します)。
  6. Phpページは常にApple Server(開発とプロダクションの両方))から成功したメッセージを返します。

Xcodeでアプリに署名する方法は次のとおりです。

enter image description hereenter image description hereenter image description hereenter image description here

通知を送信するphpページのコードは次のとおりです。

    $ctx = stream_context_create();

    //stream_context_set_option($ctx, 'ssl', 'passphrase', 'development_pwd');
    //stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck_development.pem');
    //$fp = stream_socket_client('ssl://gateway.sandbox.Push.Apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); //test

    stream_context_set_option($ctx, 'ssl', 'passphrase', 'production_pwd');
    stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck_production.pem');
    $fp = stream_socket_client('ssl://gateway.Push.Apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); //production

    echo "<p>Connection Open</p>";
    if(!$fp){
        echo "<p>Failed to connect!<br />Error Number: " . $err . " <br />Code: " . $errstrn . "</p>";
        return;
    } else {
        echo "<p>Sending notification!</p>";    
    }

    $i = 0;

    foreach ($deviceToken as $dt) {
        $dt = str_replace(' ' , '' , $dt);
        $msg = chr(0) . pack('n',32) . pack('H*', $dt) . pack('n',strlen($payload)) . $payload;
        echo "<p>" . $i . " - Message sent: " . $payload . "<br />Token: ". $dt . "<br />***" . $msg . "***</p>";
        $result = fwrite($fp, $msg, strlen($msg));
        $i++;
        if (!$result)
            echo '<p>Message not delivered ' . PHP_EOL . '!</p>';
        else
            echo '<p>Message successfully delivered ' . PHP_EOL . '!</p>';
    }
    fclose($fp);
    echo "<p>Total Notifications Sent: " . $i . "</p>";
    echo "<p>Connection Closed!</p>";
}
?>

結論:私のPCには、APNSプッシュ通知を受信するテストアプリがあります。 APNSプッシュ通知を受信しないまったく同じアプリをApp Storeでリリースしています。

私は本当に、この問題を修正するために私の力ですべてを作り、フォーラム、stackoverflow、およびAppleドキュメントの約1000ページを読みました。

私は私の問題の解決策を見つけるのを手伝ってくれるあなたのすべての人を喜んで追悼します!

22
prelite

あなたが言及したリンクは、サンドボックスAPNSリンクです。本番APNSリンクはApple documentation のとおりです:

gateway.Push.Apple.com、アウトバウンドTCPポート2195で本番環境にアクセスします。

確認すること:

  1. AppIdが配布APNSに対して有効になっています。
  2. 配布APNS SSL証明書を作成し、ビルドマシンにインストールしました(App Store送信用)。
  3. 手順2でサーバーにSSL証明書をインストールしました。
  4. 開発APNS SSL証明書を誤って使用していない。
16
gagarwal

製品とサンドボックスのデバイストークンは、同じデバイスでは異なります。

アドホックまたは配布の証明書を使用してデバイストークンを取得し、生成されたトークンを本番環境で使用してみてください。これは私にとってはうまくいきました。

13
Ravindra Naik

私は同じ問題に出くわしました。プッシュ通知は、プロダクションではなく、開発モードで届きます。私も数回すべてをチェックし、すべてが大丈夫であると確信していました。

しかし、そうではありませんでした。それはプロセスの最初のステップでした。 csrを作成します。開発と本番用のcsrファイルを作成する必要はなく、両方の証明書に同じcsrファイルを使用することになりました。うまくいきませんでした...

たぶん、将来誰かが同じ間違いをすることで、時間を節約できます。

2
butters