日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

iOS端直接調(diào)用

更新時(shí)間:

視覺智能開放平臺(tái)的API接口推薦使用SDK進(jìn)行調(diào)用,推薦在服務(wù)端進(jìn)行接入,在客戶端直接接入AccessKey ID和AccessKey Secret有泄露風(fēng)險(xiǎn),可以使用STS授權(quán)用戶調(diào)用服務(wù)。

背景信息

在進(jìn)行iOS調(diào)用之前,需要使用STS服務(wù)獲取臨時(shí)訪問(wèn)憑證。阿里云STS(Security Token Service)是阿里云提供的一種臨時(shí)訪問(wèn)權(quán)限管理服務(wù)。您可以通過(guò)STS服務(wù)給其他用戶頒發(fā)臨時(shí)訪問(wèn)憑證,該用戶可使用臨時(shí)訪問(wèn)憑證,在規(guī)定時(shí)間內(nèi)調(diào)用視覺智能開放平臺(tái)的各項(xiàng)服務(wù)。臨時(shí)訪問(wèn)憑證無(wú)需透露您的長(zhǎng)期密鑰,保障您的賬戶更加安全。獲取臨時(shí)訪問(wèn)憑證,請(qǐng)參見獲取角色的臨時(shí)身份憑證

說(shuō)明

阿里云視覺智能開放平臺(tái)各類目視覺AI能力API接入、接口使用或問(wèn)題咨詢等,請(qǐng)通過(guò)釘釘群(23109592)加入阿里云視覺智能開放平臺(tái)咨詢?nèi)郝?lián)系我們。

方案一:若文件在上海地域OSS

若您的文件存放在上海OSS中,可以參見請(qǐng)求簽名的方式進(jìn)行調(diào)用,本文以銀行卡識(shí)別(RecognizeBankCard)為例,僅展示關(guān)鍵步驟及關(guān)鍵代碼,完整的示例可下載iOSDemo。如果您需要調(diào)用其他算法,請(qǐng)參見注釋并根據(jù)實(shí)際業(yè)務(wù)修改相應(yīng)的代碼。

交互流程

image

前提條件

獲取STS臨時(shí)憑證:

  1. 授予權(quán)限:

    在獲取STS臨時(shí)憑證之前,調(diào)用者(RAM用戶和RAM角色)需要被授權(quán)有調(diào)用STS接口的權(quán)限。您可以通過(guò)設(shè)置RAM權(quán)限策略來(lái)實(shí)現(xiàn)這一點(diǎn)。相關(guān)的設(shè)置步驟和權(quán)限策略可參見使用STS臨時(shí)訪問(wèn)憑證訪問(wèn)OSS文檔。您需要根據(jù)實(shí)際需求配置更細(xì)粒度的授權(quán)策略,防止出現(xiàn)權(quán)限過(guò)大的風(fēng)險(xiǎn)。關(guān)于更細(xì)粒度的授權(quán)策略配置詳情,請(qǐng)參見視覺智能開放平臺(tái)自定義權(quán)限策略參考

    重要

    為后續(xù)步驟進(jìn)行,調(diào)用者(RAM用戶和RAM角色)需要被授權(quán)AliyunSTSAssumeRoleAccess(調(diào)用STS服務(wù)AssumeRole接口的權(quán)限)、AliyunVIAPIFullAccess(這里為了下列示例,給出的是管理視覺智能API的權(quán)限,但是在實(shí)際工作中,強(qiáng)烈建議您根據(jù)實(shí)際需求配置更細(xì)粒度的授權(quán)策略,防止出現(xiàn)權(quán)限過(guò)大的風(fēng)險(xiǎn)。關(guān)于更細(xì)粒度的授權(quán)策略配置詳情,請(qǐng)參見視覺智能開放平臺(tái)自定義權(quán)限策略參考)。

  2. 調(diào)用AssumeRole接口:

    使用已授權(quán)的RAM用戶或RAM角色調(diào)用AssumeRole接口,并按照接口文檔填寫必要參數(shù)。查閱AssumeRole接口的官方文檔以了解詳細(xì)的接口說(shuō)明和使用方法。

  3. 使用STS Token:

    調(diào)用AssumeRole接口成功后,您會(huì)收到一個(gè)包含AccessKeyIdAccessKeySecretSecurityToken的STS Token(如下代碼)。在實(shí)際調(diào)用其他阿里云服務(wù)的接口時(shí),您需要將代碼中的<ALIBABA_CLOUD_ACCESS_KEY_ID><ALIBABA_CLOUD_ACCESS_KEY_SECRET><ALIBABA_CLOUD_SECURITY_TOKEN>替換為阿里云STS Token數(shù)據(jù)中獲取的臨時(shí)AccessKeyIdAccessKeySecretSecurityToken

