Last active
January 21, 2025 12:52
-
-
Save r0yfire/2ce76b0236704a070eedfb4eb78d2095 to your computer and use it in GitHub Desktop.
Convert Stripe webhook event to the Autohost Payment Event expected format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** https://docs.autohost.ai/api#operation/reservations-payment-event **/ | |
/** | |
* Get the event type and status from a Stripe event | |
* @param {any} event - The Stripe event | |
* @returns {{event_type: string, event_status: string}} - The event type and status | |
*/ | |
const stripeEventType = ( | |
event: any | |
): { event_type: string; event_status: string } => { | |
let output: { event_type: string; event_status: string } = { | |
event_type: "", | |
event_status: "", | |
}; | |
const parts = event.event_type.split("."); | |
const eventStatuses = { | |
charge: { | |
captured: "success", | |
failed: "failure", | |
succeeded: "success", | |
updated: "success", | |
dispute: { | |
created: "warning", | |
funds_withdrawn: "failure", | |
}, | |
}, | |
}; | |
const status = eventStatuses[parts[0]]?.[parts[1]]; | |
if (status) { | |
output = { | |
event_type: parts[0], | |
event_status: status, | |
}; | |
if (event.event_type === "charge.succeeded" && !event.captured) { | |
output.event_type = "authorization"; | |
} | |
if (event.event_type === "charge.dispute.created") { | |
output.event_type = "dispute"; | |
} | |
if (event.event_type === "charge.dispute.funds_withdrawn") { | |
output.event_type = "chargeback"; | |
} | |
} | |
return output; | |
}; | |
/** | |
* Normalize a Stripe payment event | |
* @param {any} props - The Stripe payment event | |
* @returns {Promise<any>} - The normalized payment event | |
*/ | |
export const normalizeStripePaymentEvent = async (props: any): Promise<any> => { | |
props = JSON.parse(JSON.stringify(props)); | |
if ( | |
props.last_payment_error && | |
props.last_payment_error.charge && | |
props.charges | |
) { | |
props.charge = props.charges.data.find( | |
(charge) => charge.id === props.last_payment_error.charge | |
); | |
} | |
const { event_type, event_status } = stripeEventType(props); | |
const eventData = { | |
timestamp: new Date(props.created * 1000).getTime(), | |
user_id: props.user_id, | |
reservation_id: props.reservation_id, | |
event_source: "stripe", | |
event_id: props.id, | |
event_type: event_type, | |
event_status: event_status, | |
processor_status_code: props.outcome?.reason || props.failure_code || props.outcome?.type, | |
processor_message: props.failure_message || props.outcome?.type, | |
network_status_code: props.outcome?.network_status, | |
three_d_secure: props.payment_method_details?.card?.three_d_secure?.result, | |
amount: Math.round(props.amount / 100), | |
currency: (props.currency || "").toLowerCase(), | |
customer_id: props.customer, | |
name_on_card: props.source?.name || props.billing_details?.name, | |
charge_descriptor: props.description || props.calculated_statement_descriptor, | |
payment_method: props.payment_method_details?.type || props.source?.object, | |
card_type: props.source?.funding || props.payment_method_details?.card?.funding, | |
card_provider: props.source?.brand || props.payment_method_details?.card?.network, | |
card_country: props.payment_method_details?.card?.country, | |
card_last4: props.source?.last4 || props.payment_method_details?.card?.last4, | |
card_expiry_month: props.source?.exp_month || props.payment_method_details?.card?.exp_month, | |
card_expiry_year: props.source?.exp_year || props.payment_method_details?.card?.exp_year, | |
card_fingerprint: props.source?.fingerprint || props.payment_method_details?.card?.fingerprint, | |
billing_country_code: props.billing_details?.address?.country, | |
billing_address: props.billing_details?.address?.line1, | |
billing_address2: props.billing_details?.address?.line2, | |
billing_city: props.billing_details?.address?.city, | |
billing_state: props.billing_details?.address?.state, | |
billing_postal_code: props.billing_details?.address?.postal_code, | |
billing_phone: props.billing_details?.phone, | |
billing_email: props.billing_details?.email, | |
billing_name: props.billing_details?.name, | |
ip_address: props.metadata?.user_ip, | |
user_agent: props.metadata?.user_agent, | |
}; | |
if (eventData.card_expiry_month) { | |
eventData.card_expiry_month = eventData.card_expiry_month.toString().padStart(2, '0'); | |
} | |
return eventData; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment