I'm trying to create an order from my IOS app to my Shopify site.
This is what the documentation says I should do.
Create a simple order with only a product variant id.
POST /admin/orders.json
{
"order": {
"line_items": [
{
"variant_id": 447654529,
"quantity": 1
}
]
}
}
It does not say much more.
Here is what I got.
<code>
NSMutableDictionary *lineItem1=[[NSMutableDictionary alloc]init];
[lineItem1 setObject:#"1125533997" forKeyedSubscript:#"variant_id"];
[lineItem1 setObject:#"1" forKeyedSubscript:#"quantity"];
NSMutableArray *lineItems=[[NSMutableArray alloc]init];
[lineItems addObject:lineItem1];
NSMutableDictionary *orders=[[NSMutableDictionary alloc]init];
[orders setObject:lineItems forKeyedSubscript:#"line_items"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:orders options:NSJSONWritingPrettyPrinted error:&error];
NSString *myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
myString=[JuicyApi md5HexDigest:myString];
//Set parameter
NSMutableDictionary *params = [[NSMutableDictionary alloc]init];
[params setObject:myString forKeyedSubscript:#"order"];
//Generate the request with the give settings
NSMutableURLRequest *req = [self getRequestWithFunction:#"admin/orders.json" requestType:#"POST" params:params ssl:true];
</code>
The server is giving me a response that says.
<code>
{"errors":{"order":"expected String to be a Hash"}}
</code>
I tried hashing all of it, only the values, in this example everything in order, can't get it to work. Am I hashing it incorrectly?
What am I missing here?
I also had the same issue. I got fixed by setting the proper header before making the request
setHeader("Content-Type", "application/json")
Related
I am implementing web-service APIs, data content type is of JSON. The body of the request should be in a string format i.e in double quotes but when I set it in a dictionary, I get the below result. Could anyone help me to set the NSString as string value in dictionary.
NSMutableDictionary *reqParams = [NSMutableDictionary new];
[reqParams setObject:#"Data.SourceStreamRequest"forKey:#"_type"];
NSMutableDictionary *reqParams1 = [NSMutableDictionary new];
[reqParams1 setObject:#"newmjpegdataSession"forKey:#"_type"];
NSLog(#"%#:%#",reqParams,reqParams1);
Output
{
"_type" = "Data.SourceStreamRequest";
}:{
"_type" = newmjpegdataSession;
}
Could anyone help me to figure out the reason why ,the dictionary values are shown with double quotes and without double quotes.
Thank you
Use NSJSONSerialization to serialize your dictionary. Try this:
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"_type", #"Data.SourceStreamRequest",
#"_type", #"newmjpegdataSession", nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *resultAsString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"json:\n%#", resultAsString);
Output:
json: { "newmjpegdataSession" : "_type", "Data.SourceStreamRequest"
: "_type" }
When using JSON.parse(parameter-value) in JavaScript, the adapter invocation is working correctly, however when doing similarly in a native iOS app, it is failing with the following error.
Javascript Adapter Call:
var invocationData = {
adapter : 'TEST_ADAP',
procedure : 'PROC1',
parameters : [JSON.parse(A)],
};
Native Call:
json= // some json value will be come
MyConnect *connectListener = [[MyConnect alloc] initWithController:self];
[[WLClient sharedInstance] wlConnectWithDelegate:connectListener];
WLProcedureInvocationData *myInvocationData = [[WLProcedureInvocationData alloc] initWithAdapterName:#"TEST" procedureName:#"test"];
myInvocationData.parameters = [NSArray arrayWithObjects:json, nil];
for (NSString *str in myInvocationData.parameters) {
NSLog(#"values of account test %#",str);
}
PasswardPage *invokeListener = [[PasswardPage alloc] initWithController:self];
[[WLClient sharedInstance] invokeProcedure:myInvocationData withDelegate:invokeListener];
Your line
myInvocationData.parameters = [NSArray arrayWithObjects:json, nil];
is almost right.
The parameters property should be an NSArray (as you did) but the array must be made of string values - NOT a JSON object.
myInvocationData.parameters = [NSArray arrayWithObjects:#"myValue1", #"myValue2", #"myValue3", nil];
If the data you received is not in this format, you need to first convert it to this format. This is out of the scope of this question.
If you are not sure how to convert your existing format into a valid NSArray, please open a new question (tagged with Objective-C, not worklight).
We can pass JSON as NSString in iOS Native code to invoke adapter
Example
//Created Dictionary
NSMutablec *dict = [[NSMutableDictionary alloc]init];
[dict setObject:#"xyz" forKey:#"Name"];
[dict setObject:#"iOS" forKey:#"Platform"];
//Convert it to JSON Data
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
options:nil
error:&error];
//JSON Data To NSString
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
WLProcedureInvocationData * invocationData = [[WLProcedureInvocationData alloc] initWithAdapterName:#"XYZAdapter" procedureName:#"FunctionXYZ"];
//Passing jsonString (NSString Created out of JSON Data) as array to set Parameters.
[invocationData setParameters:[NSArray arrayWithObject:jsonString]];
[[WLClient sharedInstance] invokeProcedure:invocationData withDelegate:self];
I am writing an iOS application that receives data from the backend. I parse the NSData object (objectNotation) as below.
Everything works fine until I receive a special character in the one entity, which is:
"Test já"
When I receive this and I debug parsedObject, it shows "type" to be "Test j\U00e1"
So this is obviously some Unicode/UTF8 issue. I then proceeded to look all over stack overflow, and found various potential solutions to this and tried them all, to no avail.
NSString *stringTest = [[NSString alloc] initWithData:objectNotation
encoding:NSUTF8StringEncoding]; --> does not work
NSString * test2 = [NSString
stringWithCString:[stringTest cStringUsingEncoding:NSUTF8StringEncoding]
encoding:NSASCIIStringEncoding]; --> does not work
I have tried every single encoding that Obj has to offer, and it either returns the character as \U00e1, or nil, or a bunch of garbage.
I have battled with this for hours so it is a good time to post now. I appreciate any assistance. Thank you.
Code is below:
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:objectNotation options:0 error:&localError];
NSMutableArray *btms = [[NSMutableArray alloc] init];
NSArray *results = [parsedObject valueForKey:#"results"];
NSLog(#"Count %d", results.count);
NSLog(#"Count %d", parsedObject.count);
[parsedObject enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
BTM *btm = [[BTM alloc] init];
NSLog(#"%# => %#", key, value);
btm.number = key;
btm.latitude = [value valueForKey:#"lat"];
btm.longitude = [value valueForKey:#"long"];
NSString* temp = [value valueForKey:#"type”];
}
Set "application/x-www-form-urlencoded; charset=UTF-8" as 'Content-Type' while receiving data from the backend.
[requestUrl setValue:#"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
I want to make an autocomplete with a tableView, for that I have this function :
-(AutocompletionTableView *)autoCompleter
{
if (!_autoCompleter)
{
NSMutableDictionary *options = [NSMutableDictionary dictionaryWithCapacity:2];
[options setValue:[NSNumber numberWithBool:YES] forKey:ACOCaseSensitive];
[options setValue:nil forKey:ACOUseSourceFont];
_autoCompleter = [[AutocompletionTableView alloc] initWithTextField:self.textField inViewController:self withOptions:options];
_autoCompleter.autoCompleteDelegate = self;
_autoCompleter.suggestionsDictionary = [NSArray arrayWithObjects:#"hostel",#"caret",#"carrot",#"house",#"horse", nil];
}
return _autoCompleter;
}
The Problem :
Instead of autocompleting from an Array, I want to autocomplete from a remote JSON file.
Any idea on I how I can do such thing ? A code snippet will be very helpful, as I am a newbie in iOS development.
After making a request to the server using NSURLConnection, you should receive an NSData containing the following data:
["hostel","caret","carrot","house","horse"]
This NSData is something like this:
NSString* data = #"[\"hostel\",\"caret\",\"carrot\",\"house\",\"horse\"]";
NSData* dataReceived = [data dataUsingEncoding:NSUTF8StringEncoding];
So, to convert it into an array, you can call NSJSONSerialization, like this:
NSError *jsonError = nil;
NSArray *responseDictionary = [NSJSONSerialization JSONObjectWithData:dataReceived options:0 error:&jsonError];
if(jsonError == nil)
{
_autoCompleter.suggestionsDictionary = responseArray;
}
I've been breaking my head over this the whole day.
I wish to integrate my iOS app with Withings api. It uses OAuth 1.0 and I can't seem to understand fully how to implement it.
I've been downloading multiple OAuth framworks (MPOAuth,gtm-oauth,ssoauthkit) but couldn't figure out completely what exactly I should do.
I searched a lot, also in stack overflow for good references on how to go about implementing OAuth 1.0 in general & integrating with Withings in particular with no success.
Kindly explain the flow of integrating an iOS app with an api that requires OAuth 1.0. Code examples would be very helpful. Suggested 3rd party frameworks would be nice too.
Just to clarify, I fully understand the OAuth 1.0 principles, I just have problems in actually implementing it in my app.
I think that a thorough answer with code examples and good references would be very helpful for lots of people as I couldn't find one. If anyone has good experience with implementing it, please take the time to share it.
TDOAuth in my opinion was the best solution. it is clean and simple, only one .h and .m file to work with, and no complicated example projects..
This is the OAuth 1.0 flow:
step 1 - get request token
//withings additional params
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:CALL_BACK_URL forKey:#"oauth_callback"];
//init request
NSURLRequest *rq = [TDOAuth URLRequestForPath:#"/request_token" GETParameters:dict scheme:#"https" host:#"oauth.withings.com/account" consumerKey:WITHINGS_OAUTH_KEY consumerSecret:WITHINGS_OAUTH_SECRET accessToken:nil tokenSecret:nil];
//fire request
NSURLResponse* response;
NSError* error = nil;
NSData* result = [NSURLConnection sendSynchronousRequest:rq returningResponse:&response error:&error];
NSString *s = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
//parse result
NSMutableDictionary *params = [NSMutableDictionary dictionary];
NSArray *split = [s componentsSeparatedByString:#"&"];
for (NSString *str in split){
NSArray *split2 = [str componentsSeparatedByString:#"="];
[params setObject:split2[1] forKey:split2[0]];
}
token = params[#"oauth_token"];
tokenSecret = params[#"oauth_token_secret"];
step 2 - get authorize token (by loading the request in a UIWebView, the webViewDidFinishLoad delegate method will handle the call back..)
//withings additional params
NSMutableDictionary *dict2 = [NSMutableDictionary dictionary];
[dict setObject:CALL_BACK_URL forKey:#"oauth_callback"];
//init request
NSURLRequest *rq2 = [TDOAuth URLRequestForPath:#"/authorize" GETParameters:dict2 scheme:#"https" host:#"oauth.withings.com/account" consumerKey:WITHINGS_OAUTH_KEY consumerSecret:WITHINGS_OAUTH_SECRET accessToken:token tokenSecret:tokenSecret];
webView.delegate = self;
[DBLoaderHUD showDBLoaderInView:webView];
[webView loadRequest:rq2];
handle the webView as follow to initiate step 3 (I know the isAuthorizeCallBack smells a lot, but it does the job, should refactor it..)
- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{
[DBLoaderHUD hideDBLoaderInView:webView];
NSString *userId = [self isAuthorizeCallBack];
if (userId) {
//step 3 - get access token
[DBLoaderHUD showDBLoaderInView:self.view];
[self getAccessTokenForUserId:userId];
}
//ugly patchup to fix an invalid token bug
if ([webView.request.URL.absoluteString isEqualToString:#"http://oauth.withings.com/account/authorize?"])
[self startOAuthFlow];
}
- (NSString *)isAuthorizeCallBack
{
NSString *fullUrlString = webView.request.URL.absoluteString;
if (!fullUrlString)
return nil;
NSArray *arr = [fullUrlString componentsSeparatedByString:#"?"];
if (!arr || arr.count!=2)
return nil;
if (![arr[0] isEqualToString:CALL_BACK_URL])
return nil;
NSString *resultString = arr[1];
NSArray *arr2 = [resultString componentsSeparatedByString:#"&"];
if (!arr2 || arr2.count!=3)
return nil;
NSString *userCred = arr2[0];
NSArray *arr3 = [userCred componentsSeparatedByString:#"="];
if (!arr3 || arr3.count!=2)
return nil;
if (![arr3[0] isEqualToString:#"userid"])
return nil;
return arr3[1];
}
- (void)startOAuthFlow
{
[self step1];
[self step2];
}
and finally - step 3 - get access token
- (void)getAccessTokenForUserId:(NSString *)userId
{
//step 3 - get access token
//withings additional params
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:CALL_BACK_URL forKey:#"oauth_callback"];
[dict setObject:userId forKey:#"userid"];
//init request
NSURLRequest *rq = [TDOAuth URLRequestForPath:#"/access_token" GETParameters:dict scheme:#"https" host:#"oauth.withings.com/account" consumerKey:WITHINGS_OAUTH_KEY consumerSecret:WITHINGS_OAUTH_SECRET accessToken:token tokenSecret:tokenSecret];
//fire request
NSURLResponse* response;
NSError* error = nil;
NSData* result = [NSURLConnection sendSynchronousRequest:rq returningResponse:&response error:&error];
NSString *s = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
//parse result
NSMutableDictionary *params = [NSMutableDictionary dictionary];
NSArray *split = [s componentsSeparatedByString:#"&"];
for (NSString *str in split){
NSArray *split2 = [str componentsSeparatedByString:#"="];
[params setObject:split2[1] forKey:split2[0]];
}
[self finishedAthourizationProcessWithUserId:userId AccessToken:params[#"oauth_token"] AccessTokenSecret:params[#"oauth_token_secret"]];
}
I additionaly save request headers here
NSMutableDictionary *dict2 = [NSMutableDictionary dictionary];
[dict2 setObject:CALL_BACK_URL forKey:#"oauth_callback"];
NSURLRequest *rq2 = [TDOAuth URLRequestForPath:#"/authorize"
GETParameters:dict2
scheme:#"https"
host:#"oauth.withings.com/account"
consumerKey:WITHINGS_OAUTH_KEY
consumerSecret:WITHINGS_OAUTH_SECRET
accessToken:self.token
tokenSecret:self.tokenSecret];
headers = rq2.allHTTPHeaderFields;
And in callback method i will add missing parameters to the request. By doing it this way, i avoid "ugly patchup fix".
- (BOOL)webView:(UIWebView *)wV shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
if (![request.allHTTPHeaderFields objectForKey:#"Authorization"] &&
[request.URL.absoluteString rangeOfString:#"acceptDelegation=true"].location == NSNotFound){
NSMutableURLRequest *mutableCp = [request mutableCopy];
NSLog(#"request :::%#", request);
[mutableCp setAllHTTPHeaderFields:headers];
dispatch_async(dispatch_get_main_queue(), ^{
[webView loadRequest:mutableCp];
});
return NO;
}
return YES;
}
I hope it will help somebody
I would suggest you to check this project both as a reference and as a really working OAuth class. It inherits from another great project, so you you will need to add both in yours.Check if the license will suits your requirements.
https://github.com/rsieiro/RSOAuthEngine