{
  "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"
  }
}

步驟一:配置基本參數(shù)

下面提供的代碼段是調(diào)用阿里云的"銀行卡識(shí)別"服務(wù),在iOSDemo的Tool/CallApiClient.m文件中。需要將代碼中的<ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>替換為前提條件中獲取的阿里云STS Token數(shù)據(jù)的臨時(shí)AccessKeyId、AccessKeySecret、SecurityToken

/**
  <ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>需替換為STS Token數(shù)據(jù)中獲取的臨時(shí)AccessKeyId、AccessKeySecret、SecurityToken
  如果您是用的子賬號(hào)AccessKey,還需要為子賬號(hào)授予權(quán)限AliyunVIAPIFullAccess,請(qǐng)參考http://bestwisewords.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>";

步驟二:調(diào)用服務(wù)端接口并計(jì)算簽名

下面提供的代碼段是針對(duì)視覺智能開放平臺(tái)API的簽名和請(qǐng)求發(fā)送過(guò)程的實(shí)現(xiàn)。簽名是云服務(wù)常用的一種安全措施,用于確保發(fā)送到云服務(wù)的請(qǐng)求是未經(jīng)篡改的,并且是由擁有相應(yīng)憑證的合法用戶發(fā)起的。具體邏輯文檔請(qǐng)參見文檔請(qǐng)求簽名

以下是該代碼段的具體含義和步驟:

  1. 設(shè)置API請(qǐng)求參數(shù):使用bodyDict字典存儲(chǔ)必要的請(qǐng)求參數(shù),例如Action(API名稱)、ImageURL(圖片地址)等,并添加一些簽名所需系統(tǒng)參數(shù),如Timestamp(當(dāng)前時(shí)間戳)、SignatureNonce(唯一隨機(jī)值)。

  2. 生成簽名:

    • 對(duì)參數(shù)按照ASCII碼的順序進(jìn)行排序(bodyToFormString:)。

    • 根據(jù)HTTP請(qǐng)求方法、資源路徑和查詢字符串創(chuàng)建簽名字符串。

    • 使用HMAC-SHA1算法對(duì)簽名字符串進(jìn)行簽名,然后進(jìn)行Base64編碼(hmacSha1:data:)。

  3. 構(gòu)造請(qǐng)求URL:插入生成的簽名和其他查詢參數(shù)到URL中,形成最終的完整請(qǐng)求URL。

  4. 發(fā)送請(qǐng)求:

    • 創(chuàng)建一個(gè)HTTP POST請(qǐng)求(request:)。

    • 設(shè)置請(qǐng)求的相關(guān)屬性,如Content-Type

    • 使用NSURLSession將請(qǐng)求發(fā)送出去,并在請(qǐng)求完成后通過(guò)block回調(diào)處理響應(yīng)結(jié)果或錯(cuò)誤。

  5. 處理響應(yīng):

    • 請(qǐng)求成功,解析響應(yīng)數(shù)據(jù),并通過(guò)回調(diào)將結(jié)果傳遞回去。

    • 請(qǐng)求失敗,解析錯(cuò)誤信息,并通過(guò)回調(diào)將錯(cuò)誤傳遞回去。

代碼示例(單擊查看詳情)

/**
 * ========================================================================================================================
 * 以下代碼僅僅為了調(diào)用服務(wù)端接口計(jì)算簽名,其邏輯可參考文檔:http://bestwisewords.com/document_detail/144904.html
 * ========================================================================================================================
 */

