Direct calls from an iOS client

更新时间:
复制 MD 格式

You can use an SDK to call Visual Intelligence API operations. We recommend integrating the SDK on your server because embedding the AccessKey ID and AccessKey secret directly into your client can lead to security risks. To mitigate these risks, you can use the Security Token Service (STS) to authorize users to call the service.

Background information

Before you make calls from an iOS client, you must obtain temporary access credentials from the Security Token Service (STS). STS is an Alibaba Cloud service that manages temporary access permissions. You can use STS to issue temporary access credentials to users. Users can then use these credentials to call Visual Intelligence API services for a specified period. This method is more secure because you do not need to expose your long-term keys. For more information about how to obtain temporary access credentials, see Obtain temporary identity credentials for a RAM role.

Note

If you have questions about API access, API operation usage, or other issues related to Visual Intelligence API features, you can contact us by joining the DingTalk group (23109592).

Scenario 1: The file is in OSS in the China (Shanghai) region

If your file is stored in OSS in the China (Shanghai) region, see Request signature to make calls. This topic uses RecognizeBankCard as an example and shows only the key steps and code. For the complete demo, you can download iOSDemo. To call other algorithms, you can modify the code based on the comments and your business requirements.

Interaction flow

image

Prerequisites

Obtain a temporary STS credential:

  1. Grant permissions:

    Before obtaining a temporary STS credential, the caller, which can be a RAM user or RAM role, must be granted the permissions to call STS operations. You can grant permissions by configuring a RAM access policy. For more information about the configuration steps and access policies, see Use a temporary access credential provided by STS to access OSS. You can configure fine-grained authorization policies as needed to prevent excessive permissions. For more information about how to configure fine-grained authorization policies, see Custom policies for Visual Intelligence API.

    Important

    For the following steps, the caller, which can be a RAM user or RAM role, must be granted the AliyunSTSAssumeRoleAccess permission (the permission to call the AssumeRole operation of STS) and the AliyunVIAPIFullAccess permission (the permission to manage the Visual Intelligence API). For this example, we grant the full management permission. In a production environment, we strongly recommend that you configure fine-grained authorization policies as needed to prevent excessive permissions. For more information about how to configure fine-grained authorization policies, see Custom policies for Visual Intelligence API.

  2. Call the AssumeRole operation:

    You can use an authorized RAM user or RAM role to call the AssumeRole operation and fill in the required parameters as described in the documentation. For more information about the operation and its usage, see the official documentation for AssumeRole.

  3. Use the STS token:

    After you successfully call the AssumeRole operation, you will receive an STS token that contains an AccessKeyId, AccessKeySecret, and SecurityToken, as shown in the following code. When you call other Alibaba Cloud service operations, replace <ALIBABA_CLOUD_ACCESS_KEY_ID>, <ALIBABA_CLOUD_ACCESS_KEY_SECRET>, and <ALIBABA_CLOUD_SECURITY_TOKEN> in the code with the temporary AccessKeyId, AccessKeySecret, and SecurityToken from the Alibaba Cloud STS token data.

{
  "RequestId": "429D9967-C809-5A30-B65E-9B742CF*****",
  "AssumedRoleUser": {
    "Arn": "acs:ram::175805416243****:role/STStokenTestRole/STSsessionName",
    "AssumedRoleId": "39779315882322****:STSsessionName"
  },
  "Credentials": {
    "SecurityToken": "exampleToken",
    "AccessKeyId": "STS.exampleAccessKeyID",
    "AccessKeySecret": "exampleAccessKeySecret",
    "Expiration": "2024-06-12T03:21:29Z"
  }
}

Step 1: Configure basic parameters

The following code segment is used to call the "RecognizeBankCard" service of Alibaba Cloud. The code is in the Tool/CallApiClient.m file of the iOSDemo. Replace , <ALIBABA_CLOUD_ACCESS_KEY_SECRET>, and <ALIBABA_CLOUD_SECURITY_TOKEN> with the temporary AccessKeyId, AccessKeySecret, and SecurityToken from the Alibaba Cloud STS token data that you obtained in the Prerequisites section.

/**
  <ALIBABA_CLOUD_ACCESS_KEY_ID>, <ALIBABA_CLOUD_ACCESS_KEY_SECRET>, and <ALIBABA_CLOUD_SECURITY_TOKEN> must be replaced with the temporary AccessKeyId, AccessKeySecret, and SecurityToken obtained from the STS token data.
  If you use the AccessKey pair of a RAM user, you must also grant the AliyunVIAPIFullAccess permission to the RAM user. For more information, see https://help.aliyun.com/document_detail/145025.html
 */
