refactor
This commit is contained in:
+81
-20
@@ -64,7 +64,7 @@ const PlaceOrderVar = "placeOrder"
|
||||
// grain through app and taking payment via provider. Compose with
|
||||
// flow.RegisterBuiltinHooks(reg) to get the "log"/"webhook" hooks too.
|
||||
func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvider) {
|
||||
reg.Action("place_order", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
|
||||
reg.ActionWithMeta("place_order", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
|
||||
po, ok := st.Vars[PlaceOrderVar].(*messages.PlaceOrder)
|
||||
if !ok || po == nil {
|
||||
return fmt.Errorf("place_order: flow var %q is not a *PlaceOrder", PlaceOrderVar)
|
||||
@@ -78,9 +78,9 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
|
||||
st.Vars["currency"] = po.GetCurrency()
|
||||
st.Vars["orderReference"] = po.GetOrderReference()
|
||||
return nil
|
||||
})
|
||||
}, flow.CapabilityMeta{Description: "Create the order from the flow state variable `placeOrder`."})
|
||||
|
||||
reg.Action("authorize_payment", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
|
||||
reg.ActionWithMeta("authorize_payment", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
|
||||
o, err := app.Get(ctx, st.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -101,9 +101,9 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
|
||||
st.Vars["authProvider"] = auth.Provider
|
||||
st.Vars["authAmount"] = auth.Amount
|
||||
return nil
|
||||
})
|
||||
}, flow.CapabilityMeta{Description: "Authorize payment with the configured provider."})
|
||||
|
||||
reg.Action("capture_payment", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
|
||||
reg.ActionWithMeta("capture_payment", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
|
||||
authRef, _ := st.Vars["authRef"].(string)
|
||||
amount, _ := st.Vars["authAmount"].(int64)
|
||||
if amount == 0 {
|
||||
@@ -121,11 +121,11 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
|
||||
Reference: capture.Reference,
|
||||
AtMs: nowMs(),
|
||||
})
|
||||
})
|
||||
}, flow.CapabilityMeta{Description: "Capture the authorized payment."})
|
||||
|
||||
// void_payment is the compensation for authorize_payment: void with the
|
||||
// provider and cancel the order if it is still in a cancellable state.
|
||||
reg.Action("void_payment", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
|
||||
reg.ActionWithMeta("void_payment", func(ctx context.Context, st *flow.State, _ json.RawMessage) error {
|
||||
if authRef, ok := st.Vars["authRef"].(string); ok && authRef != "" {
|
||||
if err := provider.Void(ctx, authRef); err != nil {
|
||||
return err
|
||||
@@ -134,9 +134,9 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
|
||||
// Best-effort cancel; ignore if no longer cancellable.
|
||||
_, _ = app.Apply(ctx, st.ID, &messages.CancelOrder{Reason: "compensation: payment voided", AtMs: nowMs()})
|
||||
return nil
|
||||
})
|
||||
}, flow.CapabilityMeta{Description: "Void the authorization and cancel the order as compensation."})
|
||||
|
||||
reg.Action("cancel_order", func(ctx context.Context, st *flow.State, params json.RawMessage) error {
|
||||
reg.ActionWithMeta("cancel_order", func(ctx context.Context, st *flow.State, params json.RawMessage) error {
|
||||
reason := "cancelled"
|
||||
if len(params) > 0 {
|
||||
var p struct {
|
||||
@@ -147,9 +147,12 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
|
||||
}
|
||||
}
|
||||
return applyOne(ctx, app, st.ID, &messages.CancelOrder{Reason: reason, AtMs: nowMs()})
|
||||
}, flow.CapabilityMeta{
|
||||
Description: "Cancel the order with an optional reason.",
|
||||
ExampleParams: json.RawMessage(`{"reason":"customer requested cancellation"}`),
|
||||
})
|
||||
|
||||
reg.Action("issue_refund", func(ctx context.Context, st *flow.State, params json.RawMessage) error {
|
||||
reg.ActionWithMeta("issue_refund", func(ctx context.Context, st *flow.State, params json.RawMessage) error {
|
||||
o, err := app.Get(ctx, st.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -180,6 +183,64 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
|
||||
Reference: ref.Reference,
|
||||
AtMs: nowMs(),
|
||||
})
|
||||
}, flow.CapabilityMeta{
|
||||
Description: "Refund the remaining or specified captured amount.",
|
||||
ExampleParams: json.RawMessage(`{"amount":2500}`),
|
||||
})
|
||||
|
||||
reg.ActionWithMeta("create_fulfillment", func(ctx context.Context, st *flow.State, params json.RawMessage) error {
|
||||
var p struct {
|
||||
ID string `json:"id"`
|
||||
Carrier string `json:"carrier,omitempty"`
|
||||
TrackingNumber string `json:"trackingNumber,omitempty"`
|
||||
TrackingURI string `json:"trackingUri,omitempty"`
|
||||
AtMs int64 `json:"atMs,omitempty"`
|
||||
Lines []struct {
|
||||
Reference string `json:"reference"`
|
||||
Quantity int32 `json:"quantity"`
|
||||
} `json:"lines"`
|
||||
}
|
||||
if err := json.Unmarshal(params, &p); err != nil {
|
||||
return fmt.Errorf("create_fulfillment: bad params: %w", err)
|
||||
}
|
||||
if len(p.Lines) == 0 {
|
||||
return fmt.Errorf("create_fulfillment: missing lines")
|
||||
}
|
||||
id := p.ID
|
||||
if id == "" {
|
||||
fid, err := NewOrderId()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id = "f_" + fid.String()
|
||||
}
|
||||
atMs := p.AtMs
|
||||
if atMs == 0 {
|
||||
atMs = nowMs()
|
||||
}
|
||||
msg := &messages.CreateFulfillment{
|
||||
Id: id,
|
||||
Carrier: p.Carrier,
|
||||
TrackingNumber: p.TrackingNumber,
|
||||
TrackingUri: p.TrackingURI,
|
||||
AtMs: atMs,
|
||||
}
|
||||
for _, line := range p.Lines {
|
||||
if line.Reference == "" {
|
||||
return fmt.Errorf("create_fulfillment: line missing reference")
|
||||
}
|
||||
if line.Quantity <= 0 {
|
||||
return fmt.Errorf("create_fulfillment: line %q has invalid quantity %d", line.Reference, line.Quantity)
|
||||
}
|
||||
msg.Lines = append(msg.Lines, &messages.FulfillmentLine{
|
||||
Reference: line.Reference,
|
||||
Quantity: line.Quantity,
|
||||
})
|
||||
}
|
||||
return applyOne(ctx, app, st.ID, msg)
|
||||
}, flow.CapabilityMeta{
|
||||
Description: "Create a shipment / fulfillment and advance the order fulfillment status.",
|
||||
ExampleParams: json.RawMessage(`{"carrier":"dropshipper","trackingNumber":"TRACK-123","trackingUri":"https://tracking.example/TRACK-123","lines":[{"reference":"l1","quantity":1}]}`),
|
||||
})
|
||||
|
||||
registerPredicates(reg, app)
|
||||
@@ -193,39 +254,39 @@ func RegisterFlowActions(reg *flow.Registry, app Applier, provider PaymentProvid
|
||||
func registerPredicates(reg *flow.Registry, app Applier) {
|
||||
get := func(ctx context.Context, st *flow.State) (*OrderGrain, error) { return app.Get(ctx, st.ID) }
|
||||
|
||||
reg.Predicate("has_customer_email", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
reg.PredicateWithMeta("has_customer_email", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
o, err := get(ctx, st)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return o.CustomerEmail != "", nil
|
||||
})
|
||||
reg.Predicate("has_items", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
}, flow.CapabilityMeta{Description: "Run only when the order has a customer email address."})
|
||||
reg.PredicateWithMeta("has_items", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
o, err := get(ctx, st)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(o.Lines) > 0, nil
|
||||
})
|
||||
reg.Predicate("is_captured", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
}, flow.CapabilityMeta{Description: "Run only when the order contains at least one line item."})
|
||||
reg.PredicateWithMeta("is_captured", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
o, err := get(ctx, st)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return o.Status == StatusCaptured, nil
|
||||
})
|
||||
reg.Predicate("not_captured", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
}, flow.CapabilityMeta{Description: "Run only after payment has been captured."})
|
||||
reg.PredicateWithMeta("not_captured", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
o, err := get(ctx, st)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return o.Status != StatusCaptured, nil
|
||||
})
|
||||
reg.Predicate("has_open_balance", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
}, flow.CapabilityMeta{Description: "Run only before payment is captured."})
|
||||
reg.PredicateWithMeta("has_open_balance", func(ctx context.Context, st *flow.State) (bool, error) {
|
||||
o, err := get(ctx, st)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return o.CapturedAmount-o.RefundedAmount > 0, nil
|
||||
})
|
||||
}, flow.CapabilityMeta{Description: "Run only when captured amount remains to refund."})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user