+(NSString*)allKeysGotoSignatureWithDict:(NSMutableDictionary*)bodyDict endpoint:(NSString*)endpoint accessSecret:(NSString*)accessSecret httpMethod:(NSString*)httpMethod apiVersion:(NSString*)apiVersion{
    // 系統(tǒng)參數(shù)
    bodyDict[@"SignatureMethod"] = @"HMAC-SHA1";
    bodyDict[@"SignatureNonce"] = [self getNonce];
    bodyDict[@"SignatureVersion"] = @"1.0";
    bodyDict[@"Timestamp"] = [self getTimestamp];
    bodyDict[@"Format"] = @"JSON";
    // 業(yè)務(wù)API參數(shù)
    bodyDict[@"RegionId"] = @"cn-shanghai";
    bodyDict[@"Version"] = apiVersion;
    //key升序排序
    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]];
    //hmacsha1 加簽
    NSString *sign = [self hmacSha1:[NSString stringWithFormat:@"%@&",accessSecret] data:stringToSign];
    // 簽名最后也要做特殊URL編碼
    NSString *signature = [self urlEncode:sign];
    //最后結(jié)果
    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];//將加密結(jié)果進(jìn)行一次BASE64編碼。
    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];//正序排列
        }];
        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

步驟三:封裝請(qǐng)求并發(fā)送數(shù)據(jù)至指定視覺智能開放平臺(tái)API

下面提供的代碼段是如何在iOS應(yīng)用中調(diào)用阿里云的RecognizeBankCard API來(lái)識(shí)別銀行卡信息。整個(gè)過(guò)程涉及到準(zhǔn)備請(qǐng)求參數(shù)、生成請(qǐng)求簽名、構(gòu)造請(qǐng)求URL,以及發(fā)起網(wǎng)絡(luò)請(qǐng)求和處理響應(yīng)的步驟。

以下是該代碼段的具體含義和步驟:

  1. 準(zhǔn)備請(qǐng)求參數(shù):聲明一個(gè)NSMutableDictionary類型的字典bodyDict來(lái)存放請(qǐng)求需要的參數(shù),包括:

    • AccessKeyId:訪問(wèn)阿里云API需要的訪問(wèn)密鑰。

    • Action:API的操作名稱,此處為RecognizeBankCard,表示調(diào)用阿里云的銀行卡識(shí)別服務(wù)。

    • ImageURL:需要識(shí)別的銀行卡圖片的URL。

    • SecurityToken:為了支持使用臨時(shí)訪問(wèn)憑證而添加的參數(shù),需要從Security Token Service(STS)獲取。

  2. 簽名請(qǐng)求:所有請(qǐng)求到阿里云服務(wù)的API需要進(jìn)行簽名以保證請(qǐng)求的安全性。在這個(gè)示例中,allKeysGotoSignatureWithDict:endpoint:accessSecret:httpMethod:apiVersion:方法用于計(jì)算簽名并構(gòu)造最終的請(qǐng)求URL。簽名過(guò)程中會(huì)用到如HTTP方法(POST)、API版本和EndPoint等信息。

  3. 構(gòu)造請(qǐng)求URL:使用前述方法計(jì)算得到包含簽名的請(qǐng)求URLfinalUrl

  4. 發(fā)起POST請(qǐng)求:通過(guò)自定義request:responseBlock:方法使用NSURLSession發(fā)起一個(gè)POST請(qǐng)求到計(jì)算好的finalUrl。請(qǐng)求成功或失敗后,會(huì)通過(guò)回調(diào)block返回?cái)?shù)據(jù)或錯(cuò)誤信息給調(diào)用者。

  5. 異步處理響應(yīng):網(wǎng)絡(luò)請(qǐng)求和響應(yīng)處理是異步的,確保不會(huì)阻塞主線程。回調(diào)block的執(zhí)行被安排在主線程的dispatch隊(duì)列中,以便可以安全地更新UI或處理數(shù)據(jù)。

代碼示例(單擊查看詳情

/**
 以RecognizeBankCard為例。
 @param imageUrl 銀行卡圖片url
 */
+(void)recognizeBankCardWithImageUrl:(NSString*)imageUrl responseBlock:(void(^)(NSDictionary *data, NSError *error))block{
    NSMutableDictionary *bodyDict = [NSMutableDictionary dictionary];
    bodyDict[@"AccessKeyId"] = ACCESS_KEY_ID;
    // API Action,能力名稱,請(qǐng)參考具體算法文檔詳情頁(yè)中的Action參數(shù),這里以銀行卡識(shí)別為例:http://bestwisewords.com/document_detail/151893.html
    bodyDict[@"Action"] = @"RecognizeBankCard";
    // 業(yè)務(wù)參數(shù),請(qǐng)參考具體的AI能力的API文檔
    bodyDict[@"ImageURL"] = imageUrl;

    // 添加STS的SecurityToken
    bodyDict[@"SecurityToken"] = SECURITY_TOKEN;
    // 驗(yàn)簽
    // 這里endpoint為API訪問(wèn)域名,與類目相關(guān),具體類目的API訪問(wèn)域名請(qǐng)參考:http://bestwisewords.com/document_detail/143103.html
    // httpMethod推薦使用POST
    // apiVersion為API版本,與類目相關(guān),具體類目的API版本請(qǐng)參考:http://bestwisewords.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"];
    //直接發(fā)post請(qǐng)求
    [self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                block(nil,error);
            }else{
                block(responseObject, nil);
            }
        });
    }];
}