const NSString* ACCESS_KEY_ID = @"<ALIBABA_CLOUD_ACCESS_KEY_ID>";
const NSString* ACCESS_KEY_SECRET = @"<ALIBABA_CLOUD_ACCESS_KEY_SECRET>";
const NSString* SECURITY_TOKEN = @"<ALIBABA_CLOUD_SECURITY_TOKEN>";

Step 2: Call the server-side operation and calculate the signature

The following code segment demonstrates how to calculate a signature and send a request for Visual Intelligence API operations. Signatures are a common security measure for cloud services, ensuring that requests sent to the service are not tampered with and are initiated by legitimate users with the appropriate credentials. For more information about the logic, see Request signature.

The following list describes the purpose and steps of the code segment:

  1. Set API request parameters: Use the bodyDict dictionary to store the required request parameters, such as Action (the API operation name) and ImageURL (the image URL). You also need to add system parameters required for the signature, such as Timestamp (the current timestamp) and SignatureNonce (a unique random value).

  2. Generate a signature:

    • Sort the parameters in ASCII order (bodyToFormString:).

    • Create a string-to-sign based on the HTTP request method, resource path, and query string.

    • Use the HMAC-SHA1 algorithm to sign the string-to-sign, and then Base64-encode the result (hmacSha1:data:).

  3. Construct the request URL: Insert the generated signature and other query parameters into the URL to form the final request URL.

  4. Send the request:

    • Create an HTTP POST request (request:).

    • Set the request properties, such as Content-Type.

    • Use NSURLSession to send the request and use a block callback to process the response or error after the request is complete.

  5. Process the response:

    • If the request is successful, parse the response data and pass the result back through the callback function.

    • If the request fails, parse the error message and pass the error back through the callback function.

Sample code (click to view details)

/**
 * ========================================================================================================================
 * The following code is only for calculating the signature to call the server-side operation. For more information about the logic, see https://help.aliyun.com/document_detail/144904.html
 * ========================================================================================================================
 */

+(NSString*)allKeysGotoSignatureWithDict:(NSMutableDictionary*)bodyDict endpoint:(NSString*)endpoint accessSecret:(NSString*)accessSecret httpMethod:(NSString*)httpMethod apiVersion:(NSString*)apiVersion{
    // System parameters
    bodyDict[@"SignatureMethod"] = @"HMAC-SHA1";
    bodyDict[@"SignatureNonce"] = [self getNonce];
    bodyDict[@"SignatureVersion"] = @"1.0";
    bodyDict[@"Timestamp"] = [self getTimestamp];
    bodyDict[@"Format"] = @"JSON";
    // Business API parameters
    bodyDict[@"RegionId"] = @"cn-shanghai";
    bodyDict[@"Version"] = apiVersion;
    //Sort keys in ascending order
    NSString *sortedQueryString = [self bodyToFormString:bodyDict];

    NSMutableString *stringToSign = [NSMutableString string];
    [stringToSign appendString:[NSString stringWithFormat:@"%@&",httpMethod]];
    [stringToSign appendString:[NSString stringWithFormat:@"%@&",[self urlEncode:@"/"]]];
    [stringToSign appendString:[self urlEncode:sortedQueryString]];
    //Sign with HMAC-SHA1
    NSString *sign = [self hmacSha1:[NSString stringWithFormat:@"%@&",accessSecret] data:stringToSign];
    // The signature must also be URL-encoded.
    NSString *signature = [self urlEncode:sign];
    //Final result
    NSString *finalUrl = [NSString stringWithFormat:@"https://%@/?Signature=%@&%@",endpoint,signature,sortedQueryString];
    NSLog(@"finalUrl:%@",finalUrl);
    return finalUrl;
}

+(NSString*)hmacSha1:(NSString*)key data:(NSString*)data{
    const char *cKey  = [key cStringUsingEncoding:NSUTF8StringEncoding];
    const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding];
    //sha1
    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
                                          length:sizeof(cHMAC)];
    NSString *hash = [HMAC base64EncodedStringWithOptions:0];// Base64-encode the encrypted result.
    return hash;
}

+(NSString*)getNonce{
    NSTimeInterval timestamp = [[NSDate date]timeIntervalSince1970];
    NSString *string = [NSString stringWithFormat:@"%f%@",timestamp, [[NSUUID UUID]UUIDString]];
    NSString*md5 = [self md5String:string];
    return md5;
}

