跳到主要内容

TapADN SDK iOS 接入文档

SDK 概述​

TapADN SDK 是一款功能完善的 iOS 广告 SDK,支持多种广告形式:

  • 开屏广告(Splash Ad):应用启动时展示的全屏广告
  • 激励视频广告(Reward Video Ad):用户观看完整视频后获得奖励
  • Banner广告:固定位置的横幅广告
  • 插屏广告(Interstitial Ad):全屏或半屏的插屏广告
  • 信息流广告(Feed Ad):嵌入内容流中的原生广告

主要特性:

  • 丰富的自定义配置选项
  • 完善的隐私合规控制
  • 多样化的广告交互回调

系统要求​

  • 最低系统版本:iOS 11.0+
  • 开发工具:Xcode 12.0+
  • 依赖管理:CocoaPods 1.10.0+

SDK 集成​

配置 Podfile 文件​

修改 Podfile 文件,添加 SDK 依赖:

platform :ios, '11.0'
use_frameworks!

target 'YourProjectName' do
# Dirichlet Ad
pod 'DirichletAdSDK', '~> 5.3.1.6'
end

安装 SDK​

如果未安装过 CocoaPods,可以通过以下命令行进行安装:

$ sudo gem install cocoapods

通过 CocoaPods 安装前,确保 CocoaPods 索引已经更新:

$ pod repo update

运行命令进行安装:

$ pod install

Xcode 配置​

App Tracking Transparency (ATT)​

从 iOS 14 开始,需要在 Info.plist 中添加 ATT 权限描述:

<key>NSUserTrackingUsageDescription</key>
<string>该标识符将用于向您投放个性化广告</string>

iOS 14.5 以上在拉取广告前请求 ATT 权限:

#import <AppTrackingTransparency/AppTrackingTransparency.h>

if (@available(iOS 14.5, *)) {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
switch (status) {
case ATTrackingManagerAuthorizationStatusDenied:
NSLog(@"用户拒绝了跟踪权限");
break;
case ATTrackingManagerAuthorizationStatusAuthorized:
NSLog(@"用户授权了跟踪权限");
break;
case ATTrackingManagerAuthorizationStatusRestricted:
NSLog(@"跟踪权限受限");
break;
case ATTrackingManagerAuthorizationStatusNotDetermined:
NSLog(@"用户尚未决定跟踪权限");
break;
default:
break;
}
}];
}

SDK 初始化​

基本初始化​

#import <DirichletAdSDK/DirichletAdSDK.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 创建配置对象
DRASDKConfig *config = [[DRASDKConfig alloc] initWithMediaId:@"YOUR_MEDIA_ID"
mediaKey:@"YOUR_MEDIA_KEY"];

// 配置调试模式(可选,默认为 NO,正式发布前应改为 NO)
config.isDebug = NO;

// 设置是否启用摇一摇功能(可选,默认为 YES)
config.shakeEnabled = YES;

// 设置游戏渠道信息(可选)
config.gameChannel = @"TapTap";

// 初始化 SDK
[DirichletAd startWithConfig:config completion:^(BOOL success, NSError * _Nullable error) {
if (success) {
NSLog(@"SDK 初始化成功");
// 可以开始请求广告
} else {
NSLog(@"SDK 初始化失败: %@", error.localizedDescription);
}
}];

return YES;
}

完整配置示例​

// 创建配置对象
DRASDKConfig *config = [[DRASDKConfig alloc] initWithMediaId:@"YOUR_MEDIA_ID"
mediaKey:@"YOUR_MEDIA_KEY"];

// 设置媒体名称(可选)
config.mediaName = @"YourAppName";

// 设置游戏渠道(可选)
config.gameChannel = @"TapTap";

// 设置调试模式(可选)
config.isDebug = NO;

// 设置是否启用摇一摇功能(可选,默认为 YES)
config.shakeEnabled = YES;

// 设置是否启用视频预缓存(可选,默认为 YES)
config.enableVideoPreCache = YES;

// 设置 TapTap Client ID(可选)
config.tapClientId = @"YOUR_TAP_CLIENT_ID";