步驟四:頁(yè)面觸發(fā)按鈕并調(diào)用視覺智能開放平臺(tái)API

這段代碼展示了如何在iOS應(yīng)用中調(diào)用封裝后的CallApiClient類中的recognizeBankCardWithImageUrl:responseBlock:方法來(lái)識(shí)別一張銀行卡圖片的信息。這是一個(gè)Objective-C的示例,用于展示從應(yīng)用層面如何使用API客戶端。

  1. 設(shè)定圖片URL:

    • 定義變量imageUrl并將其設(shè)置為銀行卡圖片的URL地址。這張圖片存儲(chǔ)在阿里云的OSS上,并且是公開可訪問(wèn)的。

  2. 調(diào)用API識(shí)別銀行卡:

    • 通過(guò)CallApiClient類的靜態(tài)方法recognizeBankCardWithImageUrl:responseBlock:調(diào)用銀行卡識(shí)別API,傳入圖片URL和一個(gè)回調(diào)block。這個(gè)回調(diào)block將在請(qǐng)求完成后執(zhí)行,無(wú)論是成功還是失敗。

  3. 處理響應(yīng):

    • 在回調(diào)block中,首先檢查error對(duì)象來(lái)確定API調(diào)用是否成功。

      • 如果調(diào)用出現(xiàn)錯(cuò)誤(error不為nil),則應(yīng)該處理這個(gè)錯(cuò)誤。錯(cuò)誤處理可能包括日志記錄、顯示錯(cuò)誤信息給用戶等。

      • 如果調(diào)用成功(errornil),則可以從回調(diào)傳回的data字典中提取銀行卡識(shí)別的結(jié)果。這里的例子演示了如何獲取銀行卡號(hào)(cardNumber)。實(shí)際上,根據(jù)API的文檔,您可能還可以獲取到其他有用的信息(如銀行名稱、卡類型等)。

  4. 顯示結(jié)果:

    • 在成功獲取銀行卡號(hào)后,示例中使用alertInfomation:方法(在這個(gè)示例中未實(shí)現(xiàn),需要你自己定義)顯示一個(gè)提示框,將銀行卡號(hào)展示給用戶。這是一種簡(jiǎn)單直接的反饋方式,適用于快速原型或測(cè)試應(yīng)用。

說(shuō)明

這段代碼整體上展示了從發(fā)起API請(qǐng)求到接收并處理API響應(yīng)的完整流程。它對(duì)于理解如何在實(shí)際iOS應(yīng)用中集成和使用外部API是一個(gè)有用的參考。需要注意的是,在一個(gè)完整的應(yīng)用實(shí)現(xiàn)中,你可能還需要考慮更多的錯(cuò)誤處理和異常場(chǎng)景。此外,出于用戶體驗(yàn)的考慮,在請(qǐng)求發(fā)出期間,可能還需要添加加載指示器來(lái)告知用戶正在進(jìn)行網(wǎng)絡(luò)操作。

代碼示例(單擊查看詳情)

