We're building a small Unity/iOS application with an Objective-C plug-in to provide access to MusicKit. I'm going through the announcement talk which takes you through the process to access each component of MusicKit.
We've ticked off:
- Authorization to Media Library
- User Capabilities
- Getting Storefront Access code
Now we're onto the user token request and it's failing every time with the error SKErrorDomain Code=7, otherwise known as SKErrorCloudServiceNetworkConnectionFailed. The localised description written within the errors is 'Cannot connect to iTunes Store'. The final underlying error states that the HTTP status being returned is a 401 Unauthorized. See the full log of the response error here:
Error Domain=SKErrorDomain Code=7 "(null)" UserInfo={NSUnderlyingError=0x283058c60 {Error Domain=SSErrorDomain Code=109 "(null)" UserInfo={NSUnderlyingError=0x2830589f0 {Error Domain=SSErrorDomain Code=109 "Cannot connect to iTunes Store" UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store, SSErrorHTTPStatusCodeKey=401}}}}}
I've found other responses to this particular error being cited as a bad developer token. This is potentially backed up as if I change the developer token in any way (replaced some random characters with 0s), I get the same response from the request, exactly as above with the same number of underlying errors.
However, if I use 'Postman' go through the process of sending requests through the Web API instead, using the developer token as a Bearer Authorization token, I get valid 200 OK responses from a request to, for example:
https://api.music.apple.com/v1/catalog/gb/songs/1161539476
If I alter the token in any way, this GET request returns a 401 Unauthorized response.
I've provided the relevant code below, redacted all irrelevant code. Any help would be really appreciated:
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
@interface MusicKitPlugin : NSObject
{
}
@end
@implementation MusicKitPlugin
static MusicKitPlugin *_sharedInstance;
SKCloudServiceController *_csController;
NSString *_developerToken;
NSString *_userToken;
+(MusicKitPlugin*) sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"Creating MusicKitPlugin shared instance");
_sharedInstance = [[MusicKitPlugin alloc] init];
});
return _sharedInstance;
}
-(id)init
{
self = [super init];
if (self)
{
_csController = [SKCloudServiceController new];
_developerToken = @"{INSERT_DEV_TOKEN}";
_userToken = @"";
}
return self;
}
-(void)requestUserToken
{
NSLog(@"Request user token called");
[_csController requestUserTokenForDeveloperToken:_developerToken
completionHandler:^(NSString *userToken, NSError *error)
{
NSLog(@"User token request responded");
if(userToken != NULL)
{
NSLog(@"User token: %@", userToken);
_userToken = userToken;
}
else if (error != NULL)
{
[self handleError:error];
}
}];
}
-(void)handleError:(NSError *)error
{
NSLog(@"Error: %@", error);
NSLog(@"Error domain: %@", [error domain]);
NSLog(@"Error code: %ld", [error code]);
NSLog(@"Error user info: %@", [error userInfo]);
switch ([error code]) {
...
case SKErrorCloudServiceNetworkConnectionFailed:
NSLog(@"Cloud service network connection failed");
break;
...
}
}
@end
extern "C"
{
void IOS_RequestUserToken()
{
[[MusicKitPlugin sharedInstance] requestUserToken];
}
}
So I tap a button in Unity, that button calls the IOS_RequestUserToken method that is linked to in a MonoBehaviour in Unity from the Objective-C plug-in. That calls the requestUserToken function of the shared instance plug-in and it outputs:
Request user token called
User token request responded
Error: Error Domain=SKErrorDomain Code=7 "(null)" UserInfo={NSUnderlyingError=0x283058c60 {Error Domain=SSErrorDomain Code=109 "(null)" UserInfo={NSUnderlyingError=0x2830589f0 {Error Domain=SSErrorDomain Code=109 "Cannot connect to iTunes Store" UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store, SSErrorHTTPStatusCodeKey=401}}}}}
Error domain: SKErrorDomain
Error code: 7
Error user info: {
NSUnderlyingError = "Error Domain=SSErrorDomain Code=109 \"(null)\" UserInfo={NSUnderlyingError=0x2830589f0 {Error Domain=SSErrorDomain Code=109 \"Cannot connect to iTunes Store\" UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store, SSErrorHTTPStatusCodeKey=401}}}";
}
Cloud service network connection failed