// 设置自定义信息提供者(可选)
config.customInfoProvider = [[MyCustomInfoProvider alloc] init];

// 设置是否允许访问 IDFA(可选,默认为 YES)
config.allowIDFAAccess = YES;

// 初始化 SDK
[DirichletAd startWithConfig:config completion:^(BOOL success, NSError * _Nullable error) {
if (success) {
NSLog(@"SDK 初始化成功");
} else {
NSLog(@"SDK 初始化失败: %@", error.localizedDescription);
}
}];

配置参数说明​

@interface DRASDKConfig : NSObject

// ===== 必需参数 =====
/// 媒体 ID(必填)
@property (nonatomic, copy, readonly) NSString *mediaId;

/// 媒体密钥(必填)
@property (nonatomic, copy, readonly) NSString *mediaKey;

// ===== 可选参数 =====
/// 媒体名称
@property (nonatomic, copy, nullable) NSString *mediaName;

/// 游戏渠道信息
@property (nonatomic, copy, nullable) NSString *gameChannel;

/// 是否开启调试模式(默认 NO)
@property (nonatomic, assign) BOOL isDebug;

/// 是否启用摇一摇功能(默认 YES)
@property (nonatomic, assign, getter=isShakeEnabled) BOOL shakeEnabled;

/// 是否启用视频预缓存(默认 YES)
@property (nonatomic, assign, getter=isEnableVideoPreCache) BOOL enableVideoPreCache;

/// TapTap 客户端 ID
@property (nonatomic, copy, nullable) NSString *tapClientId;

/// 自定义信息提供者
@property (nonatomic, strong, nullable) id<DRACustomInfoProviding> customInfoProvider;

/// CTA 拦截器
@property (nonatomic, weak, nullable) id<DRACTAInterceptor> ctaInterceptor;

/// 是否允许访问 IDFA(默认 YES)
@property (nonatomic, assign) BOOL allowIDFAAccess;

@end

广告类型​

开屏广告​

开屏广告为用户在进入 App 时展示的全屏广告。

信息

竖屏开屏广告要求 width = 屏幕宽,height 需要 >= 75% 屏幕高,否则会影响计费。

横屏开屏广告要求 width = 屏幕宽,height 需要 = 屏幕高,否则会影响计费。

获取广告​

#import <DirichletAdSDK/DirichletAdSDK.h>

@interface SplashViewController () <DRASplashAdDelegate>
@property (nonatomic, strong) DRASplashAd *splashAd;
@end

@implementation SplashViewController

- (void)loadSplashAd {
// 创建加载请求
DRASplashAdLoadRequest *request = [[[DRASplashAdLoadRequest builder]
withSpaceId:@"YOUR_SPLASH_AD_SPACE_ID"]
withLogoImage:[UIImage imageNamed:@"app_logo"]] // 可选:配置自定义 Logo
build];

// 加载开屏广告
[DRASplashAd loadWithRequest:request completion:^(DRASplashAd * _Nullable ad, NSError * _Nullable error) {
if (error) {
NSLog(@"开屏广告加载失败: %@", error.localizedDescription);
// 跳转到主页面
[self goToMainActivity];
return;
}

if (ad && ad.isReady) {
self.splashAd = ad;
self.splashAd.delegate = self;
// 展示广告
[self.splashAd showFromViewController:self];
}
}];
}

- (void)goToMainActivity {
// 跳转到主页面逻辑
}

#pragma mark - DRASplashAdDelegate

- (void)dirichletAdDidLoad:(id<DRAAd>)ad {
NSLog(@"开屏广告加载完成");
}

- (void)dirichletAdDidShow:(id<DRAAd>)ad {
NSLog(@"开屏广告开始展示");
}

- (void)dirichletSplashAdDidValidShow:(DRASplashAd *)splashAd {
NSLog(@"开屏广告有效展示");
}

- (void)dirichletSplashAdDidSkip:(DRASplashAd *)splashAd {
NSLog(@"开屏广告被跳过");
[self goToMainActivity];
}

- (void)dirichletSplashAdDidTimeOver:(DRASplashAd *)splashAd {
NSLog(@"开屏广告倒计时结束");
[self goToMainActivity];
}