/**
 * 調(diào)用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:@"請(qǐng)求報(bào)錯(cuò),請(qǐng)檢查您代碼中的YOUR_ACCESS_KEY_ID和YOUR_ACCESS_KEY_SECRET是否已經(jīng)修改正確。"];
            } else if([error.localizedDescription containsString:@"InvalidApi.NotPurchase"]) {
                [self alertInfomation:@"請(qǐng)求報(bào)錯(cuò),您的賬號(hào)未開通視覺智能開放平臺(tái)相應(yīng)類目,請(qǐng)進(jìn)行開通:http://bestwisewords.com/document_detail/465341.html"];
            } else if([error.localizedDescription containsString:@"Unauthorized"]) {
                [self alertInfomation:@"請(qǐng)求報(bào)錯(cuò),您的子賬號(hào)未授予AliyunVIAPIFullAccess權(quán)限,請(qǐng)參考http://bestwisewords.com/document_detail/145025.html"];
            } else if([error.localizedDescription containsString:@"InvalidAction.NotFound"]) {
                [self alertInfomation:@"請(qǐng)求報(bào)錯(cuò),請(qǐng)檢查您調(diào)用的API和類目是否匹配,API和類目的關(guān)系請(qǐng)參考:http://bestwisewords.com/document_detail/465341.html,和訪問(wèn)的域名是否匹配,類目和域名的關(guān)系請(qǐng)參考:http://bestwisewords.com/document_detail/143103.html"];
            } else {
                [self alertInfomation:error.localizedDescription];
            }
        } else {
            // 獲取銀行卡號(hào),這里只是示例,請(qǐng)根據(jù)文檔獲取自己想要的出參
            NSString* cardNumber = [data objectForKey:@"CardNumber"];
            [self alertInfomation:[NSString stringWithFormat:@"銀行卡號(hào):%@", cardNumber]];
        }
    }];
}

方案二:若文件在本地或可訪問(wèn)的URL

若您的文件存放在本地或可訪問(wèn)的URL,請(qǐng)參見文件URL處理,顯式地將文件轉(zhuǎn)換成上海OSS鏈接,再按照若文件在上海地域OSS進(jìn)行調(diào)用。本文以銀行卡識(shí)別(RecognizeBankCard)為例,僅展示關(guān)鍵步驟及關(guān)鍵代碼,完整的示例可下載iOSDemo。如果您調(diào)用其他算法,請(qǐng)參見注釋和實(shí)際業(yè)務(wù)修改相應(yīng)代碼。

交互流程

image

前提條件

獲取STS臨時(shí)憑證:

  1. 授予權(quán)限:

    在獲取STS臨時(shí)憑證之前,調(diào)用者(RAM用戶和RAM角色)需要被授權(quán)有調(diào)用STS接口的權(quán)限。您可以通過(guò)設(shè)置RAM權(quán)限策略來(lái)實(shí)現(xiàn)這一點(diǎn)。相關(guān)的設(shè)置步驟可參見使用STS臨時(shí)訪問(wèn)憑證訪問(wèn)OSS文檔。您需要根據(jù)實(shí)際需求配置更細(xì)粒度的授權(quán)策略,防止出現(xiàn)權(quán)限過(guò)大的風(fēng)險(xiǎn)。關(guān)于更細(xì)粒度的授權(quán)策略配置詳情,請(qǐng)參見視覺智能開放平臺(tái)自定義權(quán)限策略參考

    重要

    為后續(xù)步驟進(jìn)行,調(diào)用者(RAM用戶和RAM角色)需要被授權(quán)AliyunSTSAssumeRoleAccess(調(diào)用STS服務(wù)AssumeRole接口的權(quán)限)、RAM角色授予上傳OSS文件的權(quán)限、AliyunVIAPIFullAccess(這里為了下列實(shí)例,給出的是管理視覺智能API的權(quán)限,您需要根據(jù)實(shí)際需求配置更細(xì)粒度的授權(quán)策略,防止出現(xiàn)權(quán)限過(guò)大的風(fēng)險(xiǎn)。關(guān)于更細(xì)粒度的授權(quán)策略配置詳情,請(qǐng)參見視覺智能開放平臺(tái)自定義權(quán)限策略參考

  2. 調(diào)用AssumeRole接口:

    使用已授權(quán)的RAM用戶或RAM角色調(diào)用AssumeRole接口,并按照接口文檔填寫必要參數(shù)。查閱AssumeRole接口的官方文檔以了解詳細(xì)的接口說(shuō)明和使用方法。

  3. 使用STS Token:

    調(diào)用AssumeRole接口成功后,您會(huì)收到一個(gè)包含AccessKeyId、AccessKeySecret和SecurityToken的STS Token(如下代碼)。在實(shí)際調(diào)用其他阿里云服務(wù)的接口時(shí),您需要將代碼中的<ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>替換為阿里云STS Token數(shù)據(jù)中獲取的臨時(shí)AccessKeyId、AccessKeySecret、SecurityToken

{
  "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"
  }
}

步驟一:配置基本參數(shù)

下面提供的代碼段是調(diào)用阿里云的"銀行卡識(shí)別"服務(wù),在iOSDemo的Tool/CallApiClient.m文件中。需要將代碼中的<ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>替換為前提條件中獲取的阿里云STS Token數(shù)據(jù)的臨時(shí)AccessKeyId、AccessKeySecret、SecurityToken

說(shuō)明

此處的臨時(shí)的AccessKeyId、AccessKeySecret、SecurityToken是為了避免暴露自己的AccessKeyId和AccessKeySecret在前端界面上。下面(步驟二)獲取的STS Token臨時(shí)訪問(wèn)權(quán)限是為了將上傳文件到臨時(shí)OSS bucket,從而得到RL地址。

/**
  <ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>需替換為STS Token數(shù)據(jù)中獲取的臨時(shí)AccessKeyId、AccessKeySecret、SecurityToken
  如果您是用的子賬號(hào)AccessKey,還需要為子賬號(hào)授予權(quán)限AliyunVIAPIFullAccess,請(qǐng)參考http://bestwisewords.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>";

步驟二:調(diào)用GetOssStsToken接口獲取臨時(shí)OSS STS Token

下面提供的代碼段是利用阿里云的Access Key ID和Access Key Secret去請(qǐng)求一個(gè)臨時(shí)的阿里云OSS(對(duì)象存儲(chǔ)服務(wù))STS(Security Token Service)令牌。這個(gè)STS令牌將允許用戶以阿里云視覺智能開放平臺(tái)官方OSS-Bucket為目標(biāo)存儲(chǔ)介質(zhì),上傳文件或數(shù)據(jù)。為便于用戶調(diào)試接口,文件在OSS上的存儲(chǔ)有效期被設(shè)定為1天。

以下是該代碼段的具體含義和步驟:

  1. 準(zhǔn)備請(qǐng)求數(shù)據(jù):使用給定的accessKeyaccessSecret,構(gòu)建一個(gè)請(qǐng)求字典bodyDict,該字典包括需要的操作Action,這里是"GetOssStsToken"

  2. 簽名和構(gòu)建最終URL:根據(jù)提供的參數(shù),包括API的端點(diǎn)(endpoint),HTTP請(qǐng)求方法(建議為POST),以及API的版本號(hào)(這里為"2020-04-01"),使用這些信息對(duì)請(qǐng)求進(jìn)行簽名,并構(gòu)建出最終的請(qǐng)求URL。

  3. 發(fā)送請(qǐng)求:通過(guò)一個(gè)POST請(qǐng)求,將準(zhǔn)備好的簽名和數(shù)據(jù)發(fā)送到設(shè)定的API端點(diǎn)。

  4. 處理響應(yīng):通過(guò)異步方式處理服務(wù)端返回的響應(yīng)。如果遇到錯(cuò)誤,回調(diào)函數(shù)將傳遞錯(cuò)誤信息;如果成功,回調(diào)函數(shù)將傳遞包含STS令牌數(shù)據(jù)的字典。

Tool/CallApiClient.m文件中recognizeBankCardWithImageUrl函數(shù)中的bodyDict[@"Action"]、endpoint、apiVersion參數(shù)及bodyDict[@"ImageURL"]這一行代表業(yè)務(wù)參數(shù)。

例如,您想使用通用分割能力,通過(guò)通用分割A(yù)PI文檔可知該能力屬于分割摳圖類目(imageseg20191230),能力名稱為SegmentCommonImage,您需要將endpoint改為imageseg.cn-shanghai.aliyuncs.com,bodyDict[@"Action"]改為SegmentCommonImage,apiVersion為2019-12-30不用修改,bodyDict[@"ImageURL"]參數(shù)名為ImageURL不用修改。獲取結(jié)果的時(shí)候,需要獲取ImageURL,其含義不是銀行卡號(hào),而是分割后的圖片地址。

代碼示例(單擊查看詳情)

/**
 獲取oss sts token,使用阿里云視覺智能開放平臺(tái)官方OSS-Bucket作為臨時(shí)存儲(chǔ),僅為方便用戶方便調(diào)試接口使用,文件存儲(chǔ)有效期為1天。
 */