// md5
+ (NSString *)md5String:(NSString *)string{
    const char *cStr = [string UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
    return [NSString stringWithFormat:
                @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            result[0], result[1], result[2], result[3],
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
    ];
}

+(NSString*)getTimestamp {
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    formatter.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];
    formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'";
    return [formatter stringFromDate:[NSDate date]];
}

+(NSString*)bodyToFormString:(NSMutableDictionary*)query{
    NSString* url = @"";
    if (query != nil && query.count > 0) {
        NSArray *keys = query.allKeys;
        NSArray*sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1,id obj2) {
            return[obj1 compare:obj2 options:NSNumericSearch];// Sort in ascending order
        }];
        NSMutableArray *arr = [NSMutableArray array];
        for (NSString *key in sortedArray) {
            NSString *value = query[key];
            if (value.length==0) {
                continue;
            }
            NSString *key2 = [NSString stringWithFormat:@"%@=%@",[self urlEncode:key],[self urlEncode:value]];
            [arr addObject:key2];
        }
        if(arr.count > 0) {
            url = [arr componentsJoinedByString:@"&"];
        }
    }
    return url;
}

+(NSString*)urlEncode:(NSString*)value{
    NSString *unreserved = @"*-._";
    NSMutableCharacterSet *allowedCharacterSet = [NSMutableCharacterSet alphanumericCharacterSet];
    [allowedCharacterSet addCharactersInString:unreserved];
    [allowedCharacterSet addCharactersInString:@" "];
    NSString *encoded = [value stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
    encoded = [encoded stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
    encoded = [encoded stringByReplacingOccurrencesOfString:@"+" withString:@"%20"];
    encoded = [encoded stringByReplacingOccurrencesOfString:@"*" withString:@"%2A"];
    encoded = [encoded stringByReplacingOccurrencesOfString:@"%7E" withString:@"~"];
    return encoded ;
}

+(void)request:(NSString*)request responseBlock:(void(^)(NSDictionary *responseObject, NSError *error))block{
    NSMutableURLRequest *msRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:request]];
    [msRequest setHTTPMethod:@"POST"];
    msRequest.timeoutInterval = 60;
    [msRequest addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:msRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        NSError *parseError = nil;
        if(httpResponse.statusCode == 200){
            NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&parseError];
            NSLog(@"response:%@",responseDictionary);
            block([responseDictionary objectForKey:@"Data"],nil);
        }else{
            NSLog(@"%@,error:%@",httpResponse,error);
            if (error) {
                block(nil,error);
            }else{
                NSDictionary *errorDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
                NSLog(@"errorDict:%@",errorDict);
                NSString *codevalue = [errorDict objectForKey:@"Code"];
                NSString *msgvalue = [errorDict objectForKey:@"Message"];
                NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"code:%@,error msg:%@",codevalue,msgvalue], NSLocalizedDescriptionKey,nil];
                parseError = [[NSError alloc] initWithDomain:NSCocoaErrorDomain code:httpResponse.statusCode userInfo:info];
                block(nil,parseError);
            }
        }
    }];
    [dataTask resume];
}

@end

Step 3: Encapsulate the request and send data to the specified Visual Intelligence API operation

The following code segment shows how to call the Alibaba Cloud RecognizeBankCard API operation in an iOS application to detect bank card information. The process involves preparing request parameters, generating a request signature, constructing a request URL, initiating a network request, and processing the response.

The following list describes the purpose and steps of the code segment:

  1. Prepare request parameters: Declare a dictionary of the NSMutableDictionary type named bodyDict to store the required request parameters. These include the following:

    • AccessKeyId: The AccessKey ID required to access Alibaba Cloud API operations.

    • Action: The name of the API operation. In this case, it is RecognizeBankCard, which indicates a call to the Alibaba Cloud bank card detection service.

    • ImageURL: The URL of the bank card image to be detected.

    • SecurityToken: A parameter added to support the use of temporary access credentials. It must be obtained from STS.

  2. Sign the request: All requests to Alibaba Cloud service API operations must be signed to ensure request security. In this example, the allKeysGotoSignatureWithDict:endpoint:accessSecret:httpMethod:apiVersion: method is used to calculate the signature and construct the final request URL. Information such as the HTTP method (POST), API version, and endpoint are used in the signing process.

  3. Construct the request URL: Use the preceding method to calculate the request URL finalUrl that contains the signature.

  4. Initiate a POST request: Use the custom request:responseBlock: method to initiate a POST request to the calculated finalUrl using NSURLSession. After the request succeeds or fails, the data or error information is returned to the caller through the block callback.

  5. Process the response asynchronously: Network requests and response processing are asynchronous to ensure that the main thread is not blocked. The execution of the block callback is scheduled in the dispatch queue of the main thread so that you can safely update the UI or process data.

