Here, we will explain how to use the functionalities the CloudRail SI iOS SDK provides.

We assume you have already installed the library, if not, have a look at Installation.

The code samples that come with each function description assume that a service that implements the respective interface has already been instantiated.

If you want to run the code samples refer to Services to find instructions on how to instantiate your service and then come back here.

General

In order to understand what functionality which service offers we need to understand the concept of interfaces and implementing services.

CloudRail SI's services all implement one or multiple of the following interfaces:

Name What is does Implementing services
Cloud Storage Upload, download, copy, delete, move, create and get information about files and/or folders in a CloudStorage provider Dropbox, Google Drive, OneDrive, OneDrive Business, Box,Egnyte
Business Cloud Storage Upload and download files, create and delete buckets, list buckets and files, get information about files Amazon S3, Microsoft Azure, Backblaze, Rackspace
Social Profile Retrieve information about a user, including an identifier to realize "Login with ..." Facebook, GitHub, Google+, LinkedIn, Slack, Twitter, Windows Live, Yahoo, Instagram
Social Interaction Retrieve a list of connections/friends/etc and post an update Facebook, FacebookPages, Twitter
Payment Manage charges, refunds and subscriptions of clients who make payments with their credit card to an account on the respective service PayPal, Stripe
Email Programmatically send text/HTML emails to one or many addresses Mailjet, SendGrid
SMS Programmatically send SMS to phones Twilio, Nexmo
Points of Interest Get a list of points of interest in around a given location in a certain radius filtered by search terms and/or categories Google Places, Foursquare, Yelp

Each interface comes with a set of functionalities and implementing that interface implies that the respective service supports all the functionality from that interface.

Interfaces

Cloud Storage

Introduction

The CloudStorage interface bundles functionality around interaction with cloud storage providers. Its main challenge consists in abstracting about how files and folders are referenced. For the sake of easy usage, we have chosen paths over identifiers. This means every file and folder will be referenced by its full path starting at the root folder for all the functions in this interface.

For example, /TestFolder/UserData.csv refers to a file called UserData.csv residing in the TestFolder folder which in turn is located at root.

Implementing services

Function Overview

Did not find the function you need? Try Advanced Request!

Functions

Upload

Declaration
/**
 *  Uploads a file to a cloud storage
 * @param filePath The path where to store the file from the root folder and including the name, e.g /myFolder/myFile.jpg
 * @param stream A stream from which the file can bwe read
 * @param size The size in bytes of the data that can be read from the stream
 */
-(void) uploadFileToPath:(nonnull NSString *)filePath
              withStream:(nonnull NSInputStream *)stream
                    size:(long)size
               overwrite:(BOOL)overwrite;
Example
// Loads a file from the application's bundle and uploads it (changes the file's name in the process)
  NSString *filePath = [[NSBundle mainBundle] pathForResource:@"UserData" ofType:@"csv"];
  NSData * data = [NSData dataWithContentsOfFile:filePath];
  NSInputStream * inputStream = [NSInputStream inputStreamWithFileAtPath:filePath];
  [cloudStorage uploadFileToPath:@"/TestFolder/Data.csv" withStream:inputStream size:data.length overwrite:YES];

Download

Declaration
/**
 *  Downloads a file from a cloud storage
 * @param filePath The path to the file from the root folder and including the name, e.g /myFolder/myFile.jpg
 * @return A stream from which the file can be read
 */
-(nonnull NSInputStream *)downloadFileWithPath:(nonnull NSString *)filePath;
Example
// Gets an InputStream which can then be written to disk, uploaded somewhere else etc.
NSInputStream * stream = [cloudStorage downloadFileWithPath:@"/TestFolder/Data.csv"];

Create Folder

Declaration
/**
 *  Creates a folder at the given path
 * @param folderPath The path to the folder from the root folder and including the name, e.g. /myNewFolder
 */
-(void)createFolderWithPath:(nonnull NSString*)folderPath;
Example
[cloudstorage createFolderWithPath:@"/TestFolder"]

Copy

Declaration
/**
 *  Copies a file from one path in the cloud storage to another
 * @param sourcePath The path of the origin file from the root folder and including the name
 * @param destinationPath The path of the destination file from the root folder and including the name
 */
-(void)copyFileFromPath:(nonnull NSString *)sourcePath
      toDestinationPath:(nonnull NSString *)destinationPath;
Example
[cloudstorage copyFileFromPath:@"/TestFolder/Data.csv" toDestinationPath:@"/CopyFolder/Data.csv"];

Delete

Declaration
/**
 *  Deletes a file from the cloud storage
 * @param filePath The path to the file to be deleted from the root folder and including the name
 */
-(void)deleteFileWithPath:(nonnull NSString *)filePath;
Example
[cloudstorage deleteFileWithPath:@"/TestFolder/UserData.csv"];

Move

Declaration
/**
 *  Moves a file in the cloud storage
 * @param sourcePath The path to the file which should be moved from the root folder and including the name
 * @param destinationPath The path to move the file to from the root folder and including the name
 */
-(void)moveFileFromPath:(nonnull NSString *)sourcePath
      toDestinationPath:(nonnull NSString *)destinationPath;
Example
[cloudstorage moveFileFromPath:@"/mudkipUPLOAD.jpg"  toDestinationPath:@"/NOT_awesomeFolder/mudkipUPLOAD.jpg"];

Get Metadata

Declaration
/**
 *  Gets metadata about the file/folder
 * @param filePath The path to the file from the root folder and including the name
 * @return A container for metadata
 */
-(nonnull CRCloudMetaData *)metadataOfFileWithPath:(nonnull NSString *)filePath;

@interface CRCloudMetaData
    // The path of the file in the cloud storage service starting from the Root.
    @property (nonatomic) NSString * path;

    // The name of the file, usually the last path component including the file extension.
    @property (nonatomic) NSString * name;

    // The size of the file (in bytes), derived from long type.
    @property (nonatomic) NSNumber * size;

    // A number describing if the file is a folder or not. Zero value representss false (NO) and positive 1 represents True (YES)
    @property (nonatomic) NSNumber * folder;

    // Timestamp that describest the last time the file was modified, derived from long type.
    @property (nonatomic) NSNumber * modifiedAt;

    // Image metadata if available
    @property (nonatomic) CRImageMetaData * imageMetaData;
@end

@interface CRImageMetaData
    // Image width
    @property (nonatomic) long width;

    // Image height
    @property (nonatomic) long height;
@end
Example
CloudMetaData * meta = [cloudstorage metadataOfFileWithPath:@"/TestFolder/Data.csv"];
NSLog(@"File size is %@",meta.size);

Get Children

Declaration
/**
 *  Gets the metadata of this folder's children
 * @param folderPath The path to the file from the root folder and including the name
 * @return A container for metadata
 */
-(nonnull NSMutableArray<CRCloudMetaData *> *)childrenOfFolderWithPath:(nonnull NSString *)folderPath;

