最近接到一個(gè)有關(guān)騰訊廣告推廣應(yīng)用的渠道,需要實(shí)現(xiàn),就是用到了廣點(diǎn)通,而它的坑爹之處就在于,iOS版本的接入方式只有API,沒有SDK,所以需要我們開發(fā)人員去逐字逐句理解然后實(shí)現(xiàn)調(diào)用他們服務(wù)端的接口,然而這個(gè)并不僅僅是一個(gè)接口調(diào)用那么簡(jiǎn)單;各種碼的獲取,各種加密方式,簡(jiǎn)直讓人蛋碎,最主要的是人家TX的技術(shù)支持聽說忙的不行,一般是不會(huì)理你的,API里面是Python語言寫的什么異或的東西,居然讓我一個(gè)寫OC的自己搞定,所以經(jīng)過這次蹚坑我決定把我的實(shí)現(xiàn)分享給大家,以便后來人乘涼??--------
引入頭文件
#import <CommonCrypto/CommonDigest.h>
#import <AdSupport/ASIdentifierManager.h>
#import "ZRGTMBase64.h"
#import "RequestModel.h" //封裝的數(shù)據(jù)請(qǐng)求類
定義基本的宏變量
//以下四個(gè)key是在創(chuàng)建一個(gè)轉(zhuǎn)化成功之后生成的(詳見文章最后備注)
#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
用到的兩個(gè)屬性
@property (nonatomic,strong)RequestModel *requestModel;
@property (nonatomic,strong) NSMutableArray *adArray;
具體代碼實(shí)現(xiàn)
//激活發(fā)送
- (void)send {
_adArray = [NSMutableArray arrayWithArray:[self loadCustomObjectWithKey:adGetKey]];
//只有第一次才發(fā)送
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];
//標(biāo)記為已發(fā)送
[_adArray addObject:@"1"];
[weakSelf saveCustomObject:_adArray];
}
} withFailedBlock:^(NSError *error) {
NSLog(@"發(fā)送失敗:%@",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),因?yàn)閎ytes里面有\(zhòng)0,而strlen只計(jì)算\0之前數(shù),所以最終的長(zhǎng)度偏小
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 - 獲取持久化數(shù)據(jù) -----
- (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;
}
備注:

TXLK(859Q%{4(2$K(467ED6.jpg
----最后,還是要感謝 gaoyuqiang30(CSDN)對(duì)我的支持指導(dǎo)-----