InAppPurchasesSystemComponent.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <time.h>
  9. #include <AzCore/RTTI/BehaviorContext.h>
  10. #include <AzCore/Serialization/SerializeContext.h>
  11. #include <AzCore/Serialization/EditContext.h>
  12. #include <AzCore/IO/FileIO.h>
  13. #include <AzCore/Outcome/Outcome.h>
  14. #include <AzCore/JSON/document.h>
  15. #include <AzCore/JSON/error/en.h>
  16. #include "InAppPurchases/InAppPurchasesResponseBus.h"
  17. #include "InAppPurchasesSystemComponent.h"
  18. namespace InAppPurchases
  19. {
  20. void SystemComponent::Init()
  21. {
  22. }
  23. void SystemComponent::Activate()
  24. {
  25. m_productInfoIndex = 0;
  26. m_purchasedProductInfoIndex = 0;
  27. InAppPurchasesRequestBus::Handler::BusConnect();
  28. InAppPurchasesResponseAccessorBus::Handler::BusConnect();
  29. }
  30. void SystemComponent::Deactivate()
  31. {
  32. // The instance is created on the first call to GetInstance()
  33. InAppPurchasesInterface::DestroyInstance();
  34. InAppPurchasesRequestBus::Handler::BusDisconnect();
  35. InAppPurchasesResponseAccessorBus::Handler::BusDisconnect();
  36. }
  37. void SystemComponent::Reflect(AZ::ReflectContext* context)
  38. {
  39. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  40. {
  41. serialize->Class<SystemComponent, AZ::Component>()
  42. ->Version(0)
  43. ;
  44. if (AZ::EditContext* ec = serialize->GetEditContext())
  45. {
  46. ec->Class<SystemComponent>("InAppPurchases", "Adds support for in app purchases on iOS and Android")
  47. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  48. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  49. ;
  50. }
  51. }
  52. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  53. {
  54. behaviorContext->EBus<InAppPurchasesRequestBus>("InAppPurchasesRequestBus")
  55. ->Event("Initialize", &InAppPurchasesRequestBus::Events::Initialize)
  56. ->Event("QueryProductInfo", &InAppPurchasesRequestBus::Events::QueryProductInfo)
  57. ->Event("QueryProductInfoFromJson", &InAppPurchasesRequestBus::Events::QueryProductInfoFromJson)
  58. ->Event("PurchaseProductWithDeveloperPayload", &InAppPurchasesRequestBus::Events::PurchaseProductWithDeveloperPayload)
  59. ->Event("PurchaseProduct", &InAppPurchasesRequestBus::Events::PurchaseProduct)
  60. ->Event("QueryPurchasedProducts", &InAppPurchasesRequestBus::Events::QueryPurchasedProducts)
  61. ->Event("ConsumePurchase", &InAppPurchasesRequestBus::Events::ConsumePurchase)
  62. ->Event("FinishTransaction", &InAppPurchasesRequestBus::Events::FinishTransaction)
  63. ;
  64. behaviorContext->EBus<InAppPurchasesResponseAccessorBus>("InAppPurchasesResponseAccessorBus")
  65. ->Event("NextProduct", &InAppPurchasesResponseAccessorBus::Events::GetNextProduct)
  66. ->Event("PreviousProduct", &InAppPurchasesResponseAccessorBus::Events::GetPreviousProduct)
  67. ->Event("NextPurchasedProduct", &InAppPurchasesResponseAccessorBus::Events::GetNextPurchasedProduct)
  68. ->Event("PreviousPurchasedProduct", &InAppPurchasesResponseAccessorBus::Events::GetPreviousPurchasedProduct)
  69. ->Event("ProductId", &InAppPurchasesResponseAccessorBus::Events::GetProductId)
  70. ->Event("ProductTitle", &InAppPurchasesResponseAccessorBus::Events::GetProductTitle)
  71. ->Event("ProductDescription", &InAppPurchasesResponseAccessorBus::Events::GetProductDescription)
  72. ->Event("ProductPrice", &InAppPurchasesResponseAccessorBus::Events::GetProductPrice)
  73. ->Event("ProductCurrencyCode", &InAppPurchasesResponseAccessorBus::Events::GetProductCurrencyCode)
  74. ->Event("ProductPriceMicro", &InAppPurchasesResponseAccessorBus::Events::GetProductPriceMicro)
  75. ->Event("PurchasedProductId", &InAppPurchasesResponseAccessorBus::Events::GetPurchasedProductId)
  76. ->Event("PurchaseTime", &InAppPurchasesResponseAccessorBus::Events::GetPurchaseTime)
  77. ->Event("OrderId", &InAppPurchasesResponseAccessorBus::Events::GetOrderId)
  78. ->Event("DeveloperPayload", &InAppPurchasesResponseAccessorBus::Events::GetDeveloperPayload)
  79. ->Event("PurchaseSignature", &InAppPurchasesResponseAccessorBus::Events::GetPurchaseSignature)
  80. ->Event("PackageName", &InAppPurchasesResponseAccessorBus::Events::GetPackageName)
  81. ->Event("PurchaseToken", &InAppPurchasesResponseAccessorBus::Events::GetPurchaseToken)
  82. ->Event("IsAutoRenewing", &InAppPurchasesResponseAccessorBus::Events::IsAutoRenewing)
  83. ->Event("RestoredOrderId", &InAppPurchasesResponseAccessorBus::Events::GetRestoredOrderId)
  84. ->Event("SubscriptionExpirationTime", &InAppPurchasesResponseAccessorBus::Events::GetSubscriptionExpirationTime)
  85. ->Event("RestoredPurchaseTime", &InAppPurchasesResponseAccessorBus::Events::GetRestoredPurchaseTime)
  86. ->Event("HasDownloads", &InAppPurchasesResponseAccessorBus::Events::HasDownloads)
  87. ->Event("IsProductOwned", &InAppPurchasesResponseAccessorBus::Events::IsProductOwned)
  88. ->Event("ResetIndices", &InAppPurchasesResponseAccessorBus::Events::ResetIndices)
  89. ;
  90. }
  91. }
  92. void SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  93. {
  94. provided.push_back(AZ_CRC_CE("InAppPurchasesService"));
  95. }
  96. void SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  97. {
  98. incompatible.push_back(AZ_CRC_CE("InAppPurchasesService"));
  99. }
  100. void SystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  101. {
  102. (void)required;
  103. }
  104. void SystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
  105. {
  106. (void)dependent;
  107. }
  108. void SystemComponent::Initialize()
  109. {
  110. if (InAppPurchasesInterface::GetInstance() != nullptr)
  111. {
  112. InAppPurchasesInterface::GetInstance()->Initialize();
  113. }
  114. }
  115. void SystemComponent::QueryProductInfoById(const AZStd::string& productId) const
  116. {
  117. AZStd::vector<AZStd::string> productIds;
  118. productIds.push_back(productId);
  119. SystemComponent::QueryProductInfoByIds(productIds);
  120. }
  121. void SystemComponent::QueryProductInfoByIds(AZStd::vector<AZStd::string>& productIds) const
  122. {
  123. if (InAppPurchasesInterface::GetInstance() != nullptr)
  124. {
  125. InAppPurchasesInterface::GetInstance()->QueryProductInfo(productIds);
  126. }
  127. }
  128. void SystemComponent::QueryProductInfo() const
  129. {
  130. if (InAppPurchasesInterface::GetInstance() != nullptr)
  131. {
  132. InAppPurchasesInterface::GetInstance()->QueryProductInfo();
  133. }
  134. }
  135. void SystemComponent::QueryProductInfoFromJson(const AZStd::string& jsonFilePath) const
  136. {
  137. if (InAppPurchasesInterface::GetInstance() != nullptr)
  138. {
  139. AZ::IO::FileIOBase* fileReader = AZ::IO::FileIOBase::GetInstance();
  140. AZStd::string fileBuffer;
  141. AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
  142. AZ::u64 fileSize = 0;
  143. if (!fileReader->Open(jsonFilePath.c_str(), AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeBinary, fileHandle))
  144. {
  145. AZ::Failure(AZStd::string::format("Failed to read %s - unable to open file", jsonFilePath.c_str()));
  146. return;
  147. }
  148. if ((!fileReader->Size(fileHandle, fileSize)) || (fileSize == 0))
  149. {
  150. fileReader->Close(fileHandle);
  151. AZ::Failure(AZStd::string::format("Failed to read %s - file truncated.", jsonFilePath.c_str()));
  152. return;
  153. }
  154. fileBuffer.resize(fileSize);
  155. if (!fileReader->Read(fileHandle, fileBuffer.data(), fileSize, true))
  156. {
  157. fileBuffer.resize(0);
  158. fileReader->Close(fileHandle);
  159. AZ::Failure(AZStd::string::format("Failed to read %s - file read failed.", jsonFilePath.c_str()));
  160. return;
  161. }
  162. fileReader->Close(fileHandle);
  163. rapidjson::Document doc;
  164. doc.Parse(fileBuffer.data());
  165. if (doc.HasParseError())
  166. {
  167. AZ_Warning("LumberyardInAppBilling", false, "Failed to parse product_ids: %s\n", rapidjson::GetParseError_En(doc.GetParseError()));
  168. return;
  169. }
  170. AZStd::vector<AZStd::string> productIdsVec;
  171. if (doc.HasMember("product_ids") && doc["product_ids"].GetType() == rapidjson::kArrayType)
  172. {
  173. rapidjson::Value& productIdsArray = doc["product_ids"];
  174. for (rapidjson::Value::ConstValueIterator itr = productIdsArray.Begin(); itr != productIdsArray.End(); itr++)
  175. {
  176. if ((*itr).HasMember("id"))
  177. {
  178. productIdsVec.push_back((*itr)["id"].GetString());
  179. }
  180. }
  181. InAppPurchasesInterface::GetInstance()->QueryProductInfo(productIdsVec);
  182. }
  183. else
  184. {
  185. AZ_Warning("O3DEInAppPurchases", false, "The JSON string provided does not contain an array named ProductIds!(Property *has* to be an array)");
  186. }
  187. }
  188. }
  189. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* SystemComponent::GetCachedProductInfo() const
  190. {
  191. if (InAppPurchasesInterface::GetInstance() != nullptr)
  192. {
  193. return &InAppPurchasesInterface::GetInstance()->GetCache()->GetCachedProductDetails();
  194. }
  195. return nullptr;
  196. }
  197. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* SystemComponent::GetCachedPurchasedProductInfo() const
  198. {
  199. if (InAppPurchasesInterface::GetInstance() != nullptr)
  200. {
  201. return &InAppPurchasesInterface::GetInstance()->GetCache()->GetCachedPurchasedProductDetails();
  202. }
  203. return nullptr;
  204. }
  205. void SystemComponent::PurchaseProductWithDeveloperPayload(const AZStd::string& productId, const AZStd::string& developerPayload) const
  206. {
  207. if (InAppPurchasesInterface::GetInstance() != nullptr)
  208. {
  209. InAppPurchasesInterface::GetInstance()->PurchaseProduct(productId, developerPayload);
  210. }
  211. }
  212. void SystemComponent::PurchaseProduct(const AZStd::string& productId) const
  213. {
  214. if (InAppPurchasesInterface::GetInstance() != nullptr)
  215. {
  216. InAppPurchasesInterface::GetInstance()->PurchaseProduct(productId);
  217. }
  218. }
  219. void SystemComponent::QueryPurchasedProducts() const
  220. {
  221. if (InAppPurchasesInterface::GetInstance() != nullptr)
  222. {
  223. InAppPurchasesInterface::GetInstance()->QueryPurchasedProducts();
  224. }
  225. }
  226. void SystemComponent::RestorePurchasedProducts() const
  227. {
  228. if (InAppPurchasesInterface::GetInstance() != nullptr)
  229. {
  230. InAppPurchasesInterface::GetInstance()->RestorePurchasedProducts();
  231. }
  232. }
  233. void SystemComponent::ConsumePurchase(const AZStd::string& purchaseToken) const
  234. {
  235. if (InAppPurchasesInterface::GetInstance() != nullptr)
  236. {
  237. InAppPurchasesInterface::GetInstance()->ConsumePurchase(purchaseToken);
  238. }
  239. }
  240. void SystemComponent::FinishTransaction(const AZStd::string& transactionId, bool downloadHostedContent) const
  241. {
  242. if (InAppPurchasesInterface::GetInstance() != nullptr)
  243. {
  244. InAppPurchasesInterface::GetInstance()->FinishTransaction(transactionId, downloadHostedContent);
  245. }
  246. }
  247. void SystemComponent::ClearCachedProductDetails()
  248. {
  249. if (InAppPurchasesInterface::GetInstance() != nullptr)
  250. {
  251. InAppPurchasesInterface::GetInstance()->GetCache()->ClearCachedProductDetails();
  252. }
  253. }
  254. void SystemComponent::ClearCachedPurchasedProductDetails()
  255. {
  256. if (InAppPurchasesInterface::GetInstance() != nullptr)
  257. {
  258. InAppPurchasesInterface::GetInstance()->GetCache()->ClearCachedPurchasedProductDetails();
  259. }
  260. }
  261. bool SystemComponent::GetNextProduct()
  262. {
  263. m_productInfoIndex++;
  264. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  265. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  266. if (productDetails != nullptr)
  267. {
  268. if (m_productInfoIndex >= productDetails->size())
  269. {
  270. m_productInfoIndex = 0;
  271. }
  272. if (productDetails->size() > 0)
  273. {
  274. return true;
  275. }
  276. }
  277. return false;
  278. }
  279. bool SystemComponent::GetPreviousProduct()
  280. {
  281. m_productInfoIndex--;
  282. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  283. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  284. productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  285. if (productDetails != nullptr)
  286. {
  287. if (m_productInfoIndex < 0)
  288. {
  289. m_productInfoIndex = static_cast<int>(productDetails->size() - 1);
  290. }
  291. if (productDetails->size() > 0)
  292. {
  293. return true;
  294. }
  295. }
  296. return false;
  297. }
  298. bool SystemComponent::GetNextPurchasedProduct()
  299. {
  300. m_purchasedProductInfoIndex++;
  301. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  302. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  303. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  304. if (purchasedProductDetails != nullptr)
  305. {
  306. if (m_purchasedProductInfoIndex >= purchasedProductDetails->size())
  307. {
  308. m_purchasedProductInfoIndex = 0;
  309. }
  310. if (purchasedProductDetails->size() > 0)
  311. {
  312. return true;
  313. }
  314. }
  315. return false;
  316. }
  317. bool SystemComponent::GetPreviousPurchasedProduct()
  318. {
  319. m_purchasedProductInfoIndex--;
  320. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  321. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  322. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  323. if (purchasedProductDetails != nullptr)
  324. {
  325. if (m_purchasedProductInfoIndex < 0)
  326. {
  327. m_purchasedProductInfoIndex = static_cast<int>(purchasedProductDetails->size() - 1);
  328. }
  329. if (purchasedProductDetails->size() > 0)
  330. {
  331. return true;
  332. }
  333. }
  334. return false;
  335. }
  336. AZStd::string SystemComponent::GetProductId()
  337. {
  338. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  339. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  340. productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  341. if (productDetails != nullptr && m_productInfoIndex >= 0 && m_productInfoIndex < productDetails->size())
  342. {
  343. return productDetails->at(m_productInfoIndex)->GetProductId();
  344. }
  345. return "";
  346. }
  347. AZStd::string SystemComponent::GetProductTitle()
  348. {
  349. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  350. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  351. productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  352. if (productDetails != nullptr && m_productInfoIndex >= 0 && m_productInfoIndex < productDetails->size())
  353. {
  354. return productDetails->at(m_productInfoIndex)->GetProductTitle();
  355. }
  356. return "";
  357. }
  358. AZStd::string SystemComponent::GetProductDescription()
  359. {
  360. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  361. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  362. productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  363. if (productDetails != nullptr && m_productInfoIndex >= 0 && m_productInfoIndex < productDetails->size())
  364. {
  365. return productDetails->at(m_productInfoIndex)->GetProductDescription();
  366. }
  367. return "";
  368. }
  369. AZStd::string SystemComponent::GetProductPrice()
  370. {
  371. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  372. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  373. productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  374. if (productDetails != nullptr && m_productInfoIndex >= 0 && m_productInfoIndex < productDetails->size())
  375. {
  376. return productDetails->at(m_productInfoIndex)->GetProductPrice();
  377. }
  378. return "";
  379. }
  380. AZStd::string SystemComponent::GetProductCurrencyCode()
  381. {
  382. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  383. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  384. productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  385. if (productDetails != nullptr && m_productInfoIndex >= 0 && m_productInfoIndex < productDetails->size())
  386. {
  387. return productDetails->at(m_productInfoIndex)->GetProductCurrencyCode();
  388. }
  389. return "";
  390. }
  391. AZ::u64 SystemComponent::GetProductPriceMicro()
  392. {
  393. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  394. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  395. productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  396. if (productDetails != nullptr && m_productInfoIndex >= 0 && m_productInfoIndex < productDetails->size())
  397. {
  398. return productDetails->at(m_productInfoIndex)->GetProductPriceMicro();
  399. }
  400. return 0;
  401. }
  402. AZStd::string SystemComponent::GetPurchasedProductId()
  403. {
  404. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  405. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  406. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  407. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  408. {
  409. return purchasedProductDetails->at(m_purchasedProductInfoIndex)->GetProductId();
  410. }
  411. return "";
  412. }
  413. AZStd::string SystemComponent::GetOrderId()
  414. {
  415. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  416. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  417. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  418. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  419. {
  420. return purchasedProductDetails->at(m_purchasedProductInfoIndex)->GetOrderId();
  421. }
  422. return "";
  423. }
  424. AZStd::string SystemComponent::GetDeveloperPayload()
  425. {
  426. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  427. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  428. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  429. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  430. {
  431. return purchasedProductDetails->at(m_purchasedProductInfoIndex)->GetDeveloperPayload();
  432. }
  433. return "";
  434. }
  435. AZStd::string SystemComponent::GetPurchaseTime()
  436. {
  437. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  438. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  439. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  440. AZStd::string date;
  441. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  442. {
  443. AZ::u64 time = purchasedProductDetails->at(m_purchasedProductInfoIndex)->GetPurchaseTime();
  444. time_t t = static_cast<time_t>(time);
  445. tm local;
  446. azlocaltime(&t, &local);
  447. date.resize(24); // 3 (day) + 3 (month) + 2 (date) + 8 (time) + 4 (year) + 4 (spaces)
  448. strftime(date.data(), date.size(), "%a %b %d %H:%M:%S %Y", &local);
  449. }
  450. return date;
  451. }
  452. AZStd::string SystemComponent::GetPurchaseSignature()
  453. {
  454. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  455. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  456. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  457. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  458. {
  459. const PurchasedProductDetailsAndroid* purchasedProductsAndroid = azrtti_cast<const PurchasedProductDetailsAndroid*>(purchasedProductDetails->at(m_purchasedProductInfoIndex).get());
  460. if (purchasedProductsAndroid)
  461. {
  462. return purchasedProductsAndroid->GetPurchaseSignature();
  463. }
  464. }
  465. return "";
  466. }
  467. AZStd::string SystemComponent::GetPackageName()
  468. {
  469. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  470. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  471. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  472. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  473. {
  474. const PurchasedProductDetailsAndroid* purchasedProductsAndroid = azrtti_cast<const PurchasedProductDetailsAndroid*>(purchasedProductDetails->at(m_purchasedProductInfoIndex).get());
  475. if (purchasedProductsAndroid)
  476. {
  477. return purchasedProductsAndroid->GetPackageName();
  478. }
  479. }
  480. return "";
  481. }
  482. AZStd::string SystemComponent::GetPurchaseToken()
  483. {
  484. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  485. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  486. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  487. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  488. {
  489. const PurchasedProductDetailsAndroid* purchasedProductsAndroid = azrtti_cast<const PurchasedProductDetailsAndroid*>(purchasedProductDetails->at(m_purchasedProductInfoIndex).get());
  490. if (purchasedProductsAndroid)
  491. {
  492. return purchasedProductsAndroid->GetPurchaseToken();
  493. }
  494. }
  495. return "";
  496. }
  497. bool SystemComponent::IsAutoRenewing()
  498. {
  499. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  500. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  501. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  502. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  503. {
  504. const PurchasedProductDetailsAndroid* purchasedProductsAndroid = azrtti_cast<const PurchasedProductDetailsAndroid*>(purchasedProductDetails->at(m_purchasedProductInfoIndex).get());
  505. if (purchasedProductsAndroid)
  506. {
  507. return purchasedProductsAndroid->GetIsAutoRenewing();
  508. }
  509. }
  510. return false;
  511. }
  512. AZStd::string SystemComponent::GetRestoredOrderId()
  513. {
  514. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  515. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  516. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  517. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  518. {
  519. const PurchasedProductDetailsApple* purchasedProductsApple = azrtti_cast<const PurchasedProductDetailsApple*>(purchasedProductDetails->at(m_purchasedProductInfoIndex).get());
  520. if (purchasedProductsApple)
  521. {
  522. return purchasedProductsApple->GetRestoredOrderId();
  523. }
  524. }
  525. return "";
  526. }
  527. AZ::u64 SystemComponent::GetSubscriptionExpirationTime()
  528. {
  529. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  530. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  531. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  532. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  533. {
  534. const PurchasedProductDetailsApple* purchasedProductsApple = azrtti_cast<const PurchasedProductDetailsApple*>(purchasedProductDetails->at(m_purchasedProductInfoIndex).get());
  535. if (purchasedProductsApple)
  536. {
  537. return purchasedProductsApple->GetSubscriptionExpirationTime();
  538. }
  539. }
  540. return 0;
  541. }
  542. AZ::u64 SystemComponent::GetRestoredPurchaseTime()
  543. {
  544. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  545. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  546. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  547. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  548. {
  549. const PurchasedProductDetailsApple* purchasedProductsApple = azrtti_cast<const PurchasedProductDetailsApple*>(purchasedProductDetails->at(m_purchasedProductInfoIndex).get());
  550. if (purchasedProductsApple)
  551. {
  552. return purchasedProductsApple->GetRestoredPurchaseTime();
  553. }
  554. }
  555. return 0;
  556. }
  557. bool SystemComponent::HasDownloads()
  558. {
  559. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  560. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  561. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  562. if (purchasedProductDetails != nullptr && m_purchasedProductInfoIndex >= 0 && m_purchasedProductInfoIndex < purchasedProductDetails->size())
  563. {
  564. const PurchasedProductDetailsApple* purchasedProductsApple = azrtti_cast<const PurchasedProductDetailsApple*>(purchasedProductDetails->at(m_purchasedProductInfoIndex).get());
  565. if (purchasedProductsApple)
  566. {
  567. return purchasedProductsApple->GetHasDownloads();
  568. }
  569. }
  570. return false;
  571. }
  572. bool SystemComponent::IsProductOwned()
  573. {
  574. const AZStd::vector<AZStd::unique_ptr<PurchasedProductDetails const> >* purchasedProductDetails = nullptr;
  575. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  576. purchasedProductDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedPurchasedProductInfo);
  577. const AZStd::vector<AZStd::unique_ptr<ProductDetails const> >* productDetails = nullptr;
  578. InAppPurchases::InAppPurchasesRequestBus::BroadcastResult(
  579. productDetails, &InAppPurchases::InAppPurchasesRequestBus::Events::GetCachedProductInfo);
  580. if (purchasedProductDetails != nullptr && productDetails != nullptr)
  581. {
  582. if (m_productInfoIndex >= 0 && m_productInfoIndex < productDetails->size())
  583. {
  584. const AZStd::string& productId = productDetails->at(m_productInfoIndex)->GetProductId();
  585. for (int i = 0; i < purchasedProductDetails->size(); i++)
  586. {
  587. if (productId.compare(purchasedProductDetails->at(i)->GetProductId()) == 0)
  588. {
  589. return true;
  590. }
  591. }
  592. }
  593. }
  594. return false;
  595. }
  596. void SystemComponent::ResetIndices()
  597. {
  598. m_productInfoIndex = 0;
  599. m_purchasedProductInfoIndex = 0;
  600. }
  601. }