@interface CRCloudMetaData
    // The path of the file in the cloud storage service starting from the Root.
    @property (nonatomic) NSString * path;

    // The name of the file, usually the last path component including the file extension.
    @property (nonatomic) NSString * name;

    // The size of the file (in bytes), derived from long type.
    @property (nonatomic) NSNumber * size;

    // A number describing if the file is a folder or not. Zero value representss false (NO) and positive 1 represents True (YES)
    @property (nonatomic) NSNumber * folder;

    // Timestamp that describest the last time the file was modified, derived from long type.
    @property (nonatomic) NSNumber * modifiedAt;

    // Image metadata if available
    @property (nonatomic) CRImageMetaData * imageMetaData;
@end

@interface CRImageMetaData
    // Image width
    @property (nonatomic) long width;

    // Image height
    @property (nonatomic) long height;
@end
Example
NSMutableArray<CRCloudMetaData *> * metas = [cloudStorage childrenOfFolderWithPath:@"/TestFolder"];
NSLog(@"Folder has %@ children", [metas count]);

Get Children Page

Declaration
/**
 * Retrieves metadata of files within the specified folder.
 * Unlike {@link CloudStorage#getChildren(String)} the result of this function only returns a
 * subset of the folder's content.
 *
 * @param path The path to the file from the root folder and including the name.
 * @param offset The first child to return metadata for.
 * @param limit The maximum amount of children that should be returned.
 *
 * @return List of metadata entries for the children of the specified folder.
 */

- (nonnull NSMutableArray<CRCloudMetaData *> *)childrenOfFolderWithPath:(nonnull NSString *) folderPath
                                                                 offset:(long) offset
                                                                  limit:(long) limit;

@interface CRCloudMetaData
    // The path of the file in the cloud storage service starting from the Root.
    @property (nonatomic) NSString * path;

    // The name of the file, usually the last path component including the file extension.
    @property (nonatomic) NSString * name;

    // The size of the file (in bytes), derived from long type.
    @property (nonatomic) NSNumber * size;

    // A number describing if the file is a folder or not. Zero value representss false (NO) and positive 1 represents True (YES)
    @property (nonatomic) NSNumber * folder;

    // Timestamp that describest the last time the file was modified, derived from long type.
    @property (nonatomic) NSNumber * modifiedAt;

    // Image metadata if available
    @property (nonatomic) CRImageMetaData * imageMetaData;
@end

@interface CRImageMetaData
    // Image width
    @property (nonatomic) long width;

    // Image height
    @property (nonatomic) long height;
@end
Example
NSMutableArray<CRCloudMetaData *> * metas = [cloudStorage childrenOfFolderWithPath:@"/TestFolder" offset:0 limit:4];
NSLog(@"Successfully gotten the first %@ children", [metas count]);

Create Share Link

Declaration
/**
 * Creates a share link and the permission is only to 'view' and download the file/folder
 *
 * @param path the path to the file/folder which the link to will be created
 * @return The url as a String
 */
- (nonnull NSString *) shareLinkForFileWithPath:(nonnull NSString *) path;
Example
NSString * shareLink = [cloudStorage shareLinkForFileWithPath: @"/TestFolder"];
NSLog(@"The share link is %@", shareLink);

Get Allocation

Declaration
/**
 *
 * @return The total space in bytes and the used space
 */
- (nonnull CRSpaceAllocation *) spaceAllocation;

@interface CRSpaceAllocation
    //The total available space in bytes
    @property (nonatomic) NSNumber * total;

    //The used space in bytes
    @property (nonatomic) NSNumber * used;
@end
Example
CRSpaceAllocation * allocation = [cloudStorage spaceAllocation];
NSLog(@"The total space is %@", allocation.total);
NSLog(@"The used space is %@", allocation.used);

Exists

Declaration
/**
 *  Checks the existance of a File or Folder
 *
 *  @param path Path to the file on cloud.
 *
 *  @return BOOL YES if the file exist at a given path
 */
- (BOOL) fileExistsAtPath:(nonnull NSString *) path;
Example
if ([cloudStorage fileExistsAtPath: @"/AppFolder"] == YES) {
    [cloudStorage createFolderWithPath: @"/AppFolder"];
}

Get Thumbnail

Declaration
/**
 *  Gets a thumbnail of the image at the path. The path must resolve into an image.
 *
 *  @param path path to the image
 *
 *  @return NSIntputStream Stream that points to the image thumbnail
 */
- (nonnull  NSInputStream *) thumbnailOfFileWithPath: (nonnull NSString *) path;
Example
NSInputStream * thumb = [cloudStorage thumbnailOfFileWithPath: @"/image.jpeg"];

Get User's Login Identifier

Declaration
/**
 * @return The currently logged in user's login identifier (name/email/...).
 */
-(NSString *) userLogin;
Example
NSString * userLogin = [cloudStorage userLogin];

Get User's Name

Declaration
/**
 * @return The currently logged in user's (full) name
 */
-(NSString *) userName;
Example
NSString * userLogin = [cloudStorage userName];

Explicit Login

Declaration
/**
 * Optional! Explicitly triggers user authentication.
 * Allows better control over the authentication process.
 * Optional because all methods that require prior authentication will
 * trigger it automatically, unless this method has been called before.
 */
-(void) login;
Example
[cloudStorage login];

Explicit Logout

Declaration
/**
 * Optional! Revokes the current authentication.
 */
 -(void) logout;
Example
[cloudStorage logout];

Save As String

Declaration
/**
 * A method to retrieve the data from a service that is intended for
 * persistent storage.
 *
 * @return The data of the service that should be stored persistently,
 * e.g. access credentials.
 */
-(NSString *) saveAsString;
Example
// Assume cs and cs2 are both instances of the same service
// cs already has a logged in user and cs2 is freshly created
NSString * data = [cs saveAsString];
[cs2 loadAsString:data];
// Now cs2 has the same user logged in as cs

Load As String

Declaration
/**
 * Loads/restores data saved by saveAsString() into the service.
 *
 * @param savedData The persistent data that was stored.
 */
-(void) loadAsString:(NSString*) savedState;
Example
// Assume cs and cs2 are both instances of the same service
// cs already has a logged in user and cs2 is freshly created
NSString * data = [cs saveAsString];
[cs2 loadAsString:data];
// Now cs2 has the same user logged in as cs

Business Cloud Storage

Introduction

This is a common interface for Bucket based Cloud Storage Services. Instead of organizing files in nested folders, they reside in a bucket.

Implementing services

Function Overview

Functions

List Buckets

Declaration
/**
 * Get a list of all buckets within your account.
 *
 * @return List of buckets. This might be an empty list if there are no buckets.
 */
 -(NSMutableArray<CRBucket *> *) listBuckets;

@interface CRBucket : CRSandboxObject
  @property (nonatomic) NSString * identifier;
  @property (nonatomic) NSString * name;
@end
Example
@try {
  [currentService listBuckets];
} @catch (NSException *exception) {
  //handle exception
}

Create Bucket

Declaration
/**
 * Creates a new empty bucket.
 *
 * @param name The name of the new bucket.
 * @return The newly created bucket.
 */
-(CRBucket *) createBucket: (NSString *) bucketName;

 @interface CRBucket : CRSandboxObject
   @property (nonatomic) NSString * identifier;
   @property (nonatomic) NSString * name;
 @end
