YandexSDK.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. #if UNITY_EDITOR
  2. using Eiko.YaSDK.Editor;
  3. #endif
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Runtime.InteropServices;
  8. using Eiko.YaSDK.Data;
  9. using UnityEngine;
  10. using UnityEngine.Audio;
  11. namespace Eiko.YaSDK
  12. {
  13. public class YandexSDK : MonoBehaviour {
  14. public AudioSource audio;
  15. #if UNITY_EDITOR
  16. [HideInInspector]
  17. public CanvasAddEditor editorCanvas;
  18. #endif
  19. public const int ReloadAdsSeconds = 30;
  20. public bool AdsEnabled { get; private set; }
  21. public static YandexSDK instance;
  22. [DllImport("__Internal")]
  23. private static extern void GetUserData();
  24. [DllImport("__Internal")]
  25. private static extern void ShowFullscreenAd();
  26. [DllImport("__Internal")]
  27. private static extern void SetData(string key,string value);
  28. [DllImport("__Internal")]
  29. private static extern void SetScore(string key, int value);
  30. [DllImport("__Internal")]
  31. private static extern void InitPlayerData();
  32. /// <summary>
  33. /// Returns an int value which is sent to index.html
  34. /// </summary>
  35. /// <param name="placement"></param>
  36. /// <returns></returns>
  37. [DllImport("__Internal")]
  38. private static extern int ShowRewardedAd(string placement);
  39. //[DllImport("__Internal")]
  40. //private static extern void GerReward();
  41. [DllImport("__Internal")]
  42. private static extern void AuthenticateUser();
  43. [DllImport("__Internal")]
  44. private static extern void InitPurchases();
  45. [DllImport("__Internal")]
  46. private static extern void Purchase(string id);
  47. [DllImport("__Internal")]
  48. private static extern string GetLang();
  49. [DllImport("__Internal")]
  50. private static extern void Review();
  51. [DllImport("__Internal")]
  52. private static extern void GetPurchases();
  53. public event Action addsOnReloaded;
  54. public event Action onUserDataReceived;
  55. public event Action onInterstitialShown;
  56. public event Action<string> onInterstitialFailed;
  57. /// <summary>
  58. /// Пользователь открыл рекламу
  59. /// </summary>
  60. public event Action<int> onRewardedAdOpened;
  61. /// <summary>
  62. /// Пользователь должен получить награду за просмотр рекламы
  63. /// </summary>
  64. public event Action<string> onRewardedAdReward;
  65. /// <summary>
  66. /// Пользователь закрыл рекламу
  67. /// </summary>
  68. public event Action<int> onRewardedAdClosed;
  69. /// <summary>
  70. /// Вызов/просмотр рекламы повлёк за собой ошибку
  71. /// </summary>
  72. public event Action<string> onRewardedAdError;
  73. /// <summary>
  74. /// Покупка успешно совершена
  75. /// </summary>
  76. public event Action<Purchase> onPurchaseSuccess;
  77. /// <summary>
  78. /// Покупка не удалась: в консоли разработчика не добавлен товар с таким id,
  79. /// пользователь не авторизовался, передумал и закрыл окно оплаты,
  80. /// истекло отведенное на покупку время, не хватило денег и т. д.
  81. /// </summary>
  82. public event Action<string> onPurchaseFailed;
  83. public event Action onClose;
  84. public event Action onPurchaseInitialize;
  85. public event Action<string> onPurchaseInitializeFailed;
  86. public Queue<int> rewardedAdPlacementsAsInt = new Queue<int>();
  87. public Queue<string> rewardedAdsPlacements = new Queue<string>();
  88. private Action<ReviewCallback> actionReview;
  89. public bool addsAvailable;
  90. private bool IsReviewed = false;
  91. public UserData user;
  92. public string adsPurchize="AddOff";
  93. public string Lang = "ru";
  94. private void Awake() {
  95. if (instance == null) {
  96. instance = this;
  97. DontDestroyOnLoad(gameObject);
  98. #if !UNITY_EDITOR && UNITY_WEBGL
  99. Lang = GetLang();
  100. #endif
  101. }
  102. else {
  103. Destroy(gameObject);
  104. }
  105. StartCoroutine(WaitAddReload());
  106. #if UNITY_EDITOR
  107. editorCanvas = Instantiate(editorCanvas);
  108. #endif
  109. onPurchaseSuccess += PurchizeCallbackAds;
  110. }
  111. /// <summary>
  112. /// Call this to ask user to authenticate
  113. /// </summary>
  114. public void Authenticate() {
  115. #if !UNITY_EDITOR && UNITY_WEBGL
  116. AuthenticateUser();
  117. #endif
  118. }
  119. /// <summary>
  120. /// Call this to show interstitial ad. Don't call frequently. There is a 3 minute delay after each show.
  121. /// </summary>
  122. public void ShowInterstitial() {
  123. if(addsAvailable&& PlayerPrefs.GetInt("AdsOff")==0)
  124. {
  125. AudioListener.pause = true;
  126. AudioListener.volume = 0;
  127. audio.volume = 0;
  128. StartCoroutine(WaitAddReload());
  129. #if !UNITY_EDITOR && UNITY_WEBGL
  130. ShowFullscreenAd();
  131. #else
  132. editorCanvas.OpenFullScreen();
  133. #endif
  134. Time.timeScale = 0;
  135. }
  136. else
  137. {
  138. Debug.LogWarning("Ad not ready!");
  139. }
  140. }
  141. /// <summary>
  142. /// Call this to show rewarded ad
  143. /// </summary>
  144. /// <param name="placement"></param>
  145. public void ShowRewarded(string placement) {
  146. #if !UNITY_EDITOR && UNITY_WEBGL
  147. int placemantId = ShowRewardedAd(placement);
  148. #else
  149. int placemantId = 0;
  150. #endif
  151. rewardedAdPlacementsAsInt.Enqueue(placemantId);
  152. rewardedAdsPlacements.Enqueue(placement);
  153. Time.timeScale = 0;
  154. AudioListener.pause = true;
  155. AudioListener.volume = 0;
  156. audio.volume=0;
  157. #if UNITY_EDITOR
  158. editorCanvas.OpenReward(placemantId);
  159. #endif
  160. }
  161. public void AdsOff()
  162. {
  163. PlayerPrefs.SetInt("AdsOff", 1);
  164. AdsEnabled = false;
  165. StopAllCoroutines();
  166. Debug.Log("AdsOff");
  167. addsAvailable = false;
  168. }
  169. public void ProcessPurchizeAdsDisabled(Action action= null)
  170. {
  171. this.action = action;
  172. ProcessPurchase(adsPurchize);
  173. }
  174. private Action action;
  175. private void PurchizeCallbackAds(Purchase purchase)
  176. {
  177. if (purchase.productID == adsPurchize)
  178. {
  179. AdsOff();
  180. onPurchaseSuccess -= PurchizeCallbackAds;
  181. action?.Invoke();
  182. }
  183. }
  184. /// <summary>
  185. /// Call this to receive user data
  186. /// </summary>
  187. public void RequestUserData() {
  188. #if !UNITY_EDITOR && UNITY_WEBGL
  189. GetUserData();
  190. #endif
  191. }
  192. public void InitializePurchases() {
  193. #if !UNITY_EDITOR && UNITY_WEBGL
  194. InitPurchases();
  195. #endif
  196. }
  197. public void ProcessPurchase(string id) {
  198. #if !UNITY_EDITOR && UNITY_WEBGL
  199. Purchase(id);
  200. #else
  201. OnPurchaseSuccess(id);
  202. #endif
  203. }
  204. public void StoreUserData(string data) {
  205. user = JsonUtility.FromJson<UserData>(data);
  206. onUserDataReceived?.Invoke();
  207. }
  208. /// <summary>
  209. /// Callback from index.html
  210. /// </summary>
  211. public void OnInterstitialShown() {
  212. Time.timeScale = 1;
  213. AudioListener.pause = false;
  214. AudioListener.volume = 1;
  215. audio.volume = 1;
  216. onInterstitialShown?.Invoke();
  217. }
  218. /// <summary>
  219. /// Callback from index.html
  220. /// </summary>
  221. /// <param name="error"></param>
  222. public void OnInterstitialError(string error) {
  223. Time.timeScale = 1;
  224. AudioListener.pause = false;
  225. AudioListener.volume = 1;
  226. onInterstitialFailed?.Invoke(error);
  227. }
  228. /// <summary>
  229. /// Callback from index.html
  230. /// </summary>
  231. /// <param name="placement"></param>
  232. public void OnRewardedOpen(int placement) {
  233. onRewardedAdOpened?.Invoke(placement);
  234. }
  235. /// <summary>
  236. /// Callback from index.html
  237. /// </summary>
  238. /// <param name="placement"></param>
  239. public void OnRewarded(int placement) {
  240. Time.timeScale = 1;
  241. if (placement == rewardedAdPlacementsAsInt.Dequeue()) {
  242. onRewardedAdReward?.Invoke(rewardedAdsPlacements.Dequeue());
  243. }
  244. }
  245. /// <summary>
  246. /// Callback from index.html
  247. /// </summary>
  248. /// <param name="placement"></param>
  249. public void OnRewardedClose(int placement) {
  250. AudioListener.pause = false;
  251. AudioListener.volume = 1;
  252. audio.volume = 1;
  253. Time.timeScale = 1;
  254. onRewardedAdClosed?.Invoke(placement);
  255. }
  256. /// <summary>
  257. /// Callback from index.html
  258. /// </summary>
  259. /// <param name="placement"></param>
  260. public void OnRewardedError(string placement) {
  261. Time.timeScale = 1;
  262. AudioListener.pause = false;
  263. AudioListener.volume = 1;
  264. audio.volume = 1;
  265. onRewardedAdError?.Invoke(placement);
  266. rewardedAdsPlacements.Clear();
  267. rewardedAdPlacementsAsInt.Clear();
  268. }
  269. public void OnPurchaseSuccess(string json)
  270. {
  271. var purchase = JsonUtility.FromJson<Purchase>(json);
  272. onPurchaseSuccess?.Invoke(purchase);
  273. }
  274. /// <summary>
  275. /// Callback from index.html
  276. /// </summary>
  277. /// <param name="error"></param>
  278. public void OnPurchaseFailed(string error) {
  279. onPurchaseFailed?.Invoke(error);
  280. }
  281. /// <summary>
  282. /// Browser tab has been closed
  283. /// </summary>
  284. /// <param name="error"></param>
  285. public void OnClose() {
  286. onClose?.Invoke();
  287. }
  288. public event Action<GetPurchasesCallback> GettedPurchase;
  289. public void TryGetPurchases()
  290. {
  291. GetPurchases();
  292. }
  293. public IEnumerator WaitAddReload()
  294. {
  295. addsAvailable = false;
  296. yield return new WaitForSecondsRealtime(ReloadAdsSeconds);
  297. addsAvailable = true;
  298. addsOnReloaded?.Invoke();
  299. }
  300. public void ShowReview(Action<ReviewCallback> action = null)
  301. {
  302. actionReview = action;
  303. if (IsReviewed)
  304. {
  305. OnReview(JsonUtility.ToJson(
  306. new ReviewCallback()
  307. {
  308. CanReview = false,
  309. FeedbackSent = false,
  310. Reason = IsReviewed ? "GAME_RATED" : "Success"
  311. }));
  312. return;
  313. }
  314. #if !UNITY_EDITOR && UNITY_WEBGL
  315. Review();
  316. #else
  317. editorCanvas.ShowReview();
  318. #endif
  319. }
  320. public void OnReview(string callback)
  321. {
  322. ReviewCallback review = JsonUtility.FromJson<ReviewCallback>(callback);
  323. if(review.FeedbackSent)
  324. {
  325. IsReviewed = true;
  326. }
  327. actionReview?.Invoke(review);
  328. }
  329. public event Action<GetDataCallback> onDataRecived;
  330. public event Action noAutorized;
  331. public void OnGetData(string json)
  332. {
  333. GetDataCallback callback;
  334. if (!string.IsNullOrEmpty(json))
  335. {
  336. callback = JsonUtility.FromJson<GetDataCallback>(json);
  337. if(callback.data==null)
  338. {
  339. callback.data = new KeyValuePairStringCallback[0];
  340. }
  341. if(callback.score == null)
  342. {
  343. callback.score = new KeyValuePairIntCallback[0];
  344. }
  345. }
  346. else
  347. {
  348. callback = new GetDataCallback();
  349. callback.data = new KeyValuePairStringCallback[0];
  350. callback.score = new KeyValuePairIntCallback[0];
  351. }
  352. onDataRecived?.Invoke(callback);
  353. }
  354. public void NoAutorized()
  355. {
  356. noAutorized?.Invoke();
  357. }
  358. public void SetPlayerData(string key, string value)
  359. {
  360. #if !UNITY_EDITOR
  361. SetData(key, value);
  362. #endif
  363. }
  364. public void SetPlayerScore(string key, int value)
  365. {
  366. #if !UNITY_EDITOR
  367. SetScore(key, value);
  368. #endif
  369. }
  370. public void InitData()
  371. {
  372. #if !UNITY_EDITOR
  373. InitPlayerData();
  374. #else
  375. StartCoroutine(InitDataEmit());
  376. #endif
  377. }
  378. #if UNITY_EDITOR
  379. private IEnumerator InitDataEmit()
  380. {
  381. yield return new WaitForSeconds(1);
  382. NoAutorized();
  383. }
  384. #endif
  385. public void OnPurchaseInitialize()
  386. {
  387. onPurchaseInitialize?.Invoke();
  388. }
  389. [ContextMenu("Test")]
  390. public void Test()
  391. {
  392. string a = "{\"purchases\":[{\"productID\":\"BuyAll\",\"purchaseTime\":0,\"purchaseToken\":\"957ff7fa-938a-4c14-9454-d8a4e990347a\"},{\"productID\":\"Skin11Unlocked\",\"purchaseTime\":0,\"purchaseToken\":\"111ab5c1-33ba-4835-92f3-acb7135ead2f\"},{\"productID\":\"BuyAll\",\"purchaseTime\":0,\"purchaseToken\":\"4fe915c5-59b9-43ef-9993-e96488c3fbd0\"},{\"productID\":\"Skin12Unlocked\",\"purchaseTime\":0,\"purchaseToken\":\"bf1cd480-cd97-44cb-9938-5f81db24c0e6\"},{\"productID\":\"AddOff\",\"purchaseTime\":0,\"purchaseToken\":\"044f9005-9a8e-4a16-9256-eaa513468d1f\"},{\"productID\":\"BuyAll\",\"purchaseTime\":0,\"purchaseToken\":\"a140dc49-2d57-403f-9352-7be76ba039e2\"},{\"productID\":\"AddOff\",\"purchaseTime\":0,\"purchaseToken\":\"a6894793-fc17-43c8-a03e-fb2afd1369e7\"}]}";
  393. var b = JsonUtility.FromJson<GetPurchasesCallback>(a);
  394. foreach (var item in b.purchases)
  395. {
  396. Debug.Log(item.productID);
  397. }
  398. }
  399. public void OnPurchaseInitializeFailed(string error)
  400. {
  401. onPurchaseInitializeFailed?.Invoke(error);
  402. }
  403. public event Action onGetPurchaseFailed;
  404. public void OnGetPurchaseFailed()
  405. {
  406. onGetPurchaseFailed?.Invoke();
  407. }
  408. }
  409. [Serializable]
  410. public class GetDataCallback
  411. {
  412. public KeyValuePairStringCallback[] data;
  413. public KeyValuePairIntCallback[] score;
  414. }
  415. [Serializable]
  416. public class KeyValuePairStringCallback
  417. {
  418. public string key;
  419. public string value;
  420. }
  421. [Serializable]
  422. public class KeyValuePairIntCallback
  423. {
  424. public string key;
  425. public int value;
  426. }
  427. public struct ReviewCallback
  428. {
  429. public bool CanReview;
  430. public string Reason;
  431. public bool FeedbackSent;
  432. }
  433. public struct UserData {
  434. public string id;
  435. public string name;
  436. public string avatarUrlSmall;
  437. public string avatarUrlMedium;
  438. public string avatarUrlLarge;
  439. }
  440. [Serializable]
  441. public class GetPurchasesCallback
  442. {
  443. public Purchase[] purchases;
  444. public string signature;
  445. }
  446. [Serializable]
  447. public class Purchase
  448. {
  449. public string productID;
  450. public string purchaseToken;
  451. public string developerPayload;
  452. public string signature;
  453. }
  454. }