+(void)getOssStsTokenWithAk:(NSString*)accessKey andSk:(NSString*)accessSecret responseBlock:(void(^)(NSDictionary *data, NSError *error))block {
    NSMutableDictionary *bodyDict = [NSMutableDictionary dictionary];
    bodyDict[@"AccessKeyId"] = accessKey;
    // 獲取阿里云視覺智能開放平臺(tái)官方OSS-Bucket的stsToken的Action固定為GetOssStsToken
    bodyDict[@"Action"] = @"GetOssStsToken";
    // 驗(yàn)簽
    // 這里endpoint為API訪問(wèn)域名,獲取阿里云視覺智能開放平臺(tái)官方OSS-Bucket的stsToken的域名固定為:viapiutils.cn-shanghai.aliyuncs.com
    // httpMethod推薦使用POST
    // apiVersion為API版本,獲取阿里云視覺智能開放平臺(tái)官方OSS-Bucket的stsToken的域名固定為:2020-04-01
    NSString *finalUrl = [self allKeysGotoSignatureWithDict:bodyDict endpoint:@"viapiutils.cn-shanghai.aliyuncs.com" accessSecret:accessSecret httpMethod:@"POST" apiVersion:@"2020-04-01"];
    //直接發(fā)post請(qǐng)求
    [self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                block(nil,error);
            }else{
                block(responseObject, nil);
            }
        });
    }];
}