Example
@try {
  [currentService createBucket:bucketName];
} @catch (NSException *exception) {
  //handle exception
}

Delete Bucket

Declaration
/**
 * Deletes the specified bucket with all its content.
 *
 * @param bucket The bucket which will be deleted.
 */
 -(void) deleteBucketWithID: (CRBucket *) bucket;

@interface CRBucket : CRSandboxObject
  @property (nonatomic) NSString * identifier;
  @property (nonatomic) NSString * name;
@end
Example
@try {
  [self.currentService deleteBucket:bucket];
} @catch (NSException *exception) {
  //handle exception
}

List Files

Declaration
/**
 * Get a list of files contained in the specified bucket.
 *
 * @param bucket The bucket containing the files.
 */
 -(NSMutableArray<CRBusinessFileMetaData *> *) listFilesInBucket: (CRBucket *) bucket;

@interface CRBucket : CRSandboxObject
  @property (nonatomic) NSString * identifier;
  @property (nonatomic) NSString * name;
@end

@interface CRBusinessFileMetaData : CRSandboxObject

  @property (nonatomic) NSString * fileID;
  @property (nonatomic) NSString * fileName;

  @property (nonatomic) NSNumber * size;
  @property (nonatomic) NSNumber * lastModified;

@end
Example
@try {
  NSMutableArray * filesList<CRBusinessFileMetadata*> = [self.currentService listFilesInBucket:bucket];
} @catch (NSException *exception) {
  //handle exception
}

Upload File

Declaration
/**
 * Uploads a new file into a bucket or replaces the file if it is already present.
 *
 * @param bucket  The bucket into which the file shall be put.
 * @param name    The name of the file.
 * @param stream The file content as a readable stream.
 * @param size    The amount of bytes that the file contains.
 */
 -(void) uploadFileToBucket: (CRBucket *) bucket
                       name: (NSString *) name
                 withStream: (NSInputStream *) stream
                       size: (long) size;

@interface CRBucket : CRSandboxObject
  @property (nonatomic) NSString * identifier;
  @property (nonatomic) NSString * name;
@end
Example
CRBucket * bucket = [[CRBucket alloc] init];
bucket.name = @"[bucket_name]";
bucket.identifier = @"[bucket_id]";

NSData * data = //data source;
NSInputStream * inputStream = [NSInputStream inputStreamWithData:data];

@try {
  [self.currentService uploadFileToBucket:bucket name:@"file_name" withStream:inputStream size:data.length];
} @catch (NSException *exception) {
  //handle exception
}

Delete File

Declaration
/**
 * Deletes a file within a bucket.
 *
 * @param fileName The name of the file.
 * @param bucket   The bucket that contains the file.
 */
 -(void) deleteFileWithName: (NSString *) fileName
                     bucket: (CRBucket *) bucket;

@interface CRBucket : CRSandboxObject
  @property (nonatomic) NSString * identifier;
  @property (nonatomic) NSString * name;
@end
Example
@try {
  [self.currentService deleteFileWithName:@"[file_name]" bucket:bucket];
} @catch (NSException *exception) {
  //handle exception
}

Download File

Declaration
//**
 * Downloads a file from a bucket.
 *
 * @param bucket   The bucket which contains the file.
 * @param fileName The name of the file.
 * @return The content of the file as a readable stream.
 */
 -(NSInputStream *) downloadFileWithName: (NSString *) fileName
                                  bucket: (CRBucket *) bucket;

@interface CRBucket : CRSandboxObject
  @property (nonatomic) NSString * identifier;
  @property (nonatomic) NSString * name;
@end
Example
@try {
  NSInputStream * stream = [self.currentService downloadFileWithName:@"[file_name]" bucket:bucket];
} @catch (NSException *exception) {
  //handle exception
}
//READ FROM STREAM

Get File Metadata

Declaration
/**
 * Get metadata of a file containing the name, the size and the last
 * modified date.
 *
 * @param bucket   The bucket where the file is located.
 * @param fileName The name of the file.
 */
 -(CRBusinessFileMetaData *) metadataOfFileWithPath: (CRBucket *) bucket
                                      fileName: (NSString *) fileName;

@interface CRBucket : CRSandboxObject
  @property (nonatomic) NSString * identifier;
  @property (nonatomic) NSString * name;
@end

@interface CRBusinessFileMetaData : CRSandboxObject

  @property (nonatomic) NSString * fileID;
  @property (nonatomic) NSString * fileName;

  @property (nonatomic) NSNumber * size;
  @property (nonatomic) NSNumber * lastModified;

@end
Example
@try {
  [self.currentService metadataOfFileInBucket:bucket fileName:@"[file_name]"];
} @catch (NSException *exception) {
  //handle exception
}

Social Profile

Introduction

The Profile interface is a common interface for Services that provide unique user identifiers and general user information.

With the getIdentifier function, "Login with ..." scenarios can be easily implemented: Whenever a user needs to login/signup, call the getIdentifier function of an instance of this interface. This will have the user login and then return a unique identifier for this user with this service. Use this to identify a user's account with your application.

All the other information might be present or not, depending on the service and how much information the user has filled out with the respective service. To avoid unnecessary requests, information is cached up to one minute.

Implementing services

Function Overview

Did not find the function you need? Try Advanced Request!

Functions

Get Identifier

Declaration
/**
 * @return A unique identifier for the authenticated user. All services provide this value. Useful for "Login with ...". Prefixed with the lowercased service name and a minus.
 */
-(nonnull NSString *)identifier;
Example
NSString * identifier = [profile identifier];

Get Full Name

Declaration
/**
 * @return The user's full name or null if not present
 */
-(nullable NSString *)fullName;
Example
NSString * name = [profile fullName];

Get Email

Declaration
/**
 * @return The user's email address or null if not present
 */
-(nullable NSString *)email;
Example
NSString * email = [profile email];

Get Gender

Declaration
/**
 * @return The user's gender, normalized to be one of "female", "male", "other" or nil if not present
 */
-(nullable NSString *)gender;
Example
NSString * gender = [profile gender];

Get Description

Declaration
/**
 * @return The description the user has given themselves or null if not present
 */
-(nullable NSString *)profileDescription;
Example
NSString * profileDescription = [profile profileDescription];

Get Date Of Birth

Declaration
/**
 * @return The date of birth in the format DateOfBirth.
 */
 -(nullable CRDateOfBirth *)dateOfBirth;
/**
 * @return The date of birth in the format DateOfBirth.
 */
 -(nullable CRDateOfBirth *)dateOfBirth;

 @interface CRDateOfBirth
   @property (nonatomic) NSNumber * year;
   @property (nonatomic) NSNumber * month;
   @property (nonatomic) NSNumber * day;
   /*
    *  Generated a NSDate from the properties: year, month, day
    *
    * @return NSDate the date object
    */
   -(NSDate *) date;
 @end
Example
CRDateOfBirth * dob = [profile dateOfBirth];
NSLog(@"%@/%@/%@", dob.day,dob.month,dob.year);

Get Locale

Declaration
/**
 * @return The locale/language setting of the user, e.g. "en", "de" or null if not present
 */
