Skip to main content

storekit/
verification_result.rs

1use serde::Deserialize;
2
3use crate::error::{StoreKitError, VerificationErrorPayload, VerificationFailure};
4use crate::private::decode_base64;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct VerificationMetadata {
8    pub jws_representation: String,
9    pub header_data: Vec<u8>,
10    pub payload_data: Vec<u8>,
11    pub signature_data: Vec<u8>,
12    pub signed_data: Vec<u8>,
13    pub signed_date: String,
14    pub device_verification: Vec<u8>,
15    pub device_verification_nonce: String,
16}
17
18impl VerificationMetadata {
19    pub fn jws_representation(&self) -> &str {
20        &self.jws_representation
21    }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum VerificationResult<T> {
26    Verified {
27        payload: T,
28        metadata: VerificationMetadata,
29    },
30    Unverified {
31        payload: T,
32        metadata: VerificationMetadata,
33        failure: VerificationFailure,
34    },
35}
36
37impl<T> VerificationResult<T> {
38    pub const fn is_verified(&self) -> bool {
39        matches!(self, Self::Verified { .. })
40    }
41
42    pub const fn payload(&self) -> &T {
43        match self {
44            Self::Verified { payload, .. } | Self::Unverified { payload, .. } => payload,
45        }
46    }
47
48    pub fn into_payload(self) -> T {
49        match self {
50            Self::Verified { payload, .. } | Self::Unverified { payload, .. } => payload,
51        }
52    }
53
54    pub const fn metadata(&self) -> &VerificationMetadata {
55        match self {
56            Self::Verified { metadata, .. } | Self::Unverified { metadata, .. } => metadata,
57        }
58    }
59
60    pub const fn verification_failure(&self) -> Option<&VerificationFailure> {
61        match self {
62            Self::Verified { .. } => None,
63            Self::Unverified { failure, .. } => Some(failure),
64        }
65    }
66
67    pub fn into_parts(self) -> (T, VerificationMetadata, Option<VerificationFailure>) {
68        match self {
69            Self::Verified { payload, metadata } => (payload, metadata, None),
70            Self::Unverified {
71                payload,
72                metadata,
73                failure,
74            } => (payload, metadata, Some(failure)),
75        }
76    }
77
78    pub fn jws_representation(&self) -> &str {
79        self.metadata().jws_representation()
80    }
81}
82
83#[derive(Debug, Deserialize)]
84pub(crate) struct VerificationMetadataPayload {
85    #[serde(rename = "jwsRepresentation")]
86    jws_representation: String,
87    #[serde(rename = "headerDataBase64")]
88    header_data_base64: String,
89    #[serde(rename = "payloadDataBase64")]
90    payload_data_base64: String,
91    #[serde(rename = "signatureDataBase64")]
92    signature_data_base64: String,
93    #[serde(rename = "signedDataBase64")]
94    signed_data_base64: String,
95    #[serde(rename = "signedDate")]
96    signed_date: String,
97    #[serde(rename = "deviceVerificationBase64")]
98    device_verification_base64: String,
99    #[serde(rename = "deviceVerificationNonce")]
100    device_verification_nonce: String,
101}
102
103impl VerificationMetadataPayload {
104    fn into_metadata(self) -> Result<VerificationMetadata, StoreKitError> {
105        Ok(VerificationMetadata {
106            jws_representation: self.jws_representation,
107            header_data: decode_base64(&self.header_data_base64, "verification header data")?,
108            payload_data: decode_base64(&self.payload_data_base64, "verification payload data")?,
109            signature_data: decode_base64(
110                &self.signature_data_base64,
111                "verification signature data",
112            )?,
113            signed_data: decode_base64(&self.signed_data_base64, "verification signed data")?,
114            signed_date: self.signed_date,
115            device_verification: decode_base64(
116                &self.device_verification_base64,
117                "verification device data",
118            )?,
119            device_verification_nonce: self.device_verification_nonce,
120        })
121    }
122}
123
124#[derive(Debug, Deserialize)]
125pub(crate) struct VerificationResultPayload<T> {
126    kind: String,
127    payload: T,
128    metadata: VerificationMetadataPayload,
129    #[serde(rename = "verificationError")]
130    verification_error: Option<VerificationErrorPayload>,
131}
132
133impl<T> VerificationResultPayload<T> {
134    pub(crate) fn into_result<U, F>(
135        self,
136        map_payload: F,
137    ) -> Result<VerificationResult<U>, StoreKitError>
138    where
139        F: FnOnce(T) -> Result<U, StoreKitError>,
140    {
141        let payload = map_payload(self.payload)?;
142        let metadata = self.metadata.into_metadata()?;
143        match self.kind.as_str() {
144            "verified" => Ok(VerificationResult::Verified { payload, metadata }),
145            "unverified" => {
146                let failure = self
147                    .verification_error
148                    .map(VerificationFailure::from_payload)
149                    .ok_or_else(|| {
150                        StoreKitError::Unknown(
151                            "StoreKit returned an unverified result without a verification error"
152                                .to_owned(),
153                        )
154                    })?;
155                Ok(VerificationResult::Unverified {
156                    payload,
157                    metadata,
158                    failure,
159                })
160            }
161            other => Err(StoreKitError::Unknown(format!(
162                "StoreKit returned an unknown verification result kind '{other}'"
163            ))),
164        }
165    }
166}