視覺智能開放平臺的API接口推薦使用SDK進行調用,推薦在服務端進行接入,在客戶端直接接入AccessKey ID和AccessKey Secret有泄露風險,可以使用STS授權用戶調用服務。
背景信息
在進行iOS調用之前,需要使用STS服務獲取臨時訪問憑證。阿里云STS(Security Token Service)是阿里云提供的一種臨時訪問權限管理服務。您可以通過STS服務給其他用戶頒發臨時訪問憑證,該用戶可使用臨時訪問憑證,在規定時間內調用視覺智能開放平臺的各項服務。臨時訪問憑證無需透露您的長期密鑰,保障您的賬戶更加安全。獲取臨時訪問憑證,請參見獲取角色的臨時身份憑證。
若文件存放在上海OSS中:
如果您的文件存放在上海OSS(阿里云對象存儲 Object Storage Service)中,則需要使用請求簽名機制進行調用。有關具體的調用方式,請參見方案一:若文件在上海地域OSS。對于OSS的具體操作,請參見開通OSS服務。
若文件在本地文件或者其他鏈接:
若是涉及其他情況(如本地文件或者其他鏈接),您需要先將文件鏈接轉換成上海OSS鏈接,具體操作,請參見文件URL處理。有關具體的調用方式,請參見方案二:若文件在本地或可訪問的URL。
阿里云視覺智能開放平臺各類目視覺AI能力API接入、接口使用或問題咨詢等,請通過釘釘群(23109592)加入阿里云視覺智能開放平臺咨詢群聯系我們。
方案一:若文件在上海地域OSS
若您的文件存放在上海OSS中,可以參見請求簽名的方式進行調用,本文以銀行卡識別(RecognizeBankCard)為例,僅展示關鍵步驟及關鍵代碼,完整的示例可下載iOSDemo。如果您需要調用其他算法,請參見注釋并根據實際業務修改相應的代碼。
交互流程
前提條件
獲取STS臨時憑證:
授予權限:
在獲取STS臨時憑證之前,調用者(RAM用戶和RAM角色)需要被授權有調用STS接口的權限。您可以通過設置RAM權限策略來實現這一點。相關的設置步驟和權限策略可參見使用STS臨時訪問憑證訪問OSS文檔。您需要根據實際需求配置更細粒度的授權策略,防止出現權限過大的風險。關于更細粒度的授權策略配置詳情,請參見視覺智能開放平臺自定義權限策略參考。
重要為后續步驟進行,調用者(RAM用戶和RAM角色)需要被授權AliyunSTSAssumeRoleAccess(調用STS服務AssumeRole接口的權限)、AliyunVIAPIFullAccess(這里為了下列示例,給出的是管理視覺智能API的權限,但是在實際工作中,強烈建議您根據實際需求配置更細粒度的授權策略,防止出現權限過大的風險。關于更細粒度的授權策略配置詳情,請參見視覺智能開放平臺自定義權限策略參考)。
調用AssumeRole接口:
使用已授權的RAM用戶或RAM角色調用AssumeRole接口,并按照接口文檔填寫必要參數。查閱AssumeRole接口的官方文檔以了解詳細的接口說明和使用方法。
使用STS Token:
調用AssumeRole接口成功后,您會收到一個包含
AccessKeyId
、AccessKeySecret
和SecurityToken
的STS Token(如下代碼)。在實際調用其他阿里云服務的接口時,您需要將代碼中的<ALIBABA_CLOUD_ACCESS_KEY_ID>
、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
、<ALIBABA_CLOUD_SECURITY_TOKEN>
替換為阿里云STS Token數據中獲取的臨時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"
}
}
步驟一:配置基本參數
下面提供的代碼段是調用阿里云的"銀行卡識別"服務,在iOSDemo的Tool/CallApiClient.m文件中。需要將代碼中的<ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>
替換為前提條件中獲取的阿里云STS Token數據的臨時AccessKeyId、AccessKeySecret、SecurityToken
。
/**
<ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>需替換為STS Token數據中獲取的臨時AccessKeyId、AccessKeySecret、SecurityToken
如果您是用的子賬號AccessKey,還需要為子賬號授予權限AliyunVIAPIFullAccess,請參考http://m.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>";
步驟二:調用服務端接口并計算簽名
下面提供的代碼段是針對視覺智能開放平臺API的簽名和請求發送過程的實現。簽名是云服務常用的一種安全措施,用于確保發送到云服務的請求是未經篡改的,并且是由擁有相應憑證的合法用戶發起的。具體邏輯文檔請參見文檔請求簽名。
以下是該代碼段的具體含義和步驟:
設置API請求參數:使用
bodyDict
字典存儲必要的請求參數,例如Action
(API名稱)、ImageURL
(圖片地址)等,并添加一些簽名所需系統參數,如Timestamp
(當前時間戳)、SignatureNonce
(唯一隨機值)。生成簽名:
對參數按照ASCII碼的順序進行排序(
bodyToFormString:
)。根據HTTP請求方法、資源路徑和查詢字符串創建簽名字符串。
使用HMAC-SHA1算法對簽名字符串進行簽名,然后進行Base64編碼(
hmacSha1:data:
)。
構造請求URL:插入生成的簽名和其他查詢參數到URL中,形成最終的完整請求URL。
發送請求:
創建一個HTTP POST請求(
request:
)。設置請求的相關屬性,如
Content-Type
。使用
NSURLSession
將請求發送出去,并在請求完成后通過block回調處理響應結果或錯誤。
處理響應:
請求成功,解析響應數據,并通過回調將結果傳遞回去。
請求失敗,解析錯誤信息,并通過回調將錯誤傳遞回去。
/**
* ========================================================================================================================
* 以下代碼僅僅為了調用服務端接口計算簽名,其邏輯可參考文檔:http://m.bestwisewords.com/document_detail/144904.html
* ========================================================================================================================
*/
+(NSString*)allKeysGotoSignatureWithDict:(NSMutableDictionary*)bodyDict endpoint:(NSString*)endpoint accessSecret:(NSString*)accessSecret httpMethod:(NSString*)httpMethod apiVersion:(NSString*)apiVersion{
// 系統參數
bodyDict[@"SignatureMethod"] = @"HMAC-SHA1";
bodyDict[@"SignatureNonce"] = [self getNonce];
bodyDict[@"SignatureVersion"] = @"1.0";
bodyDict[@"Timestamp"] = [self getTimestamp];
bodyDict[@"Format"] = @"JSON";
// 業務API參數
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];
//最后結果
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編碼。
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
步驟三:封裝請求并發送數據至指定視覺智能開放平臺API
下面提供的代碼段是如何在iOS應用中調用阿里云的RecognizeBankCard
API來識別銀行卡信息。整個過程涉及到準備請求參數、生成請求簽名、構造請求URL,以及發起網絡請求和處理響應的步驟。
以下是該代碼段的具體含義和步驟:
準備請求參數:聲明一個
NSMutableDictionary
類型的字典bodyDict
來存放請求需要的參數,包括:AccessKeyId
:訪問阿里云API需要的訪問密鑰。Action
:API的操作名稱,此處為RecognizeBankCard
,表示調用阿里云的銀行卡識別服務。ImageURL
:需要識別的銀行卡圖片的URL。SecurityToken
:為了支持使用臨時訪問憑證而添加的參數,需要從Security Token Service(STS)獲取。
簽名請求:所有請求到阿里云服務的API需要進行簽名以保證請求的安全性。在這個示例中,
allKeysGotoSignatureWithDict:endpoint:accessSecret:httpMethod:apiVersion:
方法用于計算簽名并構造最終的請求URL。簽名過程中會用到如HTTP方法(POST)、API版本和EndPoint等信息。構造請求URL:使用前述方法計算得到包含簽名的請求URL
finalUrl
。發起POST請求:通過自定義
request:responseBlock:
方法使用NSURLSession
發起一個POST請求到計算好的finalUrl
。請求成功或失敗后,會通過回調block
返回數據或錯誤信息給調用者。異步處理響應:網絡請求和響應處理是異步的,確保不會阻塞主線程。回調
block
的執行被安排在主線程的dispatch隊列中,以便可以安全地更新UI或處理數據。
/**
以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,能力名稱,請參考具體算法文檔詳情頁中的Action參數,這里以銀行卡識別為例:http://m.bestwisewords.com/document_detail/151893.html
bodyDict[@"Action"] = @"RecognizeBankCard";
// 業務參數,請參考具體的AI能力的API文檔
bodyDict[@"ImageURL"] = imageUrl;
// 添加STS的SecurityToken
bodyDict[@"SecurityToken"] = SECURITY_TOKEN;
// 驗簽
// 這里endpoint為API訪問域名,與類目相關,具體類目的API訪問域名請參考:http://m.bestwisewords.com/document_detail/143103.html
// httpMethod推薦使用POST
// apiVersion為API版本,與類目相關,具體類目的API版本請參考:http://m.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"];
//直接發post請求
[self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
block(nil,error);
}else{
block(responseObject, nil);
}
});
}];
}
步驟四:頁面觸發按鈕并調用視覺智能開放平臺API
這段代碼展示了如何在iOS應用中調用封裝后的CallApiClient
類中的recognizeBankCardWithImageUrl:responseBlock:
方法來識別一張銀行卡圖片的信息。這是一個Objective-C的示例,用于展示從應用層面如何使用API客戶端。
設定圖片URL:
定義變量
imageUrl
并將其設置為銀行卡圖片的URL地址。這張圖片存儲在阿里云的OSS上,并且是公開可訪問的。
調用API識別銀行卡:
通過
CallApiClient
類的靜態方法recognizeBankCardWithImageUrl:responseBlock:
調用銀行卡識別API,傳入圖片URL和一個回調block。這個回調block將在請求完成后執行,無論是成功還是失敗。
處理響應:
在回調block中,首先檢查
error
對象來確定API調用是否成功。如果調用出現錯誤(
error
不為nil
),則應該處理這個錯誤。錯誤處理可能包括日志記錄、顯示錯誤信息給用戶等。如果調用成功(
error
為nil
),則可以從回調傳回的data
字典中提取銀行卡識別的結果。這里的例子演示了如何獲取銀行卡號(cardNumber
)。實際上,根據API的文檔,您可能還可以獲取到其他有用的信息(如銀行名稱、卡類型等)。
顯示結果:
在成功獲取銀行卡號后,示例中使用
alertInfomation:
方法(在這個示例中未實現,需要你自己定義)顯示一個提示框,將銀行卡號展示給用戶。這是一種簡單直接的反饋方式,適用于快速原型或測試應用。
這段代碼整體上展示了從發起API請求到接收并處理API響應的完整流程。它對于理解如何在實際iOS應用中集成和使用外部API是一個有用的參考。需要注意的是,在一個完整的應用實現中,你可能還需要考慮更多的錯誤處理和異常場景。此外,出于用戶體驗的考慮,在請求發出期間,可能還需要添加加載指示器來告知用戶正在進行網絡操作。
/**
* 調用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:@"請求報錯,請檢查您代碼中的YOUR_ACCESS_KEY_ID和YOUR_ACCESS_KEY_SECRET是否已經修改正確。"];
} else if([error.localizedDescription containsString:@"InvalidApi.NotPurchase"]) {
[self alertInfomation:@"請求報錯,您的賬號未開通視覺智能開放平臺相應類目,請進行開通:http://m.bestwisewords.com/document_detail/465341.html"];
} else if([error.localizedDescription containsString:@"Unauthorized"]) {
[self alertInfomation:@"請求報錯,您的子賬號未授予AliyunVIAPIFullAccess權限,請參考http://m.bestwisewords.com/document_detail/145025.html"];
} else if([error.localizedDescription containsString:@"InvalidAction.NotFound"]) {
[self alertInfomation:@"請求報錯,請檢查您調用的API和類目是否匹配,API和類目的關系請參考:http://m.bestwisewords.com/document_detail/465341.html,和訪問的域名是否匹配,類目和域名的關系請參考:http://m.bestwisewords.com/document_detail/143103.html"];
} else {
[self alertInfomation:error.localizedDescription];
}
} else {
// 獲取銀行卡號,這里只是示例,請根據文檔獲取自己想要的出參
NSString* cardNumber = [data objectForKey:@"CardNumber"];
[self alertInfomation:[NSString stringWithFormat:@"銀行卡號:%@", cardNumber]];
}
}];
}
方案二:若文件在本地或可訪問的URL
若您的文件存放在本地或可訪問的URL,請參見文件URL處理,顯式地將文件轉換成上海OSS鏈接,再按照若文件在上海地域OSS進行調用。本文以銀行卡識別(RecognizeBankCard)為例,僅展示關鍵步驟及關鍵代碼,完整的示例可下載iOSDemo。如果您調用其他算法,請參見注釋和實際業務修改相應代碼。
交互流程
前提條件
獲取STS臨時憑證:
授予權限:
在獲取STS臨時憑證之前,調用者(RAM用戶和RAM角色)需要被授權有調用STS接口的權限。您可以通過設置RAM權限策略來實現這一點。相關的設置步驟可參見使用STS臨時訪問憑證訪問OSS文檔。您需要根據實際需求配置更細粒度的授權策略,防止出現權限過大的風險。關于更細粒度的授權策略配置詳情,請參見視覺智能開放平臺自定義權限策略參考。
重要為后續步驟進行,調用者(RAM用戶和RAM角色)需要被授權AliyunSTSAssumeRoleAccess(調用STS服務AssumeRole接口的權限)、RAM角色授予上傳OSS文件的權限、AliyunVIAPIFullAccess(這里為了下列實例,給出的是管理視覺智能API的權限,您需要根據實際需求配置更細粒度的授權策略,防止出現權限過大的風險。關于更細粒度的授權策略配置詳情,請參見視覺智能開放平臺自定義權限策略參考)
調用AssumeRole接口:
使用已授權的RAM用戶或RAM角色調用AssumeRole接口,并按照接口文檔填寫必要參數。查閱AssumeRole接口的官方文檔以了解詳細的接口說明和使用方法。
使用STS Token:
調用AssumeRole接口成功后,您會收到一個包含AccessKeyId、AccessKeySecret和SecurityToken的STS Token(如下代碼)。在實際調用其他阿里云服務的接口時,您需要將代碼中的
<ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>
替換為阿里云STS Token數據中獲取的臨時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"
}
}
步驟一:配置基本參數
下面提供的代碼段是調用阿里云的"銀行卡識別"服務,在iOSDemo的Tool/CallApiClient.m文件中。需要將代碼中的<ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>
替換為前提條件中獲取的阿里云STS Token數據的臨時AccessKeyId、AccessKeySecret、SecurityToken
。
此處的臨時的AccessKeyId、AccessKeySecret、SecurityToken是為了避免暴露自己的AccessKeyId和AccessKeySecret在前端界面上。下面(步驟二)獲取的STS Token臨時訪問權限是為了將上傳文件到臨時OSS bucket,從而得到RL地址。
/**
<ALIBABA_CLOUD_ACCESS_KEY_ID>、<ALIBABA_CLOUD_ACCESS_KEY_SECRET>、<ALIBABA_CLOUD_SECURITY_TOKEN>需替換為STS Token數據中獲取的臨時AccessKeyId、AccessKeySecret、SecurityToken
如果您是用的子賬號AccessKey,還需要為子賬號授予權限AliyunVIAPIFullAccess,請參考http://m.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>";
步驟二:調用GetOssStsToken接口獲取臨時OSS STS Token
下面提供的代碼段是利用阿里云的Access Key ID和Access Key Secret去請求一個臨時的阿里云OSS(對象存儲服務)STS(Security Token Service)令牌。這個STS令牌將允許用戶以阿里云視覺智能開放平臺官方OSS-Bucket為目標存儲介質,上傳文件或數據。為便于用戶調試接口,文件在OSS上的存儲有效期被設定為1天。
以下是該代碼段的具體含義和步驟:
準備請求數據:使用給定的
accessKey
和accessSecret
,構建一個請求字典bodyDict
,該字典包括需要的操作Action
,這里是"GetOssStsToken"
。簽名和構建最終URL:根據提供的參數,包括API的端點(endpoint),HTTP請求方法(建議為POST),以及API的版本號(這里為
"2020-04-01"
),使用這些信息對請求進行簽名,并構建出最終的請求URL。發送請求:通過一個POST請求,將準備好的簽名和數據發送到設定的API端點。
處理響應:通過異步方式處理服務端返回的響應。如果遇到錯誤,回調函數將傳遞錯誤信息;如果成功,回調函數將傳遞包含STS令牌數據的字典。
Tool/CallApiClient.m文件中recognizeBankCardWithImageUrl函數中的bodyDict[@"Action"]、endpoint、apiVersion參數及bodyDict[@"ImageURL"]這一行代表業務參數。
例如,您想使用通用分割能力,通過通用分割API文檔可知該能力屬于分割摳圖類目(imageseg20191230),能力名稱為SegmentCommonImage,您需要將endpoint改為imageseg.cn-shanghai.aliyuncs.com,bodyDict[@"Action"]改為SegmentCommonImage,apiVersion為2019-12-30不用修改,bodyDict[@"ImageURL"]參數名為ImageURL不用修改。獲取結果的時候,需要獲取ImageURL,其含義不是銀行卡號,而是分割后的圖片地址。
/**
獲取oss sts token,使用阿里云視覺智能開放平臺官方OSS-Bucket作為臨時存儲,僅為方便用戶方便調試接口使用,文件存儲有效期為1天。
*/
+(void)getOssStsTokenWithAk:(NSString*)accessKey andSk:(NSString*)accessSecret responseBlock:(void(^)(NSDictionary *data, NSError *error))block {
NSMutableDictionary *bodyDict = [NSMutableDictionary dictionary];
bodyDict[@"AccessKeyId"] = accessKey;
// 獲取阿里云視覺智能開放平臺官方OSS-Bucket的stsToken的Action固定為GetOssStsToken
bodyDict[@"Action"] = @"GetOssStsToken";
// 驗簽
// 這里endpoint為API訪問域名,獲取阿里云視覺智能開放平臺官方OSS-Bucket的stsToken的域名固定為:viapiutils.cn-shanghai.aliyuncs.com
// httpMethod推薦使用POST
// apiVersion為API版本,獲取阿里云視覺智能開放平臺官方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"];
//直接發post請求
[self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
block(nil,error);
}else{
block(responseObject, nil);
}
});
}];
}
步驟三:使用臨時OSS STS Token將文件上傳到阿里云視覺智能開放平臺官方OSS Bucket
下面提供的代碼段是將一些圖像數據上傳到阿里云對象存儲服務(OSS)使用一個臨時的STS Token進行認證和授權的功能。
以下是該代碼段的具體含義和步驟:
通過
CallApiClient
獲取STS Token: 使用提供的Access Key ID (accessKeyId
) 和Access Key Secret (accessKeySecret
),以及一個可能已經存在的securityToken
,來請求從CallApiClient
獲取STS Token。初始化OSS Client: 使用獲取到的臨時憑證信息,創建一個OSS客戶端(
OSSClient
)實例以進行后續的OSS操作。客戶端配置(OSSClientConfiguration
)包括設置重試次數、請求超時和資源傳輸最長時間等。設置上傳請求: 創建一個
OSSPutObjectRequest
對象以指定上傳文件的詳細信息。文件將被上傳到固定的Bucket("viapi-customer-temp"
),而對象鍵(objectKey
)則由Access Key ID和一個隨機UUID組成以確保唯一性。執行上傳任務: 調用
putObject:
方法來實際上傳圖像數據,這個過程將會異步進行。獲取上傳文件的URL: 成功上傳后,使用OSS客戶端預簽名URL功能(
presignConstrainURLWithBucketName:withObjectKey:withExpirationInterval:
)獲取上傳文件的訪問URL。回調返回URL: 執行回調函數
block
,傳遞上傳文件的URL給調用者,或者在上傳失敗時返回錯誤信息。
這一步需要在Frameworks中引入libresolv.tbd和AliyunOSSiOS.framework。其中,libresolv.tbd為系統庫,關于編譯和獲取AliyunOSSiOS.framework,請參見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,用來初始化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; // 網絡請求遇到異常失敗后的重試次數
conf.timeoutIntervalForRequest = 20; // 網絡請求的超時時間
conf.timeoutIntervalForResource = 24*60*60; // 允許資源傳輸的最長時間
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地址,調用視覺智能開放平臺API
下面提供的代碼段用于上傳文件到OSS后獲取URL地址,調用視覺智能開放平臺API。具體的操作步驟與若文件在上海地域OSS進行調用一致。且每一步代碼都已封裝好,完整的示例代碼可下載iOSDemo。
以下是該代碼段的具體含義和步驟:
參數設置:通過構建一個字典
bodyDict
,設置所需的 API 參數。這包括:AccessKeyId
和AccessKeySecret
:用于身份驗證的憑證。SecurityToken
:作為臨時安全憑證,通常與STS服務一起使用。ImageURL
:需要識別的銀行卡圖片的URL。Action
:指明要調用的API能力,這里是"RecognizeBankCard"
,即識別銀行卡。
準備API請求:
代碼構建了一個簽名后的最終URL
finalUrl
,該過程涵蓋了設置API的端點(endpoint)、推薦使用的POST方法、API的版本號,以及根據訪問密鑰、API端點和其他參數生成簽名的過程。
執行API請求:向構建好的
finalUrl
發送POST請求。這是通過request:responseBlock:
方法實現的,該方法的具體實現尚未顯示,但可假定它負責將請求發送到服務器并處理響應。響應處理:請求的響應通過異步回調
responseBlock
進行處理。如果請求成功,API的響應數據(識別出的銀行卡信息等)會通過block(responseObject, nil)
返回給調用者。如果請求過程中出現錯誤,通過block(nil, error)
將錯誤返回給調用者。
Tool/CallApiClient.m
文件中recognizeBankCardWithImageUrl
函數中的bodyDict[@"Action"]
、endpoint
、apiVersion
參數及bodyDict[@"ImageURL"]
這一行代表業務參數。
例如,您想使用通用分割能力,通過通用分割API文檔可知該能力屬于分割摳圖類目(imageseg20191230),能力名稱為SegmentCommonImage
,您需要將endpoint
改為imageseg.cn-shanghai.aliyuncs.com
,bodyDict[@"Action"]
改為SegmentCommonImage
,apiVersion
為2019-12-30
不用修改,bodyDict[@"ImageURL"]
參數名為ImageURL
不用修改。獲取結果的時候,需要獲取ImageURL
,其含義不是銀行卡號,而是分割后的圖片地址。
+(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,能力名稱,請參考具體算法文檔詳情頁中的Action參數,這里以銀行卡識別為例:http://m.bestwisewords.com/document_detail/151893.html
bodyDict[@"Action"] = @"RecognizeBankCard";
// 業務參數,請參考具體的AI能力的API文檔
bodyDict[@"ImageURL"] = imageUrl;
bodyDict[@"SecurityToken"] = securityToken;
// 驗簽
// 這里endpoint為API訪問域名,與類目相關,具體類目的API訪問域名請參考:http://m.bestwisewords.com/document_detail/143103.html
// httpMethod推薦使用POST
// apiVersion為API版本,與類目相關,具體類目的API版本請參考:http://m.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"];
//直接發post請求
[self request:finalUrl responseBlock:^(NSDictionary *responseObject, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
block(nil,error);
}else{
block(responseObject, nil);
}
});
}];
}