-(nullable NSString *)locale;
Example
NSString * locale = [profile locale];

Get Picture URL

Declaration
/**
 * @return The URL of the user's profile picture or null if not present.
 */
 -(nonnull NSString *)pictureURL;
Example
NSString * pictureURL = [profile pictureURL];

Explicit Login

Declaration
/**
* Optional! Explicitly triggers user authentication.
* Allows better control over the authentication process.
* Optional because all methods that require prior authentication will
* trigger it automatically, unless this method has been called before.
*/
-(void) login;
Example
[profile login];

Explicit Logout

Declaration
/**
* Optional! Revokes the current authentication.
*/
-(void) logout;
Example
[profile logout];

Save As String

Declaration
/**
* A method to retrieve the data from a service that is intended for
* persistent storage.
*
* @return The data of the service that should be stored persistently,
* e.g. access credentials.
*/
-(nonnull NSString *) saveAsString;
Example
// Assume cs and cs2 are both instances of the same service
// cs already has a logged in user and cs2 is freshly created
NSString * data = [cs saveAsString];
[cs2 loadAsString:data];
// Now cs2 has the same user logged in as cs

Load As String

Declaration
/**
* Loads/restores data saved by saveAsString() into the service.
*
* @param savedData The persistent data that was stored.
*/
-(void) loadAsString:(nonnull NSString*) savedState;
Example
// Assume cs and cs2 are both instances of the same service
// cs already has a logged in user and cs2 is freshly created
NSString * data = [cs saveAsString];
[cs2 loadAsString:data];
// Now cs2 has the same user logged in as cs

Social Interaction

Introduction

This is a common interface for services that provide a set of social functionalities. Currently the functionalities are limited to receiving a list of user ids with which the currently logged in user has a connection to and who is also using your app and to post an update to a users timeline.

Implementing services

Function Overview

Functions

Get Connections

Declaration
/**
 * Retrieves a list of connection/friend/etc. IDs.
 * The IDs are compatible with those returned by Profile.getIdentifier().
 * @return A (possibly empty) list of IDs
 */
-(nonnull NSArray<NSString *>*) connections;
Example
NSArray<NSString *>* connections = [social connections];
NSLog(@"List of connections %@",  connections);

Post Update

Declaration
/**
 * Creates a new post/update to the currently logged in user's wall/stream/etc.
 * @param content The post's content
 */
-(void) postUpdateWithContent:(nonnull NSString *) content;
Example
[self.service postUpdateWithContent:@"I love using CloudRail!!!"];

Post Image

Declaration
/**
 * Creates a new post/update to the currently logged in user's wall/stream/etc posting an
 * image and a message.
 * Throws an exception if the message is too long for the service instance.
 *
 * @param message The message that shall be posted together with the image.
 * @param image Stream containing the image content.
 */
- (void) postImageWithMessage:(nonnull NSString *) message
                        image:(nonnull NSInputStream *) image;
Example
NSData * data = //image source;
NSInputStream * inputStream = [NSInputStream inputStreamWithData:data];
[social postImageWithMessage:@"I love using CloudRail!!" image:inputStream];

Post Video

Declaration
/**
 * Creates a new post/update to the currently logged in user's wall/stream/etc posting a
 * video and a message.
 * Throws an exception if the message is too long for the service instance.
 *
 * @param message The message that shall be posted together with the video.
 * @param video Stream containing the video content.
 * @param size The size of the video in bytes.
 * @param mimeType The mime type of the video, for instance video/mp4.
 */
- (void) postVideoWithMessage:(nonnull NSString *) message
                        video:(nonnull NSInputStream *) video
                         size:(long) size
                     mimeType:(nonnull NSString *) mimeType;
Example
NSData * data = //video source;
NSInputStream * inputStream = [NSInputStream inputStreamWithData:data];
[social postVideoWithMessage:@"I love using CloudRail!!"
                       video:inputStream
                        size:3242456
                    mimeType:@"video/mp4"];

Explicit Login

Declaration
/**
 * (Optional) Explicitly triggers user authentication.
 * Allows better control over the authentication process.
 * Optional because all methods that require prior authentication will trigger it automatically,
 * unless this method has been called before.
 */
-(void) login;
Example
[social login];

Explicit Logout

Declaration
/**
 * (Optional) Revokes the current authentication.
 */
-(void) logout;
Example
[social logout];

Save As String

Declaration
/**
 *  A method to retrieve the data from a service that is intended for persistent storage
 * @return The data of the service that should be stored persistently, e.g. access credentials
 */
-(nonnull NSString *) saveAsString;
Example
// Assume social and social2 are both instances of the same service
// social already has a logged in user and social2 is freshly created
NSString * data = [social saveAsString];
[social2 loadAsString:data];
// Now social2 has the same user logged in as social

Load As String

Declaration

/**
 *  Loads/restores data saved by saveAsString method into the service
 * @param savedState The persistent data that was stored
 */
-(void) loadAsString:(nonnull NSString*) savedState;
Example
// Assume social and social2 are both instances of the same service
// social already has a logged in user and social2 is freshly created
NSString * data = [social saveAsString];
[social2 loadAsString:data];
// Now social2 has the same user logged in as social

Payment

Introduction

Payment is a common interface for services that allow you to collect payments from credit cards. It serves three main purposes: perform single charges, refund previously made charges and manage subscriptions. In order to properly test your integration, all services do provide some sort of testing environment and/or test values.

Implementing services

Function Overview

Functions

Create Charge

Declaration
/**
 * Charges a credit card and returns a charge resource.
 *
 * @param amount A positive integer in the smallest currency unit (e.g. cents)
 *      representing how much to charge the credit card.
 * @param currency A three-letter ISO code for currency.
 * @param source The credit card to be charged.
 * @return A charge resource representing the newly created payment.
 */
-(nonnull CRCharge *)createChargeWithAmount:(nonnull NSNumber *)amount
                                   currency:(nonnull NSString *)currency
                                     source:(nonnull CRCreditCard *)source;

@interface CRCharge : CRSandboxObject
 @property (nonatomic) NSString  * identifier; // ID of the newly generated charge
 @property (nonatomic) NSNumber * amount; // amount that was charged
 @property (nonatomic) NSString * currency; // currency in which the amount was charged
 @property (nonatomic) CRCreditCard * source; // credit card that was charged
 @property (nonatomic) NSNumber * created; // timestamp of when the charge was created
 @property (nonatomic) NSString * status; // current state of the charge. Possible values are: 'pending', 'succeeded' or 'failed'
 @property (nonatomic) NSNumber * refunded; // if the payment has been completely refunded or not
@end

@interface CRCreditCard : CRSandboxObject
  //CostumerData
  @property (nonatomic) NSString * firstName;
  @property (nonatomic) NSString * lastName;
  @property (nonatomic) CRAddress * address;
  @property (nonatomic) NSString * number;
  @property (nonatomic) NSString * cvc;   // Card validation code
  @property (nonatomic) NSNumber * expire_month; // Values between 1 and 12
  @property (nonatomic) NSNumber * expire_year; // Four digit expiration data
  @property (nonatomic) NSString * type; // Can have the following values: visa, mastercard, discover, amex

