Skip to main content

storekit/
app_transaction.rs

1use core::ptr;
2
3use serde::Deserialize;
4
5use crate::app_store::{AppStoreEnvironment, AppStorePlatform};
6use crate::error::StoreKitError;
7use crate::ffi;
8use crate::private::{decode_base64, error_from_status, parse_json_ptr};
9use crate::verification_result::{VerificationResult, VerificationResultPayload};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct AppTransaction {
13    pub app_id: Option<u64>,
14    pub app_transaction_id: String,
15    pub app_version: String,
16    pub app_version_id: Option<u64>,
17    pub bundle_id: String,
18    pub environment: AppStoreEnvironment,
19    pub original_app_version: String,
20    pub original_purchase_date: String,
21    pub original_platform: Option<AppStorePlatform>,
22    pub preorder_date: Option<String>,
23    pub json_representation: Vec<u8>,
24}
25
26impl AppTransaction {
27    pub fn shared() -> Result<VerificationResult<Self>, StoreKitError> {
28        let mut result_json = ptr::null_mut();
29        let mut error_message = ptr::null_mut();
30        let status =
31            unsafe { ffi::sk_app_transaction_shared(&mut result_json, &mut error_message) };
32        if status != ffi::status::OK {
33            return Err(unsafe { error_from_status(status, error_message) });
34        }
35        let payload = unsafe {
36            parse_json_ptr::<VerificationResultPayload<AppTransactionPayload>>(
37                result_json,
38                "app transaction",
39            )
40        }?;
41        payload.into_result(AppTransactionPayload::into_app_transaction)
42    }
43
44    pub fn refresh() -> Result<VerificationResult<Self>, StoreKitError> {
45        let mut result_json = ptr::null_mut();
46        let mut error_message = ptr::null_mut();
47        let status =
48            unsafe { ffi::sk_app_transaction_refresh(&mut result_json, &mut error_message) };
49        if status != ffi::status::OK {
50            return Err(unsafe { error_from_status(status, error_message) });
51        }
52        let payload = unsafe {
53            parse_json_ptr::<VerificationResultPayload<AppTransactionPayload>>(
54                result_json,
55                "refreshed app transaction",
56            )
57        }?;
58        payload.into_result(AppTransactionPayload::into_app_transaction)
59    }
60}
61
62#[derive(Debug, Deserialize)]
63pub(crate) struct AppTransactionPayload {
64    #[serde(rename = "appID")]
65    app_id: Option<u64>,
66    #[serde(rename = "appTransactionID")]
67    app_transaction_id: String,
68    #[serde(rename = "appVersion")]
69    app_version: String,
70    #[serde(rename = "appVersionID")]
71    app_version_id: Option<u64>,
72    #[serde(rename = "bundleID")]
73    bundle_id: String,
74    environment: String,
75    #[serde(rename = "originalAppVersion")]
76    original_app_version: String,
77    #[serde(rename = "originalPurchaseDate")]
78    original_purchase_date: String,
79    #[serde(rename = "originalPlatform")]
80    original_platform: Option<String>,
81    #[serde(rename = "preorderDate")]
82    preorder_date: Option<String>,
83    #[serde(rename = "jsonRepresentationBase64")]
84    json_representation_base64: String,
85}
86
87impl AppTransactionPayload {
88    pub(crate) fn into_app_transaction(self) -> Result<AppTransaction, StoreKitError> {
89        Ok(AppTransaction {
90            app_id: self.app_id,
91            app_transaction_id: self.app_transaction_id,
92            app_version: self.app_version,
93            app_version_id: self.app_version_id,
94            bundle_id: self.bundle_id,
95            environment: AppStoreEnvironment::from_raw(self.environment),
96            original_app_version: self.original_app_version,
97            original_purchase_date: self.original_purchase_date,
98            original_platform: self.original_platform.map(AppStorePlatform::from_raw),
99            preorder_date: self.preorder_date,
100            json_representation: decode_base64(
101                &self.json_representation_base64,
102                "app transaction JSON representation",
103            )?,
104        })
105    }
106}