Sample code (click to view details)

/**
 This example uses RecognizeBankCard.
 @param imageUrl The URL of the bank card image.
 */
+(void)recognizeBankCardWithImageUrl:(NSString*)imageUrl responseBlock:(void(^)(NSDictionary *data, NSError *error))block{
    NSMutableDictionary *bodyDict = [NSMutableDictionary dictionary];
    bodyDict[@"AccessKeyId"] = ACCESS_KEY_ID;
    // API Action. This is the name of the feature. For the Action parameter of a specific algorithm, see its API documentation. This example uses bank card detection: https://help.aliyun.com/document_detail/151893.html
    bodyDict[@"Action"] = @"RecognizeBankCard";
    // Business parameters. For more information, see the API documentation for the specific AI feature.
    bodyDict[@"ImageURL"] = imageUrl;

    // Add the SecurityToken from STS.
    bodyDict[@"SecurityToken"] = SECURITY_TOKEN;
    // Signature verification
    // The endpoint is the API endpoint, which is related to the category. For the API endpoints of specific categories, see https://help.aliyun.com/document_detail/143103.html
    // We recommend that you use the POST method.
    // The apiVersion is the API version, which is related to the category. For the API versions of specific categories, see https://help.aliyun.com/document_detail/464194.html
    NSString *finalUrl = [self allKeysGotoSignatureWithDict:bodyDict endpoint:@"ocr.cn-shanghai.aliyuncs.com" accessSecret:ACCESS_KEY_SECRET httpMethod:@"POST" apiVersion:@"2019-12-30"];
    //Send a POST request directly.
    [self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                block(nil,error);
            }else{
                block(responseObject, nil);
            }
        });
    }];
}

Step 4: Trigger the button on the page and call the Visual Intelligence API operation

This code shows how to call the recognizeBankCardWithImageUrl:responseBlock: method in the encapsulated CallApiClient class in an iOS application to detect bank card information. This is an Objective-C example that shows how to use the API client at the application layer.

  1. Set the image URL:

    • Define the variable imageUrl and set it to the URL of the bank card image. This image is stored on Alibaba Cloud OSS and is publicly accessible.

  2. Call the API operation to detect the bank card:

    • Call the recognizeBankCardWithImageUrl:responseBlock: static method of the CallApiClient class, passing an image URL and a callback block that is executed after the request is complete, regardless of whether it succeeds or fails.

  3. Process the response:

    • In the callback block, first check the error object to determine whether the API call was successful.

      • If an error occurred during the call (error is not nil), you must handle the error. Error handling may include logging the error or displaying an error message to the user.

      • If the call is successful (error is nil), you can extract the bank card detection result from the data dictionary returned by the callback. This example shows how to retrieve the bank card number (cardNumber). Based on the API documentation, you may also be able to retrieve other useful information, such as the bank name and card type.

  4. Display the result:

    • After successfully retrieving the bank card number, the example uses the alertInfomation: method, which is not implemented in this example and must be defined by you, to display a prompt that shows the bank card number to the user. This is a simple and direct feedback method suitable for rapid prototyping or testing applications.

Note

This code shows the complete process from initiating an API request to receiving and processing the API response. It is a useful reference for understanding how to integrate and use external API operations in a real iOS application. In a complete application, you may also need to consider more error handling and exception scenarios. In addition, for a better user experience, you may want to add a loading indicator during the request to inform the user that a network operation is in progress.

Sample code (click to view details)

/**
 * Call the API
 */