@end

@interface CRAddress : CRSandboxObject

@property (nonatomic) NSString * country; // ID of the newly generated charge
@property (nonatomic) NSString * city; // City/Suburb/Town/Village
@property (nonatomic) NSString * state;
@property (nonatomic) NSString * line1; // Street address/PO Box/Company name
@property (nonatomic) NSString * line2; // Apartment/Suite/Unit/Building
@property (nonatomic) NSString * postalCode;

@end
Example
CRCreditCard * source = [[CRCreditCard alloc] initWithCvc:nil
       expireMonth:@6
        expireYear:@2021
            number:@"xxxxxxxxxxxxxxxx"
              type:@"visa"
         firstName:@"firstName"
          lastName:@"lastName"
           address:nil];

CRCharge * charge = [self.service createChargeWithAmount:@500 currency:@"USD" source:source];
NSLog(@"Charge: %@", charge.description);

Get Charge

Declaration
/**
 * Returns information about an existing charge. Mostly used to get an update
 * on the status of the charge.
 *
 * @param id The ID of the charge.
 * @return A charge resource for the provided ID.
 */
-(nonnull CRCharge *)chargeWithIdentifier:(nonnull NSString *)identifier;

@interface CRCharge : CRSandboxObject
 @property (nonatomic) NSString  * identifier; // ID of the newly generated charge
 @property (nonatomic) NSNumber * amount; // amount that was charged
 @property (nonatomic) NSString * currency; // currency in which the amount was charged
 @property (nonatomic) CRCreditCard * source; // credit card that was charged
 @property (nonatomic) NSNumber * created; // timestamp of when the charge was created
 @property (nonatomic) NSString * status; // current state of the charge. Possible values are: 'pending', 'succeeded' or 'failed'
 @property (nonatomic) NSNumber * refunded; // if the payment has been completely refunded or not
@end

@interface CRCreditCard : CRSandboxObject
  @property (nonatomic) NSString * firstName;
  @property (nonatomic) NSString * lastName;
  @property (nonatomic) CRAddress * address;
  @property (nonatomic) NSString * number;
  @property (nonatomic) NSString * cvc;   // Card validation code
  @property (nonatomic) NSNumber * expire_month; // Values between 1 and 12
  @property (nonatomic) NSNumber * expire_year; // Four digit expiration data
  @property (nonatomic) NSString * type; // Can have the following values: visa, mastercard, discover, amex
@end

@interface CRAddress : CRSandboxObject
  @property (nonatomic) NSString * country; // ID of the newly generated charge
  @property (nonatomic) NSString * city; // City/Suburb/Town/Village
  @property (nonatomic) NSString * state;
  @property (nonatomic) NSString * line1; // Street address/PO Box/Company name
  @property (nonatomic) NSString * line2; // Apartment/Suite/Unit/Building
  @property (nonatomic) NSString * postalCode;
@end
Example
CRCharge * charge = [payment chargeWithIdentifier:@"ChargeID"];
NSLog(@"Charge: %@", charge.description);

List Charges

Declaration
/**
 * Receive a list of charges within a specified timeframe.
 *
 * @param from Timestamp representing the start date for the list.
 * @param to Timestamp representing the end date for the list.
 * @param creditCard Optionally the credit card information so it can be listed all the charges of this specific credit card.
 * @return List of charge resources.
 */
-(nonnull NSMutableArray<CRCharge *> *)listChargesFrom:(nonnull NSNumber *)from
                                                    to:(nonnull NSNumber *)to
                                            creditCard:(nonnull CRCreditCard *)creditCard;

@interface CRCharge : CRSandboxObject
 @property (nonatomic) NSString  * identifier; // ID of the newly generated charge
 @property (nonatomic) NSNumber * amount; // amount that was charged
 @property (nonatomic) NSString * currency; // currency in which the amount was charged
 @property (nonatomic) CRCreditCard * source; // credit card that was charged
 @property (nonatomic) NSNumber * created; // timestamp of when the charge was created
 @property (nonatomic) NSString * status; // current state of the charge. Possible values are: 'pending', 'succeeded' or 'failed'
 @property (nonatomic) NSNumber * refunded; // if the payment has been completely refunded or not
@end

@interface CRCreditCard : CRSandboxObject
  @property (nonatomic) NSString * firstName;
  @property (nonatomic) NSString * lastName;
  @property (nonatomic) CRAddress * address;
  @property (nonatomic) NSString * number;
  @property (nonatomic) NSString * cvc;   // Card validation code
  @property (nonatomic) NSNumber * expire_month; // Values between 1 and 12
  @property (nonatomic) NSNumber * expire_year; // Four digit expiration data
  @property (nonatomic) NSString * type; // Can have the following values: visa, mastercard, discover, amex
@end

@interface CRAddress : CRSandboxObject

  @property (nonatomic) NSString * country; // ID of the newly generated charge
  @property (nonatomic) NSString * city; // City/Suburb/Town/Village
  @property (nonatomic) NSString * state;
  @property (nonatomic) NSString * line1; // Street address/PO Box/Company name
  @property (nonatomic) NSString * line2; // Apartment/Suite/Unit/Building
  @property (nonatomic) NSString * postalCode;

@end
Example

long current = [NSDate date].timeIntervalSince1970;
long aWeekAgo = current - 604800;
NSArray<CRCharge*> *charges = [payment listChargesFrom:current to:@aWeekAgo creditCard:source];

Completely Refund Charge

Declaration
/**
 * Refund a previously made charge.
 *
 * @param id The ID of the charge to be refunded.
 * @return A refund resource.
 */
-(nonnull CRRefund *)refundChargeWithIdentifier:(nonnull NSString *)identifier;

@interface CRRefund : CRSandboxObject

@property (nonatomic) NSString * identifier; // The ID of the newly created refund
@property (nonatomic) NSNumber * amount; //  The amount that has been refunded
@property (nonatomic) NSNumber * created; // Timestamp representing the creation time of this refund
@property (nonatomic) NSString * currency; // The currency in which the refund was made
@property (nonatomic) NSString * chargeID; // Reference to the Charge that was refunded
@property (nonatomic) NSString * state; // Can have the following values: 'pending', 'succeeded' or 'failed'.
@end
Example
CRRefund * refund = [payment refundChargeWithIdentifier:@"ChargeID"];
NSLog(@"Refund: %@", refund);

Partially Refund Charge

Declaration
/**
 * Refund a specified amount from a previously made charge.
 *
 * @param id The ID of the charge to be refunded.
 * @param amount The amount that shall be refunded.
 * @return A refund resource.
 */
-(nonnull CRRefund *)partiallyRefundChargeWithIdentifier:(nonnull NSString *)identifier
                                                  amount:(nonnull NSNumber *)amount;

@interface CRRefund : CRSandboxObject

@property (nonatomic) NSString * identifier; // The ID of the newly created refund
@property (nonatomic) NSNumber * amount; //  The amount that has been refunded
@property (nonatomic) NSNumber * created; // Timestamp representing the creation time of this refund
@property (nonatomic) NSString * currency; // The currency in which the refund was made
@property (nonatomic) NSString * chargeID; // Reference to the Charge that was refunded
@property (nonatomic) NSString * state; // Can have the following values: 'pending', 'succeeded' or 'failed'.
@end
Example
CRRefund * refund = [payment partiallyRefundChargeWithIdentifier:@"ChargeID" amount:@100];
NSLog(@"Refund: %@", refund);

Get Refund

Declaration
/**
 * Returns information about the refunds for a specific charge.
 *
 * @param id The ID of the charge.
 * @return A refund resource for the provided charge.
 */
-(nonnull CRRefund *)refundWithIdentifier:(nonnull NSString *)identifier;

@interface CRRefund : CRSandboxObject

@property (nonatomic) NSString * identifier; // The ID of the newly created refund
@property (nonatomic) NSNumber * amount; //  The amount that has been refunded
@property (nonatomic) NSNumber * created; // Timestamp representing the creation time of this refund
@property (nonatomic) NSString * currency; // The currency in which the refund was made
@property (nonatomic) NSString * chargeID; // Reference to the Charge that was refunded
@property (nonatomic) NSString * state; // Can have the following values: 'pending', 'succeeded' or 'failed'.
@end
Example
CRRefund * refund = [payment refundWithIdentifier:@"ChargeID"];
NSLog(@"Refund: %@", refund);

Get Refunds for Charge

Declaration
/**
 * Returns information about an existing refund. Mostly used to get an update
 * on the status of the refund.
 *
 * @param id The ID of the refund.
 * @return A refund resource for the provided ID.
 */
-(nonnull NSMutableArray<CRRefund *> *)refundsForChargeWithIdentifier:(nonnull NSString *)identifier;
.
@interface CRRefund : CRSandboxObject

@property (nonatomic) NSString * identifier; // The ID of the newly created refund
@property (nonatomic) NSNumber * amount; //  The amount that has been refunded
@property (nonatomic) NSNumber * created; // Timestamp representing the creation time of this refund
@property (nonatomic) NSString * currency; // The currency in which the refund was made
@property (nonatomic) NSString * chargeID; // Reference to the Charge that was refunded
@property (nonatomic) NSString * state; // Can have the following values: 'pending', 'succeeded' or 'failed'.
@end
Example
NSArray<CRRefund *>* refunds = [payment refundsForChargeWithIdentifier:@"ChargeID"];
NSLog(@"Refunds: %@", refunds);
Log.i("info", "Refunds: " + refunds.toString());

Create Subscription Plan

Declaration
/**
 * Creates a subscription plan which is required to use subscription based payments.
 * The result of this method can be used together with 'createSubscription' in
 * order to subscribe someone to your subscription plan.
 *
 * @param name The name for the subscription plan.
 * @param amount The amount that is charged on a regular basis. A positive integer
 *      in the smallest currency unit (e.g. cents).
 * @param currency A three-letter ISO code for currency.
 * @param description A description for this subscription plan.
 * @param interval Specifies the billing frequency together with interval_count.
 *      Allowed values are:day, week, month or year.
 * @param interval_count Specifies the billing frequency together with interval.
 *      For example:interval_count = 2 and interval = "week" -> Billed every
 *      two weeks.
 * @return Returns the newly created subscription plan resource.
 */
-(nonnull CRSubscriptionPlan *)createSubscriptionPlanWithName:(nonnull NSString *)name
                                                       amount:(nonnull NSNumber *)amount
                                                     currency:(nonnull NSString *)currency
                                                  description:(nonnull NSString *)description
                                                     interval:(nonnull NSString *)Longerval
                                                intervalCount:(nonnull NSNumber *)Longerval_count;
.

@interface CRSubscriptionPlan : CRSandboxObject
  @property (nonatomic) NSString * identifier; // The ID of the subscription plan
  @property (nonatomic) NSString * name; // The name of the subscription plan
  @property (nonatomic) NSString * subscriptionDescription; /// The description field of the subscription plan
  @property (nonatomic) NSNumber * created; // Timestamp representing the creation time of this subscription plan
  @property (nonatomic) NSNumber * amount; // The amount that is charged on a regular basis
  @property (nonatomic) NSString * currency; // The currency in which the amount is charged
  @property (nonatomic) NSString * interval; // The billing interval. Can have the following values: 'day', 'week', 'month' or 'year'.
  @property (nonatomic) NSNumber * interval_count; // The billing frequency
@end
Example
CRSubscriptionPlan * plan = [payment createSubscriptionPlanWithName:@"My subscription plan" amount:@500 currency:@"USD" description:@"Awesome subscription plan." interval:@"week" intervalCount:@2];
NSLog(@"Subscription Plan: %@", plan);

List Subscription Plans

Declaration
/**
 * Returns a list of all existing subscription plans.
 *
 * @return List of subscription plans.
 */
-(nonnull NSMutableArray<CRSubscriptionPlan *> *)listSubscriptionPlans;

@interface CRSubscriptionPlan : CRSandboxObject
  @property (nonatomic) NSString * identifier; // The ID of the subscription plan
  @property (nonatomic) NSString * name; // The name of the subscription plan
  @property (nonatomic) NSString * subscriptionDescription; /// The description field of the subscription plan
  @property (nonatomic) NSNumber * created; // Timestamp representing the creation time of this subscription plan
  @property (nonatomic) NSNumber * amount; // The amount that is charged on a regular basis
  @property (nonatomic) NSString * currency; // The currency in which the amount is charged
  @property (nonatomic) NSString * interval; // The billing interval. Can have the following values: 'day', 'week', 'month' or 'year'.
  @property (nonatomic) NSNumber * interval_count; // The billing frequency
@end
Example
NSArray<CRSubscriptionPlan*> * plans = [payment listSubscriptionPlans];
NSLog(@"Subscription Plans: %@", plans);

Create Subscription

Declaration
/**
 * Subscribes a new customer to an existing subscription plan.
 *
 * @param planID The ID of the subscription plan.
 * @param name A name for the subscription.
 * @param description A description for the subscription.
 * @param creditCard The customer that shall be subscribed.
 * @return The newly created subscription resource.
 */
-(nonnull CRSubscription *)createSubscriptionWithPlanID:(nonnull NSString *)planID
                                                   name:(nonnull NSString *)name
                                            description:(nonnull NSString *)description
                                                 source:(nonnull CRCreditCard *)source;

@interface CRCreditCard : CRSandboxObject
  @property (nonatomic) NSString * firstName;
  @property (nonatomic) NSString * lastName;
  @property (nonatomic) CRAddress * address;
  @property (nonatomic) NSString * number;
  @property (nonatomic) NSString * cvc;   // Card validation code
  @property (nonatomic) NSNumber * expire_month; // Values between 1 and 12
  @property (nonatomic) NSNumber * expire_year; // Four digit expiration data
  @property (nonatomic) NSString * type; // Can have the following values: visa, mastercard, discover, amex
@end

@interface CRAddress : CRSandboxObject

