# اتصال Unity — نسخه ۱
## مسیر کوتاه
۱. رسانه و جایگاه را در پنل بسازید و تأیید کنید. ۲. همین SDK را نصب کنید. ۳. شناسه UNT_ نمونه را با جایگاه همان فرمت جایگزین کنید.
اپ شما به سرور، دامنه اختصاصی، JWT یا کلید API نیاز ندارد. نشانی HTTPS مثال، سرور خود دیدنکس است. پس از تغییر دامنه پلتفرم، نشانی جدید را در همان یک تنظیم جایگزین کنید. شناسه بسته واقعی اپ باید با رسانه تأییدشده برابر باشد.
## نصب و پیشنیاز
ZIP را باز کنید؛ در Package Manager از Add package from disk، فایل package.json را انتخاب کنید. نمونه Samples~/DidnexQuickStart.cs را به Assets کپی و به یک GameObject اضافه کنید. در Scene یک Canvas همراه EventSystem بسازید و RectTransform ظرف تبلیغ را به bannerContainer بدهید. شناسههای placements را در Inspector تنظیم کنید.
Unity 2022.3 یا جدیدتر با UGUI؛ هدف Android/iOS. Editor برای تحویل تبلیغ زنده، WebGL و دسکتاپ پشتیبانی نمیشوند. ظرف درون صفحه حداقل ۱۰۰×۱۸۰ واحد منطقی داشته باشد.
```
using Didnex;
var ads=DidnexAds.CreateDirect("https://didnex.com");
var handle=await ads.ShowBannerAsync("UNT_BANNER",bannerContainer);
// Removal: handle?.Dispose();
// Owner shutdown: Destroy(ads.gameObject);
```
## Manifest و تنظیمات سیستمعامل
فایل `sdk/unity/Samples~/AndroidManifest.xml` کنار مثال است. قطعهها را با تنظیمات موجود ادغام کنید. مجوز اینترنت در Android باید در manifest اصلی نسخه Release هم باشد. تبلیغ پایه به مجوز مکان، شناسه تبلیغاتی، دسترسی حافظه یا اعلان نیاز ندارد.
```
```
برای Flutter/Unity در iOS، حداقل iOS 15 و PrivacyInfo.xcprivacy بسته را رعایت کنید. ATS را برای نشانی HTTPS باز نکنید. پوش پسزمینه تنها پس از رضایت و تنظیم سرویس سیستمعامل فعال میشود؛ Inbox به Firebase یا مجوز اعلان نیاز ندارد.
## فونت، ظاهر و کنترل سروری
ظاهر کارت در هر دو روش مستقیم و پراکسی از پاسخ همان تبلیغ خوانده میشود. مدیر در تنظیمات ← ظاهر تبلیغ و SDK، رنگ، زمینه، فونت، گردی کارت، جای نشان و پخش خودکار ویدیوی معمولی را تعیین میکند. ابتدا یکبار SDK و اپ را بهروزرسانی کنید؛ سپس تغییرات پشتیبانیشده در درخواست بعدی تبلیغ اعمال میشوند. فونت Noto Sans Arabic فارسی و لوگو از سرور خود دیدنکس کش میشوند؛ خطای این داراییهای اختیاری باعث noFill یا خطای تبلیغ نمیشود. Unity برای UGUI یک فونت کوچک فارسی همراه و شکلدهی حروف در مرز نمایش دارد. سرور کد اجرایی جدید به اپ نمیفرستد.
فونت حدود ۲۴۵ کیبیبایت است و پس از کش برای هر تبلیغ دوباره دریافت نمیشود؛ پاکشدن کش میتواند دریافت دوباره را لازم کند. پخش، لمس و تشخیص دیدپذیری روی دستگاه باقی میمانند. توقف دستی، پسزمینه و پایان ویدیو رعایت میشوند. نشان شبکه و دکمههای صدا، توقف و بستن، کلیک تبلیغدهنده ثبت نمیکنند. بدنه و دکمه مقصد امضاشده مشترک دارند. لمس بازی تعاملی به خود بازی میرسد. در وب مبدأ دیدنکس را در `font-src` سیاست CSP مجاز کنید.
## همه فرمتها
فرمت در پنل و روی جایگاه تعیین میشود؛ نوع متد را مطابق جدول انتخاب کنید. `playable` از مسیر تمامصفحه و `audio` از مسیر درون صفحه استفاده میکند. ویدیوی معمولی فقط هنگام فعالبودن اپ و حداقل ۵۰٪ دیدهشدن، خودکار و بیصداست؛ صوت و جایزه نیازمند انتخاب کاربرند. محدودیت مرورگر ممکن است پخش دستی را لازم کند.
| فرمت | شناسه قراردادی | روش نمایش |
|---|---|---|
| بنر | `banner` | درون صفحه |
| بنر تطبیقی | `adaptive_banner` | درون صفحه |
| همسان | `native` | درون صفحه |
| ویدیوی همسان | `native_video` | درون صفحه |
| ویدیوی درون محتوا | `video` | درون صفحه |
| بینابینی | `interstitial` | تمامصفحه |
| ویدیوی جایزهدار | `rewarded` | جایزهدار |
| بینابینی جایزهدار | `rewarded_interstitial` | جایزهدار |
| آغاز اپ | `app_open` | تمامصفحه |
| بازی تعاملی | `playable` | تمامصفحه |
| صوتی | `audio` | درون صفحه |
| کاروسلی | `carousel` | درون صفحه |
| نظرسنجی | `poll` | درون صفحه |
### بنر
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("banner") {unitId="UNT_BANNER"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### بنر تطبیقی
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("adaptive_banner") {unitId="UNT_ADAPTIVE_BANNER"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### همسان
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("native") {unitId="UNT_NATIVE"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### ویدیوی همسان
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("native_video") {unitId="UNT_NATIVE_VIDEO"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### ویدیوی درون محتوا
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("video") {unitId="UNT_VIDEO"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### بینابینی
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("interstitial") {unitId="UNT_INTERSTITIAL"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### ویدیوی جایزهدار
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("rewarded") {unitId="UNT_REWARDED"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### بینابینی جایزهدار
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("rewarded_interstitial") {unitId="UNT_REWARDED_INTERSTITIAL"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### آغاز اپ
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("app_open") {unitId="UNT_APP_OPEN"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### بازی تعاملی
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("playable") {unitId="UNT_PLAYABLE"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### صوتی
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("audio") {unitId="UNT_AUDIO"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### کاروسلی
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("carousel") {unitId="UNT_CAROUSEL"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### نظرسنجی
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("poll") {unitId="UNT_POLL"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · بنر
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("banner") {unitId="UNT_BANNER"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · بنر تطبیقی
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("adaptive_banner") {unitId="UNT_ADAPTIVE_BANNER"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · همسان
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("native") {unitId="UNT_NATIVE"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · ویدیوی همسان
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("native_video") {unitId="UNT_NATIVE_VIDEO"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · ویدیوی درون محتوا
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("video") {unitId="UNT_VIDEO"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · بینابینی
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("interstitial") {unitId="UNT_INTERSTITIAL"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · ویدیوی جایزهدار
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("rewarded") {unitId="UNT_REWARDED"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · بینابینی جایزهدار
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("rewarded_interstitial") {unitId="UNT_REWARDED_INTERSTITIAL"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · آغاز اپ
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("app_open") {unitId="UNT_APP_OPEN"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · بازی تعاملی
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("playable") {unitId="UNT_PLAYABLE"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · صوتی
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("audio") {unitId="UNT_AUDIO"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · کاروسلی
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("carousel") {unitId="UNT_CAROUSEL"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
### سرور اختیاری · نظرسنجی
برای این روش، پراکسی خودتان و callback نشست فعلی اپ را تکمیل کنید؛ تابع خالی نمونه اتصال واقعی ایجاد نمیکند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("poll") {unitId="UNT_POLL"}};
string diagnosticToken = String.IsNullOrEmpty("") ? null : "";
DidnexAds ads;DidnexAdHandle banner;bool busy;
// Replace with the current authenticated session from YOUR app.
string CurrentAppSession(){return "";}
void Awake(){try{ads=DidnexAds.Create("https://YOUR-BACKEND.example/ads",CurrentAppSession,adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId,diagnosticToken:diagnosticToken);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId,diagnosticToken:diagnosticToken);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer,diagnosticToken:diagnosticToken);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
## نمونه کامل قابل استفاده
فایل `sdk/unity/Samples~/DidnexQuickStart.cs` در همین بسته قرار دارد. نام package/namespace مثال متعلق به اپ نمونه است؛ آن را با پروژه میزبان هماهنگ کنید. شناسههای UNT_ جایگزیناند و برای دریافت تبلیغ واقعی باید عوض شوند.
```
using System;
using UnityEngine;
namespace Didnex.Samples {
public sealed class DidnexQuickStart : MonoBehaviour {
public RectTransform bannerContainer;
public string adOrigin="https://didnex.com";
[Serializable] public class Placement { public string format,unitId; public Placement(string f){format=f;unitId="UNT_"+f.ToUpperInvariant();} }
public Placement[] placements={new Placement("banner"),new Placement("adaptive_banner"),new Placement("native"),new Placement("native_video"),new Placement("video"),new Placement("interstitial"),new Placement("rewarded"),new Placement("rewarded_interstitial"),new Placement("app_open"),new Placement("playable"),new Placement("audio"),new Placement("carousel"),new Placement("poll")};
DidnexAds ads;DidnexAdHandle banner;bool busy;
void Awake(){try{ads=DidnexAds.CreateDirect(adOrigin);ads.OnEvent+=(kind,code)=>{Debug.Log("Didnex "+kind);if(kind=="noFill"||kind=="error")SetSlotHeight(0);};}catch(Exception){Debug.LogWarning("Didnex configuration unavailable");}}
// Connect UI buttons to ShowFormat, passing the format string from the list.
public async void ShowFormat(string format){if(ads==null||busy)return;var p=Array.Find(placements,x=>x.format==format);if(p==null)return;busy=true;
try{if(format=="rewarded"||format=="rewarded_interstitial"){var receipt=await ads.ShowRewardedAsync(p.unitId);if(receipt!=null){/* Already credited. Refresh the selected hosted wallet. */}}
else if(format=="interstitial"||format=="app_open"||format=="playable"){await ads.ShowInterstitialAsync(p.unitId);}
else{SetSlotHeight(300);banner?.Dispose();banner=await ads.ShowBannerAsync(p.unitId,bannerContainer);if(this==null)banner?.Dispose();}
}catch(Exception){Debug.LogWarning("Didnex ad unavailable");}finally{busy=false;}
}
void SetSlotHeight(float height){if(bannerContainer==null)return;var layout=bannerContainer.GetComponent();if(layout!=null)layout.preferredHeight=height;else bannerContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,height);}
void OnApplicationPause(bool paused){banner?.SetActive(!paused);}
void OnDestroy(){banner?.Dispose();if(ads!=null)Destroy(ads.gameObject);}
}
}
```
## اعتبارسنجی اختیاری اپ
برای Flutter فقط در صورت استفاده از Play Integrity، در android/gradle.properties مقدار `didnex.enablePlayIntegrity=true` و در client گزینه enableIntegrity را فعال کنید. اتصال پایه بدون این وابستگی کار میکند. برای Android بومی، DidnexIntegrity.kt و وابستگی Google Play را اضافه کنید؛ provider باید با سیاست پنل هماهنگ باشد. این قابلیت برای توزیع خارج Google Play الزام عمومی نیست.
## خطا، چرخه عمر و جایزه
نداشتن تبلیغ، قطع اینترنت یا خطای سرور باید فقط فضای تبلیغ را جمع کند؛ شروع اپ را به تبلیغ وابسته نکنید. بیوقفه retry نکنید؛ درخواست بعدی را به فرصت طبیعی بعدی اپ موکول کنید. برای تمامصفحه یک نمونه تازه، صفحه قابل نمایش و اقدام مناسب کاربر لازم است؛ از resume برای نمایش خودکار استفاده نکنید.
تست اتصال را با diagnosticToken از پنل انجام دهید. رسانهٔ تست متناسب با فرمت بارگذاری میشود؛ هزینه، درآمد یا جایزه ندارد. بارگذاری گزارششده تأیید کامپایل یا پخش روی همهٔ دستگاهها نیست. برای آزمون رسانه و درآمد، کمپین و رسانه تأییدشده و بودجه واقعی لازم است. هیچ جایزهای با صرف loaded، click یا نمایش ناقص ایجاد نکنید. فقط رسید `verified=true` و `applied=true` از سمت سرور معتبر است؛ SDK جایزه را پیشتر در کیف نصب ثبت کرده، دوباره اعتبار ندهید. برای مصرف، externalId را پیش از ارسال ذخیره کنید و در retry عوض نکنید.
## کیف، پوش و سرور اختیاری
- کیف نصب و محدودیت بازیابی: https://didnex.com/docs/publisher/wallet
- پوش اختصاصی همین پلتفرم، Manifest، FCM/APNs و نمونه پسزمینه: https://didnex.com/docs/publisher/push-unity
- روش سروری برای اتصال جایزه به حساب موجود اپ: https://didnex.com/docs/publisher/server
همه ۱۳ فرمت در اتصال مستقیم و پراکسی اختیاری موجودند. پراکسی فقط روی سرور خودتان کلید خصوصی md_ را نگه میدارد. هیچ JWT یا کلید را در فایل نمونه یا پنل کپی کد ثابت نکنید. برای APIهای کیف، رضایت و پوش، شکست واقعی را کنترل کنید؛ موجودی یا موفقیت جعلی نشان ندهید.
## تشخیص خطا
| وضعیت | بررسی |
|---|---|
| noFill | رسانه و جایگاه فعال، کمپین سازگار، بودجه، زمان و فیلتر دستگاه/لوکیشن |
| package mismatch | شناسه واقعی خروجی اپ و رسانه ثبتشده؛ debug flavor ممکن است پسوند داشته باشد |
| 403 در وب | Origin دقیق سایت تأییدشده و HTTPS |
| شبکه/مهلت | دسترسی دامنه دیدنکس از دستگاه، INTERNET نسخه Release و تنظیم TLS |
| تصویر تست فقط | diagnosticToken را پس از پایان تست بردارید؛ کارت تست کمپین زنده نیست |
| جایزه ثبت نشد | رضایت، تماشای کامل، ترتیب رویدادها و رسید سرور؛ موجودی را محلی تغییر ندهید |
| پوش دیده نشد | ابتدا Inbox را بررسی کنید؛ سپس رضایت، توکن تازه، تنظیم provider و مجوز سیستمعامل |
## وضعیت آزمون
آزمونهای قرارداد سرور، وب و بستهبندی در مخزن اجرا میشوند. وضعیت کامپایل منطبق با هش منبع در SDK Lab و releases.json ثبت میشود؛ اجرای دستگاه فقط با رسید مستقل device_playback قابل تأیید است.
قبل از انتشار اپ: ساخت Release، اینترنت قطع، DNS نامعتبر، پاسخ ۵۰۰/JSON خراب، رسانه خراب، خروج صفحه حین درخواست، pause/resume و تکرار claim را بررسی کنید. فایلهای tool/verify یا scripts/sdk-build.mjs مسیر تکرار آزمون را مشخص میکنند. هیچ انتشار pub.dev/Maven عمومی در این بسته ادعا نمیشود.
## تبلیغات و پوش در یک بسته
کنترلر پوش از همان کلاینت تبلیغات ساخته میشود؛ دانلود یا نصب بسته دوم لازم نیست. راهنمای `PUSH.md` داخل همین بسته شامل نمونه اتصال مشترک، رضایت، دریافت، گزارش و چرخه عمر است. روشهای قدیمی Initialize همچنان سازگارند؛ فایلهای SDK را از دو ZIP همزمان به پروژه کپی نکنید.
## شناسه جایگاه چیست و از کجا بگیرم؟
پوش در دیدنکس از **شناسه عمومی یکی از جایگاههای فعال همان رسانه** برای پیدا کردن اپ یا سایت شما استفاده میکند. پیشوند واقعی این شناسه `UNT_` است. این مقدار نام اپ، شناسه بسته، شناسه رسانه با پیشوند `AST_`، توکن FCM یا کلید API نیست و محرمانه نیست.
در پنل ناشر، «جایگاههای تبلیغ» را باز کنید؛ شناسه زیر نام جایگاه دیده میشود. همان شناسه کامل را کپی کنید. راه سادهتر: در «پوش ← اتصال رسانهها»، برای رسانه خود «کد پوش» را بزنید و پلتفرم را انتخاب کنید؛ کد با شناسه واقعی شما ساخته میشود و نیازی به حدس یا جایگزینی دستی ندارد.
در مثال عمومی زیر، `placementId` یا `PlacementId` یا `PLACEMENT_ID` متغیری برای نگهداری همین شناسه است. متن `PASTE_YOUR_PLACEMENT_ID_HERE` فقط محل جایگزینی است و شناسه قابل استفاده نیست. آن را با شناسه کامل جایگاه خودتان که با `UNT_` شروع میشود عوض کنید. یک جایگاه فعال کافی است؛ جایگاه مخصوص پوش و نمایش تبلیغ برای عضوکردن مخاطب لازم نیست. رسانه نیز باید فعال و تأییدشده باشد و پوش آن در پنل فعال شده باشد.
| مقدار | محل دریافت / کاربرد |
| --- | --- |
| شناسه جایگاه (`UNT_…`) | پنل ناشر ← جایگاههای تبلیغ؛ ورودی ایجاد کنترلر پوش |
| شناسه بسته | تنظیمات پروژه اپ؛ باید با رسانه اپ ثبتشده یکسان باشد |
| دامنه دیدنکس | نشانی همین سرویس؛ سرور اختصاصی ناشر لازم نیست |
| کلید خصوصی API | داخل اپ یا مرورگر قرار نمیگیرد |
اگر `inactive_inventory` دیدید، فعال و تأییدبودن رسانه و فعالبودن جایگاه همان رسانه را بررسی کنید. کپیکردن شناسه از یک حساب یا رسانه دیگر اتصال را درست نمیکند.
## اتصال ساده با شناسه روشن — ۸.۱۷
یک کلاینت را در طول عمر اپ نگه دارید و همان را برای تبلیغ و پوش به کار ببرید. این فراخوانی فقط تنظیم محلی است؛ موفقیت اتصال شبکه با دریافت تبلیغ یا عضویت موفق مشخص میشود. init خودکار اجازه اعلان نمیگیرد و هیچ پیام واقعی ارسال نمیکند. برای تغییر دامنه، origin همان یک تنظیم را تغییر دهید. شناسه عمومی جایگاه (`UNT_…`) باید متعلق به رسانه فعال و تأییدشده خودتان باشد؛ کلید خصوصی وارد اپ نکنید.
```
const string PlacementId = "PASTE_YOUR_PLACEMENT_ID_HERE";
var client = Didnex.DidnexAds.Initialize("https://didnex.com");
var ad = await client.ShowBannerAsync(PlacementId, bannerContainer);
var push = client.CreatePush(PlacementId);
// OnMessage returns true only after actual display. Permission is separate.
```
این قطعه، الگوی راهاندازی است؛ مثال کامل همه فرمتها، مدیریت خطا و چرخه عمر در ادامه همین راهنما و پوشه Examples بسته قرار دارد. در Flutter کد بالا داخل `Future main() async` قرار میگیرد؛ `MyApp` ویجت واقعی اپ شماست. در B4A فایل جدید `Didnex.bas` هم بهعنوان Class اضافه شود. برای دامنه اختصاصی B4A، initializer اصلی `DidnexAds.Initialize(Me,"Ads",origin,Application.PackageName)` همچنان معتبر است. روش اختیاری پراکسی همان قرارداد نمایش را دارد و برای اتصال مستقیم هیچ سرور ناشری لازم نیست.
### قرارداد اندازه
`slot.version=1` و `slot.profile` از جایگاه میآیند. نسبت یا ارتفاع فایلِ دانلودشده اندازه بیرونی را تغییر نمیدهد. تصویر و ویدیو با contain داخل کادر قرار میگیرند؛ برای `noFill` و خطا کادر جمع میشود. پس از یکبار بهروزرسانی SDK، تعویض فایل هماندازه یا شروع پخش ویدیو باعث تغییر چیدمان نمیشود. برای پروفایل غیراستانداردِ پیشفرض، متادیتای جایگاه و اندازه میزبان را مطابق همان پروفایل تنظیم کنید؛ در Unity/Godot مستطیل میزبان تحت کنترل اپ است.
| پروفایل | نسبت رسانه / اندازه مرجع | نوار ثابت زیر رسانه |
|---|---|---|
| بنر کوچک / بزرگ | ۳۲۰×۵۰ / ۳۲۰×۱۰۰ | ندارد |
| بنر مستطیل / عریض | ۳۰۰×۲۵۰ / ۷۲۸×۹۰ | ندارد |
| تطبیقی | نسبت ۳۲۰×۵۰ با عرض میزبان | ندارد |
| همسان تصویری | ۱۶:۹ یا مربع | ۸۴ پیکسل منطقی |
| همسان ویدیویی / کاروسل | ۱۶:۹ | ۸۴ پیکسل منطقی |
| ویدیوی درون محتوا | ۱۶:۹ | ندارد |
| صوتی | کادر ۹۶ پیکسل منطقی | ندارد |
| نظرسنجی | کادر مرجع ۳۲۰×۳۰۰ | ۸۴ پیکسل منطقی |
| بینابینی، جایزه، آغاز اپ و بازی | میزبان تمامصفحه با حاشیه امن | قالب ثابت میزبان |
اینها پروفایل محصول دیدنکساند؛ ادعای گواهی IAB یا ابعاد پیکسلی واحد جهانی برای تمام فرمتها ندارند. فایل میتواند چند برابر اندازه مرجع باشد. تصویر کوچکِ خارج از حداقل یا نسبت نامطابق پیش از ثبت کمپین رد میشود؛ حداقل و نسبت دقیق در فرم کمپین و `GET /api/display-profiles` قابل دریافتاند. برای ویدیوی افقی حداقل ۳۲۰×۱۸۰ و پیشنهاد ۶۴۰×۳۶۰ است. فایلهای کمپین قدیمی بدون پروفایل با حفظ نسبت داخل کادر ثابت قرار میگیرند. برای اعمال renderer جدید در SDK نصبشده، اپ باید یک بار بهروزرسانی شود؛ تغییر سرور بهتنهایی کد قدیمی را عوض نمیکند.
### حدود آزمون این نسخه
آزمون قرارداد سرور، رسیدها، noFill، فایل خراب، قطع ارتباط و یکپارچگی بستهها در مخزن وجود دارد. ساخت بومی با هش همین سورس فقط وقتی در `releases.json` مقدار `nativeBuild=passed` دارد تأیید شده است. نبود چنین رسیدی یعنی کامپایل بومی/پخش روی دستگاه تأیید نشده؛ موفقیت تست جاوااسکریپت جای آن را نمیگیرد. AARهای قدیمی داخل پوشه سازگاری را معادل ساخت جدید تلقی نکنید؛ برای Android و Godot از پروژه سورس و gradlew استفاده کنید.