步驟三:使用臨時(shí)OSS STS Token將文件上傳到阿里云視覺智能開放平臺(tái)官方OSS Bucket

下面提供的代碼段是將一些圖像數(shù)據(jù)上傳到阿里云對(duì)象存儲(chǔ)服務(wù)(OSS)使用一個(gè)臨時(shí)的STS Token進(jìn)行認(rèn)證和授權(quán)的功能。

以下是該代碼段的具體含義和步驟:

  1. 通過(guò)CallApiClient獲取STS Token: 使用提供的Access Key ID (accessKeyId) 和Access Key Secret (accessKeySecret),以及一個(gè)可能已經(jīng)存在的securityToken,來(lái)請(qǐng)求從CallApiClient獲取STS Token。

  2. 初始化OSS Client: 使用獲取到的臨時(shí)憑證信息,創(chuàng)建一個(gè)OSS客戶端(OSSClient)實(shí)例以進(jìn)行后續(xù)的OSS操作。客戶端配置(OSSClientConfiguration)包括設(shè)置重試次數(shù)、請(qǐng)求超時(shí)和資源傳輸最長(zhǎng)時(shí)間等。

  3. 設(shè)置上傳請(qǐng)求: 創(chuàng)建一個(gè)OSSPutObjectRequest對(duì)象以指定上傳文件的詳細(xì)信息。文件將被上傳到固定的Bucket("viapi-customer-temp"),而對(duì)象鍵(objectKey)則由Access Key ID和一個(gè)隨機(jī)UUID組成以確保唯一性。

  4. 執(zhí)行上傳任務(wù): 調(diào)用putObject:方法來(lái)實(shí)際上傳圖像數(shù)據(jù),這個(gè)過(guò)程將會(huì)異步進(jìn)行。

  5. 獲取上傳文件的URL: 成功上傳后,使用OSS客戶端預(yù)簽名URL功能(presignConstrainURLWithBucketName:withObjectKey:withExpirationInterval:)獲取上傳文件的訪問(wèn)URL。

  6. 回調(diào)返回URL: 執(zhí)行回調(diào)函數(shù)block,傳遞上傳文件的URL給調(diào)用者,或者在上傳失敗時(shí)返回錯(cuò)誤信息。

說(shuō)明

這一步需要在Frameworks中引入libresolv.tbd和AliyunOSSiOS.framework。其中,libresolv.tbd為系統(tǒng)庫(kù),關(guān)于編譯和獲取AliyunOSSiOS.framework,請(qǐng)參見OSSiOS SDK安裝

代碼示例(單擊查看詳情)

#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 {
            // 獲取到sts token,用來(lái)初始化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; // 網(wǎng)絡(luò)請(qǐng)求遇到異常失敗后的重試次數(shù)
            conf.timeoutIntervalForRequest = 20; // 網(wǎng)絡(luò)請(qǐng)求的超時(shí)時(shí)間
            conf.timeoutIntervalForResource = 24*60*60; // 允許資源傳輸?shù)淖铋L(zhǎng)時(shí)間
            conf.maxConcurrentRequestCount = 30;
            OSSClient *client = [[OSSClient alloc] initWithEndpoint:@"http://oss-cn-shanghai.aliyuncs.com" credentialProvider:credential clientConfiguration:conf];
            
            OSSPutObjectRequest * put = [OSSPutObjectRequest new];
            // bucketName固定填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]; // 阻塞直到上傳完成
            });
        }
    }];
}

@end

步驟四:上傳之后得到OSS的URL地址,調(diào)用視覺智能開放平臺(tái)API