@property (nonatomic) NSString * country; // ID of the newly generated charge
@property (nonatomic) NSString * city; // City/Suburb/Town/Village
@property (nonatomic) NSString * state;
@property (nonatomic) NSString * line1; // Street address/PO Box/Company name
@property (nonatomic) NSString * line2; // Apartment/Suite/Unit/Building
@property (nonatomic) NSString * postalCode;

@end

@interface CRSubscription : CRSandboxObject
@property (nonatomic) NSString * identifier; // The subscription ID
@property (nonatomic) NSNumber * created;  // Timestamp representing the time the subscription was created
@property (nonatomic) NSString * name; // The name of the subscription
@property (nonatomic) NSString * subscriptionDescription; // The description field of the subscription
@property (nonatomic) NSString * subscriptionPlanID;
@property (nonatomic) NSNumber * lastCharge; // Timestamp representing the last time a charge was made
@property (nonatomic) NSNumber * nextCharge; // Timestamp representing the next time a charge will be made
@property (nonatomic) CRCreditCard * creditCard; // The credit card that will be charged on a regular basis
@property (nonatomic) NSString * state;  // Can have the following values: active or canceled.

@end
Example
CRCreditCard * source = [[CRCreditCard alloc] initWithCvc:nil
       expireMonth:@6
        expireYear:@2021
            number:@"xxxxxxxxxxxxxxxx"
              type:@"visa"
         firstName:@"firstName"
          lastName:@"lastName"
           address:nil];

CRSubscription * subscription =[payment createSubscriptionWithPlanID:@"PlanID" name:@"My Subscription" description:@"My Subscription" source:source];
NSLog(@"Subscription: %@", subscription);

Cancel Subscription

Declaration
/**
 * Cancel an active subscription.
 *
 * @param id ID of the subscription that should be canceled.
 */
-(void)cancelSubscriptionWithIdentifier:(nonnull NSString *)identifier;
Example
[payment cancelSubscriptionWithIdentifier:@"SubscriptionID"];

SMS

Introduction

This is a common interface for Services that provide the possibility to programmatically send SMS, e.g. for signup confirmations.

Implementing services

Function Overview

Functions

Send SMS

Declaration
/**
 * Sends an SMS message, used like sendSMS("CloudRail", "+4912345678", "Hello from CloudRail").
 * Throws if an error occurs.
 *
 * @param fromName A alphanumeric sender id to identify/brand the sender. Only works in some countries.
 * @param toNumber The recipients phone number in E.164 format, e.g. +4912345678.
 * @param content The message content. Limited to 1600 characters, messages > 160 characters are sent and charged as multiple messages.
 */
-(void) sendSmsFromName:(nonnull NSString *)fromName
               toNumber:(nonnull NSString *)toNumber
                content:(nonnull NSString *)content;
Example
[sms sendSmsFromName:@"CloudRail" toNumber:@"+491234567890" content:@"Hello from CloudRail"];

Email

Introduction

This is a common interface for Services that provide the possibility to programmatically send Emails, e.g. for signup confirmations.

Implementing services

Function Overview

Functions

Send Email

Declaration
/**
 * Sends an email. Used like sendEmail("info@cloudrail.com", "CloudRail", Arrays.asList("foo@bar.com", "bar@foo.com"), "Welcome", "Hello from CloudRail", null, null, null).
 * Throws if an error occurs.
 *
 * @param fromAddress Mandatory. The sender email address. Must normally be registered with the corresponding service.
 * @param fromName Mandatory. The from name to be displayed to the recipient(s).
 * @param toAddresses Mandatory. A list of recipient email addresses.
 * @param subject Mandatory. The email's subject line.
 * @param textBody The email's body plain text part. Either this and/or the htmlBody must be specified.
 * @param htmlBody The email's body HTML part. Either this and/or the textBody must be specified.
 * @param ccAddresses Optional. A list of CC recipient email addresses.
 * @param bccAddresses Optional. A list of BCC recipient email addresses.
 */
-(void)sendEmailFromAddress:(NSString *)fromAddress
         fromName:(NSString *)fromName
      toAddresses:(NSMutableArray<NSString *> *)toAddresses
          subject:(NSString *)subject
         textBody:(NSString *)textBody
         htmlBody:(NSString *)htmlBody
      ccAddresses:(NSMutableArray<NSString *> *)ccAddresses
     bccAddresses:(NSMutableArray<NSString *> *)bccAddresses;
Example
email.sendEmail(
    "info@cloudrail.com",
    "CloudRail",
    Arrays.asList("foo@bar.com", "bar@foo.com"),
    "Welcome", "Hello from CloudRail",
    null,
    null,
    null
);
[email sendEmailFromAddress:@"info@cloudrail.com"
                          fromName:@"CloudRail"
                       toAddresses:[@[@"foo@bar.com"] mutableCopy]
                           subject:@"Welcome"
                          textBody:@"Hello from CloudRail"
                          htmlBody:@""
                       ccAddresses:[@[]mutableCopy] bccAddresses:[@[] mutableCopy]];

Points of Interest

Introduction

This is a common interface for services that provide information about Points of Interest close to a given location. This location can be specified by passing latitude and longitude as well as a search radius. Furthermore, results can be limited by providing an optional search term or a list of categories.

Implementing services

Function Overview

Functions

Get Nearby POIs

Declaration
/**
 * Returns a list of POIs that are close to the passed location and filters them by certain criteria.
 *
 * @param latitude   The latitude of the target location.
 * @param longitude  The longitude of the target location.
 * @param radius     The search radius in metres.
 * @param searchTerm Optional search term that has to be matched.
 * @param categories Optional list of categories. Available categories can be found in the main documentation.
 * @return A list of POIs for the target location.
 */
-(nonnull NSMutableArray<CRPOI *> *) nearbyPoisWithLatitude:(nonnull NSNumber *)latitude
                                                  longitude:(nonnull NSNumber *)longitude
                                                     radius:(nonnull NSNumber *)radius
                                                 searchTerm:(nullable NSString *)searchTerm
                                                 categories:(nullable NSMutableArray<NSString *> *)categories;
@interface CRPOI : CRSandboxObject
  @property (nonatomic) NSString * name; // The name of the POI
  @property (nonatomic) NSString * imageURL; // A URL that can be used to display an image for this POI
  @property (nonatomic) NSString * phone; // The phone number if there is one
  @property (nonatomic) NSMutableArray<NSString *> * categories; // List of categories that apply to this POI
  @property (nonatomic) CRLocation * location; // A Location object containing the location of the POI
@end

@interface CRLocation : CRSandboxObject
  @property (nonatomic) NSNumber * longitude;
  @property (nonatomic) NSNumber * latitude;
@end
Example
//Mannheim : 49.483927, 8.473272
NSMutableArray<CRPOI*> * poi =  [self.service nearbyPoisWithLatitude:@49.483927 longitude:@8.473272 radius:@3000 searchTerm:@"Restaurant" categories:nil];
NSLog(@"info: %@", poi);

POI Categories

