首页 文章

如何使用SNS主题向特定成员发送推送?

提问于
浏览
1

我正在使用AWS SNS发送推送通知,现在我正在使用 aws-php-sdkpublish 方法发送推送特定设备 . My requirement is sent push to thousands of members within 30 seconds . 当我使用发布方法时,需要5分钟才能发送1000个用户 . 我已经阅读了关于 topic 它一次发送多个成员,但我的方案是我想将推送发送给特定用户,而不是所有主题用户 .

例如,我在一个主题中注册了10,000个成员,但是从这10,000个成员中我发送了9000个,有时是1000个成员 .

所以任何人都知道如何使用主题发送推送,但仅限于特定成员 .

我还想到另一种情况,每次我创建新主题并注册该主题的成员然后向他发送消息然后删除 topic ,但这里每次注册成员时它也需要时间 . 因此,如果您有想要一次注册多个成员,那么它对我也有帮助 .

下面是我目前发送推送的代码 .

$arn = "user arn";
    $sns = new Aws\Sns\SnsClient(array(
                    'version' => 'latest',
                    'key' => my_aws_key,
                    'secret' => aws_secret,
                    'region' => region,
                    'profile' => profile_name,
                    'debug' => false,
                    'http' => array('verify' => false)
                ));
$appArn = "application arn";

$sns->publish(array('Message' => '{ "GCM": "{\"data\": { \"message\": \" This is my message \"} }"}',
                     'MessageStructure' => 'json',
                     'TargetArn' => $arn
                        ));

