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}