- (void)callApi {
    
    NSString* imageUrl = @"http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/ocr/RecognizeBankCard/yhk1.jpg";
    [CallApiClient recognizeBankCardWithImageUrl:imageUrl responseBlock:^(NSDictionary * _Nonnull data, NSError * _Nonnull error) {
        if (error) {
            if ([error.localizedDescription containsString:@"InvalidAccessKeyId.NotFound"]) {
                [self alertInfomation:@"Request error. Check whether you have correctly modified YOUR_ACCESS_KEY_ID and YOUR_ACCESS_KEY_SECRET in your code."];
            } else if([error.localizedDescription containsString:@"InvalidApi.NotPurchase"]) {
                [self alertInfomation:@"Request error. Your account has not activated the corresponding category of Visual Intelligence API. Activate it at: https://help.aliyun.com/document_detail/465341.html"];
            } else if([error.localizedDescription containsString:@"Unauthorized"]) {
                [self alertInfomation:@"Request error. Your RAM user is not granted the AliyunVIAPIFullAccess permission. For more information, see https://help.aliyun.com/document_detail/145025.html"];
            } else if([error.localizedDescription containsString:@"InvalidAction.NotFound"]) {
                [self alertInfomation:@"Request error. Check whether the API operation you are calling matches the category and the endpoint. For more information about the mapping between API operations and categories, see https://help.aliyun.com/document_detail/465341.html. For more information about the mapping between categories and endpoints, see https://help.aliyun.com/document_detail/143103.html"];
            } else {
                [self alertInfomation:error.localizedDescription];
            }
        } else {
            // Obtain the bank card number. This is only an example. Obtain the response parameters you need based on the documentation.
            NSString* cardNumber = [data objectForKey:@"CardNumber"];
            [self alertInfomation:[NSString stringWithFormat:@"Bank Card Number: %@", cardNumber]];
        }
    }];
}

Scenario 2: The file is local or at an accessible URL

If your file is local or at an accessible URL, see Process file URLs to explicitly convert the file to an OSS link in the China (Shanghai) region. Then, you can make the call as described in Scenario 1: The file is in OSS in the China (Shanghai) region. This topic uses RecognizeBankCard as an example and shows only the key steps and code. For the complete demo, you can download iOSDemo. To call other algorithms, you can modify the code based on the comments and your business requirements.

Interaction flow

image

Prerequisites

Obtain a temporary STS credential:

  1. Grant permissions:

    Before obtaining a temporary STS credential, the caller, which can be a RAM user or RAM role, must be granted the permissions to call STS operations. You can grant permissions by configuring a RAM access policy. For more information about the configuration steps, see Use a temporary access credential provided by STS to access OSS. You can configure fine-grained authorization policies as needed to prevent excessive permissions. For more information about how to configure fine-grained authorization policies, see Custom policies for Visual Intelligence API.

    Important

    For the following steps, the caller, which can be a RAM user or RAM role, must be granted the AliyunSTSAssumeRoleAccess permission (the permission to call the AssumeRole operation of STS), the permissions for a RAM role to upload files to OSS, and the AliyunVIAPIFullAccess permission (the permission to manage the Visual Intelligence API). For this example, we grant the full management permission. However, you need to configure fine-grained authorization policies as needed to prevent excessive permissions. For more information about how to configure fine-grained authorization policies, see Custom policies for Visual Intelligence API.

  2. Call the AssumeRole operation:

    You can use an authorized RAM user or RAM role to call the AssumeRole operation and fill in the required parameters as described in the documentation. For more information about the operation and its usage, see the official documentation for AssumeRole.

  3. Use the STS token:

    After you successfully call the AssumeRole operation, you will receive an STS token that contains an AccessKeyId, AccessKeySecret, and SecurityToken, as shown in the following code. When you call other Alibaba Cloud service operations, replace <ALIBABA_CLOUD_ACCESS_KEY_ID>, <ALIBABA_CLOUD_ACCESS_KEY_SECRET>, and <ALIBABA_CLOUD_SECURITY_TOKEN> in the code with the temporary AccessKeyId, AccessKeySecret, and SecurityToken from the Alibaba Cloud STS token data.

{
  "RequestId": "429D9967-C809-5A30-B65E-9B742CF*****",
  "AssumedRoleUser": {
    "Arn": "acs:ram::175805416243****:role/STStokenTestRole/STSsessionName",
    "AssumedRoleId": "39779315882322****:STSsessionName"
  },
  "Credentials": {
    "SecurityToken": "exampleToken",
    "AccessKeyId": "STS.exampleAccessKeyID",
    "AccessKeySecret": "exampleAccessKeySecret",
    "Expiration": "2024-06-12T03:21:29Z"
  }
}

Step 1: Configure basic parameters