- (void)dirichletAdDidClose:(id<DRAAd>)ad {
NSLog(@"开屏广告关闭");
self.splashAd = nil;
[self goToMainActivity];
}

- (void)dirichletAd:(id<DRAAd>)ad didFailWithError:(NSError *)error {
NSLog(@"开屏广告错误: %@", error.localizedDescription);
}

@end

激励视频广告​

激励视频是一种全屏播放的视频广告,用户可以在观看完整的视频后获取奖励。

信息
  • 全屏横屏(宽高比 16:9)
  • 全屏竖屏(宽高比 9:16)

获取广告​

#import <DirichletAdSDK/DirichletAdSDK.h>

@interface RewardedAdViewController () <DRARewardedAdDelegate>
@property (nonatomic, strong) DRARewardedAd *rewardedAd;
@end

@implementation RewardedAdViewController

- (void)loadRewardedAd {
// 创建加载请求
DRARewardedAdLoadRequest *request = [[[DRARewardedAdLoadRequest builder]
withSpaceId:@"YOUR_REWARD_AD_SPACE_ID"]
withRewardName:@"金币"] // 可选:奖励名称
withRewardAmount:100] // 可选:奖励数量
build];

// 加载激励视频广告
[DRARewardedAd loadWithRequest:request completion:^(DRARewardedAd * _Nullable ad, NSError * _Nullable error) {
if (error) {
NSLog(@"激励视频广告加载失败: %@", error.localizedDescription);
return;
}

if (ad) {
self.rewardedAd = ad;
self.rewardedAd.delegate = self;
NSLog(@"激励视频广告加载成功");
}
}];
}

- (void)showRewardedAd {
if (self.rewardedAd && self.rewardedAd.isReady) {
[self.rewardedAd showFromViewController:self];
} else {
NSLog(@"激励视频广告未就绪");
}
}

#pragma mark - DRARewardedAdDelegate

- (void)dirichletAdDidLoad:(id<DRAAd>)ad {
NSLog(@"激励视频广告加载完成");
}

- (void)dirichletAdDidShow:(id<DRAAd>)ad {
NSLog(@"激励视频广告开始展示");
}

- (void)dirichletAdDidClick:(id<DRAAd>)ad {
NSLog(@"用户点击激励视频广告");
}

- (void)rewardedAd:(DRARewardedAd *)ad
didVerifyReward:(BOOL)verified
rewardAmount:(NSInteger)amount
rewardName:(NSString *)name {
if (verified) {
NSLog(@"用户获得奖励: %@ x %ld", name, (long)amount);
// 发放奖励给用户
} else {
NSLog(@"奖励验证失败");
}
}

- (void)dirichletAdDidClose:(id<DRAAd>)ad {
NSLog(@"激励视频广告关闭");
self.rewardedAd = nil;
}

- (void)dirichletAd:(id<DRAAd>)ad didFailWithError:(NSError *)error {
NSLog(@"激励视频广告错误: %@", error.localizedDescription);
}

@end

插屏广告​

插屏广告支持「全屏视频广告」、「全屏图文广告」和「半屏图文广告」等形式。

提示

插屏广告分横竖屏形式,强烈建议在后台配置后正确使用横屏或竖屏广告,若用错配置的 orientation,可能会出现 UI 兼容异常问题。

获取广告​

#import <DirichletAdSDK/DirichletAdSDK.h>

@interface InterstitialViewController () <DRAInterstitialAdDelegate>
@property (nonatomic, strong) DRAInterstitialAd *interstitialAd;
@end

@implementation InterstitialViewController

- (void)loadInterstitialAd {
// 创建加载请求
DRAInterstitialAdLoadRequest *request = [[[DRAInterstitialAdLoadRequest builder]
withSpaceId:@"YOUR_INTERSTITIAL_AD_SPACE_ID"]
build];

// 加载插屏广告
[DRAInterstitialAd loadWithRequest:request completion:^(DRAInterstitialAd * _Nullable ad, NSError * _Nullable error) {
if (error) {
NSLog(@"插屏广告加载失败: %@", error.localizedDescription);
return;
}

if (ad) {
self.interstitialAd = ad;
self.interstitialAd.delegate = self;
NSLog(@"插屏广告加载成功");
}
}];
}

