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 {
15 pub bundle_identifier: Option<String>,
16 pub bundle_name: Option<String>,
17 pub bundle_version: Option<String>,
18 pub receipt_url: Option<String>,
19 pub can_make_payments: bool,
20 pub device_verification_id: Option<String>,
21 pub is_bundled: bool,
22 pub executable_path: Option<String>,
23}
24
25impl StoreContext {
26 pub fn current() -> Result<Self, StoreKitError> {
27 let mut context_json = core::ptr::null_mut();
28 let mut error_message = core::ptr::null_mut();
29 let status = unsafe { ffi::sk_store_context_json(&mut context_json, &mut error_message) };
30 if status != ffi::status::OK {
31 return Err(unsafe { crate::private::error_from_status(status, error_message) });
32 }
33 let payload = unsafe {
34 crate::private::parse_json_ptr::<StoreContextPayload>(context_json, "store context")
35 }?;
36 Ok(payload.into_store_context())
37 }
38
39 pub fn can_make_payments() -> Result<bool, StoreKitError> {
40 AppStore::can_make_payments()
41 }
42
43 pub fn device_verification_id() -> Result<Option<String>, StoreKitError> {
44 AppStore::device_verification_id()
45 }
46
47 pub fn current_products<I, S>(identifiers: I) -> Result<Vec<Product>, StoreKitError>
48 where
49 I: IntoIterator<Item = S>,
50 S: AsRef<str>,
51 {
52 Product::products_for(identifiers)
53 }
54
55 pub fn current_entitlements() -> Result<TransactionStream, StoreKitError> {
56 Transaction::current_entitlements()
57 }
58
59 pub fn transaction_updates() -> Result<TransactionStream, StoreKitError> {
60 Transaction::updates()
61 }
62
63 pub fn current_storefront() -> Result<Option<Storefront>, StoreKitError> {
64 Storefront::current()
65 }
66
67 pub fn app_transaction() -> Result<VerificationResult<AppTransaction>, StoreKitError> {
68 AppTransaction::shared()
69 }
70
71 pub fn receipt() -> Result<Option<AppReceipt>, StoreKitError> {
72 ReceiptValidator::current_receipt()
73 }
74}
75
76#[derive(Debug, Deserialize)]
77struct StoreContextPayload {
78 #[serde(rename = "bundleIdentifier")]
79 bundle_identifier: Option<String>,
80 #[serde(rename = "bundleName")]
81 bundle_name: Option<String>,
82 #[serde(rename = "bundleVersion")]
83 bundle_version: Option<String>,
84 #[serde(rename = "receiptURL")]
85 receipt_url: Option<String>,
86 #[serde(rename = "canMakePayments")]
87 can_make_payments: bool,
88 #[serde(rename = "deviceVerificationID")]
89 device_verification_id: Option<String>,
90 #[serde(rename = "isBundled")]
91 is_bundled: bool,
92 #[serde(rename = "executablePath")]
93 executable_path: Option<String>,
94}
95
96impl StoreContextPayload {
97 fn into_store_context(self) -> StoreContext {
98 StoreContext {
99 bundle_identifier: self.bundle_identifier,
100 bundle_name: self.bundle_name,
101 bundle_version: self.bundle_version,
102 receipt_url: self.receipt_url,
103 can_make_payments: self.can_make_payments,
104 device_verification_id: self.device_verification_id,
105 is_bundled: self.is_bundled,
106 executable_path: self.executable_path,
107 }
108 }
109}