hotel_stay v1

examples/hotel/temporal/hotel.flow · dandori doc

When a stay is booked, hold an amount on the card, and capture it on the day of check-out. A rule decides the amount and whether the front desk looks first; the payment is a Stripe PaymentIntent. Written for Temporal: the Stripe calls are activities dandori writes, and the Transport gives them the secret key; Stripe's webhook tells the workflow of the booking that the customer's 3-D Secure step is over, by the booking's id (an event); and a booking the guest cancels releases its hold (on cancel)

flow
repeat at most 12 timesreviewautoon card_declinedrequires_actionon timeoutrequires_capture,requires_payment_method,requires_confirmation,canceledrequires_capturerequires_payment_method,requires_confirmation,requires_actionon unexpected_statecanceledon unexpected_statesucceededprocessingsucceeded,requires_payment_methodprocessingafter 12 roundssucceededprocessing,requires_payment_methodhotel_stay v175 quote = hold(…)rule hold_amount.ruletimeout, failure → on failure!76 match quote.handling77 succeed outcome = awaiting_review78 pi ← create_intent(…)POST stripe /v1/payment_intentsstarts · retry 2 times every 2 secondstimeout, failure → on failure!79 pi ← confirm_intent(…)POST stripe /v1/payment_intents/{intent}/confirmsends confirmcard_declined → line 80; unexpected_state, timeout, failure → on failure!80 pi ← get_intent(…)GET stripe /v1/payment_intents/{intent}observes · retry 3 times every 2 secondstimeout, failure → on failure!81 match pi.status83 pi ← customer_authenticated()eventobserves · timeout 1 hourtimeout → line 84; failure → on failure!84 pi ← get_intent(…)GET stripe /v1/payment_intents/{intent}observes · retry 3 times every 2 secondstimeout, failure → on failure!86 match pi.status87 wait until booking.check_out89 pi ← cancel_intent(…)POST stripe /v1/payment_intents/{intent}/cancelsends cancelunexpected_state → line 90; timeout, failure → on failure!91 fail CardDeclined"The card could not be held"92 fail PaymentCanceled"The PaymentIntent was canceled"93 pi ← capture_intent(…)POST stripe /v1/payment_intents/{intent}/capturesends capture · retry 2 times every 5 secondsunexpected_state → line 94; timeout, failure → on failure!94 fail HoldExpired"The hold had expired by check-out"95 match pi.status96 succeed outcome = stayed99 wait 1 hour100 pi ← get_intent(…)GET stripe /v1/payment_intents/{intent}observes · retry 3 times every 2 secondstimeout, failure → on failure!101 match pi.status103 break104 match pi.status105 succeed outcome = stayed106 fail SettlementUnclear"The capture has no clear outcome; handing it o…leaving pi
on failure
requires_payment_method,requires_confirmation,requires_action,requires_captureon unexpected_stateon failureprocessingnone108 on failure109 match pi.status112 pi ← cancel_intent(…)POST stripe /v1/payment_intents/{intent}/cancelsends cancel113 fail CleanupFailed"Stripe refused to release the hold; the captur…leaving pi114 fail CleanupFailed"Releasing the hold failed; handing it over to …leaving pi115 fail SettlementUnclear"Failed in the middle of the capture; handing i…leaving pifails with the same error
on cancel
requires_payment_method,requires_confirmation,requires_action,requires_captureon unexpected_stateon failureprocessingnone118 on cancel119 match pi.status122 pi ← cancel_intent(…)POST stripe /v1/payment_intents/{intent}/cancelsends cancel123 fail CleanupFailed"Stripe refused to release the hold; the captur…leaving pi124 fail CleanupFailed"Releasing the hold failed; handing it over to …leaving pi125 fail SettlementUnclear"Cancelled in the middle of the capture; handin…leaving piends cancelled

Calls

