How can I send an SMS message programatically from an iPhone app? I'm using Twilio right now, and can correctly set up a HTTP Request, authenticate with the server, and get a response.
There must be some misconfiguration of the HTTP Headers as I can get a response from the Twilio servers but never passes the right data through.
My current code is in a method that's called by a simple button press.
- (IBAction)sendButtonPressed:(id)sender {
NSLog(#"Button pressed.");
NSString *kYourTwillioSID = #"AC8c3...f6da3";
NSString *urlString = [NSString stringWithFormat:#"https://AC8c3...6da3:bf...0b7#api.twilio.com/2010-04-01/Accounts/%#/SMS/Messages", kYourTwillioSID];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setValue:#"+18584334333" forHTTPHeaderField:#"From"];
[request setValue:#"+13063707780" forHTTPHeaderField:#"To"];
[request setValue:#"Hello\n" forHTTPHeaderField:#"Body"];
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (!error) {
NSString *response_details = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"%#",response_details);
}
NSLog(#"Request finished %#", error);
If you are just looking to send an SMS message in iOS you can use the MFMessageComposeViewController inside of the MessageUI.framework. As you know though, this requires user-interaction.
As you had requested, you can use Twilio to send SMS directly using almost any platform. For iOS you can use the following Swift code to hit the Twilio API and send any text messages you'd like:
func tappedSendButton() {
print("Tapped button")
// Use your own details here
let twilioSID = "AC8c3...6da3"
let twilioSecret = "bf2...b0b7"
let fromNumber = "4152226666"
let toNumber = "4153338888"
let message = "Hey"
// Build the request
let request = NSMutableURLRequest(URL: NSURL(string:"https://\(twilioSID):\(twilioSecret)#api.twilio.com/2010-04-01/Accounts/\(twilioSID)/SMS/Messages")!)
request.HTTPMethod = "POST"
request.HTTPBody = "From=\(fromNumber)&To=\(toNumber)&Body=\(message)".dataUsingEncoding(NSUTF8StringEncoding)
// Build the completion block and send the request
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
print("Finished")
if let data = data, responseDetails = NSString(data: data, encoding: NSUTF8StringEncoding) {
// Success
print("Response: \(responseDetails)")
} else {
// Failure
print("Error: \(error)")
}
}).resume()
For any further API interaction you can check out the official docs: https://www.twilio.com/docs/api/rest
Use AFNetworking to send request.
NSString *kTwilioSID = #"AC73bb270.......4d418cb8";
NSString *kTwilioSecret = #"335199.....9";
NSString *kFromNumber = #"+1......1";
NSString *kToNumber = #"+91.......8";
NSString *kMessage = #"Hi";
NSString *urlString = [NSString
stringWithFormat:#"https://%#:%##api.twilio.com/2010-04-01/Accounts/%#/SMS/Messages/",
kTwilioSID, kTwilioSecret,kTwilioSID];
NSDictionary*
dic=#{#"From":kFromNumber,#"To":kToNumber,#"Body":kMessage};
__block NSArray* jsonArray;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer=[AFHTTPResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes=[NSSet setWithObject:#"application/xml"];
[manager POST:urlString parameters:para success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSError* err;
NSLog(#"success %#",[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
jsonArray=[NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments
error:&err];
[_del getJsonResponsePOST:jsonArray];
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
[_del getError:[NSString stringWithFormat:#"%#",error]];
}];
It could be this:
The number +YOURNUMBER is unverified. Trial accounts cannot send messages to unverified numbers; verify +YOURNUMBER at twilio.com/user/account/phone-numbers/verified, or purchase a Twilio number to send messages to unverified numbers.
Twilio with Swift 2.2+, Alamofire, SwiftyJSON -> answer:
import Alamofire
import SwiftyJSON
........
........
//twillio config
private static let TWILIO_ACCOUNT_SID = "A...7"
private static let TWILIO_AUTH_TOKEN = "6...5"
//end url string is .json,to get response as JSON
static let URL_TWILIO_SMS = "https://\(TWILIO_ACCOUNT_SID):\(TWILIO_AUTH_TOKEN)#api.twilio.com/2010-04-01/Accounts/\(TWILIO_ACCOUNT_SID)/SMS/Messages.json"
Alamofire.request(.POST, URL_TWILIO_SMS, parameters: ["To":"+880....6","From":"+1...9","Body":"Hellow Rafsun"])
.responseJSON { response in
if let jso = response.result.value {
let json = JSON(jso)
//Twilio response
if let twStatus = json["status"].string,twSentMessage = json["body"].string where twStatus == "queued"{
//Twilio message sent
}else{
//Twilio message not sent
}
}else if let error = response.result.error?.localizedDescription{
//parse error
}
}
An example (updated) for Xcode 8 and Swift 3.
https://www.twilio.com/blog/2016/11/how-to-send-an-sms-from-ios-in-swift.html
We don't recommend storing your credentials client side and so the post shows you how to avoid a potential vulnerability using a server-side language of your choosing and Alamofire for HTTP requests:
#IBAction func sendData(sender: AnyObject) {
let headers = [
"Content-Type": "application/x-www-form-urlencoded"
]
let parameters: Parameters = [
"To": phoneNumberField.text ?? "",
"Body": messageField.text ?? ""
]
Alamofire.request("YOUR_NGROK_URL/sms", method: .post, parameters: parameters, headers: headers).response { response in
print(response)
}
}
Related
When I use AFNetworking to post parameters is NSMutableDictionary, this request is succeeded.
But when I used NSURLSession, the self.request!.HTTPBody must be NSData, so request failed.
How can I use NSURLSession to make request succeeded?
postDict[#"jgId"] = "1000000000";
[manager GET:SELECTDEPART parameters:postDict success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"-----%#", error);
}];
//use NSData
NSJSONSerialization.dataWithJSONObject(postDict, options: NSJSONWritingOptions.PrettyPrinted)
Please help me.
let params = ["jgId": "1000000000"]
let data = try? JSONSerialization.data(withJSONObject: params, options: [JSONSerialization.WritingOptions(rawValue: 0)])
var request = URLRequest(url: URL(string: "https://my-url.com")!, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 30)
request.httpMethod = "POST"
request.httpBody = data
request.allHTTPHeaderFields = [:]
URLSession.shared.dataTask(with: request) { (data, response, error) in
}
You are correct, for NSURLSession you need NSData.
But you can easily convert an NSDictionary to NSData by using NSKeyedArchiver.
You are using GET method to request data from server, so your parameters is not sent by request HTTPBody data. Your params is simple past via request URL.
In question You have SELECTDEPART as base URL of request and postDict as parameter. The following code use NSURLSession to make GET request with parameters
// get request URL from base URL and params
NSURLComponents *components = [NSURLComponents componentsWithString:#"http://stackoverflow.com"]; // some thing like SELECTDEPART in your question
NSDictionary *params = #{ #"q": #"ios", #"count": #"10" }; // params of request like your postDict
NSMutableArray *queryItems = [NSMutableArray array];
for (NSString *key in params.allKeys) {
[queryItems addObject:[NSURLQueryItem queryItemWithName:key value:params[key]]];
}
components.queryItems = queryItems;
NSURL *url = components.URL;
// create request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = #"GET";
// data task with NSURLSession
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
// parse your data here
} else {
// handle error here
}
}];
[task resume];
I have successfully implemented profile sharing option with PayPal iOS Sdk.
I am getting proper code once user logged in to paypal account in the app.
I have tried to get the user information with curl command I got success.
Now I want to implement 2nd and 3rd step through api call.
Below is what I have implemented for getting refresh token from PayPal server.
func getTheRefreshToken(authToken:NSString) {
print("Token \(authToken)")
let urlPath: String = "https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice"
let url: NSURL = NSURL(string: urlPath)!
let request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
let basicAuthCredentials: String = "AXvaZH_Bs9**CLIENTID**0RbhP0G8Miw-y:ED_xgio**SECRET**YFwMOWLfcVGs"
let plainData = (basicAuthCredentials as NSString).dataUsingEncoding(NSUTF8StringEncoding)
let base64String = "Basic \(plainData!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)))"
request.HTTPMethod = "POST"
let params = ["grant_type":"authorization_code","redirect_uri":"urn:ietf:wg:oauth:2.0:oob", "authorization_code":authToken as String] as Dictionary<String, String>
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue(base64String, forHTTPHeaderField: "Authorization")
request.timeoutInterval = 60
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(params, options: [])
request.HTTPShouldHandleCookies=false
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) in
let refreshResponse = NSString(data: data!, encoding: NSISOLatin1StringEncoding)
print("Response \(refreshResponse!)")
}
}
Every time I am getting the error with grant_type as null.
Error
Response {"error_description":"Grant type is null","error":"invalid_grant","correlation_id":"e5d4cc9c47d21","information_link":"https://developer.paypal.com/docs/api/#errors"}
A couple things here...
1. You should never have your client Secret stored on the client side for security reasons.
2. Can you attempt the call from your server using the curl commands outline here and let me know the result?
The only thing I can see from our internal logs is the same as the error or grant_type missing. Running the test from your server, using the authorization code in the response, should let us know if it's just something in your code that's getting discombobulated.
Using this code you can refresh or got new Access token on PayPal.
NSString *clientID = #"YOUR_CLIENT_ID";
NSString *secret = #"YOUR_SECRET";
NSString *authString = [NSString stringWithFormat:#"%#:%#", clientID, secret];
NSData * authData = [authString dataUsingEncoding:NSUTF8StringEncoding];
NSString *credentials = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:0]];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
[configuration setHTTPAdditionalHeaders:#{ #"Accept": #"application/json", #"Accept-Language": #"en_US", #"Content-Type": #"application/x-www-form-urlencoded", #"Authorization": credentials }];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"https://api.sandbox.paypal.com/v1/oauth2/token"]];
request.HTTPMethod = #"POST";
NSString *dataString = #"grant_type=client_credentials";
NSData *theData = [dataString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:theData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSLog(#"data = %#", [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]);
}
}];
[task resume];
This will give this Response.
data = {
"access_token" = "A101.S6WF1CZIz9TcamYexl6k1mBsXhxEL1OWtotHq37UVHDrK7roty_4DweKXMhObfCP.7hNTzK62FqlDn3K9bqCjUIFmsVy";
"app_id" = "APP-80W284485P519543T";
"expires_in" = 32042;
nonce = "2016-12-26T10:24:12Z8qEQBxdSGdAbNMg2ivVmUNTUJfyFuSL30OI_W9UCgGA";
scope = "https://uri.paypal.com/services/subscriptions https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://uri.paypal.com/services/applications/webhooks openid https://uri.paypal.com/payments/payouts https://api.paypal.com/v1/vault/credit-card/.*";
"token_type" = Bearer;
}
I want to use vimeo to host videos for a AppleTV app. I realise I will need a pro account to do exactly what I want, but at the moment just trying to do a POC.
What I need to achieve is to retrieve a url of my private video that expires after 1 hour, and I want the app to be authenticated with my credentials, not having the user have to sign in (as if the have the app, then they can view the videos).
Code that I am using is below, the constants set are:
kVimeoToken is an access token I created on vimeo for the app, and I have imported the vimeo api into my project.
-(NSString*) getVimeoUrls2 {
VIMClient *client = [[VIMClient alloc] initWithDefaultBaseURL];
AFJSONRequestSerializer *serializer= [AFJSONRequestSerializer serializer];
NSString *token = kVimeoToken;
//[serializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[serializer setValue:#"application/vnd.vimeo.*+json; version=3.2" forHTTPHeaderField:#"Accept"];
[serializer setValue:[NSString stringWithFormat:#"Bearer %#", token] forHTTPHeaderField:#"Authorization"];
client.requestSerializer = serializer;
__block NSString *str= nil;
[client requestURI:#"/me" completionBlock:^(VIMServerResponse *response, NSError *error)
{
id JSONObject = response.result;
NSLog(#"JSONObject: %#", JSONObject);
NSLog(#"Error: %#", [error localizedDescription]);
str = [[NSString alloc] initWithData:JSONObject encoding:NSUTF8StringEncoding];
}];
return str;
}
All I get back is an empty string, any idea what I am doing wrong?
If I change the access token so it is incorrect then I get back an error message {"error":"You must provide a valid authenticated access token."}, so it appears that I get authenticated ok. I have also tried some other endpoints but all of them end up with an empty string.
I have tried two separate approaches, both with the same result...i.e none, or an empty string.
I posted the question on the vimeo forums and got provided these two links:
developer.vimeo.com/api/authentication#single-user
github.com/vimeo/VIMNetworking#lightweight-use
The is the output from the log for the above code is below:
2016-01-09 08:13:26.091 tvOSShortGame[68357:91090409] server start (/me/watched/videos)
2016-01-09 08:13:26.461 tvOSShortGame[68357:91090448] server success 0.370109 sec (/me/watched/videos)
..and if I change the endpoint to /xxx (to force an error)
2016-01-09 08:07:28.826 tvOSShortGame[67829:91039056] server start (/xxx)
2016-01-09 08:07:29.003 tvOSShortGame[67829:91039045] server failure 0.177531 sec (/xxx)
2016-01-09 08:07:29.003 tvOSShortGame[67829:91039460] JSONObject: (null)
2016-01-09 08:07:29.003 tvOSShortGame[67829:91039460] Error: Request failed: not found (404)
Other endpoints get the same result, reports success but there is no JSON object returned.
Any help appreciated.
I finally got this working by using Postman which I saw on one of the Vimeo forums. It produces the correct code in multiple languages, and shows the resulting JSON so you can validate your endpoints.
Hope someone finds it useful.
//Obj C version
NSDictionary *headers = #{ #"authorization": #"Bearer MY_VIMEO_TOKEN",
#"cache-control": #"no-cache",
#"postman-token": #"MY_POSTMAN_TOKEN" };
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://api.vimeo.com/videos/116999999"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:#"GET"];
[request setAllHTTPHeaderFields:headers];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"%#", error);
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSLog(#"%#", httpResponse);
}
}];
[dataTask resume];
//Swift version
let headers = [
"authorization": "Bearer MY_VIMEO_TOKEN",
"cache-control": "no-cache",
]
var request = NSMutableURLRequest(URL: NSURL(string: "https://api.vimeo.com/videos/116999999")!,
cachePolicy: .UseProtocolCachePolicy,
timeoutInterval: 10.0)
request.HTTPMethod = "GET"
request.allHTTPHeaderFields = headers
var str = ""
let session = NSURLSession.sharedSession()
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error)
} else {
let httpResponse = response as? NSHTTPURLResponse
str = self.parseJSON(data!)
}
})
dataTask.resume()
I want to be able to send push notification to a topic from device to device. I am already able to receive the notifications if I send them from a server but in the end I don't want a server to interact with my apps.
I wrote a method that send the notification that look like this :
-(void)sendNotif {
NSDictionary *message = #{
#"notification" : #"{ \"text\" : \"test\", \"title\" : \"test\"}",
#"to" : #"/topics/test"
};
// kSenderID is the senderID you want to send the message to
NSString *kSenderID = #"X";
NSString *to = [NSString stringWithFormat:#"%##gcm.googleapis.com", kSenderID];
DLOG(#"dict %#, to : %#",message, to);
[[GCMService sharedInstance] sendMessage:message to:to withId:#"id1"];
}
But it seems nothing is sent.
So I have 2 questions :
How do I write my method?
How do I implement the callback methods?
A solution I found is to create my own HTTPRequest like in google example :
-(void)sendNotif {
NSString *sendUrl = #"https://android.googleapis.com/gcm/send";
NSString *subscriptionTopic = #"/topics/test";
NSString *title = notifTitle.text;
NSString *body = notifBody.text;
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:sendUrl ]];
req.HTTPMethod = #"POST";
[req setValue:#"application/json" forHTTPHeaderField: #"Content-Type"];
[req setValue:#"key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" forHTTPHeaderField: #"Authorization"];
NSDictionary *message = [self getMessageTo:subscriptionTopic withTitle:title withBody:body];
NSError *jsonError;
NSMutableString *jsonString;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:message options:NSJSONWritingPrettyPrinted error:&jsonError];
if (! jsonData) {
NSLog(#"Got an error: %#", jsonError);
} else {
jsonString = [[NSMutableString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
DLOG(#"json string%#", jsonString);
req.HTTPBody = jsonData;
[NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if (error != nil) {
DLOG(#"truc error %#",error);
} else {
DLOG(#"Success! Response from the GCM server:");
DLOG(#"%#",response);
}
}];
}
-(NSDictionary *) getMessageTo:(NSString *) to withTitle:(NSString *) title withBody:(NSString *) body{
// [START notification_format]
NSDictionary *message = #{
#"notification" : #{#"title" : title,#"text" : body},
#"to" : to
};
return message;
// [END notification_format]
}
There is no normal way to publish a message to topic from the client. The one proposed by the question author him/herself is basically a hack that requires keeping the API key on the client which is very insecure.
The main reason why it is not allowed is that it would let adversary to tamper with the client and send spam messages to other users.
How to post this type of format
{
"Authentication": {
"Username": "testUser#123",
"Password": "testPassword#123"
},
"FileID": "2",
"RequestType": 5
}
I know how to post this type of format to json in objective-c, here is my code
NSURL *url=[NSURL URLWithString:#"http://adservicedev.azurewebsites.net/order/json/process"];
dict = #{#"Authentication":#{#"Username":#"testUser#123",#"Password":#"testPassword#123"},#"RequestType":[NSNumber numberWithInt:4]};
if([NSJSONSerialization isValidJSONObject:dict])
{
__jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
__jsonString = [[NSString alloc]initWithData:__jsonData encoding:NSUTF8StringEncoding];
NSLog(#"Error %#", __jsonString);
}
// Be sure to properly escape your url string.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody: __jsonData];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%lu", (unsigned long)[__jsonData length]] forHTTPHeaderField:#"Content-Length"];
NSError *errorReturned = nil;
NSURLResponse *theResponse =[[NSURLResponse alloc]init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&errorReturned];
but am new to swift language,how to write the same in swift.Please help me out.
Thanks in advance
Well that's the way you need to implement.
Swift code
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/php/index.php")!)
request.HTTPMethod = "GET"
let postString = "" // if you want to pass some string to the url you can also do it here i.e type=user now on php side you can get the value by using $_GET['type'] or $_REQUEST['type']
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
if error != nil
{
println("error=\(error)")
return
}
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
var FileID : NSString = jsonResult["FileID"]! as NSString
var RequestType : NSString = jsonResult["RequestType"]! as NSString
let Auth : AnyObject = jsonResult["Authentication"]!
var Username : NSString = Auth["Username"]! as NSString
var Password : NSString = Auth["Password"]! as NSString
println("Username : \(Username)")
println("Password : \(Password)")
println("RequestType : \(RequestType)")
println("FileID : \(FileID)")
println("Auth : \(Auth)")
}
task.resume()
PHP code (index.php)
<?php
$v = '{"Authentication": {"Username": "testUser#123","Password": "testPassword#123" },"FileID": "2","RequestType": 5}';
echo $v;
?>
Final Output