Following @Tlaquetzal example, I ended up doing something like below
In pod file
pod 'GoogleAPIClientForREST'
pod 'JWT'
Using ServiceGenerator and Discovery Document as mentioned above, generated set of DialogFlow v2beta1 classes. Command line
./ServiceGenerator --outputDir . --verbose --gtlrFrameworkName GTLR --addServiceNameDir yes --guessFormattedNames https://dialogflow.googleapis.com/\$discovery/rest?version=v2beta1
And added them to the project.
#import "DialogflowV2Beta1/GTLRDialogflow.h"
Next step is to generate JWT Token. I have used this library JSON Web Token implementation in Objective-C. I want to connect using a service account.
NSInteger unixtime = [[NSNumber numberWithDouble: [[NSDate date] timeIntervalSince1970]] integerValue];
NSInteger expires = unixtime + 3600; //expire in one hour
NSString *iat = [NSString stringWithFormat:@"%ld", unixtime];
NSString *exp = [NSString stringWithFormat:@"%ld", expires];
NSDictionary *payload = @{
@"iss": @"<YOUR-SERVICE-ACCOUNT-EMAIL>",
@"sub": @"<YOUR-SERVICE-ACCOUNT-EMAIL>",
@"aud": @"https://dialogflow.googleapis.com/",
@"iat": iat,
@"exp": exp
};
NSDictionary *headers = @{
@"alg" : @"RS256",
@"typ" : @"JWT",
@"kid" : @"<KID FROM YOUR SERVICE ACCOUNT FILE>"
};
NSString *algorithmName = @"RS256";
NSData *privateKeySecretData = [[[NSDataAsset alloc] initWithName:@"<IOS-ASSET-NAME-JSON-SERVICE-ACCOUNT-FILE>"] data];
NSString *passphraseForPrivateKey = @"<PASSWORD-FOR-PRIVATE-KEY-IN-CERT-JSON>";
JWTBuilder *builder = [JWTBuilder encodePayload:payload].headers(headers).secretData(privateKeySecretData).privateKeyCertificatePassphrase(passphraseForPrivateKey).algorithmName(algorithmName);
NSString *token = builder.encode;
// check error
if (builder.jwtError == nil) {
JwtToken *jwtToken = [[JwtToken alloc] initWithToken:token expires:expires];
success(jwtToken);
}
else {
// error occurred.
MSLog(@"ERROR. jwtError = %@", builder.jwtError);
failure(builder.jwtError);
}
When token is generated, it can be used for an hour (or time you specify above).
To make a call to dialogflow you need to define your project path. To create a project path for the call, append to the code below your unique session identifier. Session is like a conversation for dialogflow, so different users should use different session ids
#define PROJECTPATH @"projects/<YOUR-PROJECT-NAME>/agent/sessions/"
Making dialogflow call
// Create the service
GTLRDialogflowService *service = [[GTLRDialogflowService alloc] init];
//authorise with token
service.additionalHTTPHeaders = @{
@"Authorization" : [NSString stringWithFormat:@"Bearer %@", self.getToken.token]
};
// Create the request object (The JSON payload)
GTLRDialogflow_GoogleCloudDialogflowV2beta1DetectIntentRequest *request = [GTLRDialogflow_GoogleCloudDialogflowV2beta1DetectIntentRequest object];
//create query
GTLRDialogflow_GoogleCloudDialogflowV2beta1QueryInput *queryInput = [GTLRDialogflow_GoogleCloudDialogflowV2beta1QueryInput object];
//text query
GTLRDialogflow_GoogleCloudDialogflowV2beta1TextInput *userText = [GTLRDialogflow_GoogleCloudDialogflowV2beta1TextInput object];
userText.text = question;
userText.languageCode = LANGUAGE;
queryInput.text = @"YOUR QUESTION TO dialogflow agent"; //userText;
// Set the information in the request object
//request.inputAudio = myInputAudio;
//request.outputAudioConfig = myOutputAudioConfig;
request.queryInput = queryInput;
//request.queryParams = myQueryParams;
//Create API project path with session
NSString *pathAndSession = [NSString stringWithFormat:@"%@%@", PROJECTPATH, [self getSession]];
// Create a query with session (Path parameter) and the request object
GTLRDialogflowQuery_ProjectsAgentSessionsDetectIntent *query = [GTLRDialogflowQuery_ProjectsAgentSessionsDetectIntent queryWithObject:request session:pathAndSession];
// Create a ticket with a callback to fetch the result
// GTLRServiceTicket *ticket =
[service executeQuery:query
completionHandler:^(GTLRServiceTicket *callbackTicket, GTLRDialogflow_GoogleCloudDialogflowV2beta1DetectIntentResponse *detectIntentResponse, NSError *callbackError) {
// This callback block is run when the fetch completes.
if (callbackError != nil) {
NSLog(@"error");
NSLog(@"Fetch failed: %@", callbackError);
//TODO: Register failure with analytics
failure( callbackError );
}
else {
// NSLog(@"Success");
// The response from the agent
// NSLog(@"%@", detectIntentResponse.queryResult.fulfillmentText);
NSString *response = detectIntentResponse.queryResult.fulfillmentText;
success( response );
}
}];
This is a basic implementation, but works and good for demo.
Good luck