iOS Authorize.net integration issue - iphone

I am developing iOS app, in which I have integrated authorize.net payment gateways using auth.net iOS API.
I followed each and every steps which are mentioned in their doc. Now each time, when a transaction request is sent to auth.net server on live environment it gives me error (Code E00007) i.e. "User authentication failed due to invalid authentication values".
I checked Login ID and Transaction Key and those are correct.
Even I tried with Auth.net support person, but still it did not work out.
The test enviroment and request were successful. But on Live env. it gives me the problem
My code follows:
For device registration:
Here I have put XXXX.... instead of real transaction key and login id.
MobileDeviceRegistrationRequest *mobileDeviceRegistrationRequest =
[MobileDeviceRegistrationRequest mobileDeviceRegistrationRequest];
mobileDeviceRegistrationRequest.mobileDevice.mobileDeviceId =
[[[UIDevice currentDevice] uniqueIdentifier]
stringByReplacingOccurrencesOfString:#"-" withString:#"_"];
mobileDeviceRegistrationRequest.mobileDevice.mobileDescription = #"iPhone";
mobileDeviceRegistrationRequest.anetApiRequest.merchantAuthentication.name = #"XXXXXXXXX";
mobileDeviceRegistrationRequest.anetApiRequest.merchantAuthentication.password = #"XXXXXXXXXXXXXX";
[AuthNet authNetWithEnvironment:ENV_LIVE];
AuthNet *an = [AuthNet getInstance];
[an mobileDeviceRegistrationRequest:mobileDeviceRegistrationRequest];
After that the code for payment request:
MobileDeviceLoginRequest *mobileDeviceLoginRequest = [MobileDeviceLoginRequest mobileDeviceLoginRequest];
mobileDeviceLoginRequest.anetApiRequest.merchantAuthentication.name = #"XXXXX";
mobileDeviceLoginRequest.anetApiRequest.merchantAuthentication.password = #"XXXXXX";
mobileDeviceLoginRequest.anetApiRequest.merchantAuthentication.mobileDeviceId =
[[[UIDevice currentDevice] uniqueIdentifier] stringByReplacingOccurrencesOfString:#"-" withString:#"_"];
// Set up an AuthNet instance.
[AuthNet authNetWithEnvironment:ENV_LIVE];
AuthNet *an = [AuthNet getInstance];
[an setDelegate:self];
// Process a mobile device login request.
[an mobileDeviceLoginRequest:mobileDeviceLoginRequest];
But in the initial registering request I am receiving the failure with error code E00007. Any settings I missed?

please provide the transaction key
mobileDeviceLoginRequest.anetApiRequest.merchantAuthentication.transactionKey = #"XXXXXX";
it works for me

Related

why gamekit auto-match always timeout

I'm a newbie iOS developer, currently working on a board game. I would like to integrate UIGameKit, but I'm having trouble. It seems to always fail to auto-match, and invite friends...
I did check the build bundle id, and i've enabled gc in itunes connect, but still no luck. When I click "play now" on the device or simulator, nothing happens until it times out. When I click "invite friend", it also will fail with the following error message:
ERROR: {
GKServerStatusCode = 5008;
NSLocalizedDescription = "The requested operation could not be completed due to an error communicating with the server.";
NSUnderlyingError = "Error Domain=GKServerErrorDomain Code=5008 \"The operation couldn\U2019t be completed. status = 5008, missing required key: self-push-token\" UserInfo=0xae53360 {GKServerStatusCode=5008, NSLocalizedFailureReason=status = 5008, missing required key: self-push-token}";
I don't understand what gamekit required key am I missing? What is the self-push-token the error message is asking for?
(Editors Remark: Don't think below code is relevant, will leave here anyways)
GKMatchRequest* request = [[GKMatchRequest alloc] init];
request.minPlayers = 2;
request.maxPlayers = 2;
GKMatchmakerViewController* hostVC = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
if (hostVC != nil)
{
hostVC.matchmakerDelegate = self;
[self presentViewController:hostVC];
}
Can any help? I tried to find some good samples to build a simple gamekit auto-match app but didn't have any luck, does anyone have a suggestion for me?

OAuth refresh token error

I'm using OAuth 2.0 to sign into a website. so each time when i try to log into the server i got a response that refer to an expiration date, access token and refresh token. the problem is the token is expired before the given time that i got from the server. so i figure out that there is an interval between the time of the server and the time of the iPhone. when i looked at the code of the SDK facebook there is no logic to handle this issue, it's a simple comparison. so my question is this issue from server side i mean the implementation of OAuth is incorrect or it's an issue from the client side?
Facebook Code:
- (BOOL)isSessionValid {
return (self.accessToken != nil && self.expirationDate != nil
&& NSOrderedDescending == [self.expirationDate compare:[NSDate date]]);
}
My code :
// Get the remaining period of the token to expire and subtract 30 sec
int delay = ([expirationDate timeIntervalSinceDate:serverDateTaken] - 30);
// Save the new Expiring date
objectOAuth.expiresIn = [[[NSDate date] dateByAddingTimeInterval:delay] description];
+ (BOOL)isSessionValid
{
// Get expiration date
OAuth *authParam = [Connection getSessionParameters];
// Formating
static NSString *timeZone = #"UTC";
NSDate *expirationDate = [Connection getDateFromString:authParam.expiresIn withTimeZone:timeZone];
// get the remaining period
int diff = [expirationDate timeIntervalSinceNow];
// Check if it's expired
return (diff <= 0);
}
Unfortunately there isn't really any good mechanism to check the time skew between the client and the server. I would stick with the simple check since there is less code that needs to be maintained and debugged. And no matter how much you check, you will still need to handle getting back a TOKEN EXPIRED error.

RestKit request seems to work only once

Alright I've been debugging the whole day but can't figure out what the problem is with my code.
The goal is to send a POST with RestKit to the Heroku API with a username/password to retrieve the API key.
The problem is that I'm only able to sent the request once. When sending the request the second time I get errors. (So first time I do get the API key binded to my object, but the second time just a error)
I'm using the current version of RestKit (0.10)
The code:
- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
}
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObject:(id)object
{
Account *account = (Account *)object;
NSLog(#"API_KEY: %#", account.apiKey);
}
- (IBAction) login:(id)sender
{
Account *account = [[Account alloc] init];
account.email = [emailField text];
account.password = [passwordField text];
[[RKObjectManager sharedManager] postObject:account delegate:self];
}
LOG
/// ---> FIRST CLICK
2012-05-25 14:57:00.028 HerokuApp[11154:fb03] API_KEY: 1234567890
/// ---> SECOND CLICK
2012-05-25 14:57:03.427 HerokuApp[11154:fb03] W restkit.network:RKObjectLoader.m:281 Unable to find parser for MIME Type 'text/html'
2012-05-25 14:57:03.427 HerokuApp[11154:fb03] W restkit.network:RKObjectLoader.m:309 Encountered unexpected response with status code: 200 (MIME Type: text/html -> URL: https://api.heroku.com/login -- https://api.heroku.com -- https://api.heroku.com -- https://api.heroku.com)
2012-05-25 14:57:03.429 HerokuApp[11154:fb03] didFailWithError: Error Domain=org.restkit.RestKit.ErrorDomain Code=4 "The operation couldn’t be completed. (org.restkit.RestKit.ErrorDomain error 4.)"
Can anybody help me explaining why this behaviour is occuring?
Perhaps the API behaves differently when you are logged in. From your log messages, it is appearing to return back text/html content, and not something that RestKit knows how to deal with.
Run in the simulator on a machine where Wireshark is capturing packets. Reproduce the error, then find the TCP stream where this is happening and look at it. If you need help, update your question with the result of "Follow Stream" in Wireshark so that we can see the full HTTP traffic.

User not logged in error in Facebook SDK iOS

How can I fix this error in my program? Using Facebook SDK.
Error Domain=facebookErrDomain Code=10000 "The operation couldn’t be completed. (facebookErrDomain error 10000.)" UserInfo=0x5da9b10 {error=<CFBasicHash 0x5db09a0 [0x1087400]>{type = mutable dict, count = 2,
entries =>
2 : <CFString 0x5db7920 [0x1087400]>{contents = "type"} = <CFString 0x5d35420 [0x1087400]>{contents = "OAuthException"}
3 : <CFString 0x5d34970 [0x1087400]>{contents = "message"} = <CFString 0x5da96b0 [0x1087400]>{contents = "Error validating access token: The session is invalid because the user logged out."}
}
}
I think the solution enbr posted is not complete. I will explain why:
Access token errors are returned when the Facebook session expires and you continue using an old access token. Logout is not the only scenario in which sessions expire (e.g. change login password in the web). Hence, it is not enough to simply clean the user defaults after logout.
From the client side, we don't know if the access token we have is actually valid, until a response comes with such information. Therefore, you need to detect access token errors and restore the Facebook instance to a working state by cleaning the old access token and expiration date. This way, the user will need to login again to obtain a new access token.
So, IMO, what you need to do is:
Handle errors and detect when an access token error has occurred.
When an access token error occurs, logout automatically and clean user defaults to remove old access token (step 3).
As a result of logout, you need to clean user defaults for access token and expiration date (as enbr posted).
Here you have some code that can be used to detect access token errors:
-(BOOL)isAccessTokenError:(NSError *) error {
if ([[error domain] isEqualToString:#"facebookErrDomain"] && [error code] == 10000 ) {
NSDictionary *userInfo = [error userInfo];
NSDictionary *errorAsDictionary = [userInfo objectForKey:#"error"];
if ([[errorAsDictionary objectForKey:#"type"] isEqualToString:#"OAuthException"]) {
//Invalid access token
return YES;
}
}
if ([[error domain] isEqualToString:#"facebookErrDomain"] && ([error code] == 110 || [error code] == 190)) {
//Error accessing access token
return YES;
}
return NO;
}
The places to handle such errors are:
- (void)request:(FBRequest*)request didFailWithError:(NSError*)error;
- (void)dialog:(FBDialog*)dialog didFailWithError:(NSError *)error;
I hope this helps.
UPDATE:
I forgot to mention. If you are using the SSO feature (most likely), I think it is a very good idea to clean the facebook cookies before login. Sometimes, after an invalid access token error, it seems login won't bring back the Facebook object to a working state (valid access token) unless a "clean login" is performed. Not always work though.
Also, If you are not using the SSO feature, this used to fix the ghost login popup that appeared to automatically disappear again.
This is how I clean the cookies:
NSHTTPCookieStorage* cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray* facebookCookies = [cookies cookiesForURL:
[NSURL URLWithString:#"http://login.facebook.com"]];
for (NSHTTPCookie* cookie in facebookCookies) {
[cookies deleteCookie:cookie];
}
enter code here
I just recently came across this error also. Here is the solution. Place this code in your main FBSessionDelegate (probably your app delegate).
- (void)fbDidLogout {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults removeObjectForKey:#"FBAccessTokenKey"];
[defaults removeObjectForKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
Then delete and reinstall the app!

How to detect the active iTunes store on the iPhone/iPod Touch/iPad?

I'd like to be able to determine which store the user connects to from inside my app, so that I can direct them to some appropriate content for their device AND store. Does anyone know how to get this information?
Basically, if the user is in the UK, and connects to the UK store, I want my function/method to return GB, if in Korea, I want KR, Australia = AU etc. Any help would be appreciated.
The approach of getting the country code of the user's locale will work ... but only if the user's iTunes store is the same as their locale. This won't always be the case.
If you create an in-app purchase item, you can use Apple's StoreKit APIs to find out the user's actual iTunes country even if it's different from their device locale. Here's some code that worked for me:
- (void) requestProductData
{
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers:
[NSSet setWithObject: PRODUCT_ID]];
request.delegate = self;
[request start];
}
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *myProducts = response.products;
for (SKProduct* product in myProducts) {
NSLocale* storeLocale = product.priceLocale;
storeCountry = (NSString*)CFLocaleGetValue((CFLocaleRef)storeLocale, kCFLocaleCountryCode);
NSLog(#"Store Country = %#", storeCountry);
}
[request release];
// If product request didn't work, fallback to user's device locale
if (storeCountry == nil) {
CFLocaleRef userLocaleRef = CFLocaleCopyCurrent();
storeCountry = (NSString*)CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode);
}
// Now we're ready to start creating URLs for the itunes store
[super start];
}
Since iOS 13.0, Apple introduced the SKStorefront API.
It allows you to check the current AppStore country the user is connected to.
SKStorefront: An object containing the location and unique identifier of an Apple App Store storefront.
Overview
In-app products you create through App Store Connect are available for sale in every region with an App Store. You can use the storefront information to determine the customer's region, and offer in-app products suitable for that region. You must maintain your own list of product identifiers and the storefronts in which you want to make them available.
Topics
countryCode: The three-letter code representing the country associated with the App Store storefront.
identifier: A value defined by Apple that uniquely identifies an App Store storefront.
https://developer.apple.com/documentation/storekit/skstorefront
So far you can use 2 methods with their pros and cons:
StoreFront
->SDK >= 13
->The three-letter code representing the country associated with the App Store storefront
if let storeFront = SKPaymentQueue.default().storefront{
print("StoreFront CountryCode = ", storeFront.countryCode)
}
else {
print("StoreFront NOT Available")
}
OR
SKCloudServiceController
-> Available from iOS 9.3.
-> Requires permission. On tvOS it can become messy as I can't find a way to change the permissions in settings...
-> Permission text quite confusing.
let skCloudServiceController = SKCloudServiceController()
SKCloudServiceController.requestAuthorization { (status) in
guard status == .authorized else {
return
}
skCloudServiceController.requestStorefrontCountryCode(completionHandler: { (countryCode, error) in
if let error = error {
print("Failure: ", error)
}
else if let countryCode = countryCode {
print("Country code: ", countryCode)
}
})
}
Don't forget to include that in your .plist file:
<key>NSAppleMusicUsageDescription</key>
<string>Store information</string>
A hard way to get this function is to set up up a single app for every app store country. Each app holds it's own country store information. This assumes, that a user sticks to one store, which should be true for most people.
I suggest you try iTunes deep links. For example, http://itunes.com/apps/appname should take the user to the local App Store where she spends money.
I need the same functionality. At the moment I'm considering reading using data from NSLocale as default, but adding a setting in settings.app for user to customise this if it does not match.
This function is taken from an answer to another question of mine.
- (NSString *)getUserCountry
{
NSLocale *locale = [NSLocale currentLocale];
return [locale objectForKey: NSLocaleCountryCode];
}
You should probably use
[[userDefaults dictionaryRepresentation] objectForKey:#"NSLocaleCode"];
This will return a language code like en_US or en_UK or en_AU or even zh_CN, zh_MY, jp_JP and so on.
Parse the correct codes which you support and direct them accordingly.