- (void)showInterstitialAd {
if (self.interstitialAd && self.interstitialAd.isReady) {
[self.interstitialAd showFromViewController:self];
} else {
NSLog(@"插屏广告未就绪");
}
}

#pragma mark - DRAInterstitialAdDelegate

- (void)dirichletAdDidLoad:(id<DRAAd>)ad {
NSLog(@"插屏广告加载完成");
}

- (void)dirichletAdDidShow:(id<DRAAd>)ad {
NSLog(@"插屏广告开始展示");
}

- (void)dirichletAdDidClick:(id<DRAAd>)ad {
NSLog(@"用户点击插屏广告");
}

- (void)dirichletAdDidClose:(id<DRAAd>)ad {
NSLog(@"插屏广告关闭");
self.interstitialAd = nil;
}

- (void)dirichletAd:(id<DRAAd>)ad didFailWithError:(NSError *)error {
NSLog(@"插屏广告错误: %@", error.localizedDescription);
}

@end

模版渲染 Banner:开发者不用自行对广告样式进行编辑和渲染,可直接调用相关接口进行广告展示。

获取广告​

#import <DirichletAdSDK/DirichletAdSDK.h>

@interface BannerViewController () <DRABannerAdViewDelegate>
@property (nonatomic, strong) DRABannerAdView *bannerView;
@end

@implementation BannerViewController

- (void)loadBannerAd {
// 创建 Banner 视图
self.bannerView = [[DRABannerAdView alloc] init];
self.bannerView.delegate = self;
self.bannerView.frame = CGRectMake(0, 0, 320, 50);
[self.view addSubview:self.bannerView];

// 创建加载请求
DRABannerAdLoadRequest *request = [[[DRABannerAdLoadRequest builder]
withSpaceId:@"YOUR_BANNER_AD_SPACE_ID"]
build];

// 加载广告
[self.bannerView loadWithRequest:request];
}

#pragma mark - DRABannerAdViewDelegate

- (void)bannerAdViewDidLoad:(DRABannerAdView *)bannerAdView {
NSLog(@"Banner 广告加载完成");
}

- (void)bannerAdViewDidShow:(DRABannerAdView *)bannerAdView {
NSLog(@"Banner 广告展示");
}

- (void)bannerAdViewDidClick:(DRABannerAdView *)bannerAdView {
NSLog(@"Banner 广告被点击");
}

- (void)bannerAdView:(DRABannerAdView *)bannerAdView didFailWithError:(NSError *)error {
NSLog(@"Banner 广告加载失败: %@", error.localizedDescription);
}

@end

信息流广告​

信息流广告是融入内容流的原生广告,支持模板渲染和自定义渲染两种方式。

模板渲染信息流广告​

#import <DirichletAdSDK/DirichletAdSDK.h>

@interface FeedViewController () <DRATemplateFeedAdDelegate>
@property (nonatomic, strong) DRATemplateFeedAd *templateFeedAd;
@end

- (void)loadTemplateFeedAd {
// 创建加载请求
DRATemplateFeedAdLoadRequest *request = [[[DRATemplateFeedAdLoadRequest builder]
withSpaceId:@"YOUR_FEED_AD_SPACE_ID"]
build];

// 加载广告
[DRATemplateFeedAd loadWithRequest:request
completion:^(DRATemplateFeedAd * _Nullable ad, NSError * _Nullable error) {
if (error || !ad) {
NSLog(@"信息流广告加载失败: %@", error.localizedDescription);
return;
}

self.templateFeedAd = ad;
ad.delegate = self;

DRAFeedRenderOptions *options = [DRAFeedRenderOptions defaultOptions];
options.videoPlaybackPolicy = DRAFeedVideoPlaybackPolicyAutoAlways;
options.muteOnStart = YES;
[ad renderWithTemplateOptions:options];
}];
}

#pragma mark - DRATemplateFeedAdDelegate

- (void)templateFeedAd:(id<DRATemplateFeedAd>)ad
didRenderSuccessWithView:(UIView *)templateView {
templateView.frame = self.contentView.bounds;
templateView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:templateView];
}

