Skip to main content

storekit/
app_store.rs

1use core::ptr;
2
3use crate::error::StoreKitError;
4use crate::ffi;
5use crate::private::{error_from_status, take_string};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8/// Wraps `StoreKit.AppStore.Environment`.
9pub enum AppStoreEnvironment {
10    /// Represents the `Production` `StoreKit` case.
11    Production,
12    /// Represents the `Sandbox` `StoreKit` case.
13    Sandbox,
14    /// Represents the `Xcode` `StoreKit` case.
15    Xcode,
16    /// Preserves an unrecognized `StoreKit` case.
17    Unknown(String),
18}
19
20impl AppStoreEnvironment {
21    /// Returns the raw `StoreKit` string for this App Store environment.
22    pub fn as_str(&self) -> &str {
23        match self {
24            Self::Production => "production",
25            Self::Sandbox => "sandbox",
26            Self::Xcode => "xcode",
27            Self::Unknown(value) => value.as_str(),
28        }
29    }
30
31    pub(crate) fn from_raw(raw: String) -> Self {
32        match raw.as_str() {
33            "production" => Self::Production,
34            "sandbox" => Self::Sandbox,
35            "xcode" => Self::Xcode,
36            _ => Self::Unknown(raw),
37        }
38    }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
42/// Wraps the platform value associated with `StoreKit.AppTransaction`.
43pub enum AppStorePlatform {
44    /// Represents the `IOS` `StoreKit` case.
45    IOS,
46    /// Represents the `MacOS` `StoreKit` case.
47    MacOS,
48    /// Represents the `TvOS` `StoreKit` case.
49    TvOS,
50    /// Represents the `VisionOS` `StoreKit` case.
51    VisionOS,
52    /// Preserves an unrecognized `StoreKit` case.
53    Unknown(String),
54}
55
56impl AppStorePlatform {
57    /// Returns the raw `StoreKit` string for this App Store platform.
58    pub fn as_str(&self) -> &str {
59        match self {
60            Self::IOS => "iOS",
61            Self::MacOS => "macOS",
62            Self::TvOS => "tvOS",
63            Self::VisionOS => "visionOS",
64            Self::Unknown(value) => value.as_str(),
65        }
66    }
67
68    pub(crate) fn from_raw(raw: String) -> Self {
69        match raw.as_str() {
70            "iOS" => Self::IOS,
71            "macOS" => Self::MacOS,
72            "tvOS" => Self::TvOS,
73            "visionOS" => Self::VisionOS,
74            _ => Self::Unknown(raw),
75        }
76    }
77}
78
79/// Helpers backed by `StoreKit.AppStore`.
80#[derive(Debug, Clone, Copy, Default)]
81pub struct AppStore;
82
83impl AppStore {
84    /// Calls `StoreKit.AppStore.canMakePayments`.
85    pub fn can_make_payments() -> Result<bool, StoreKitError> {
86        let mut raw_value = 0;
87        let mut error_message = ptr::null_mut();
88        let status =
89            unsafe { ffi::sk_app_store_can_make_payments(&mut raw_value, &mut error_message) };
90        if status == ffi::status::OK {
91            Ok(raw_value != 0)
92        } else {
93            Err(unsafe { error_from_status(status, error_message) })
94        }
95    }
96
97    /// Calls the `StoreKit` device verification identifier API.
98    pub fn device_verification_id() -> Result<Option<String>, StoreKitError> {
99        let mut uuid_ptr = ptr::null_mut();
100        let mut error_message = ptr::null_mut();
101        let status =
102            unsafe { ffi::sk_app_store_device_verification_id(&mut uuid_ptr, &mut error_message) };
103        if status == ffi::status::OK {
104            Ok(unsafe { take_string(uuid_ptr) })
105        } else {
106            Err(unsafe { error_from_status(status, error_message) })
107        }
108    }
109
110    /// Calls `StoreKit.AppStore.sync()`.
111    pub fn sync() -> Result<(), StoreKitError> {
112        let mut error_message = ptr::null_mut();
113        let status = unsafe { ffi::sk_app_store_sync(&mut error_message) };
114        if status == ffi::status::OK {
115            Ok(())
116        } else {
117            Err(unsafe { error_from_status(status, error_message) })
118        }
119    }
120
121    /// Calls the `StoreKit` manage-subscriptions API.
122    pub fn show_manage_subscriptions() -> Result<(), StoreKitError> {
123        let mut error_message = ptr::null_mut();
124        let status = unsafe { ffi::sk_app_store_show_manage_subscriptions(&mut error_message) };
125        if status == ffi::status::OK {
126            Ok(())
127        } else {
128            Err(unsafe { error_from_status(status, error_message) })
129        }
130    }
131
132    /// Calls the `StoreKit` review-request API.
133    pub fn request_review() -> Result<(), StoreKitError> {
134        let mut error_message = ptr::null_mut();
135        let status = unsafe { ffi::sk_app_store_request_review(&mut error_message) };
136        if status == ffi::status::OK {
137            Ok(())
138        } else {
139            Err(unsafe { error_from_status(status, error_message) })
140        }
141    }
142
143    /// Calls `StoreKit.AppStore.presentOfferCodeRedeemSheet()`.
144    pub fn present_offer_code_redeem_sheet() -> Result<(), StoreKitError> {
145        let mut error_message = ptr::null_mut();
146        let status =
147            unsafe { ffi::sk_app_store_present_offer_code_redeem_sheet(&mut error_message) };
148        if status == ffi::status::OK {
149            Ok(())
150        } else {
151            Err(unsafe { error_from_status(status, error_message) })
152        }
153    }
154}