4

我曾多次尝试向我的应用程序发送推送通知,但无济于事。我遵循了许多教程并遵循了所有步骤。我从 APNS 服务器收到了成功的消息,但没有消息到达设备。我已经使用成功到达的开发证书测试了发送,并且我已经生成了适当的生产证书并在 php 脚本中使用它们。我将在下面发布我的代码。如果您发现我做错了什么,请告诉我。我只是不知道它是什么...

任何帮助将不胜感激。

<?php
$link=mysqli_connect('****','****','****','***');
if(mysqli_connect_errno())
{
    header('HTTP/1.1 400');
    header('Content-type: text/html');
    echo 'Connection Error: %s\n',mysqli_connect_error();
    exit;
}
echo "Connected to Database<br />";
echo "Querying Database<br />";
switch ($_REQUEST['App'])
{
    case "O2":
        $query="SELECT Token FROM O2CalculatorPushTokens";
        break;
    case "LZA":
        $query="SELECT Token FROM LZAPushTokens";
        break;
    case "MorseCode":
        $query="SELECT Token FROM MorseCodePushTokens";
        break;
    default:
        echo "Unknown App.";    
        exit;
}
$result=mysqli_query($link,$query);
echo mysqli_num_rows($result)."<br />";
if ($result==false)
{
    echo "No tokens to send to.";
}
else
{
    //Set SSL context
    $ctx = stream_context_create();
    echo "Loading SSL Certificate...<br>";
    switch($_REQUEST['App'])
    {
        case "O2":
            stream_context_set_option($ctx, 'ssl', 'local_cert', 'SSL/O2CalculatorProductionSSL.pem');
            break;
        case "LZA":
            stream_context_set_option($ctx, 'ssl', 'local_cert', 'SSL/LandingZoneAssistantProductionSSL.pem');
            break;
        case "MorseCode":
            stream_context_set_option($ctx, 'ssl', 'local_cert', 'SSL/MorseCodeProductionSSL.pem');
            break;
        default:
            exit;
    }   
    echo "Unlocking SSL Certificate...<br><br>";
    stream_context_set_option($ctx, 'ssl', 'passphrase', '****');

    //Open a connection to the APNS server
    echo "Connecting to APNS server...<br>";
    $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<br><br>");
    else echo "Connected to APNS!<br />";

    //Create the payload body
    echo "Creating message...<br>";
    $body['aps'] = array('alert' => $_REQUEST['PushMessageTextArea']);
    echo $body."<br>";

    //Encode the payload as JSON
    echo "Encoding message...<br>";
    $payload = json_encode($body);
    echo $payload."<br>";

    while($row=mysqli_fetch_assoc($result))
    {
        //Build the binary notification
        echo "Sending message to ".$row['Token']."<br>";
        $msg = chr(0).pack('n',32).pack('H*',$row['Token']).pack('n',strlen($payload)).$payload;
        //Send it to the server
        $PushResult = fwrite($fp, $msg, strlen($msg));
        if (!$PushResult) echo "Message not delivered! <br />";
        else echo "Message successfully delivered! <br />";
    };

    //Close connection to the server
    echo "Closing APNS connection...<br><br>";
    fclose($fp);
    mysqli_free_result($result);
}
mysqli_close($link);

还有我的 iPhone 脚本...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.

//Register for push notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert)];
return YES;
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"registeredForPush"])
{
    //Remove spaces and brackets from deviceToken
    NSString* token  = [deviceToken description];
    token = [token stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];

    NSMutableString *params = [[NSMutableString alloc] initWithFormat:@"Token="];
    [params appendString:token];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.bluelineapps.net/****.php"] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:100.0];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (connection)
    {
    //Show alert
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Thank you!" message:@"Thank you for registering for updates. Please rate this app in the AppStore after you've had some time to use it. Feedback is welcome and can be sent using the 'Feedback' tab below. Enjoy!" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
    [alert dismissWithClickedButtonIndex:0 animated:TRUE];
    [alert show];
    }
    else
    {
        //Show Error
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Registration error!" message:@"Failed to register for updates. Please try again later in your 'Settings' app. Sorry for the inconvenience." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
        [alert dismissWithClickedButtonIndex:0 animated:TRUE];
        [alert show];
    }
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"registeredForPush"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}
}

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(@"Failed to get token, error: %@", error);
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Landing Zone Assistant" message:[userInfo valueForKeyPath:@"alert"] delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
[alert show];
}

@end

更新:

好的,所以在删除所有 Mobile Provisioning 配置文件、所有证书、所有 .pem 文件、所有内容并为开发和生产重新生成所有证书、密钥、权限和配置文件之后,我的问题仍然存在......

使用沙盒网关向设备上的调试版本发送消息,成功。使用主苹果网关发送消息以在测试设备上发布 Ad Hoc 版本,不成功....

有任何想法吗?

我没有收到来自 APNS 服务的错​​误消息,一切都成功了。没有构建错误。全新的最新证书...


更新:

我在这里从 Apple 技术支持处找到了这篇文章,并按照所有步骤检查了所有内容。据我所知,一切都检查完毕。我的生产版本确实包含生产的 aps_environment 。

我还发现了这种生成 .pem 文件的方法,这与我之前的尝试有些不同,所以我尝试了这个,但它仍然不起作用。我的代码仍然与上面相同,因为问题似乎出在其他地方,但是如果有人在扫描时看到某些东西,请告诉我。我只是想让这个工作。

我很乐意在这个问题上悬赏,但我没有足够的声誉,我一直试图通过帮助别人解决问题来获得一些。


更新:

在搜索时,我在此处找到了 Apple 的另一份文档,其中有一行说明“注意生产环境中的设备令牌和开发(沙盒)环境中的设备令牌的值不同。” 所以我想另一个问题是。

开发和生产模式的 deviceToken 是否不同?


更新:

我知道这会越来越长,但我试图展示我已经采取了哪些步骤来尝试自我解决这个问题。

我一直在文档中看到这个 Entrust CA 证书弹出。我已经使用它来验证与 APNS 网关的连接,但是在发送推送消息时我没有在我的连接中使用它,因为我所看到的示例都没有显示使用它。这是必需的吗?如果是这样,我该如何使用它?


更新:

我决定尝试使用 PhoneGap 重新开发我的应用程序并接触更多的受众,所以我现在将关闭它。感谢大家的帮助。

4

1 回答 1

-1

在你查看代码之前,打开生产配置文件并仔细检查它是否有条目:

    <key>ProvisionsAllDevices</key><true/>

我猜该设备已在开发配置文件中注册,因此它在那里工作但不适用于 prod 的事实让我相信问题出在配置文件本身。您必须拥有 Apple 的 Enterprise Developer 帐户才能创建可配置任何设备的配置文件。

于 2012-12-15T06:23:40.580 回答