The following code segment is used to call the "RecognizeBankCard" service of Alibaba Cloud. The code is in the Tool/CallApiClient.m file of the iOSDemo. Replace <ALIBABA_CLOUD_ACCESS_KEY_ID>, <ALIBABA_CLOUD_ACCESS_KEY_SECRET>, and <ALIBABA_CLOUD_SECURITY_TOKEN> with the temporary AccessKeyId, AccessKeySecret, and SecurityToken from the Alibaba Cloud STS token data that you obtained in the Prerequisites section.

Note

The temporary AccessKey ID, AccessKey secret, and security token here are used to avoid exposing your own AccessKey ID and AccessKey secret on the frontend. The temporary STS token obtained in Step 2 is used to upload the file to a temporary OSS bucket to retrieve a URL.

/**
  <ALIBABA_CLOUD_ACCESS_KEY_ID>, <ALIBABA_CLOUD_ACCESS_KEY_SECRET>, and <ALIBABA_CLOUD_SECURITY_TOKEN> must be replaced with the temporary AccessKeyId, AccessKeySecret, and SecurityToken obtained from the STS token data.
  If you use the AccessKey pair of a RAM user, you must also grant the AliyunVIAPIFullAccess permission to the RAM user. For more information, see https://help.aliyun.com/document_detail/145025.html
 */
const NSString* ACCESS_KEY_ID = @"YOUR_ACCESS_KEY_ID";
const NSString* ACCESS_KEY_SECRET = @"YOUR_ACCESS_KEY_SECRET";
const NSString* SECURITY_TOKEN = @"<ALIBABA_CLOUD_SECURITY_TOKEN>";

Step 2: Call the GetOssStsToken operation to obtain a temporary OSS STS token

The following code segment uses an Alibaba Cloud AccessKey ID and AccessKey secret to request a temporary Alibaba Cloud OSS STS token. This STS token allows a user to upload files or data to the official OSS bucket of the Visual Intelligence API. For testing purposes, files are stored in OSS for one day.

The following list describes the purpose and steps of the code segment:

  1. Prepare request data: Use the given accessKey and accessSecret to build a request dictionary bodyDict. This dictionary includes the required operation Action, which is "GetOssStsToken".

  2. Sign and build the final URL: Use the provided parameters, including the API endpoint, the recommended POST HTTP request method, and the API version number ("2020-04-01"), to sign the request and build the final request URL.

  3. Send the request: Send the prepared signature and data to the specified API endpoint through a POST request.

  4. Process the response: Process the response returned from the server-side asynchronously. If an error occurs, the callback function passes the error information. If the request is successful, the callback function passes a dictionary containing the STS token data.

In the `recognizeBankCardWithImageUrl` function in the `Tool/CallApiClient.m` file, the `bodyDict[@"Action"]`, `endpoint`, and `apiVersion` parameters, and the `bodyDict[@"ImageURL"]` line are business parameters.

For example, if you want to use the universal segmentation feature, the SegmentCommonImage API documentation shows that this feature belongs to the image segmentation category (imageseg20191230) and its name is SegmentCommonImage. You need to change the endpoint to `imageseg.cn-shanghai.aliyuncs.com`, change `bodyDict[@"Action"]` to `SegmentCommonImage`, and set `apiVersion` to `2019-12-30`. The parameter name `bodyDict[@"ImageURL"]` does not need to be changed. When you retrieve the result, you need to retrieve the `ImageURL`, which is the URL of the segmented image, not a bank card number.

Sample code (click to view details)

/**
 Obtain the OSS STS token. Use the official OSS bucket of the Visual Intelligence API for temporary storage. This is only for testing the operation. The file is stored for one day.
 */
+(void)getOssStsTokenWithAk:(NSString*)accessKey andSk:(NSString*)accessSecret responseBlock:(void(^)(NSDictionary *data, NSError *error))block {
    NSMutableDictionary *bodyDict = [NSMutableDictionary dictionary];
    bodyDict[@"AccessKeyId"] = accessKey;
    // The Action to obtain the STS token for the official OSS bucket of the Visual Intelligence API is fixed as GetOssStsToken.
    bodyDict[@"Action"] = @"GetOssStsToken";
    // Signature verification
    // The endpoint to obtain the STS token for the official OSS bucket of the Visual Intelligence API is fixed as viapiutils.cn-shanghai.aliyuncs.com.
    // We recommend that you use the POST method.
    // The API version to obtain the STS token for the official OSS bucket of the Visual Intelligence API is fixed as 2020-04-01.
    NSString *finalUrl = [self allKeysGotoSignatureWithDict:bodyDict endpoint:@"viapiutils.cn-shanghai.aliyuncs.com" accessSecret:accessSecret httpMethod:@"POST" apiVersion:@"2020-04-01"];
    //Send a POST request directly.
    [self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                block(nil,error);
            }else{
                block(responseObject, nil);
            }
        });
    }];
}

