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