修改sign。
键盘里ai回复的bug
This commit is contained in:
@@ -41,38 +41,10 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||
}
|
||||
|
||||
- (void)getSignWithParare:(NSDictionary *)bodyParams{
|
||||
|
||||
NSString *appId = @"loveKeyboard";
|
||||
NSString *secret = @"kZJM39HYvhxwbJkG1fmquQRVkQiLAh2H"; // 和服务端保持一致
|
||||
NSString *timestamp = [KBSignUtils currentTimestamp];
|
||||
NSString *nonce = [KBSignUtils generateNonceWithLength:16];
|
||||
// 1. 组装参与签名的所有参数
|
||||
NSMutableDictionary<NSString *, NSString *> *signParams = [NSMutableDictionary dictionary];
|
||||
signParams[@"appId"] = appId;
|
||||
signParams[@"timestamp"] = timestamp;
|
||||
signParams[@"nonce"] = nonce;
|
||||
// 把 body 里的字段也加入签名参数
|
||||
[bodyParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||||
if ([obj isKindOfClass:[NSString class]]) {
|
||||
signParams[key] = obj;
|
||||
} else {
|
||||
signParams[key] = [obj description];
|
||||
}
|
||||
}];
|
||||
NSString *sign = [KBSignUtils signWithParams:signParams secret:secret];
|
||||
|
||||
// 将签名相关字段合并进默认请求头
|
||||
NSDictionary<NSString *, NSString *> *signHeaders = [KBSignUtils signHeadersWithBodyParams:bodyParams];
|
||||
NSMutableDictionary<NSString *, NSString *> *headers =
|
||||
[self.defaultHeaders mutableCopy] ?: [NSMutableDictionary dictionary];
|
||||
|
||||
if (sign.length > 0) {
|
||||
headers[@"X-Sign"] = sign;
|
||||
}
|
||||
headers[@"X-App-Id"] = appId;
|
||||
headers[@"X-Timestamp"] = timestamp;
|
||||
headers[@"X-Nonce"] = nonce;
|
||||
|
||||
// 触发 copy 语义,确保对外仍是不可变字典
|
||||
[headers addEntriesFromDictionary:signHeaders ?: @{}];
|
||||
self.defaultHeaders = headers;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#import "KBHostAppLauncher.h"
|
||||
#import "KBInputBufferManager.h"
|
||||
#import "KBResponderUtils.h" // 统一查找 UIInputViewController 的工具
|
||||
#import "KBSignUtils.h"
|
||||
#import "KBSkinManager.h"
|
||||
#import "KBStreamOverlayView.h" // 带关闭按钮的流式层
|
||||
#import "KBStreamTextView.h" // 流式文本视图
|
||||
@@ -435,11 +436,32 @@
|
||||
cachePolicy:NSURLRequestReloadIgnoringCacheData
|
||||
timeoutInterval:60];
|
||||
request.HTTPMethod = @"POST";
|
||||
[request setValue:@"text/event-stream" forHTTPHeaderField:@"Accept"];
|
||||
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
|
||||
// 签名头(后端要求,否则会 401:Missing sign headers)
|
||||
NSDictionary<NSString *, NSString *> *signHeaders =
|
||||
[KBSignUtils signHeadersWithBodyParams:payload];
|
||||
[signHeaders enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj,
|
||||
BOOL *stop) {
|
||||
if (key.length == 0 || obj.length == 0) {
|
||||
return;
|
||||
}
|
||||
[request setValue:obj forHTTPHeaderField:key];
|
||||
}];
|
||||
NSString *token = KBAuthManager.shared.current.accessToken ?: @"";
|
||||
if (token.length > 0) {
|
||||
[request setValue:token forHTTPHeaderField:@"auth-token"];
|
||||
}
|
||||
// 与主 App 的请求头保持一致(Bearer)
|
||||
NSDictionary<NSString *, NSString *> *authHeader =
|
||||
[[KBAuthManager shared] authorizationHeader];
|
||||
[authHeader enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj,
|
||||
BOOL *stop) {
|
||||
if (key.length == 0 || obj.length == 0) {
|
||||
return;
|
||||
}
|
||||
[request setValue:obj forHTTPHeaderField:key];
|
||||
}];
|
||||
request.HTTPBody = bodyData;
|
||||
|
||||
self.streamHasOutput = NO;
|
||||
@@ -463,7 +485,7 @@
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self)
|
||||
return;
|
||||
[self kb_handleEventSourceError:event.error];
|
||||
// [self kb_handleEventSourceError:event.error];
|
||||
}
|
||||
forEvent:WJXEventNameError
|
||||
queue:NSOperationQueue.mainQueue];
|
||||
|
||||
@@ -95,7 +95,7 @@ static void KBMaiPoint_DebugLogError(NSURLResponse *response, NSError *error) {
|
||||
@"eventId": trimmedName,
|
||||
@"value": val.copy
|
||||
};
|
||||
[self postPath:KB_MAI_POINT_PATH_GENERIC_DATA parameters:params completion:completion];
|
||||
// [self postPath:KB_MAI_POINT_PATH_GENERIC_DATA parameters:params completion:completion];
|
||||
}
|
||||
|
||||
- (void)reportPageExposureWithEventName:(NSString *)eventName
|
||||
|
||||
@@ -30,6 +30,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// 简单 nonce 生成(默认 16 位)
|
||||
+ (NSString *)generateNonceWithLength:(NSUInteger)length;
|
||||
|
||||
/// 生成本项目后端约定的签名请求头(X-Sign/X-App-Id/X-Timestamp/X-Nonce)。
|
||||
/// bodyParams:参与签名的业务参数(如 JSON body 字段)。内部会做类型容错与空值过滤。
|
||||
+ (NSDictionary<NSString *, NSString *> *)signHeadersWithBodyParams:(nullable NSDictionary *)bodyParams;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -10,6 +10,32 @@
|
||||
|
||||
@implementation KBSignUtils
|
||||
|
||||
static NSString *const KBSignAppId = @"loveKeyboard";
|
||||
static NSString *const KBSignSecret = @"kZJM39HYvhxwbJkG1fmquQRVkQiLAh2H";
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
+ (NSString *)urlEncode:(NSString *)value {
|
||||
if (!value) return @"";
|
||||
// 按 application/x-www-form-urlencoded 规则编码(更贴近后端常见实现)
|
||||
@@ -96,4 +122,50 @@
|
||||
return [uuid substringToIndex:length];
|
||||
}
|
||||
|
||||
+ (NSDictionary<NSString *, NSString *> *)signHeadersWithBodyParams:(NSDictionary *)bodyParams {
|
||||
NSString *timestamp = [self currentTimestamp];
|
||||
NSString *nonce = [self generateNonceWithLength:16];
|
||||
|
||||
NSMutableDictionary<NSString *, NSString *> *signParams = [NSMutableDictionary dictionary];
|
||||
if (KBSignAppId.length > 0) {
|
||||
signParams[@"appId"] = KBSignAppId;
|
||||
}
|
||||
if (timestamp.length > 0) {
|
||||
signParams[@"timestamp"] = timestamp;
|
||||
}
|
||||
if (nonce.length > 0) {
|
||||
signParams[@"nonce"] = nonce;
|
||||
}
|
||||
|
||||
if ([bodyParams isKindOfClass:[NSDictionary class]] && bodyParams.count > 0) {
|
||||
[bodyParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||||
if (![key isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
NSString *value = KBSignStringFromObject(obj);
|
||||
if (value.length == 0) {
|
||||
return;
|
||||
}
|
||||
signParams[(NSString *)key] = value;
|
||||
}];
|
||||
}
|
||||
|
||||
NSString *sign = [self signWithParams:signParams secret:KBSignSecret ?: @""];
|
||||
|
||||
NSMutableDictionary<NSString *, NSString *> *headers = [NSMutableDictionary dictionary];
|
||||
if (sign.length > 0) {
|
||||
headers[@"X-Sign"] = sign;
|
||||
}
|
||||
if (KBSignAppId.length > 0) {
|
||||
headers[@"X-App-Id"] = KBSignAppId;
|
||||
}
|
||||
if (timestamp.length > 0) {
|
||||
headers[@"X-Timestamp"] = timestamp;
|
||||
}
|
||||
if (nonce.length > 0) {
|
||||
headers[@"X-Nonce"] = nonce;
|
||||
}
|
||||
return [headers copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -33,29 +33,6 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||
|
||||
@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 {
|
||||
static KBNetworkManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBNetworkManager new]; });
|
||||
return m;
|
||||
@@ -84,48 +61,10 @@ static NSString *KBSignStringFromObject(id obj) {
|
||||
}
|
||||
|
||||
- (void)getSignWithParare:(NSDictionary *)bodyParams{
|
||||
|
||||
NSString *appId = @"loveKeyboard";
|
||||
NSString *secret = @"kZJM39HYvhxwbJkG1fmquQRVkQiLAh2H"; // 和服务端保持一致
|
||||
NSString *timestamp = [KBSignUtils currentTimestamp];
|
||||
NSString *nonce = [KBSignUtils generateNonceWithLength:16];
|
||||
// 1. 组装参与签名的所有参数
|
||||
NSMutableDictionary<NSString *, NSString *> *signParams = [NSMutableDictionary dictionary];
|
||||
signParams[@"appId"] = appId;
|
||||
signParams[@"timestamp"] = timestamp;
|
||||
signParams[@"nonce"] = nonce;
|
||||
// 把 body 里的字段也加入签名参数
|
||||
[bodyParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||||
NSString *value = KBSignStringFromObject(obj);
|
||||
if (value.length == 0) {
|
||||
return;
|
||||
}
|
||||
signParams[key] = value;
|
||||
}];
|
||||
NSString *signSource = [KBSignUtils signSourceStringWithParams: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
|
||||
|
||||
// 将签名相关字段合并进默认请求头
|
||||
NSDictionary<NSString *, NSString *> *signHeaders = [KBSignUtils signHeadersWithBodyParams:bodyParams];
|
||||
NSMutableDictionary<NSString *, NSString *> *headers =
|
||||
[self.defaultHeaders mutableCopy] ?: [NSMutableDictionary dictionary];
|
||||
|
||||
if (sign.length > 0) {
|
||||
headers[@"X-Sign"] = sign;
|
||||
}
|
||||
headers[@"X-App-Id"] = appId;
|
||||
headers[@"X-Timestamp"] = timestamp;
|
||||
headers[@"X-Nonce"] = nonce;
|
||||
|
||||
// 触发 copy 语义,确保对外仍是不可变字典
|
||||
[headers addEntriesFromDictionary:signHeaders ?: @{}];
|
||||
self.defaultHeaders = headers;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user