2 回答

  • 2

    我建议使用 publishAsync() 方法 .

    $userArnCollection = array(
        'arn:XXX',
        'arn:YYY',
        'arn:ZZZ',
    );
    $sns = new Aws\Sns\SnsClient(array(
        'version' => 'latest',
        'key'     => my_aws_key,
        'secret'  => aws_secret,
        'region'  => region,
        'profile' => profile_name,
        'debug'   => false,
        'http'    => array('verify' => false)
    ));
    
    foreach ($userArnCollection as $userArn) {
        $sns->publishAsync(array(
            'Message'          => '{ "GCM": "{\"data\": { \"message\": \" This is my message \"} }"}',
            'MessageStructure' => 'json',
            'TargetArn'        => $userArn
        ));
    }
    

    EDIT

    承诺处理的示例

    $userArnCollection = array(
        'arn:XXX',
        'arn:YYY',
        'arn:ZZZ',
    );
    $sns = new Aws\Sns\SnsClient(array(
        'version' => 'latest',
        'key'     => my_aws_key,
        'secret'  => aws_secret,
        'region'  => region,
        'profile' => profile_name,
        'debug'   => false,
        'http'    => array('verify' => false)
    ));
    
    $promises = array();
    foreach ($userArnCollection as $userArn) {
        $promises[] = $sns->publishAsync(array(
            'Message'          => '{ "GCM": "{\"data\": { \"message\": \" This is my message \"} }"}',
            'MessageStructure' => 'json',
            'TargetArn'        => $userArn
        ));
    }
    
    $results = \GuzzleHttp\Promise\unwrap($promises);
    
  • 2

    在尝试了很多解决方案之后,我能够在一分钟内发送数千个通知,这里我正在显示代码我是如何做到的,我已经完成了 php multicurl 功能,所以我执行多个并行进程并且所有进程同时发送通知 .

    Define multi curl and prepare URL to send notification

    假设我有5000个成员,我有一些令牌和其他成员详细信息 $device_type_ids_arr 我是所有成员的一部分到500一堆,所以每次curl执行它发送通知给500个成员

    $_datas = array_chunk($device_type_ids_arr, 500);
    /*initialise multi curl*/
    $mh = curl_multi_init();
    $handles = array();
    /* Perform loop for each 500 members batch */
    foreach ($_datas as $batchPart) {
        $ch = curl_init();
        $postData['devices'] = $batchPart;
        $postData['push_content'] = $push_content;
        $data_string = json_encode($postData);
        curl_setopt($ch, CURLOPT_URL, base_url() . "EmailPipe/sendNotification/"); //your URL to call amazon service (Explain below)
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_USERAGENT, 'User-Agent: curl/7.39.0');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length:' . strlen($data_string))
        );
        curl_multi_add_handle($mh, $ch);
        $handles[] = $ch;
    }
    // execute requests and poll periodically until all have completed
    $isRunning = null;
    do {
        curl_multi_exec($mh, $isRunning);
    } while ($isRunning > 0);
    
    /* Once all execution are complete remove curl handler */
    foreach ($handles as $ch) {
        curl_multi_remove_handle($mh, $ch);
    }
    /* Close multi curl */
    curl_multi_close($mh);
    

    Function which is received curl request and send notification

    function sendCurlSignal() {
        require_once APPPATH . 'libraries/aws-sdk/aws-autoloader.php';
        $pipeArr = json_decode(file_get_contents('php://input'), true);
        $push_content = $pipeArr["push_content"];
        $device_id_arr = $pipeArr["devices"];
        $sns = new Aws\Sns\SnsClient(array(
            'version' => 'latest',
            'key' => "Amazon key",
            'secret' => "Amazon secret",
            'region' => "region like eu-west-1",
            'profile' => "Amazon account user",
            'debug' => false,
            'http' => array('verify' => false)
        ));
        $appArn = "SNS application arn";
        $promises = $results = $retArr = array();
    
        foreach ($device_id_arr as $key => $device_detail) {
            $arn = $device_detail['arn']; /* SNS ARN of each device */
            $token = $device_detail['token_id']; /* Registered token */
            $userid = $device_detail['member_id'];
            /* If you don't have arn then add arn for specific token in amazon */
            if (empty($arn)) {
                try {
                    $updatedArn = $sns->createPlatformEndpoint(array('PlatformApplicationArn' => $appArn, 'Token' => $token));
                    $arn = $newArn = isset($updatedArn['EndpointArn']) ? $updatedArn['EndpointArn'] : "";
                    //update member detail with new arn
                    if ($newArn != "" && $userid != "" && $token != "") {
                        /* You can update arn into database for this member */
                    }
                } catch (Exception $e) {
                    /* Get error if any */
                    $errorMsg = $e->getMessage();
                    $newFile = fopen("error_arn_fail.txt", "a+");
                    fwrite($newFile, "Member Id:" . $userid . "\r\nToken:" . $token . "\r\n" . $errorMsg . "\r\n");
                    fclose($newFile);
                }
            }
            if (!empty($arn)) {
                try {
                    $promises[$userid] = $sns->publishAsync(array(
                        'Message' => '{ "GCM": "{\"data\": { \"message\": \"' . $push_content . '\" } }"}',
                        'MessageStructure' => 'json',
                        'TargetArn' => $arn
                    ));
                    $promises[$userid]->arn = $arn;
                    $promises[$userid]->token = $token;
                } catch (Exception $e) {
                    $errorMsg = $e->getMessage();
                    $newFile = fopen("error_async_fail_signal.txt", "a+");
                    fwrite($newFile, $errorMsg . "\r\n");
                    fclose($newFile);
                }
            }
        }
        /* Broadcast push notification */
        $results = \GuzzleHttp\Promise\settle($promises)->wait(TRUE);
    
        /* if you want to get result of broadcast and sent message id then do following */
        foreach ($results as $key => $value) {
            if (isset($value['reason'])) {
                /* Reason come in case of fail */
                $message = $value['reason']->getMessage();
                $token = (isset($promises[$key]->token)) ? $promises[$key]->token : "";
                $arn = (isset($promises[$key]->arn)) ? $promises[$key]->arn : "";
                if (empty($arn) || empty($token) || empty($key)) {
                    $newFile = fopen("error_empty_detail_result.txt", "a+");
                    fwrite($newFile, "Member Id:" . $key . "\r\nArn:" . $arn . "\r\nToken:" . $token . "\r\n");
                    fclose($newFile);
                }
                /* Handle error */
                if (strpos($message, "Endpoint is disabled") !== false && $token != "" && $arn != "") {
                    try {
                        $res = $sns->setEndpointAttributes(array(
                            'Attributes' => array("Token" => $token, "Enabled" => "true"),
                            'EndpointArn' => $arn
                        ));
                    } catch (Exception $e) {
                        $errorMsg = $e->getMessage();
                        $newFile = fopen("error_endpoint_disable.txt", "a+");
                        fwrite($newFile, "Member Id:" . $key . "\r\nArn:" . $arn . "\r\nToken:" . $token . "\r\n" . $errorMsg . "\r\n");
                        fclose($newFile);
                    }
                }
                if (strpos($message, "No endpoint found for the target arn specified") !== false && $token != "") {
                    try {
                        $updatedArn = $sns->createPlatformEndpoint(array('PlatformApplicationArn' => $appArn, 'Token' => $token));
                        $arn = $newArn = isset($updatedArn['EndpointArn']) ? $updatedArn['EndpointArn'] : "";
                        //update member detail with new arn
                        if ($newArn != "" && !empty($key) && $token != "") {
                            /* You can update arn into database for this member */
                        }
                    } catch (Exception $e) {
                        $errorMsg = $e->getMessage();
                        $newFile = fopen("error_arn_fail.txt", "a+");
                        fwrite($newFile, "Member Id:" . $key . "\r\nToken:" . $token . "\r\n" . $errorMsg . "\r\n");
                        fclose($newFile);
                    }
                }
                /* After handle error resed notification to this users */
                if (!empty($arn)) {
                    try {
                        $publishRes = $sns->publish(array(
                            'Message' => '{ "GCM": "{\"data\": { \"message\": \"' . $push_content . '\" } }"}',
                            'MessageStructure' => 'json',
                            'TargetArn' => $arn
                        ));
                        $retArr[$key] = $publishRes->get("MessageId");
                    } catch (Exception $e) {
                        $errorMsg = $e->getMessage();
                        $newFile = fopen("error_push_not_sent.txt", "a+");
                        fwrite($newFile, "Member Id:" . $key . "\r\nARN:" . $arn . "\r\nToken:" . $token . "\r\n" . $errorMsg . "\r\n");
                        fclose($newFile);
                    }
                }
            } else {
                $retArr[$key] = $results[$key]['value']->get("MessageId");
            }
        }
    
        /* All member data get into one array to perform database operation */
        if (isset($retArr) && !empty($retArr)) {
            /* in $retArr you get each member amazon message id */
        }
    }
    

相关问题