AWS Dedicated long code number fails to send SMS - amazon-web-services

I have requested a dedicated long code number from AWS Pinpoint. And I have enabled two way sms for it. And tried to send TRANSACTIONAL SMS to a number, Although SMS's are receiving but they are not from My dedicated long code but they are from default senderId IM-NOTICE.
SAMPLE PYTHON CODE I TRIED:
region = "ap-south-1"
originationNumber = "+91xxxxxxxxxx"
destinationNumber = "+91xxxxxxxxxx"
message = ("This is a sample message sent from Amazon Pinpoint by using the "
"AWS SDK for Python (Boto 3).")
applicationId = "xxxxxxxxxxxxxxxxx"
messageType = "TRANSACTIONAL"
registeredKeyword = "xxxxxx"
senderId = "MySenderID"
client = boto3.client('pinpoint',
aws_access_key_id='AKIAIVXXXXXXKHXXXXP33RWFHLNXXXXXXXYYA',
aws_secret_access_key='XXXUPbs6Kj6O2iXXXXXXXXXXXXXXX',
region_name=region)
try:
response = client.send_messages(
ApplicationId=applicationId,
MessageRequest={
'Addresses': {
destinationNumber: {
'ChannelType': 'SMS'
}
},
'MessageConfiguration': {
'SMSMessage': {
'Body': message,
'Keyword': registeredKeyword,
'MessageType': messageType,
'OriginationNumber': originationNumber,
'SenderId': senderId
}
}
}
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Message sent! Message ID: "
+ response['MessageResponse']['Result'][destinationNumber]['MessageId'])

Related

Multiple connected clients to AWS serverless websocket

When I connect to the web-socket from two devices, only the most recent one works. I remembered that the connection is related to the ConnectionId. When a new connection is created, a new ConnectionId is generated too. I was thinking that in the case of two devices, I would need two parameters set up in the parameter store: ConnectioId1 and ConnectionId2. But what should I change in the lambda functions to be able to connect two devices?
myConnection.js lambda function:
const AWS = require('aws-sdk')
var mySSM_Client = new AWS.SSM();
exports.handler = async (event, context) => {
console.log(event);
let connectionId = event.requestContext.connectionId;
console.log("myConnectionID is: ", connectionId)
var params = {
Name: 'connection_id',
Value: connectionId,
Overwrite: true
};
var mySSM_request = await mySSM_Client.putParameter(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log("success: ", data); // successful response
}).promise()
console.log("My request: ", mySSM_request)
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
sendIoTdata.py lambda function:
import json
import boto3
Websocket_HTTPS_URL = "**********/production"
client = boto3.client("apigatewaymanagementapi", endpoint_url = Websocket_HTTPS_URL)
ssm_Client = boto3.client('ssm')
def lambda_handler(event, context):
print(event)
response_ssm = ssm_Client.get_parameter(Name='connection_id')
print("my stored connection id: ", response_ssm['Parameter']['Value'] )
connectionId = response_ssm['Parameter']['Value'] #dig into the response blob to get our string cvalue
Test_Message = json.dumps({ "message": "Hello from lambda, hardcoded test message"})
IoT_Message = json.dumps(event)
#AWS API Gateway API's require 'key=value' arguments
response = client.post_to_connection(ConnectionId = connectionId, Data = IoT_Message)

How to add content_available when I use fcm by aws pinpoint? (iOS background message handler)

I was checked that setBackgroundMessageHandler of #react-native-firebase/messaging module works well when tested as follows body through FCM REST API.
{
"to" : DEVICE_TOKEN,
"notification" : {
"body" : "TEST BODY",
"title": "TEST TITLE"
},
"content_available":true
}
I want to send FCM message through aws pinpoint.
When I checked, #react-native-firebase/messaging module can receive notification type message.
Therefore, to send a notification message, I create and send a message as shown below.
let params = {
ApplicationId: applicationID /* required */,
SendUsersMessageRequest: {
/* required */
MessageConfiguration: {
/* required */
GCMMessage: {
"RawContent": `{\"notification\": {\"title\": \"${title}\",\"body\":\"${message}\", \"sound\":\"default\"}, \"content_available\": \"true\"}`
},
},
Users: users,
},
};
try {
return await pinpoint.sendUsersMessages(params).promise();
} catch (err) {
console.log('Error - ', err);
}
LOG A new FCM message arrived! {"messageId":"1656032665101862","data":{"pinpoint.campaign.campaign_id":"_DIRECT"},"notification":{"body":"TEST BODY","sound":"default","title":"TEST TITLE"},"from":"560179008583"}
However, when checking the remoteMessage, the content_available value cannot be received by the app.
Is there any way to send content_available using AWS Pinpoint's GCMMessage?
If you have any guides or advice for me to solve this problem, please.

