最近接到一个有关腾讯广告推广应用的渠道,需要实现,就是用到了广点通,而它的坑爹之处就在于,iOS版本的接入方式只有API,没有SDK,所以需要我们开发人员去逐字逐句理解然后实现调用他们服务端的接口,然而这个并不仅仅是一个接口调用那么简单;各种码的获取,各种加密方式,简直让人蛋碎,最主要的是人家TX的技术支持听说忙的不行,一般是不会理你的,API里面是Python语言写的什么异或的东西,居然让我一个写OC的自己搞定,所以经过这次蹚坑我决定把我的实现分享给大家,以便后来人乘凉😄--------
引入头文件
#import <CommonCrypto/CommonDigest.h>
#import <AdSupport/ASIdentifierManager.h>
#import "ZRGTMBase64.h"
#import "RequestModel.h" //封装的数据请求类
定义基本的宏变量
//以下四个key是在创建一个转化成功之后生成的(详见文章最后备注)
#define gdt_encrypt_key @"xxxxxxxxxx"
#define gdt_sign_key @"xxxxxxxxxx"
#define gdt_app_id @"xxxxxxxxxx"
#define gdt_advertiser_id @"xxxxxxx"
#define adGetKey @"ZRAdDowlondCountObjectKey"
#define CC_MD5_DIGEST_LENGTH 16
用到的两个属性
@property (nonatomic,strong)RequestModel *requestModel;
@property (nonatomic,strong) NSMutableArray *adArray;
具体代码实现
//激活发送
- (void)send {
_adArray = [NSMutableArray arrayWithArray:[self loadCustomObjectWithKey:adGetKey]];
//只有第一次才发送
if (_adArray.count && [[_adArray objectAtIndex:0] isEqualToString:@"1"]) {
return;
}
if (!self.requestModel) {
self.requestModel = [[RequestModel alloc] init];
}
__weak typeof(self) weakSelf = self;
[self.requestModel loadDataeWithURlString:[self generateUrl] withResultBlock:^(NSDictionary *dict) {
if ([[[dict objectForKey:@"ret"] stringValue] isEqualToString:@"0"]) {
[_adArray removeAllObjects];
//标记为已发送
[_adArray addObject:@"1"];
[weakSelf saveCustomObject:_adArray];
}
} withFailedBlock:^(NSError *error) {
NSLog(@"发送失败:%@",error);
}];
}
//生成url
-(NSString *)generateUrl {
NSString *result = @"";
NSString *encrypt_key = gdt_encrypt_key;
NSString *sign_key = gdt_sign_key;
NSString *app_id = gdt_app_id;
NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSString *conv_type = @"MOBILEAPP_ACTIVITE";
NSString *app_type = @"IOS";
NSString *advertiser_id = gdt_advertiser_id;
NSString *conv_time = [NSString stringWithFormat:@"%.0lf", [NSDate date].timeIntervalSince1970];
NSString *muid = [self generateMuid:idfa];
NSString *query_string = [NSString stringWithFormat:@"muid=%@&conv_time=%@", muid, conv_time];
NSString *encode_page = [NSString stringWithFormat:@"http://t.gdt.qq.com/conv/app/%@/conv?%@", app_id, query_string];
NSString *temp = [NSString stringWithFormat:@"%@&GET&%@", sign_key, [self encodeToPercentEscapeString:encode_page]];
NSString *signature = [self getMd5_32Bit_String:temp];
NSString* base_data = [query_string stringByAppendingFormat:@"&sign=%@", signature];
NSString* v_data = [self encodeToPercentEscapeString:[ZRGTMBase64 stringByEncodingData:[self simpleXor:base_data key:encrypt_key]]];
NSLog(@"query_string: %@", query_string);
NSLog(@"v_data: %@", v_data);
result = [NSString stringWithFormat:@"http://t.gdt.qq.com/conv/app/%@/conv?v=%@&conv_type=%@&app_type=%@&advertiser_id=%@", app_id, v_data, conv_type, app_type, advertiser_id];
NSLog(@"\n%@", result);
return result;
}
//生成muid
- (NSString *)generateMuid:(NSString *)idfa {
idfa = [idfa uppercaseString];
NSString* result = [self getMd5_32Bit_String:idfa];
NSLog(@"muid--%@", result);
return result;
}
//异或操作
- (NSData *)simpleXor:(NSString *)info key:(NSString *)key {
const char *infoBytes = [info UTF8String];
const char *keyBytes = [key UTF8String];
int i = 0, j = 0;
char *bytes = malloc(strlen(infoBytes));
for (i = 0; i < strlen(infoBytes); i++) {
bytes[i] = (char)(infoBytes[i]^keyBytes[j]);
j++;
j = j%(key.length);
}
//这一定要用strlen(infoBytes),不要用strlen(bytes),因为bytes里面有\0,而strlen只计算\0之前数,所以最终的长度偏小
NSData *data = [NSData dataWithBytes:bytes length:strlen(infoBytes)];
return data;
}
- (NSString *)getMd5_32Bit_String:(NSString *)srcString{
const char *cstr = [srcString UTF8String];
uint8_t digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(cstr, (int)strlen(cstr), digest);
NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x",digest[i]];
}
return [result lowercaseString];
}
//urlEncode
- (NSString *)encodeToPercentEscapeString: (NSString *) input
{
NSString *outputStr = (NSString *)
CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)input,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8));
return outputStr;
}
#pragma mark - 获取持久化数据 -----
- (void)saveCustomObject:(NSArray *)obj
{
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:obj];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:myEncodedObject forKey:adGetKey];
[defaults synchronize];
}
- (NSArray *)loadCustomObjectWithKey:(NSString *)key
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *myEncodedObject = [defaults objectForKey:key];
NSArray *obj = (NSArray *)[NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject];
return obj;
}
备注:
----最后,还是要感谢 gaoyuqiang30(CSDN)对我的支持指导-----
网友评论