How to send Extra parameters in payload via Amazon

2019-01-21 14:05发布

问题:

This is something new i am asking as i haven't got it any answers for it on SO.

I am using Amazon SNS Push for sending push to my registered devices, everything is working good, i can register devices on my app first start, can send push etc etc. The problem i am facing is that, i want to open a specific page when i open my app through push. I want to send some extra params with the payload but i am not able to do that.

I tried this Link :- http://docs.aws.amazon.com/sns/latest/api/API_Publish.html

we have only one key i.e. "Message", in which we can pass the payload as far as i know.

i want pass a payload like this :-

{
    aps = {
            alert = "My Push text Msg";
          };
    "id" = "123",
    "s" = "section"
}

or any other format is fine, i just wanted to pass 2-3 values along with payload so that i can use them in my app.

The code i am using for sending push is :-

// Load the AWS SDK for PHP
if($_REQUEST)
{
    $title=$_REQUEST["push_text"];

    if($title!="")
    {
        require 'aws-sdk.phar';


        // Create a new Amazon SNS client
        $sns = Aws\Sns\SnsClient::factory(array(
            'key'    => '...',
            'secret' => '...',
            'region' => 'us-east-1'
        ));

        // Get and display the platform applications
        //print("List All Platform Applications:\n");
        $Model1 = $sns->listPlatformApplications();

        print("\n</br></br>");*/

        // Get the Arn of the first application
        $AppArn = $Model1['PlatformApplications'][0]['PlatformApplicationArn'];

        // Get the application's endpoints
        $Model2 = $sns->listEndpointsByPlatformApplication(array('PlatformApplicationArn' => $AppArn));

        // Display all of the endpoints for the first application
        //print("List All Endpoints for First App:\n");
        foreach ($Model2['Endpoints'] as $Endpoint)
        {
          $EndpointArn = $Endpoint['EndpointArn'];
          //print($EndpointArn . "\n");
        }
        //print("\n</br></br>");

        // Send a message to each endpoint
        //print("Send Message to all Endpoints:\n");
        foreach ($Model2['Endpoints'] as $Endpoint)
        {
          $EndpointArn = $Endpoint['EndpointArn'];

          try
          {
            $sns->publish(array('Message' => $title,
                    'TargetArn' => $EndpointArn));

            //print($EndpointArn . " - Succeeded!\n");
          }
          catch (Exception $e)
          {
            //print($EndpointArn . " - Failed: " . $e->getMessage() . "!\n");
          }
        }
    }
}
?>

Any help or idea will be appreciated. Thanks in advance.

回答1:

The Amazon SNS documentation is still lacking here, with few pointers on how to format a message to use a custom payload. This FAQ explains how to do it, but doesn't provide an example.

The solution is to publish the notification with the MessageStructure parameter set to json and a Message parameter that is json-encoded, with a key for each transport protocol. There always needs to be a default key too, as a fallback.

This is an example for iOS notifications with a custom payload:

array(
    'TargetArn' => $EndpointArn,
    'MessageStructure' => 'json',
    'Message' => json_encode(array(
        'default' => $title,
        'APNS' => json_encode(array(
            'aps' => array(
                'alert' => $title,
            ),
            // Custom payload parameters can go here
            'id' => '123',
            's' => 'section'
        ))

    ))
);

The same goes for other protocols as well. The format of the json_encoded message must be like this (but you can omit keys if you don't use the transport):

{ 
    "default": "<enter your message here>", 
    "email": "<enter your message here>", 
    "sqs": "<enter your message here>", 
    "http": "<enter your message here>", 
    "https": "<enter your message here>", 
    "sms": "<enter your message here>", 
    "APNS": "{\"aps\":{\"alert\": \"<message>\",\"sound\":\"default\"} }", 
    "APNS_SANDBOX": "{\"aps\":{\"alert\": \"<message>\",\"sound\":\"default\"} }", 
    "GCM": "{ \"data\": { \"message\": \"<message>\" } }", 
    "ADM": "{ \"data\": { \"message\": \"<message>\" } }" 
}


回答2:

From a Lambda function (Node.js) the call should be:

exports.handler = function(event, context) {

  var params = {
    'TargetArn' : $EndpointArn,
    'MessageStructure' : 'json',
    'Message' : JSON.stringify({
      'default' : $title,
      'APNS' : JSON.stringify({
        'aps' : { 
          'alert' : $title,
          'badge' : '0',
          'sound' : 'default'
        },
        'id' : '123',
        's' : 'section',
      }),
      'APNS_SANDBOX' : JSON.stringify({
        'aps' : { 
          'alert' : $title,
          'badge' : '0',
          'sound' : 'default'
        },
        'id' : '123',
        's' : 'section',
      })
    })
  };

  var sns = new AWS.SNS({apiVersion: '2010-03-31', region: 'us-east-1' });
  sns.publish(params, function(err, data) {
    if (err) {
      // Error
      context.fail(err);
    }
    else {
      // Success
      context.succeed();
    }
  });
}

You can simplify by specifying only one protocol: APNS or APNS_SANDBOX.



回答3:

I am too inexperienced to comment here but I would like to draw peoples attention to the nested json_encode. This is important without it the APNS string will not be parsed by Amazon and it will send only the default message value.

I was doing the following:

$message = json_encode(array(
   'default'=>$msg,
   'APNS'=>array(
      'aps'=>array(
         'alert'=>$msg,
         'sound'=>'default'
         ),
         'id'=>$id,
         'other'=>$other
       )
     )
   );

But this will not work. You MUST json_encode the array under 'APNS' separately as shown in felixdv's answer. Don't ask me why as the outputs look exactly the same in my console log. Although the docs show that the json string under the 'APNS' key should be wrapped in "" so suspect this has something to do with it.

http://docs.aws.amazon.com/sns/latest/dg/mobile-push-send-custommessage.html

Dont be fooled though as the JSON will validate fine without these double quotes.

Also I am not sure about emkman's comment. Without the 'default' key in the above structure being sent to a single endpoint ARN I would receive an error from AWS.

Hope that speeds up someones afternoon.

EDIT

Subsequently cleared up the need to nest the json_encodes - it creates escaped double quotes which despite the docs saying arent required at the API they are for the whole string for GCM and as above the sub array under APNS for apple. This maybe my implementation but its pretty much out of the box using the AWS PHP SDK and was the only way to make it send custom data.



回答4:

Easy to miss that you need to add APNS_SANDBOX as well as APNS for testing locally.