shopify_client/webhooks/
mod.rs

1pub mod types;
2
3use serde_json::Value;
4use types::{
5    CustomersDataRequestPayload, CustomersRedactPayload, ShopRedactPayload, WebhookParseError,
6    WebhookPayload,
7};
8
9pub enum WebhookTopic {
10    CustomersDataRequest,
11    CustomersRedact,
12    ShopRedact,
13}
14
15impl WebhookTopic {
16    pub fn from_header(header: &str) -> Option<Self> {
17        match header.to_lowercase().as_str() {
18            "customers/data_request" => Some(WebhookTopic::CustomersDataRequest),
19            "customers/redact" => Some(WebhookTopic::CustomersRedact),
20            "shop/redact" => Some(WebhookTopic::ShopRedact),
21            _ => None,
22        }
23    }
24}
25
26pub fn parse_webhook(
27    topic: WebhookTopic,
28    payload: &str,
29) -> Result<WebhookPayload, WebhookParseError> {
30    match topic {
31        WebhookTopic::CustomersDataRequest => {
32            serde_json::from_str::<CustomersDataRequestPayload>(payload)
33                .map(WebhookPayload::CustomersDataRequest)
34                .map_err(|e| WebhookParseError::ParseError(e.to_string()))
35        }
36        WebhookTopic::CustomersRedact => serde_json::from_str::<CustomersRedactPayload>(payload)
37            .map(WebhookPayload::CustomersRedact)
38            .map_err(|e| WebhookParseError::ParseError(e.to_string())),
39        WebhookTopic::ShopRedact => serde_json::from_str::<ShopRedactPayload>(payload)
40            .map(WebhookPayload::ShopRedact)
41            .map_err(|e| WebhookParseError::ParseError(e.to_string())),
42    }
43}
44
45pub fn parse_webhook_from_value(
46    topic: WebhookTopic,
47    payload: Value,
48) -> Result<WebhookPayload, WebhookParseError> {
49    match topic {
50        WebhookTopic::CustomersDataRequest => {
51            serde_json::from_value::<CustomersDataRequestPayload>(payload)
52                .map(WebhookPayload::CustomersDataRequest)
53                .map_err(|e| WebhookParseError::ParseError(e.to_string()))
54        }
55        WebhookTopic::CustomersRedact => serde_json::from_value::<CustomersRedactPayload>(payload)
56            .map(WebhookPayload::CustomersRedact)
57            .map_err(|e| WebhookParseError::ParseError(e.to_string())),
58        WebhookTopic::ShopRedact => serde_json::from_value::<ShopRedactPayload>(payload)
59            .map(WebhookPayload::ShopRedact)
60            .map_err(|e| WebhookParseError::ParseError(e.to_string())),
61    }
62}
63
64pub fn parse_webhook_with_header(
65    topic_header: &str,
66    payload: &str,
67) -> Result<WebhookPayload, WebhookParseError> {
68    let topic =
69        WebhookTopic::from_header(topic_header).ok_or(WebhookParseError::UnknownWebhookType)?;
70    parse_webhook(topic, payload)
71}
72
73pub fn parse_webhook_with_header_from_value(
74    topic_header: &str,
75    payload: Value,
76) -> Result<WebhookPayload, WebhookParseError> {
77    let topic =
78        WebhookTopic::from_header(topic_header).ok_or(WebhookParseError::UnknownWebhookType)?;
79    parse_webhook_from_value(topic, payload)
80}
81
82pub fn try_parse_webhook(payload: &str) -> Result<WebhookPayload, WebhookParseError> {
83    if let Ok(data_request) = serde_json::from_str::<CustomersDataRequestPayload>(payload) {
84        return Ok(WebhookPayload::CustomersDataRequest(data_request));
85    }
86
87    if let Ok(customers_redact) = serde_json::from_str::<CustomersRedactPayload>(payload) {
88        return Ok(WebhookPayload::CustomersRedact(customers_redact));
89    }
90
91    if let Ok(shop_redact) = serde_json::from_str::<ShopRedactPayload>(payload) {
92        return Ok(WebhookPayload::ShopRedact(shop_redact));
93    }
94
95    Err(WebhookParseError::UnknownWebhookType)
96}
97
98pub fn try_parse_webhook_from_value(payload: Value) -> Result<WebhookPayload, WebhookParseError> {
99    if let Ok(data_request) = serde_json::from_value::<CustomersDataRequestPayload>(payload.clone())
100    {
101        return Ok(WebhookPayload::CustomersDataRequest(data_request));
102    }
103
104    if let Ok(customers_redact) = serde_json::from_value::<CustomersRedactPayload>(payload.clone())
105    {
106        return Ok(WebhookPayload::CustomersRedact(customers_redact));
107    }
108
109    if let Ok(shop_redact) = serde_json::from_value::<ShopRedactPayload>(payload) {
110        return Ok(WebhookPayload::ShopRedact(shop_redact));
111    }
112
113    Err(WebhookParseError::UnknownWebhookType)
114}