Using AWS Lambda Console to send push using SNS

I tried every possible solution on the internet with no hope
What I am trying to do is simply use aws lambda functions (through the aws console) to fetch user fcm token from lets say DynamoDB (not included in the question), use that token to create endpointArn, send push to that specific device
I tested to send Using SNS console and the push gets to the device successfully but I failed to get it to the device using Lambda functions although it gives success status and message ID
Here is the code I used
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set region
AWS.config.update({region: 'us-east-1'});
const sns = new AWS.SNS()
const sampleMessage = {
"GCM": {
"notification": {
"body": "Sample message for Android endpoints",
"title":"Title Test"
}
}
}
exports.handler = async (event) => {
const snsPayload = JSON.stringify(sampleMessage);
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
const params = {
PlatformApplicationArn: '<Platform Arn>',
Token: '<FCM Token>'
};
try {
const endpointData = await sns.createPlatformEndpoint(params).promise();
const paramsMessage = {
Message: snsPayload,
TargetArn: endpointData.EndpointArn
};
var publishTextPromise = await sns.publish(paramsMessage).promise();
response.MessageId = publishTextPromise.MessageId;
response.result = 'Success';
}
catch (e) {
console.log(e.stack)
response.result = 'Error'
}
return response;
};
After some trials and errors I figured out the solution for my own question
1- The GCM part of the payload should be a string not a json
2- The message parameter should have an attribute that explicitly sets the mime type of the payload to Json
Taking all that into consideration
const GCM_data = {
'notification': {
'body': 'Hellow from lambda function',
'title': 'Notification Title'
}
}
const data = {
"GCM": JSON.stringify(GCM_data)
}
const snsPayload = JSON.stringify(data)
and the params should look like
const paramsMessage = {
Message: snsPayload,
TargetArn: endpointData.EndpointArn,
MessageStructure: 'json'
};
and this will work :)

Instance created via Service Account unable to use Google Cloud Speech API - authentication error