- (void)templateFeedAd:(id<DRATemplateFeedAd>)ad
didRenderFailWithError:(NSError *)error {
NSLog(@"信息流广告渲染失败: %@", error.localizedDescription);
}

自定义渲染信息流广告​

#import <DirichletAdSDK/DirichletAdSDK.h>

@interface FeedViewController () <DRACustomFeedDelegate>
@property (nonatomic, strong) DRACustomFeedAd *customFeedAd;
@property (nonatomic, strong) DRACustomFeedAdContainerView *customFeedAdView;
@end

- (void)loadCustomFeedAd {
DRACustomFeedAdLoadRequest *request = [[[DRACustomFeedAdLoadRequest builder]
withSpaceId:@"YOUR_FEED_AD_SPACE_ID"]
build];

[DRACustomFeedAd loadWithRequest:request
completion:^(DRACustomFeedAd * _Nullable ad, NSError * _Nullable error) {
if (error || !ad) {
NSLog(@"自定义信息流广告加载失败: %@", error.localizedDescription);
return;
}

// 广告容器对广告对象为弱引用,展示期间必须由接入方强引用广告对象
self.customFeedAd = ad;
ad.delegate = self;

DRACustomFeedAdContainerView *adView =
[[DRACustomFeedAdContainerView alloc] initWithFrame:self.contentView.bounds];
adView.viewController = self;

UIView *mediaContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, adView.bounds.size.width, 180)];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(12, 188, adView.bounds.size.width - 24, 24)];
titleLabel.text = ad.adData.title;

UIButton *ctaButton = [UIButton buttonWithType:UIButtonTypeSystem];
ctaButton.frame = CGRectMake(12, 220, adView.bounds.size.width - 24, 40);
[ctaButton setTitle:ad.adData.callToAction ?: @"查看详情" forState:UIControlStateNormal];

[adView addSubview:mediaContainer];
[adView addSubview:titleLabel];
[adView addSubview:ctaButton];

[adView renderAd:ad options:[DRAFeedRenderOptions defaultOptions]];

UIView *mediaView = adView.mediaView;
if (mediaView) {
mediaView.frame = mediaContainer.bounds;
mediaView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[mediaContainer addSubview:mediaView];
}

[adView registerInteractionViews:@[
[DRAFeedInteractionRegistration registrationWithView:mediaContainer
role:DRAFeedInteractionRoleCreative],
[DRAFeedInteractionRegistration registrationWithView:ctaButton
role:DRAFeedInteractionRoleCallToAction]
]];

self.customFeedAdView = adView;
[self.contentView addSubview:adView];
}];
}
注意

自定义渲染场景不会自动推断可点击区域,必须调用 registerInteractionViews:。列表复用或页面销毁时,请调用 unregisterAllViews 和 stopMediaRendering,并释放持有的广告对象。

高级功能​

自定义信息提供者​

通过实现 DRACustomInfoProviding 协议可以提供位置和用户画像信息:

@interface MyCustomInfoProvider : NSObject <DRACustomInfoProviding>
@end

@implementation MyCustomInfoProvider

- (BOOL)canUseLocation {
// 控制是否允许使用位置信息
return YES;
}

- (CLLocationDegrees)latitude {
// 返回当前纬度
return 39.9042;
}

- (CLLocationDegrees)longitude {
// 返回当前经度
return 116.4074;
}

- (NSDictionary<NSString *, NSString *> *)userProfile {
// 返回用户画像信息
return @{
@"age": @"25",
@"gender": @"1"
};
}

@end

// 使用自定义信息提供者
config.customInfoProvider = [[MyCustomInfoProvider alloc] init];

CTA 拦截器​

通过实现 DRACTAInterceptor 协议可以自定义广告跳转行为:

@interface MyCTAInterceptor : NSObject <DRACTAInterceptor>
@end

@implementation MyCTAInterceptor

- (BOOL)interceptCTAActionWithContext:(DRACTAContext *)context {
// 自定义处理逻辑
if (context.actionType == DRACTAActionTypeOpenURL) {
NSURL *url = context.url;
// 使用自定义的 WebView 打开
return YES; // 返回 YES 拦截默认行为
}
return NO; // 返回 NO 执行默认行为
}