Step 3: Use the temporary OSS STS token to upload the file to the official Visual Intelligence API OSS bucket

The following code segment uploads image data to Alibaba Cloud OSS using a temporary STS token for authentication and authorization.

The following list describes the purpose and steps of the code segment:

  1. Obtain an STS token through CallApiClient: Use the provided AccessKey ID (accessKeyId), AccessKey secret (accessKeySecret), and a possibly existing securityToken to request an STS token from CallApiClient.

  2. Initialize the OSS client: Use the retrieved temporary credential information to create an OSS client (OSSClient) instance for subsequent OSS operations. The client configuration (OSSClientConfiguration) includes setting the number of retries, request timeout, and maximum resource transfer time.

  3. Set the upload request: Create an OSSPutObjectRequest object to specify the details of the file to be uploaded. The file is uploaded to the fixed bucket ("viapi-customer-temp"), and the object key (objectKey) is composed of the AccessKey ID and a random UUID to ensure uniqueness.

  4. Execute the upload task: Call the putObject: method to upload the image data. This process is asynchronous.

  5. Retrieve the URL of the uploaded file: After the upload is successful, use the presigned URL feature of the OSS client (presignConstrainURLWithBucketName:withObjectKey:withExpirationInterval:) to retrieve the access URL of the uploaded file.

  6. Return the URL through a callback: Execute the callback function block to pass the URL of the uploaded file to the caller, or return an error message if the upload fails.

Note

For this step, you need to import `libresolv.tbd` and `AliyunOSSiOS.framework` in Frameworks. `libresolv.tbd` is a system library. For information about how to compile and retrieve `AliyunOSSiOS.framework`, see Install the OSS iOS SDK.

Sample code (click to view details)

#import "ViapiUtils.h"
#import "CallApiClient.h"
#import <AliyunOSSiOS/AliyunOSSiOS.h>

@implementation ViapiUtils

+(void)uploadWithAk:(NSString*)accessKeyId andSk:(NSString*)accessKeySecret andToken:(NSString*)securityToken  andData:(NSData *)imageData responseBlock:(void(^)(NSString *imageUrl, NSError *error))block {
    [CallApiClient getOssStsTokenWithAk:accessKeyId andSk:accessKeySecret andToken:securityToken responseBlock:^(NSDictionary * _Nonnull data, NSError * _Nonnull error) {
        if (error) {
            block(nil, error);
        } else {
            // Obtain the STS token to initialize the OSS client.
            id<OSSCredentialProvider> credential = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
                    OSSFederationToken * token = [OSSFederationToken new];
                    token.tAccessKey = [data objectForKey:@"AccessKeyId"];
                    token.tSecretKey =[data objectForKey:@"AccessKeySecret"];
                    token.tToken =[data objectForKey:@"SecurityToken"];
                    return token;
            }];
            OSSClientConfiguration *conf = [OSSClientConfiguration new];
            conf.maxRetryCount = 3; // Number of retries after a network request fails due to an exception.
            conf.timeoutIntervalForRequest = 20; // Timeout interval for network requests.
            conf.timeoutIntervalForResource = 24*60*60; // Maximum time allowed for resource transfer.
            conf.maxConcurrentRequestCount = 30;
            OSSClient *client = [[OSSClient alloc] initWithEndpoint:@"http://oss-cn-shanghai.aliyuncs.com" credentialProvider:credential clientConfiguration:conf];
            
            OSSPutObjectRequest * put = [OSSPutObjectRequest new];
            // The bucketName is fixed as viapi-customer-temp.
            put.bucketName = @"viapi-customer-temp";
            NSString *sourceNameObjectKey = [NSString stringWithFormat:@"%@/%@",accessKeyId,[[NSUUID UUID]UUIDString]];
            put.objectKey = sourceNameObjectKey;
            NSLog(@"put.objectKey:%@ [NSData dataWithContentsOfFile:file]==%@",put.objectKey,data);
            put.uploadingData = imageData;
            OSSTask * putTask = [client putObject:put];
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                [putTask continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
                    if (!task.error) {
                        OSSTask *downloadURLTask = [client presignConstrainURLWithBucketName:@"viapi-customer-temp" withObjectKey:put.objectKey withExpirationInterval:24*3600];
                        NSString * string = downloadURLTask.result;
                        NSLog(@"inner string:%@", string);
                        NSArray *arr =[string componentsSeparatedByString:@"?"];
                        NSString* imageUrl = arr.count > 0 ? arr[0] :string;
                        NSLog(@"upload object success! %@", imageUrl);
                        block(imageUrl, nil);
                    } else {
                        NSLog(@"upload object failed, error: %@" , putTask.error);
                        block(nil, putTask.error);
                    }
                    return nil;
                }];
                [putTask waitUntilFinished]; // Block until the upload is complete.
            });
        }
    }];
}