下面提供的代碼段用于上傳文件到OSS后獲取URL地址,調(diào)用視覺智能開放平臺(tái)API。具體的操作步驟與若文件在上海地域OSS進(jìn)行調(diào)用一致。且每一步代碼都已封裝好,完整的示例代碼可下載iOSDemo

以下是該代碼段的具體含義和步驟:

  1. 參數(shù)設(shè)置:通過(guò)構(gòu)建一個(gè)字典 bodyDict,設(shè)置所需的 API 參數(shù)。這包括:

    • AccessKeyIdAccessKeySecret:用于身份驗(yàn)證的憑證。

    • SecurityToken:作為臨時(shí)安全憑證,通常與STS服務(wù)一起使用。

    • ImageURL:需要識(shí)別的銀行卡圖片的URL。

    • Action:指明要調(diào)用的API能力,這里是"RecognizeBankCard",即識(shí)別銀行卡。

  2. 準(zhǔn)備API請(qǐng)求:

    • 代碼構(gòu)建了一個(gè)簽名后的最終URLfinalUrl,該過(guò)程涵蓋了設(shè)置API的端點(diǎn)(endpoint)、推薦使用的POST方法、API的版本號(hào),以及根據(jù)訪問(wèn)密鑰、API端點(diǎn)和其他參數(shù)生成簽名的過(guò)程。

  3. 執(zhí)行API請(qǐng)求:向構(gòu)建好的 finalUrl 發(fā)送POST請(qǐng)求。這是通過(guò) request:responseBlock: 方法實(shí)現(xiàn)的,該方法的具體實(shí)現(xiàn)尚未顯示,但可假定它負(fù)責(zé)將請(qǐng)求發(fā)送到服務(wù)器并處理響應(yīng)。

  4. 響應(yīng)處理:請(qǐng)求的響應(yīng)通過(guò)異步回調(diào) responseBlock 進(jìn)行處理。如果請(qǐng)求成功,API的響應(yīng)數(shù)據(jù)(識(shí)別出的銀行卡信息等)會(huì)通過(guò) block(responseObject, nil) 返回給調(diào)用者。如果請(qǐng)求過(guò)程中出現(xiàn)錯(cuò)誤,通過(guò) block(nil, error) 將錯(cuò)誤返回給調(diào)用者。

Tool/CallApiClient.m文件中recognizeBankCardWithImageUrl函數(shù)中的bodyDict[@"Action"]endpointapiVersion參數(shù)及bodyDict[@"ImageURL"]這一行代表業(yè)務(wù)參數(shù)。

例如,您想使用通用分割能力,通過(guò)通用分割A(yù)PI文檔可知該能力屬于分割摳圖類目(imageseg20191230),能力名稱為SegmentCommonImage,您需要將endpoint改為imageseg.cn-shanghai.aliyuncs.combodyDict[@"Action"]改為SegmentCommonImageapiVersion2019-12-30不用修改,bodyDict[@"ImageURL"]參數(shù)名為ImageURL不用修改。獲取結(jié)果的時(shí)候,需要獲取ImageURL,其含義不是銀行卡號(hào),而是分割后的圖片地址。

代碼示例(單擊查看詳情)

+(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,能力名稱,請(qǐng)參考具體算法文檔詳情頁(yè)中的Action參數(shù),這里以銀行卡識(shí)別為例:http://bestwisewords.com/document_detail/151893.html
    bodyDict[@"Action"] = @"RecognizeBankCard";
    // 業(yè)務(wù)參數(shù),請(qǐng)參考具體的AI能力的API文檔
    bodyDict[@"ImageURL"] = imageUrl;

    bodyDict[@"SecurityToken"] = securityToken;

    // 驗(yàn)簽
    // 這里endpoint為API訪問(wèn)域名,與類目相關(guān),具體類目的API訪問(wèn)域名請(qǐng)參考:http://bestwisewords.com/document_detail/143103.html
    // httpMethod推薦使用POST
    // apiVersion為API版本,與類目相關(guān),具體類目的API版本請(qǐng)參考:http://bestwisewords.com/document_detail/464194.html
    NSString *finalUrl = [self allKeysGotoSignatureWithDict:bodyDict endpoint:@"ocr.cn-shanghai.aliyuncs.com" accessSecret:accessSecret httpMethod:@"POST" apiVersion:@"2019-12-30"];
    //直接發(fā)post請(qǐng)求
    [self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                block(nil,error);
            }else{
                block(responseObject, nil);
            }
        });
    }];
}