NSURLConnection SSL HTTP Basic Auth - iphone

I am unable to get a url request to do both ssl urls and basic authentication. I did check the other related questions and they dont seem to work
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
// NSLog(#"We are checking protection Space!");
if([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSLog(#"Can Auth Secure Requestes!");
return YES;
}
else if([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
NSLog(#"Can Auth Basic Requestes!");
return YES;
//return NO;
}
NSLog(#"Cannot Auth!");
return NO;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSLog(#"Trust Challenge Requested!");
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
NSLog(#"HTTP Auth Challenge Requested!");
NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:#"user" password:#"pass" persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
[credential release];
}
Can't seem to figure out what im doing wrong here. The Connection description says Secure Connection Failed. I have tried with simply ssl and no basic it works fine. I have also tried without ssl and basic and it works fine.

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
if([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
return YES;
}
else
{
if([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
return YES;
}
}
return NO;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
else
{
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
NSURLCredential *creden = [[NSURLCredential alloc] initWithUser:#"USERNAME" password:#"PASSWORD" persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:creden forAuthenticationChallenge:challenge];
[creden release];
}
else
{
[[challenge sender]cancelAuthenticationChallenge:challenge];
}
}
}

It works fine actually, the problem had to do with the SSL certificate.

I think the accepted answer may end up incorrectly trusting invalid server certificates, as it doesn't validate the server trust.
Apple's documentation for NSURLCredential credentialForTrust: indicates that you should actually validate the server trust before you use it:
Before creating a server trust credential, it is the responsibility of the delegate of an NSURLConnection object or an NSURLDownload object to evaluate the trust. Do this by calling SecTrustEvaluate, passing it the trust obtained from the serverTrust method of the server’s NSURLProtectionSpace object. If the trust is invalid, the authentication challenge should be cancelled with cancelAuthenticationChallenge:.
Apple's documentation for NSURLAuthenticationChallenge also indicates how a challenge's proposedCredential should be taken into account.
Taking this into account would yield (ARC) code something like this:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge
{
if (challenge.proposedCredential)
{
if (challenge.previousFailureCount == 0)
{
[challenge.sender useCredential:challenge.proposedCredential forAuthenticationChallenge:challenge];
}
else
{
// The server has rejected the proposed credential, and
// you should use that credential to populate a password
// or certificate chooser dialog, then provide a new credential.
// You can create password-based credentials by calling the
// credentialWithUser:password:persistence: method or create
// certificate-based credentials with the
NSLog(#"Need to add code here to create new credential...");
}
}
else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSLog(#"Trust Challenge Requested!");
// As per NSURLCredential class reference, verify the server trust...
SecTrustResultType trustResult = kSecTrustResultInvalid;
const OSStatus status = SecTrustEvaluate(challenge.protectionSpace.serverTrust, &trustResult);
if (noErr == status &&
(
kSecTrustResultProceed == trustResult ||
// https://developer.apple.com/library/mac/qa/qa1360/_index.html
kSecTrustResultUnspecified == trustResult
)
)
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
else
{
NSLog(#"Failed to verify server trust, cancelling...");
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}
else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
NSLog(#"HTTP Auth Challenge Requested!");
NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:#"user" password:#"pass" persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
}

Related

Handle ACAccountStoreDidChangeNotification for Facebook & Twitter in iOS 6+

I am using Social framework for Facebook & Twitter integration. For this I followed this link
Everything is working fine except when I app receives ACAccountStoreDidChangeNotification , it crashes.
App crashes when
1) I installed app for first time & user don't have Facebook / Twitter account configured in Settings.
2) When I call any method of Facebook / Twitter , it gives me error code 6 as I don't have account configured which is right.
3) I click on HOME button so my app enters background & add account in Settigs.
4) Once I configured account & come back to app , my app launches from background & receives ACAccountStoreDidChangeNotification.
5) In selector of ACAccountStoreDidChangeNotification my account object is nil so my app crashes. So I checked for the nil
Here is my code
#pragma mark - Request Facebook Account Access
-(void)requestFacebookAccountAccess
{
requestType = kNoOpRequest;
// Register for Account Change notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(accountChanged:) name:ACAccountStoreDidChangeNotification object:nil];
self.accountStore = [[ACAccountStore alloc]init];
ACAccountType *FBaccountType= [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
// Set facebook permissions
NSArray *permissions = nil;
// We need to ask for Basic permission first
if (![kUserDefaults boolForKey:FACEBOOK_BASIC_PERMISSION]) {
permissions = #[#"email",#"user_about_me",#"user_location",#"friends_about_me"];
self.isBasicFacebookPermissionsRequested = YES;
}
else {
permissions = #[#"email",#"user_about_me",#"user_location",#"friends_about_me",#"publish_stream"];
}
//use ACAccountStore to help create your dictionary
NSDictionary *dictFacebook = #{
ACFacebookAppIdKey: kFacebookAppIDKey,
ACFacebookPermissionsKey: permissions,
ACFacebookAudienceKey: ACFacebookAudienceFriends
};
[self.accountStore requestAccessToAccountsWithType:FBaccountType options:dictFacebook completion:^(BOOL granted, NSError *error) {
if (granted) {
if (self.isBasicFacebookPermissionsRequested) {
self.isBasicFacebookPermissionsRequested = NO;
[kUserDefaults saveBasicFacebookPermissionsGrantedStatus:YES];
//[self requestFacebookAccountAccess];
}
// User granted permission to Accout
NSArray *accountsArray = [self.accountStore accountsWithAccountType:FBaccountType];
if ([accountsArray count]>0) {
//It will always be the last object with SSO
self.facebookAccount = [accountsArray lastObject];
NSLog(#"In %s::IS MAIN THREAD:- %#",__PRETTY_FUNCTION__,[NSThread isMainThread]?#"YES":#"NO");
if ([self.delegate respondsToSelector:#selector(didFacebookAccountAccessGranted)]) {
dispatch_async(dispatch_get_main_queue(),^{
[self.delegate didFacebookAccountAccessGranted];
});
}
}
else {
[self showAlertWithTitle:#"Error" andMessage:#"You don't have any Facebook accounts set up yet.Please set a Facebbok account and try again."];
}
}
else {
DLog(#"User denied permission to Accout::Localized Error:- %#",error.localizedDescription);
if([error code]==6) {
[self showAlertWithTitle:#"Error" andMessage:#"Please setup facebook account from Settings"];
if ([self.delegate respondsToSelector:#selector(didFacebookAccountAccessDenied:)]) {
dispatch_async(dispatch_get_main_queue(),^{
[self.delegate didFacebookAccountAccessDenied:error];
});
}
}
else if ([self.delegate respondsToSelector:#selector(didFacebookAccountAccessDenied:)]) {
dispatch_async(dispatch_get_main_queue(),^{
[self.delegate didFacebookAccountAccessDenied:error];
});
}
else {
// User denied permission to Account
[self showAlertWithTitle:#"Error" andMessage:[NSString stringWithFormat:#"User denied permission to Accout::Error:- %#",error.localizedDescription]];
}
}
}];
}
#pragma mark - Get Logged In User Info
-(void)getLoggedInUserInfo
{
NSURL *requestURL = [NSURL URLWithString:#"https://graph.facebook.com/fql"];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:#"SELECT current_location,uid,name,sex,birthday,email,pic FROM user WHERE uid=me()",#"q", nil];
requestType = kGetLoggedInUserInfoRequest;
[self requestDataUsingURL:requestURL parameters:dict requestMethod:SLRequestMethodGET];
}
#pragma mark - Request Data From Facebook
-(void)requestDataUsingURL:(NSURL*)requestURL parameters:(NSDictionary*)params requestMethod:(SLRequestMethod)reuqestMethod
{
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:reuqestMethod
URL:requestURL
parameters:params];
request.account = self.facebookAccount;
[request performRequestWithHandler:^(NSData *data,
NSHTTPURLResponse *response,
NSError *error)
{
NSDictionary *dictData =[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(!error)
{
if([dictData objectForKey:#"error"]!=nil)
{
DLog(#"Request Data From Facebook Errro:- %#",dictData);
[self attemptRenewCredentials];
if ([self.delegate respondsToSelector:#selector(didGetFacebookError:)]) {
dispatch_async(dispatch_get_main_queue(),^{
[self.delegate didGetFacebookError:dictData];
});
}
}
else {
// Process the response
//NSLog(#"Response Dictionary contains: %#", dictData );
if ([self.delegate respondsToSelector:#selector(didPostToFacebook:)]) {
dispatch_async(dispatch_get_main_queue(),^{
[self.delegate didPostToFacebook:dictData];
});
}
}
}
else{
if ([self.delegate respondsToSelector:#selector(didGetFacebookError:)]) {
dispatch_async(dispatch_get_main_queue(),^{
[self.delegate didGetFacebookError:dictData];
});
}
else {
[self showAlertWithTitle:#"Error" andMessage:#"Some error occured while processing Facebook request"];
}
}
}];
}
-(void)accountChanged:(NSNotification *)notif
{
if (self.facebookAccount!=nil) {
[self attemptRenewCredentials];
}
else {
[self requestFacebookAccountAccess];
}
}
#pragma mark - Attempt to Renew Credentials
-(void)attemptRenewCredentials
{
[self.accountStore renewCredentialsForAccount:(ACAccount *)self.facebookAccount completion:^(ACAccountCredentialRenewResult renewResult, NSError *error){
if(!error)
{
switch (renewResult) {
case ACAccountCredentialRenewResultRenewed:
NSLog(#"Good to go");
[self againRequestFacebook];
break;
case ACAccountCredentialRenewResultRejected:
NSLog(#"User declined permission");
break;
case ACAccountCredentialRenewResultFailed:
NSLog(#"non-user-initiated cancel, you may attempt to retry");
break;
default:
break;
}
}
else{
//handle error gracefully
NSLog(#"error from renew credentials%#",error);
}
}];
}
-(void)againRequestFacebook
{
switch (requestType) {
case kGetLoggedInUserInfoRequest:
[self getLoggedInUserInfo];
break;
case kGetFriendsInfoRequest:
[self getFacebookFriendsInfo];
break;
case kPostToWallRequest:
[self postToFacebookWallInBackgroundForUserId:fbUserIdForPost withParams:paramsToPost];
break;
default:
break;
}
}
#pragma mark - Remove Observer for Notification
-(void)dealloc
{
requestType = kNoOpRequest;
[[NSNotificationCenter defaultCenter] removeObserver:ACAccountStoreDidChangeNotification];
}
But accountChanged method gets called multiple times.
What is wrong in this ? How can I handle this situation ?
Any kind of help is highly appreciated.
Thanks in advance.
I am facing the same problem...so i used a work around by having a BOOL value in NSUserDefaults to execute accountChanged method only once
-(void)accountChanged:(NSNotification *)notif
{
BOOL calledAccountChanged =[[[NSUserDefaults standardUserDefaults] objectForKey:DidAccountChanged] boolValue];
if(!calledAccountChanged)
{
if (self.facebookAccount!=nil) {
[self attemptRenewCredentials];
}
else {
[self requestFacebookAccountAccess];
}
}
}
Then we can change DidAccountChanged value later in the code...
If you have better solution do post it...

Pair with a bluetooth peripheral using ios 5

I am developing a proximity sensing application using bluetooth technology 4.0. I am able to discover the devices. But I am not able to pair with them. Nor can i call [peripheral readRssi] method. The way I want to achieve this is that if the central scans for say 10 devices and after finding those many, it should stop the scan and then pair the devices and then constantly read the RSSI values.
My piece of code.
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
BOOL (^test)(id obj, NSUInteger idx, BOOL *stop);
test = ^ (id obj, NSUInteger idx, BOOL *stop) {
if([[[obj peripheral] name] compare:peripheral.name] == NSOrderedSame)
return YES;
return NO;
};
PeripheralCell* cell;
NSUInteger t=[peripherals indexOfObjectPassingTest:test];
if(t!= NSNotFound)
{
cell=[peripherals objectAtIndex:t];
cell.peripheral=peripheral;
cell.rssi=RSSI;
//NSLog(#"%#",RSSI);
[scanResultTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:t inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}
else{
cell=[[PeripheralCell alloc] init];
[peripherals addObject: cell];
[myPeripheral addObject: peripheral];
cell.peripheral=peripheral;
cell.rssi=RSSI;
NSLog(#"UUID===%#",[peripheral UUID]);
[scanResultTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:[peripherals count]-1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
if([myPeripheral count]==3)
{
[manager stopScan];
for(CBPeripheral *p in myPeripheral)
{
[manager connectPeripheral:p options:nil]; //this calls didConnectPeripheral but gets disconnected after some time
[p readRssi]; //this does not work even after connecting
}
}
}
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
//self.cBReady = false;
switch (central.state) {
case CBCentralManagerStatePoweredOff:
NSLog(#"CoreBluetooth BLE hardware is powered off");
break;
case CBCentralManagerStatePoweredOn:
NSLog(#"CoreBluetooth BLE hardware is powered on and ready");
//self.cBReady = true;
break;
case CBCentralManagerStateResetting:
NSLog(#"CoreBluetooth BLE hardware is resetting");
break;
case CBCentralManagerStateUnauthorized:
NSLog(#"CoreBluetooth BLE state is unauthorized");
break;
case CBCentralManagerStateUnknown:
NSLog(#"CoreBluetooth BLE state is unknown");
break;
case CBCentralManagerStateUnsupported:
NSLog(#"CoreBluetooth BLE hardware is unsupported on this platform");
break;
default:
break;
}
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(#"connected peripheral");
}
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;
{
NSLog(#"peripheral disconnected");
}
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(#"updated rssi");
}
how can i pair the devices...
After much searching and trail and error I found out that my code is correct. I just had to remove the devices from the ipad's Setting.
Goto Settings > General > Bluetooth > Devices.
Select the device by clicking the accessory indicator. In the next screen just click on "Forget this Device".
Running the application again solved my problem.

How to import a SSL certificate into my Application's keychain

I want to import a SSL certificate into my Application's keychain. I got a sample project from apple and I tested it. I am sure that technically it can be done. But my question is that, what kind of approach should I use while asking the client to install the certificate. I thought about the following options,
->Prompting the user to install the credentials at the application launch.
->Maintaining a settings page to control the credentials.
As my application totally depends upon web services I cannot proceed without the credentials. Please post your suggestions.
Ask your certificate provider for a link to download the certificate. Just Download and Store the certificate in your resources folder.
The below set of code snippets will do the work for you. Please post comments if you don't understand the below.
SecIdentityRef identity = NULL;
SecTrustRef trust = NULL;
NSData *PKCS12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"test_iphone_services" ofType:#"p12"]];
//Calling the method
[Child extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]
+ (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data
{
OSStatus securityError = errSecSuccess;
//testtest is the passsword for the certificate.
NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:#"testtest" forKey:(id)kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import((CFDataRef)inPKCS12Data,(CFDictionaryRef)optionsDictionary,&items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
*outIdentity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
*outTrust = (SecTrustRef)tempTrust;
} else {
NSLog(#"Failed with error code %d",(int)securityError);
return NO;
}
return YES;
}
#pragma mark - NSURLConnection Delegate Methods
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(#"trust %#", trust);
NSURLCredential *credential;
NSURLCredentialPersistence persistence;
persistence = NSURLCredentialPersistencePermanent;
credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:persistence];
NSLog(#"credential %#", credential);
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
}

Problem using NSURLConnection and server trust authentication challenge

Good day to everybody,
I'm working on a singleton that should manage the download of contents through the internet, I know that exist ASIHttp request and that is an excellent lib, but I have my own reasons for not using it.
The class works pretty fine except for one thing: I'm trying to deal with the public folder of my MobileMe account without success. I uploaded a file inside it and trying to download using my class.
Reading some questions on stackOF and reading docs I came up into that code, but it seems to do not work:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
if([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSLog(#"SERVER TRUST AUTH");
return YES;
}
else if([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
NSLog(#"HTTP BASIC AUTH");
return YES;
}
NSLog(#"NO AUTH");
return NO;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSLog(#"Authetication");
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSLog(#"Trust Challange");
SecTrustResultType trustResultType;
OSStatus err=SecTrustEvaluate(challenge.protectionSpace.serverTrust, &trustResultType);
NSLog(#"SecTrustResult %lu %ld",trustResultType,err);
if (trustResultType == kSecTrustResultProceed || trustResultType == kSecTrustResultConfirm || trustResultType == kSecTrustResultUnspecified) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
else{
[challenge.sender cancelAuthenticationChallenge:challenge];
}
// [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
NSLog(#"HTTP Challenge");
NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:#"user" password:#"pass" persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
[credential release];
}
else{
[[challenge sender]cancelAuthenticationChallenge:challenge];
}
}
Now I'm stuck because from the log I can see that the evaluate function return a result of 4 that corresponds to a kSecTrustResultUnspecified but nothing is working even if I say to the challenge sender to continueWithoutCredentialForAuthenticationChallenge.
The url of the file is : https://public.me.com/XXXX/Objective.zip (link removed)the zip is the ObjectiveZip library that I also implemented in my class.
Any suggestion?

in app purchase non consumable product

I have written the following code.
But when i execute this code, i got log, which shows "no products available".
I am unable to find the reason.
-(void)viewDidLoad {
[super viewDidLoad];
if ([SKPaymentQueue canMakePayments])
{
SKProductsRequest *productsRequest=[[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObject:#"com.cmp.name.prdt"]];
productsRequest.delegate=self;
[productsRequest start];
}
else {
NSLog(#"Parental Control are enabled");
}
}
-(IBAction)btnpurchase
{
NSString* isPurchased = [[NSUserDefaults standardUserDefaults] stringForKey:#"com.cmp.name.prdt"];
if ([#"purchased" compare:isPurchased]==NSOrderedSame)
{
///do some task
}
else
{
SKPayment * payment=[SKPayment paymentWithProductIdentifier:#"com.cmp.name.prdt"];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
SKProduct *validProduct=nil;
int count=[response.products count];
if (count>0) {
validProduct=[response.products objectAtIndex:0];
}
else if(!validProduct)
{
NSLog(#"no products available");
}
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaaction in transactions)
{
switch (transaaction.transactionState)
{
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
[[SKPaymentQueue defaultQueue]finishTransaction:transaaction];
[[NSUserDefaults standardUserDefaults] setObject:#"purchased" forKey:#"com.cmp.name.prdt"];
[[NSUserDefaults standardUserDefaults] synchronize];
break;
case SKPaymentTransactionStateRestored:
[[SKPaymentQueue defaultQueue]finishTransaction:transaaction];
break;
case SKPaymentTransactionStateFailed:
if (transaaction.error.code!=SKErrorPaymentCancelled) {
NSLog(#"Error encountered");
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaaction];
break;
default:
break;
}
}
}
Could anyone help me out in this?
You can try out with following piece of code
//PRODUCT REQUEST DELEGATE METHOD
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"The product request didReceiveResponse :%#",[response description]);
NSLog(#"The products are :%#",[response.products description]);
NSLog(#"The invalidProductIdentifiers are:%#",[response.invalidProductIdentifiers description]);
NSArray *products=response.products;
for(SKProduct *currentProduct in products){
NSLog(#"THE Product price is :%#",currentProduct.price);
NSLog(#"THE Product description is :%#",currentProduct.localizedDescription);
NSLog(#"THE Product title is :%#",currentProduct.localizedTitle);
NSLog(#"THE Product's product identifier is :%#",currentProduct.productIdentifier);
}
}
THIS WILL LOG THE PRODUCT DETAILS REGISTERED ON iTUNES CONNECT IN CONSOLE WINDOW
Unfortunately, Apple does not respond with any useful information about why your purchases do not show up. I would go through this checklist. In my apps, things didn't work for a few days, then the suddenly started working. Be sure your financial info is correct.