@end

// 使用 CTA 拦截器
config.ctaInterceptor = [[MyCTAInterceptor alloc] init];

清理缓存​

// 清理所有缓存
[DirichletAd clearAllCache];

测试与调试​

开启调试模式​

在开发阶段,建议开启 SDK 的调试模式以获取详细日志:

DRASDKConfig *config = [[DRASDKConfig alloc] initWithMediaId:@"YOUR_MEDIA_ID" 
mediaKey:@"YOUR_MEDIA_KEY"];
// 配置调试模式(正式发布时务必关闭)
config.isDebug = NO;

// 初始化 SDK
[DirichletAd startWithConfig:config completion:^(BOOL success, NSError * _Nullable error) {
// ...
}];

注意:

  • 调试模式会输出大量日志,帮助排查问题
  • 正式发布时必须关闭调试模式(设置为 NO)
  • 调试模式可能影响性能,不要在生产环境使用

问题排查清单​

如果遇到广告无法展示的问题,请按以下清单排查:

  • SDK 是否正确初始化(在 AppDelegate 的 didFinishLaunchingWithOptions 中)
  • mediaId、mediaKey 等参数是否正确
  • 是否在主线程调用 SDK 方法
  • 广告容器是否正确添加到布局
  • ViewController 是否已销毁(广告展示时)
  • 是否开启了调试模式查看日志
  • 广告位 ID(spaceId)是否正确
  • 是否在合适的时机调用清理方法
  • ATT 权限是否已请求

常见问题​

SDK 初始化失败怎么办?​

请检查以下几点:

  1. 确保 mediaId 和 mediaKey 正确
  2. 检查网络连接状态
  3. 查看控制台日志输出,定位具体错误原因

广告加载失败怎么办?​

可能的原因:

  1. 广告位配置错误
  2. 网络连接问题
  3. 广告位无可用广告
  4. 请求频率过高

如何处理广告生命周期事件?​

每种广告类型都有对应的代理协议:

  • DRARewardedAdDelegate: 激励视频广告代理
  • DRAInterstitialAdDelegate: 插屏广告代理
  • DRASplashAdDelegate: 开屏广告代理
  • DRABannerAdViewDelegate: Banner 广告代理
  • DRAFeedAdDelegate: 信息流广告代理

支持哪些 iOS 版本?​

最低支持 iOS 11.0,建议使用 iOS 12.0 及以上版本以获得最佳性能。

如何避免内存泄漏?​

  1. 及时调用广告对象的清理方法
  2. 不要在静态变量中持有广告对象
  3. ViewController 销毁时清理所有广告引用
  4. 使用 weak delegate 引用

更新日志​

v5.2.1.9 (2026-09-10)​

  • 【优化】 提升稳定性

v5.2.1.5 (2026-08-31)​

  • 【优化】 提升稳定性

v5.1.2.3 (2026-08-12)​

  • 【优化】 提升稳定性

v5.1.1.1 (2026-08-06)​

  • 【优化】 广告样式优化
  • 【优化】 提升 SDK 整体稳定性及兼容性

v4.2.8.3 (2026-07-28)​

  • 【优化】 提升 SDK 整体稳定性及兼容性

v4.2.0.1 (2026-01-01)​

  • 稳定性提升,性能优化
  • 修复已知问题

v4.1.2.5 (2025-12-05)​

  • 稳定性提升
  • 修复已知问题

v4.1.2.0 (2025-12-01)​

  • 稳定性优化
  • 修复已知问题

v4.1.0.14 (2025-11-11)​

  • 优化 SDK 体积与启动性能
  • 修复已知问题,提升整体稳定性

v4.1.0.13 (2025-11-07)​

  • 新增 allowIDFAAccess 配置项,默认为 YES
  • 优化广告加载性能
  • 修复已知问题

v4.1.0.11 (2025-10-29)​

  • 首个正式发布版本
  • 支持激励视频、插屏、开屏、Banner、信息流广告
  • 支持自定义 CTA 拦截器
  • 支持自定义信息提供者