@end

Step 4: After uploading, obtain the OSS URL and call the Visual Intelligence API operation

The following code segment is used to retrieve the URL after uploading a file to OSS and then call a Visual Intelligence API operation. The procedure is the same as in Scenario 1: The file is in OSS in the China (Shanghai) region. Each step is encapsulated in the code. For the complete sample code, you can download iOSDemo.

The following list describes the purpose and steps of the code segment:

  1. Set parameters: Build a dictionary bodyDict to set the required API parameters. These include the following:

    • AccessKeyId and AccessKeySecret: Credentials for identity verification.

    • SecurityToken: A temporary security credential, usually used with STS.

    • ImageURL: The URL of the bank card image to be detected.

    • Action: Specifies the API feature to be called. In this case, it is "RecognizeBankCard", which means to detect a bank card.

  2. Prepare the API request:

    • The code builds a signed final URL finalUrl. This process includes setting the API endpoint, the recommended POST method, the API version, and generating a signature based on the AccessKey pair, API endpoint, and other parameters.

  3. Execute the API request: Send a POST request to the built finalUrl. This is implemented by the request:responseBlock: method. The specific implementation of this method is not shown, but you can assume that it is responsible for sending the request to the server and processing the response.

  4. Process the response: The response to the request is processed through the asynchronous callback responseBlock. If the request is successful, the API response data, such as the detected bank card information, is returned to the caller through block(responseObject, nil). If an error occurs during the request, the error is returned to the caller through block(nil, error).

In the `Tool/CallApiClient.m` file, the `recognizeBankCardWithImageUrl` function's `bodyDict[@"Action"]`, `endpoint`, and `apiVersion` parameters, and the `bodyDict[@"ImageURL"]` line are business parameters.

For example, if you want to use the universal segmentation feature, the SegmentCommonImage API documentation shows that this feature belongs to the image segmentation category (imageseg20191230) and its name is SegmentCommonImage. You need to change the endpoint to imageseg.cn-shanghai.aliyuncs.com, change bodyDict[@"Action"] to SegmentCommonImage, and set apiVersion to 2019-12-30. The parameter name bodyDict[@"ImageURL"] does not need to be changed. When you retrieve the result, you need to retrieve the ImageURL, which is the URL of the segmented image, not a bank card number.

Sample code (click to view details)

+(void)recognizeBankCardWithImageUrl:(NSString*)imageUrl andAk:(NSString*)accessKey andSk:(NSString*)accessSecret andToken:(NSString*)securityToken  responseBlock:(void(^)(NSDictionary *data, NSError *error))block{
    NSMutableDictionary *bodyDict = [NSMutableDictionary dictionary];
    bodyDict[@"AccessKeyId"] = accessKey;
    // API Action. This is the name of the feature. For the Action parameter of a specific algorithm, see its API documentation. This example uses bank card detection: https://help.aliyun.com/document_detail/151893.html
    bodyDict[@"Action"] = @"RecognizeBankCard";
    // Business parameters. For more information, see the API documentation for the specific AI feature.
    bodyDict[@"ImageURL"] = imageUrl;

    bodyDict[@"SecurityToken"] = securityToken;

    // Signature verification
    // The endpoint is the API endpoint, which is related to the category. For the API endpoints of specific categories, see https://help.aliyun.com/document_detail/143103.html
    // We recommend that you use the POST method.
    // The apiVersion is the API version, which is related to the category. For the API versions of specific categories, see https://help.aliyun.com/document_detail/464194.html
    NSString *finalUrl = [self allKeysGotoSignatureWithDict:bodyDict endpoint:@"ocr.cn-shanghai.aliyuncs.com" accessSecret:accessSecret httpMethod:@"POST" apiVersion:@"2019-12-30"];
    //Send a POST request directly.
    [self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                block(nil,error);
            }else{
                block(responseObject, nil);
            }
        });
    }];
}