storekit/
store_context.rs1use serde::Deserialize;
2
3use crate::app_store::AppStore;
4use crate::app_transaction::AppTransaction;
5use crate::error::StoreKitError;
6use crate::ffi;
7use crate::product::Product;
8use crate::receipt_validator::{AppReceipt, ReceiptValidator};
9use crate::storefront::Storefront;
10use crate::transaction::{Transaction, TransactionStream};
11use crate::verification_result::VerificationResult;
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct StoreContext {
16 pub bundle_identifier: Option<String>,
18 pub bundle_name: Option<String>,
20 pub bundle_version: Option<String>,
22 pub receipt_url: Option<String>,
24 pub can_make_payments: bool,
26 pub device_verification_id: Option<String>,
28 pub is_bundled: bool,
30 pub executable_path: Option<String>,
32}
33
34impl StoreContext {
35 pub fn current() -> Result<Self, StoreKitError> {
37 let mut context_json = core::ptr::null_mut();
38 let mut error_message = core::ptr::null_mut();
39 let status = unsafe { ffi::sk_store_context_json(&mut context_json, &mut error_message) };
40 if status != ffi::status::OK {
41 return Err(unsafe { crate::private::error_from_status(status, error_message) });
42 }
43 let payload = unsafe {
44 crate::private::parse_json_ptr::<StoreContextPayload>(context_json, "store context")
45 }?;
46 Ok(payload.into_store_context())
47 }
48
49 pub fn can_make_payments() -> Result<bool, StoreKitError> {
51 AppStore::can_make_payments()
52 }
53
54 pub fn device_verification_id() -> Result<Option<String>, StoreKitError> {
56 AppStore::device_verification_id()
57 }
58
59 pub fn current_products<I, S>(identifiers: I) -> Result<Vec<Product>, StoreKitError>
61 where
62 I: IntoIterator<Item = S>,
63 S: AsRef<str>,
64 {
65 Product::products_for(identifiers)
66 }
67
68 pub fn current_entitlements() -> Result<TransactionStream, StoreKitError> {
70 Transaction::current_entitlements()
71 }
72
73 pub fn transaction_updates() -> Result<TransactionStream, StoreKitError> {
75 Transaction::updates()
76 }
77
78 pub fn current_storefront() -> Result<Option<Storefront>, StoreKitError> {
80 Storefront::current()
81 }
82
83 pub fn app_transaction() -> Result<VerificationResult<AppTransaction>, StoreKitError> {
85 AppTransaction::shared()
86 }
87
88 pub fn receipt() -> Result<Option<AppReceipt>, StoreKitError> {
90 ReceiptValidator::current_receipt()
91 }
92}
93
94#[derive(Debug, Deserialize)]
95struct StoreContextPayload {
96 #[serde(rename = "bundleIdentifier")]
97 bundle_identifier: Option<String>,
98 #[serde(rename = "bundleName")]
99 bundle_name: Option<String>,
100 #[serde(rename = "bundleVersion")]
101 bundle_version: Option<String>,
102 #[serde(rename = "receiptURL")]
103 receipt_url: Option<String>,
104 #[serde(rename = "canMakePayments")]
105 can_make_payments: bool,
106 #[serde(rename = "deviceVerificationID")]
107 device_verification_id: Option<String>,
108 #[serde(rename = "isBundled")]
109 is_bundled: bool,
110 #[serde(rename = "executablePath")]
111 executable_path: Option<String>,
112}
113
114impl StoreContextPayload {
115 fn into_store_context(self) -> StoreContext {
116 StoreContext {
117 bundle_identifier: self.bundle_identifier,
118 bundle_name: self.bundle_name,
119 bundle_version: self.bundle_version,
120 receipt_url: self.receipt_url,
121 can_make_payments: self.can_make_payments,
122 device_verification_id: self.device_verification_id,
123 is_bundled: self.is_bundled,
124 executable_path: self.executable_path,
125 }
126 }
127}