激励视频奖励发放说明​

奖励发放条件​

一般视频总时长为 10~60s,30s 以上的视频播放到 30s 时会显示"跳过"按钮。低于30s的激励视频观看达到 90% 即会回调奖励验证接口,高于 30s 激励视频观看到第 27s 的时候即会回调奖励验证接口。

奖励发放主要流程​

  • **客户端回调的优势:**对接简单、高效,通过接口回调结果在客户端完成奖励是否发放即可。
  • **服务端回调的优势:**开发者可在服务端进行二次校验,保证广告有效性后做出奖励发放,反作弊能力强。

奖励验证服务端回调 (S2S 验证)​

提示

S2S 验证需要开发者提供奖励发放的回调 URL,Security Key 由 Dirichlet Ad 服务端生成并提供给开发者,现阶段通过 KA 单点对接提供

  • 服务器回调模式不是必须的,只是增加了一次第三方服务器的验证判断。具体的奖励发放由客户端完成。
  • 服务端回调逻辑:Dirichlet Ad 根据"奖励发放条件",先通过 "Dirichlet Ad 服务端"访问"开发者媒体服务端"向开发者确认是否进行奖励发放,再依据"开发者服务端"返回的 true/false,在客户端给出是/否发放奖励的回调。
  • Dirichlet Ad 服务端只是透传验证请求,不会在中间过程添加校验逻辑。为了保障开发者利益和用户体验,开发者可以在验证环节增加自己的校验逻辑。

SDK 奖励发放回调接口​

接口说明

/// 激励视频奖励验证回调
/// @param ad 激励视频广告对象
/// @param verified 是否验证通过
/// @param amount 奖励数量
/// @param name 奖励名称
- (void)rewardedAd:(DRARewardedAd *)ad
didVerifyReward:(BOOL)verified
rewardAmount:(NSInteger)amount
rewardName:(NSString *)name;

透传参数

SDK 传给 Dirichlet Ad 服务端:

字段名称字段定义字段类型备注
user_id用户idstring调用SDK透传,应用对用户的唯一标识
extra其他信息string调用SDK传入并透传,如无需要则为空

奖励验证方式​

1. 同步验证

  1. 满足"奖励发放条件"
  2. 调用"奖励验证回调接口",并等待返回
  3. 调用 didVerifyReward 回调
    • verified = 回调接口返回的 isValid
    • 如果接口异常,verified = NO
  4. 开发者可根据 verified 决定是否发放奖励

2. 异步验证

  1. 满足"奖励发放条件"
  2. 调用"奖励验证回调接口",不等待返回
  3. 调用 didVerifyReward 回调
    • verified = YES(满足"奖励发放条件")
  4. 开发者可通过服务端查询结果,决定是否发放奖励

奖励验证回调接口​

接口请求方式

  • 接口请求方式: GET
  • 服务端会以 GET 方式请求第三方服务的回调链接,并拼接以下参数回传:
pid=%s&user_id=%s&trans_id=%s&extra=%s&sign=%s

请求参数定义

字段名称字段定义字段类型备注
pid广告位 IDstring
user_id用户 IDstring调用 SDK 透传,应用对用户的唯一标识
trans_id交易 IDstring完成观看的唯一交易 ID,唯一标识该次激励广告
extra其他信息string调用 SDK 传入并透传,如无需要则为空
sign签名string签名

签名生成方式

  • 获得 SecurityKey,在申请配置激励广告位页面,设置服务端验证回调接口时获取
  • 将 trans_id 和 SecurityKey 用 ':' 符号连接
  • 使用 sha256 生成签名,用小写 16 进制
sign = sha256(trans_id:SecurityKey)

返回值约定

  • 返回值格式: json
  • 返回示例:
{"isValid":true}

返回值定义

字段名称字段定义字段类型备注
isValid校验结果bool判定结果,是否发放奖励

SDK 错误码说明​

以下为 iOS SDK 5.3.0.1 中公开接口可返回的常见错误。请同时读取 NSError.domain、code 和 localizedDescription。同一个数字在不同接口或错误域中可能有不同含义,不能套用 Android 错误码表。

初始化与广告接口​