I followed Google's Quick-Start documentation for the Speech API to enable billing and API for an account. This account has authorized a service account to create Compute instances on its behalf. After creating an instance on the child account, hosting a binary to use the Speech API, I am unable to successfully use the example C# code provided by Google in the C# speech example:
try
{
var speech = SpeechClient.Create();
var response = speech.Recognize(new RecognitionConfig()
{
Encoding = RecognitionConfig.Types.AudioEncoding.Linear16,
LanguageCode = "en"
}, RecognitionAudio.FromFile(audioFiles[0]));
foreach (var result in response.Results)
{
foreach (var alternative in result.Alternatives)
{
Debug.WriteLine(alternative.Transcript);
}
}
} catch (Exception ex)
// ...
}
Requests fail on the SpeechClient.Create() line with the following error:
--------------------------- Grpc.Core.RpcException: Status(StatusCode=Unauthenticated, Detail="Exception occured in
metadata credentials plugin.")
at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task)
at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task)
at Grpc.Core.Internal.AsyncCall`2.UnaryCall(TRequest msg)
at
Grpc.Core.Calls.BlockingUnaryCall[TRequest,TResponse](CallInvocationDetails`2
call, TRequest req)
at
Grpc.Core.DefaultCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2
method, String host, CallOptions options, TRequest request)
at
Grpc.Core.Internal.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2
method, String host, CallOptions options, TRequest request)
at
Google.Cloud.Speech.V1.Speech.SpeechClient.Recognize(RecognizeRequest
request, CallOptions options)
at
Google.Api.Gax.Grpc.ApiCall.<>c__DisplayClass0_0`2.b__1(TRequest
req, CallSettings cs)
at
Google.Api.Gax.Grpc.ApiCallRetryExtensions.<>c__DisplayClass1_0`2.b__0(TRequest
request, CallSettings callSettings)
at Google.Api.Gax.Grpc.ApiCall`2.Sync(TRequest request,
CallSettings perCallCallSettings)
at
Google.Cloud.Speech.V1.SpeechClientImpl.Recognize(RecognizeRequest
request, CallSettings callSettings)
at Google.Cloud.Speech.V1.SpeechClient.Recognize(RecognitionConfig
config, RecognitionAudio audio, CallSettings callSettings)
at Rc2Solver.frmMain.RecognizeWordsGoogleSpeechApi() in
C:\Users\jorda\Google
Drive\VSProjects\Rc2Solver\Rc2Solver\frmMain.cs:line 1770
--------------------------- OK
I have verified that the Speech API is activated. Here is the scope that the service account uses when creating the Compute instances:
credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(me)
{
Scopes = new[] { ComputeService.Scope.Compute, ComputeService.Scope.CloudPlatform }
}.FromPrivateKey(yk)
);
I have found no information or code online about specifically authorizing or authenticating the Speech API for service account actors. Any help is appreciated.
It turns out the issue was that the Cloud Compute instances needed to be created with a ServiceAccount parameter specified. Otherwise the Cloud instances were not part of a ServiceAccount default credential, which is referenced by the SpeechClient.Create() call. Here is the proper way to create an instance attached to a service account, and it will use the SA tied to the project ID:
service = new ComputeService(new BaseClientService.Initializer() {
HttpClientInitializer = credential,
ApplicationName = "YourAppName"
});
string MyProjectId = "example-project-27172";
var project = await service.Projects.Get(MyProjectId).ExecuteAsync();
ServiceAccount servAcct = new ServiceAccount() {
Email = project.DefaultServiceAccount,
Scopes = new [] {
"https://www.googleapis.com/auth/cloud-platform"
}
};
Instance instance = new Instance() {
MachineType = service.BaseUri + MyProjectId + "/zones/" + targetZone + "/machineTypes/" + "g1-small",
Name = name,
Description = name,
Disks = attachedDisks,
NetworkInterfaces = networkInterfaces,
ServiceAccounts = new [] {
servAcct
},
Metadata = md
};
batchRequest.Queue < Instance > (service.Instances.Insert(instance, MyProjectId, targetZone),
(content, error, i, message) => {
if (error != null) {
AddEventMsg("Error creating instance " + name + ": " + error.ToString());
} else {
AddEventMsg("Instance " + name + " created");
}
});

google glass notification mismatch development and production server

I try to send notification through menu in my app using mirror api. for development environment I am using a proxy server but in production I am using just SSl cause it is public domain. my callback URL for this two section is bellow
// development
callbackUrl = "https://3a4660af.ngrok.com/notify";
// production
if (callbackUrl.equals("https://www.mydomain.com:8080/notify")) {
callbackUrl = "https://www.mydomain.com:8443/notify";
} else {
callbackUrl = "https://www.mydomain.com:8443/notify";
}
LOG.info("\ncallbackUrl : " + callbackUrl);
Subscription subscription = new Subscription();
subscription.setCollection(collection);
subscription.setVerifyToken(userId);
subscription.setCallbackUrl(callbackUrl);
subscription.setUserToken(userId);
getMirror(credential).subscriptions().insert(subscription)
.execute();
But when I try to read notification from notification class I got mismatch so that the notification action is not working. the notification log in bellow
//development
got raw notification : { "collection": "timeline",
"itemId": "6fa2445e-b14f-46b2-9cff-f0d44d63ecab",
"operation": "UPDATE", "verifyToken": "103560737611562800385",
"userToken": "103560737611562800385",
"userActions": [ { "type": "CUSTOM", "payload": "dealMenu" } ]}
//production
got raw notification : "collection": "timeline",
"operation": "UPDATE",
"userToken": "103560737611562800385", { "payload": "dealMenu" ]null
in Notification class
BufferedReader notificationReader = new BufferedReader(
new InputStreamReader(request.getInputStream()));
String notificationString = "";
// Count the lines as a very basic way to prevent Denial of Service
// attacks
int lines = 0;
while (notificationReader.ready()) {
notificationString += notificationReader.readLine();
lines++;
LOG.info("\ngot raw notification during read : "
+ notificationString);
// No notification would ever be this long. Something is very wrong.
if (lines > 1000) {
throw new IOException(
"Attempted to parse notification payload that was unexpectedly long.");
}
}
LOG.info("\ngot raw notification : " + notificationString);
JsonFactory jsonFactory = new JacksonFactory();
LOG.info("\ngot jsonFactory : " + jsonFactory);
// If logging the payload is not as important, use
// jacksonFactory.fromInputStream instead.
Notification notification = jsonFactory.fromString(notificationString,
Notification.class);
LOG.info("\n got notification " + notification);
In production I cannot received all the perimeters what I need. Why this mismatch happen???