LineCallCallsRetriesTimeoutWhen it failsCase after
75quote = hold(…)rule hold_amount.rule2 times, after 1 second and 2 (failure)—timeout, failure → on failure—
78pi ← create_intent(…)POST stripe /v1/payment_intents, starts payment_intent.payment then attach, key2 times every 2 seconds (failure, timeout)—timeout, failure → on failurepi: requires_confirmation
79pi ← confirm_intent(…)POST stripe /v1/payment_intents/{intent}/confirm, sends confirm, key——card_declined → line 80
unexpected_state, timeout, failure → on failure
pi: requires_payment_method, requires_action, requires_capture, canceled
80pi ← get_intent(…)GET stripe /v1/payment_intents/{intent}, observes, idempotent3 times every 2 seconds (failure, timeout)—timeout, failure → on failurepi: requires_payment_method, requires_confirmation, requires_action, requires_capture, canceled
83pi ← customer_authenticated()event, observes—1 hourtimeout → line 84
failure → on failure
pi: requires_payment_method, requires_action, requires_capture, canceled
84pi ← get_intent(…)GET stripe /v1/payment_intents/{intent}, observes, idempotent3 times every 2 seconds (failure, timeout)—timeout, failure → on failurepi: requires_payment_method, requires_action, requires_capture, canceled
89pi ← cancel_intent(…)POST stripe /v1/payment_intents/{intent}/cancel, sends cancel, key——unexpected_state → line 90
timeout, failure → on failure
pi: canceled
93pi ← capture_intent(…)POST stripe /v1/payment_intents/{intent}/capture, sends capture, key2 times every 5 seconds (failure, timeout)—unexpected_state → line 94
timeout, failure → on failure
pi: processing, succeeded
100pi ← get_intent(…)GET stripe /v1/payment_intents/{intent}, observes, idempotent3 times every 2 seconds (failure, timeout)—timeout, failure → on failurepi: requires_payment_method, processing, succeeded
112pi ← cancel_intent(…)POST stripe /v1/payment_intents/{intent}/cancel, sends cancel, key——unexpected_state → line 113
timeout, failure → line 114
pi: canceled
122pi ← cancel_intent(…)POST stripe /v1/payment_intents/{intent}/cancel, sends cancel, key——unexpected_state → line 123
timeout, failure → line 124
pi: canceled

Ends

LineEndpi
77succeed outcome = awaiting_reviewnot started
91fail CardDeclined "The card could not be held"canceled
92fail PaymentCanceled "The PaymentIntent was canceled"canceled
94fail HoldExpired "The hold had expired by check-out"canceled
96succeed outcome = stayedsucceeded
105succeed outcome = stayedsucceeded
106fail SettlementUnclear "The capture has no clear outcome; handing it over to staff" leaving pihanded over as it is: requires_payment_method, processing, succeeded
113fail CleanupFailed "Stripe refused to release the hold; the capture may have gone through. Handing it over to staff" leaving pihanded over as it is: requires_payment_method, processing, succeeded, canceled
114fail CleanupFailed "Releasing the hold failed; handing it over to staff" leaving pihanded over as it is: requires_payment_method, requires_confirmation, requires_action, processing, requires_capture, succeeded, canceled
115fail SettlementUnclear "Failed in the middle of the capture; handing it over to staff" leaving pihanded over as it is: requires_payment_method, processing, succeeded
115on failure runs to its end, and the workflow fails with the error that started itnot started, or canceled
123fail CleanupFailed "Stripe refused to release the hold; the capture may have gone through. Handing it over to staff" leaving pihanded over as it is: requires_payment_method, processing, succeeded, canceled
124fail CleanupFailed "Releasing the hold failed; handing it over to staff" leaving pihanded over as it is: requires_payment_method, requires_confirmation, requires_action, processing, requires_capture, succeeded, canceled
125fail SettlementUnclear "Cancelled in the middle of the capture; handing it over to staff" leaving pihanded over as it is: requires_payment_method, processing, succeeded
125on cancel runs to its end, and the workflow ends cancellednot started, or canceled