下表错误域为 com.dirichlet.ad,需结合调用场景判断。

调用场景错误码说明
初始化1001初始化配置为空
初始化1002初始化配置无效,或初始化组件不可用;以错误消息为准
广告加载1000SDK 未初始化
激励视频加载1001请求为空
Banner 加载1001已有加载请求正在进行
广告加载1002请求或广告位参数无效
广告加载1003SDK 配置不可用
广告加载1004加载期间广告对象已释放
开屏、插屏展示1005广告尚未就绪
开屏、插屏展示1006广告展示失败
竞胜通知1007、1009分别表示通知参数为空、广告处理对象不可用
竞败通知1008、1010分别表示通知参数为空、广告处理对象不可用
激励视频展示2001广告尚未就绪
信息流加载2001未返回可用广告数据
模板信息流渲染2001广告已失效
激励视频、开屏、插屏展示2002广告已失效,需要重新加载
模板信息流渲染2002广告视图创建失败
激励视频展示2003广告展示失败
广告加载2004广告响应无效
广告加载3000广告加载失败,具体原因见错误消息
广告加载3008广告无填充
广告展示4000广告展示失败
视频播放4001视频播放失败
广告加载8003请求数据序列化失败

其他可返回的错误域​

以下错误可由广告加载等公开接口返回。错误域不同,即使 code 相同也不能合并判断。

错误域错误码说明
com.dirichlet.ad.rewarded.core1广告运行环境不可用
com.dirichlet.ad.rewarded.core2广告加载组件不可用
com.dirichlet.ad.rewarded.core3广告加载组件状态无效
com.dirichlet.ad.feed.core、com.dirichlet.ad.feed.express.core1001已有信息流加载请求正在进行
同上1003SDK 配置不可用
同上1004广告对象已释放
同上2001信息流广告数据为空或无效
同上1007、1008分别表示竞胜、竞败通知参数为空

服务端错误码说明​

服务端业务错误通过加载失败回调返回,NSError.domain 为 com.dirichlet.ad,code 为 3000。可在 localizedDescription 中查看具体服务端码,例如 Server error code: 10008。下表用于解释错误消息中的服务端码,不用于直接匹配 error.code。

服务端错误码说明处理建议
10001请求缺少设备信息确认 SDK 已正确初始化;持续出现时保留错误信息联系技术支持
10002请求中的设备标识信息不完整保留错误信息联系技术支持;此错误不代表某个具体标识(如 OAID)为空
10003请求缺少媒体信息检查媒体初始化配置
10004请求缺少应用信息核对应用信息与媒体配置,持续出现时联系技术支持
10005请求缺少 SDK 信息检查 SDK 依赖是否完整、版本是否配套
10006请求缺少网络信息保留错误信息联系技术支持;此错误不代表设备未联网
10008广告位不存在或与媒体不匹配核对媒体 ID、广告位 ID 及所属关系
10011当前请求没有可用广告源检查广告位投放配置,持续出现时联系技术支持
10012应用包名无效核对应用包名及媒体配置
20002没有广告满足底价要求检查广告位底价是否合理
20004广告位请求频率达到限制降低请求频率,避免失败后立即循环请求
20005媒体请求频率达到限制检查应用整体请求频率,稍后重试
20009当前返回的广告未通过可用性检查稍后重试,持续出现时联系技术支持
20011当前请求受到频次限制避免短时间重复请求,稍后重试
20014当前请求暂无可返回的广告稍后重试;持续出现时提供请求信息联系技术支持

服务端返回 20014 时同样按 3000 处理,请结合错误消息区分原因。以上说明仅适用于 TapADN 自身广告请求。请求信息由 SDK 自动生成,开发者无需手动补齐上述请求字段。

错误处理​

// 在初始化、加载或广告代理的失败回调中记录 NSError。
NSLog(@"TapADN error: domain=%@, code=%ld, message=%@",
error.domain, (long)error.code, error.localizedDescription);

对于未列出的错误,请记录完整错误信息,并按对应接口的失败流程处理。联系技术支持时,提供 SDK 版本、广告类型、广告位 ID、调用场景及完整错误信息;若错误中带有请求标识,请一并提供。