Compare commits
1 Commits
822a814f85
...
dev_st_重构A
| Author | SHA1 | Date | |
|---|---|---|---|
| 61095a379f |
@@ -20,6 +20,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
|
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
|
||||||
secret:(NSString *)secret;
|
secret:(NSString *)secret;
|
||||||
|
|
||||||
|
/// 获取签名原始拼接字符串(HMAC 前的明文)
|
||||||
|
+ (NSString *)signSourceStringWithParams:(NSDictionary<NSString *, NSString *> *)params
|
||||||
|
secret:(NSString *)secret;
|
||||||
|
|
||||||
/// 秒级时间戳(字符串)
|
/// 秒级时间戳(字符串)
|
||||||
+ (NSString *)currentTimestamp;
|
+ (NSString *)currentTimestamp;
|
||||||
|
|
||||||
@@ -29,4 +33,3 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,16 @@
|
|||||||
|
|
||||||
+ (NSString *)urlEncode:(NSString *)value {
|
+ (NSString *)urlEncode:(NSString *)value {
|
||||||
if (!value) return @"";
|
if (!value) return @"";
|
||||||
// 和 Swift 里的 .urlQueryAllowed 类似
|
// 按 application/x-www-form-urlencoded 规则编码(更贴近后端常见实现)
|
||||||
NSCharacterSet *allowed = [NSCharacterSet URLQueryAllowedCharacterSet];
|
NSMutableCharacterSet *allowed = [NSMutableCharacterSet alphanumericCharacterSet];
|
||||||
|
[allowed addCharactersInString:@"-._*"];
|
||||||
NSString *encoded = [value stringByAddingPercentEncodingWithAllowedCharacters:allowed];
|
NSString *encoded = [value stringByAddingPercentEncodingWithAllowedCharacters:allowed];
|
||||||
return encoded ?: value;
|
if (!encoded) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
// 空格改为 +(URLEncoder 风格)
|
||||||
|
encoded = [encoded stringByReplacingOccurrencesOfString:@"%20" withString:@"+"];
|
||||||
|
return encoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *)hmacSHA256:(NSString *)data secret:(NSString *)secret {
|
+ (NSString *)hmacSHA256:(NSString *)data secret:(NSString *)secret {
|
||||||
@@ -41,6 +47,12 @@
|
|||||||
|
|
||||||
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
|
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
|
||||||
secret:(NSString *)secret {
|
secret:(NSString *)secret {
|
||||||
|
NSString *dataString = [self signSourceStringWithParams:params secret:secret];
|
||||||
|
return [self hmacSHA256:dataString secret:secret];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)signSourceStringWithParams:(NSDictionary<NSString *, NSString *> *)params
|
||||||
|
secret:(NSString *)secret {
|
||||||
|
|
||||||
// 1. 过滤空值 & sign 自身
|
// 1. 过滤空值 & sign 自身
|
||||||
NSMutableDictionary<NSString *, NSString *> *filtered = [NSMutableDictionary dictionary];
|
NSMutableDictionary<NSString *, NSString *> *filtered = [NSMutableDictionary dictionary];
|
||||||
@@ -62,15 +74,11 @@
|
|||||||
[components addObject:part];
|
[components addObject:part];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *encodedSecret = [self urlEncode:secret];
|
NSString *encodedSecret = [self urlEncode:secret ?: @""];
|
||||||
NSString *secretPart = [NSString stringWithFormat:@"secret=%@", encodedSecret];
|
NSString *secretPart = [NSString stringWithFormat:@"secret=%@", encodedSecret];
|
||||||
[components addObject:secretPart];
|
[components addObject:secretPart];
|
||||||
|
|
||||||
NSString *dataString = [components componentsJoinedByString:@"&"];
|
return [components componentsJoinedByString:@"&"];
|
||||||
|
|
||||||
// 4. HMAC-SHA256
|
|
||||||
NSString *sign = [self hmacSHA256:dataString secret:secret];
|
|
||||||
return sign;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *)currentTimestamp {
|
+ (NSString *)currentTimestamp {
|
||||||
@@ -89,4 +97,3 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -119,12 +119,7 @@ autoShowBusinessError:NO
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *encodedContent =
|
NSString *path = API_AI_CHAT_MESSAGE;
|
||||||
[content stringByAddingPercentEncodingWithAllowedCharacters:
|
|
||||||
[NSCharacterSet URLQueryAllowedCharacterSet]];
|
|
||||||
NSString *path = [NSString
|
|
||||||
stringWithFormat:@"%@?content=%@&companionId=%ld", API_AI_CHAT_MESSAGE,
|
|
||||||
encodedContent ?: @"", (long)companionId];
|
|
||||||
NSDictionary *params = @{
|
NSDictionary *params = @{
|
||||||
@"content" : content ?: @"",
|
@"content" : content ?: @"",
|
||||||
@"companionId" : @(companionId)
|
@"companionId" : @(companionId)
|
||||||
|
|||||||
@@ -33,6 +33,29 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
|
|
||||||
@implementation KBNetworkManager
|
@implementation KBNetworkManager
|
||||||
|
|
||||||
|
static NSString *KBSignStringFromObject(id obj) {
|
||||||
|
if (!obj || obj == (id)kCFNull) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if ([obj isKindOfClass:[NSString class]]) {
|
||||||
|
return (NSString *)obj;
|
||||||
|
}
|
||||||
|
if ([obj isKindOfClass:[NSNumber class]]) {
|
||||||
|
return [(NSNumber *)obj stringValue];
|
||||||
|
}
|
||||||
|
if ([obj isKindOfClass:[NSArray class]] || [obj isKindOfClass:[NSDictionary class]]) {
|
||||||
|
NSJSONWritingOptions options = 0;
|
||||||
|
if (@available(iOS 11.0, *)) {
|
||||||
|
options = NSJSONWritingSortedKeys;
|
||||||
|
}
|
||||||
|
NSData *data = [NSJSONSerialization dataWithJSONObject:obj options:options error:nil];
|
||||||
|
if (data.length > 0) {
|
||||||
|
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [obj description];
|
||||||
|
}
|
||||||
|
|
||||||
+ (instancetype)shared {
|
+ (instancetype)shared {
|
||||||
static KBNetworkManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBNetworkManager new]; });
|
static KBNetworkManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBNetworkManager new]; });
|
||||||
return m;
|
return m;
|
||||||
@@ -73,14 +96,24 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
signParams[@"nonce"] = nonce;
|
signParams[@"nonce"] = nonce;
|
||||||
// 把 body 里的字段也加入签名参数
|
// 把 body 里的字段也加入签名参数
|
||||||
[bodyParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
[bodyParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||||||
if ([obj isKindOfClass:[NSString class]]) {
|
NSString *value = KBSignStringFromObject(obj);
|
||||||
signParams[key] = obj;
|
if (value.length == 0) {
|
||||||
} else {
|
return;
|
||||||
signParams[key] = [obj description];
|
|
||||||
}
|
}
|
||||||
|
signParams[key] = value;
|
||||||
}];
|
}];
|
||||||
|
NSString *signSource = [KBSignUtils signSourceStringWithParams:signParams secret:secret];
|
||||||
NSString *sign = [KBSignUtils signWithParams:signParams secret:secret];
|
NSString *sign = [KBSignUtils signWithParams:signParams secret:secret];
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (signSource.length > 0) {
|
||||||
|
NSString *secretPart = [NSString stringWithFormat:@"secret=%@", [KBSignUtils urlEncode:secret ?: @""]];
|
||||||
|
NSString *masked = [signSource stringByReplacingOccurrencesOfString:secretPart withString:@"secret=***"];
|
||||||
|
KBLOG(@"[KBNetwork] sign source: %@", masked);
|
||||||
|
KBLOG(@"[KBNetwork] sign value: %@", sign ?: @"");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// 将签名相关字段合并进默认请求头
|
// 将签名相关字段合并进默认请求头
|
||||||
NSMutableDictionary<NSString *, NSString *> *headers =
|
NSMutableDictionary<NSString *, NSString *> *headers =
|
||||||
[self.defaultHeaders mutableCopy] ?: [NSMutableDictionary dictionary];
|
[self.defaultHeaders mutableCopy] ?: [NSMutableDictionary dictionary];
|
||||||
@@ -202,6 +235,7 @@ autoShowBusinessError:YES
|
|||||||
parameters:(NSDictionary *)parameters
|
parameters:(NSDictionary *)parameters
|
||||||
headers:(NSDictionary<NSString *,NSString *> *)headers
|
headers:(NSDictionary<NSString *,NSString *> *)headers
|
||||||
completion:(KBNetworkDataCompletion)completion {
|
completion:(KBNetworkDataCompletion)completion {
|
||||||
|
[self getSignWithParare:parameters];
|
||||||
if (!self.isEnabled) {
|
if (!self.isEnabled) {
|
||||||
NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain
|
NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain
|
||||||
code:KBNetworkErrorDisabled
|
code:KBNetworkErrorDisabled
|
||||||
@@ -243,6 +277,7 @@ autoShowBusinessError:YES
|
|||||||
completion:(KBNetworkCompletion)completion
|
completion:(KBNetworkCompletion)completion
|
||||||
{
|
{
|
||||||
NSLog(@"[KBNetworkManager] UPLOAD called, enabled=%d, path=%@", self.isEnabled, path);
|
NSLog(@"[KBNetworkManager] UPLOAD called, enabled=%d, path=%@", self.isEnabled, path);
|
||||||
|
[self getSignWithParare:@{}];
|
||||||
if (![self ensureEnabled:completion]) return nil;
|
if (![self ensureEnabled:completion]) return nil;
|
||||||
|
|
||||||
NSString *urlString = [self buildURLStringWithPath:path];
|
NSString *urlString = [self buildURLStringWithPath:path];
|
||||||
@@ -330,6 +365,7 @@ autoShowBusinessError:YES
|
|||||||
parameters:(NSDictionary *)parameters
|
parameters:(NSDictionary *)parameters
|
||||||
headers:(NSDictionary<NSString *, NSString *> *)headers
|
headers:(NSDictionary<NSString *, NSString *> *)headers
|
||||||
completion:(KBNetworkCompletion)completion {
|
completion:(KBNetworkCompletion)completion {
|
||||||
|
[self getSignWithParare:parameters ?: @{}];
|
||||||
if (!fileURL || !fileURL.isFileURL) {
|
if (!fileURL || !fileURL.isFileURL) {
|
||||||
if (completion) {
|
if (completion) {
|
||||||
NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain
|
NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain
|
||||||
|
|||||||
Reference in New Issue
Block a user