Use one or many of the below category keywords with the Points of Interest interface

  • airport
  • amusement_park
  • aquarium
  • bank
  • bar
  • beauty_salon
  • art_gallery
  • bakery
  • bicycle_store
  • book_store
  • bowling_alley
  • bus_station
  • cafe
  • car_dealer
  • car_rental
  • car_wash
  • casino
  • cemetery
  • church
  • clothing_store
  • convenience_store
  • courthouse
  • dentist
  • department_store
  • doctor
  • electronics_store
  • embassy
  • finance
  • fire_station
  • florist
  • food
  • funeral_home
  • furniture_store
  • gas_station
  • grocery_or_supermarket
  • gym
  • hardware_store
  • health
  • hindu_temple
  • hospital
  • jewelry_store
  • laundry
  • lawyer
  • library
  • locksmith
  • mosque
  • movie_theater
  • museum
  • night_club
  • parks
  • parking
  • pet_store
  • pharmacy
  • physiotherapist
  • police
  • post_office
  • real_estate_agency
  • restaurant
  • rv_park
  • school
  • shoe_store
  • shopping_mall
  • spa
  • stadium
  • synagogue
  • taxi_stand
  • train_station
  • travel_agency
  • university
  • veterinary_care
  • zoo

Advanced Request

The methods above are chosen to reflect most commonly used functionalities and thus those that all services implementing an interface have in common. It follows that the APIs of the services CloudRail integrates with offer more, service-specific functionality that is missing from CloudRail. To mitigate this, the advanced request functionality was introduced. It allows a developer to specify the raw HTTP request against an API and thus access all of its functionality. To be more than just another HTTP Client, CloudRail supports the developer by taking care of authentication and error checking.

Supported services

Currently, the advanced request function is present on all services implementing the CloudStorage interface and those implementing the Profile interface. More services will follow soon.

Example

We want to list all shared folders of a Dropbox account and know through the Dropbox API documentation that this functionality is supported by Dropbox (https://www.dropbox.com/developers/documentation/http/documentation#sharing-list_folders). Yet, it is not supported by the CloudRail Dropbox service so we use advanced request. The example assumes that you are already familiar with the installation and intialization of a CloudRail service integration.

// Initialize like usual
[CRCloudRail setAppKey:@"[CloudRail key]"];
CRDropbox * dropbox = [[CRDropbox alloc] initWithClientId:@"[clientId]" clientSecret:@"[clientSecret]";

// Specify the URL of the Dropbox API endpoint, the base URL is prepended by default
CRAdvancedRequestSpecification * req = [[CRAdvancedRequestSpecification alloc] initWithUrl:@"/sharing/list_folders"];

// Set the HTTP request method to POST
req.method = @"POST";

// Specify the body and let it be converted to JSON
NSMutableDictionary * body = [[NSMutableDictionary alloc] init];
[body setValue:[NSNumber numberWithInt:100] forKey:@"limit"];
[req setBodyStringifyJson:body];

// Specify the headers
NSMutableDictionary * headers = [[NSMutableDictionary alloc] init];
[headers setValue:@"application/json" forKey:@"Content-Type"];
req.headers = headers;

// Execute the request, CloudRail will start the authentication flow if necessary
// and append the authorization header.
// The response is checked for errors.
CRAdvancedRequestResponse * res = [self.currentService advancedRequestWithSpecification:req];

// Extract the parsed response body
NSDictionary * jsonRes = [res bodyJsonParsed];

Specification

All supported services have an advancedRequest method:

- (CRAdvancedRequestResponse *) advancedRequestWithSpecification: (CRAdvancedRequestSpecification *) specification;

The AdvancedRequestSpecification looks like this:

@interface CRAdvancedRequestSpecification : CRSandboxObject

@property (nonatomic) NSString * url;
@property (nonatomic) NSString * method;
@property (nonatomic) NSInputStream * body;
@property (nonatomic) NSMutableDictionary * headers;
@property (nonatomic) NSNumber * appendAuthorization;
@property (nonatomic) NSNumber * checkErrors;
@property (nonatomic) NSNumber * appendBaseUrl;

- (instancetype) initWithUrl:(NSString *) url;

#pragma mark - Different methods to set the body

- (void) setBodyAsString: (NSString *) body;
- (void) setBodyStringifyJson: (id) body;
- (void) setBodyStringifyXml: (id) body;

@end

The AdvancedRequestResponse looks like this:

@interface CRAdvancedRequestResponse : CRSandboxObject

@property (nonatomic) NSInputStream * body;
@property (nonatomic) NSDictionary * headers;
@property (nonatomic) NSNumber * status;
@property (nonatomic) NSString * _stringBody;

#pragma mark - Body transformation methods

- (NSString *) bodyAsString;
- (id) bodyJsonParsed;
- (NSDictionary *) bodyXmlParsed;

@end

Limitations

The requests are facilitated by prepending a Base URL, adding authorization and doing error checking. This assumes similar behavior in those regards of all API methods. Yet sometimes, this is not the case. You might have to disable authentication and do it on your own, e.g. because insufficient scopes are requested. You might have to disable error checking or do additional checking because the defaults are wrong or not sufficient. You might have to disable prepeding the base URL because a certain API endpoint has a different one. Do read up on each service in the Services section to learn about what base URL is prepended, what authorization appending does and which errors are caught.

External Authentication

The standard authentication used in the SDK uses WebViews to perform its duty because it's the most convenient way to do it. However, there are services out there which do not allow the use of WebViews for their authentication flow (namely Google). This is because a user is not able to verify the website that is being displayed to them when using WebViews. For this purpose we introduced the external authentication which uses SFSafariViewController to perform the authentication.

The external authentication can of course be used with every service. But Google is the first one to only allow this type of authentication (for new apps already and for old apps it will be mandatory within the next months). Since this type of authentication does require some more work, the following paragraphs will guide you through the process.

How to use external authentication

First of all you need to tell the SDK that you want to use the external authentication for a particular service. This is done by calling a single method useAdvancedAuthentication before making any call to the SDK. The method does not take any parameters and needs to be called on the service itself since it is not part of the protocol. Calling this method will make the SDK open the website for authentication in the SFSafariViewController.

Now the issue is that we do not get the information if the user has granted access or not. For this to happen we need to tell the OS that our application can handle certain URLs that are opened within the browser (custom URLs). This is done by declaring a URL scheme in your info.plist:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>com.cloudrail.TestApplication</string>
        </array>
    </dict>
</array>

Since the redirect URI we specified for this example is com.cloudrail.TestApplication:/oauth2redirect we have to register the scheme com.cloudrail.TestApplication, this is the bundle ID of your application. For further information on the redirect URI have a look at the documentation on the particular service you are integrating.

What we have achieved so far is that we use the SFSafariViewController for the authentication and we listen for the redirect that will be performed when the user grants access. Now we have to handle the information coming back. By registering the URL scheme above the application will receive the requested URL to complete the authentication process. The code for doing this might look like this:

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
  [[NSNotificationCenter defaultCenter] postNotificationName:@"kCloseSafariViewControllerNotification" object:url];
  return YES;
}

@end

We add the above method to the AppDelegate. This method is called whenever a URL is opened that fits one of the schemes you have registered. The URL we get is then sent to the SDK using the default notification center. If you followed these steps, you should now be able to easily handle the external authentication.