flamingo.me/flamingo-commerce/v3@v3.11.0/checkout/module.go (about) 1 package checkout 2 3 import ( 4 "flamingo.me/dingo" 5 "github.com/go-playground/form/v4" 6 7 "flamingo.me/flamingo/v3/core/healthcheck/domain/healthcheck" 8 "flamingo.me/flamingo/v3/framework/flamingo" 9 "flamingo.me/flamingo/v3/framework/web" 10 flamingographql "flamingo.me/graphql" 11 12 "flamingo.me/flamingo-commerce/v3/checkout/infrastructure/contextstore" 13 "flamingo.me/flamingo-commerce/v3/checkout/interfaces/graphql/dto" 14 "flamingo.me/flamingo-commerce/v3/payment" 15 16 "flamingo.me/flamingo-commerce/v3/cart" 17 "flamingo.me/flamingo-commerce/v3/checkout/application/placeorder" 18 "flamingo.me/flamingo-commerce/v3/checkout/domain/placeorder/process" 19 "flamingo.me/flamingo-commerce/v3/checkout/domain/placeorder/states" 20 "flamingo.me/flamingo-commerce/v3/checkout/infrastructure/locker" 21 "flamingo.me/flamingo-commerce/v3/checkout/interfaces/controller" 22 "flamingo.me/flamingo-commerce/v3/checkout/interfaces/graphql" 23 ) 24 25 type ( 26 // Module registers our checkout module 27 Module struct { 28 PlaceOrderLockType string `inject:"config:commerce.checkout.placeorder.lock.type"` 29 PlaceOrderContextStore string `inject:"config:commerce.checkout.placeorder.contextstore.type"` 30 } 31 ) 32 33 // Configure module 34 func (m *Module) Configure(injector *dingo.Injector) { 35 injector.Bind((*form.Decoder)(nil)).ToProvider(form.NewDecoder).AsEagerSingleton() 36 37 if m.PlaceOrderLockType == "redis" { 38 injector.Bind(new(locker.Redis)).ToProvider(locker.NewRedis).In(dingo.Singleton) 39 injector.Bind(new(placeorder.TryLocker)).To(new(locker.Redis)) 40 injector.BindMap(new(healthcheck.Status), "placeorder.locker.redis").To(new(locker.Redis)) 41 } else { 42 injector.Bind(new(placeorder.TryLocker)).ToProvider(locker.NewMemory).In(dingo.Singleton) 43 } 44 45 if m.PlaceOrderContextStore == "redis" { 46 injector.Bind(new(contextstore.Redis)).In(dingo.Singleton) 47 injector.Bind(new(process.ContextStore)).To(new(contextstore.Redis)) 48 injector.BindMap(new(healthcheck.Status), "placeorder.contextstore.redis").To(new(contextstore.Redis)) 49 } else { 50 injector.Bind(new(process.ContextStore)).To(new(contextstore.Memory)).In(dingo.Singleton) 51 } 52 53 injector.Bind(new(process.PaymentValidatorFunc)).ToInstance(placeorder.PaymentValidator) 54 55 injector.Bind(new(process.State)).AnnotatedWith("startState").To(states.New{}) 56 injector.Bind(new(process.State)).AnnotatedWith("failedState").To(states.Failed{}) 57 injector.BindMap(new(process.State), new(states.New).Name()).To(states.New{}) 58 injector.BindMap(new(process.State), new(states.PrepareCart).Name()).To(states.PrepareCart{}) 59 injector.BindMap(new(process.State), new(states.ValidateCart).Name()).To(states.ValidateCart{}) 60 injector.BindMap(new(process.State), new(states.ValidatePaymentSelection).Name()).To(states.ValidatePaymentSelection{}) 61 injector.BindMap(new(process.State), new(states.CreatePayment).Name()).To(states.CreatePayment{}) 62 injector.BindMap(new(process.State), new(states.CompleteCart).Name()).To(states.CompleteCart{}) 63 injector.BindMap(new(process.State), new(states.CompletePayment).Name()).To(states.CompletePayment{}) 64 injector.BindMap(new(process.State), new(states.PlaceOrder).Name()).To(states.PlaceOrder{}) 65 injector.BindMap(new(process.State), new(states.ValidatePayment).Name()).To(states.ValidatePayment{}) 66 injector.BindMap(new(process.State), new(states.WaitForCustomer).Name()).To(states.WaitForCustomer{}) 67 injector.BindMap(new(process.State), new(states.Success).Name()).To(states.Success{}) 68 injector.BindMap(new(process.State), new(states.Failed).Name()).To(states.Failed{}) 69 injector.BindMap(new(process.State), new(states.ShowIframe).Name()).To(states.ShowIframe{}) 70 injector.BindMap(new(process.State), new(states.ShowHTML).Name()).To(states.ShowHTML{}) 71 injector.BindMap(new(process.State), new(states.ShowWalletPayment).Name()).To(states.ShowWalletPayment{}) 72 injector.BindMap(new(process.State), new(states.Redirect).Name()).To(states.Redirect{}) 73 injector.BindMap(new(process.State), new(states.PostRedirect).Name()).To(states.PostRedirect{}) 74 injector.BindMap(new(process.State), new(states.TriggerClientSDK).Name()).To(states.TriggerClientSDK{}) 75 76 // bind internal states to graphQL states 77 injector.BindMap(new(dto.State), new(states.New).Name()).To(dto.Wait{}) 78 injector.BindMap(new(dto.State), new(states.PrepareCart).Name()).To(dto.Wait{}) 79 injector.BindMap(new(dto.State), new(states.ValidateCart).Name()).To(dto.Wait{}) 80 injector.BindMap(new(dto.State), new(states.ValidatePaymentSelection).Name()).To(dto.Wait{}) 81 injector.BindMap(new(dto.State), new(states.CreatePayment).Name()).To(dto.Wait{}) 82 injector.BindMap(new(dto.State), new(states.CompleteCart).Name()).To(dto.Wait{}) 83 injector.BindMap(new(dto.State), new(states.CompletePayment).Name()).To(dto.Wait{}) 84 injector.BindMap(new(dto.State), new(states.PlaceOrder).Name()).To(dto.Wait{}) 85 injector.BindMap(new(dto.State), new(states.ValidatePayment).Name()).To(dto.Wait{}) 86 injector.BindMap(new(dto.State), new(states.WaitForCustomer).Name()).To(dto.WaitForCustomer{}) 87 injector.BindMap(new(dto.State), new(states.Success).Name()).To(dto.Success{}) 88 injector.BindMap(new(dto.State), new(states.Failed).Name()).To(dto.Failed{}) 89 injector.BindMap(new(dto.State), new(states.ShowHTML).Name()).To(dto.ShowHTML{}) 90 injector.BindMap(new(dto.State), new(states.ShowWalletPayment).Name()).To(dto.ShowWalletPayment{}) 91 injector.BindMap(new(dto.State), new(states.ShowIframe).Name()).To(dto.ShowIframe{}) 92 injector.BindMap(new(dto.State), new(states.Redirect).Name()).To(dto.Redirect{}) 93 injector.BindMap(new(dto.State), new(states.PostRedirect).Name()).To(dto.PostRedirect{}) 94 injector.BindMap(new(dto.State), new(states.TriggerClientSDK).Name()).To(dto.TriggerClientSDK{}) 95 96 web.BindRoutes(injector, new(routes)) 97 web.BindRoutes(injector, new(apiRoutes)) 98 99 injector.BindMulti(new(flamingographql.Service)).To(graphql.Service{}) 100 } 101 102 // CueConfig definition 103 func (m *Module) CueConfig() string { 104 // language=cue 105 return ` 106 commerce: checkout: { 107 Redis :: { 108 maxIdle: number | *25 109 idleTimeoutMilliseconds: number | *240000 110 network: string | *"tcp" 111 address: string | *"localhost:6379" 112 database: number | *0 113 ttl: string | *"2h" 114 } 115 useDeliveryForms: bool | *true 116 usePersonalDataForm: bool | *false 117 skipReviewAction: bool | *false 118 skipStartAction?: bool 119 showReviewStepAfterPaymentError?: bool 120 showEmptyCartPageIfNoItems?: bool 121 redirectToCartOnInvalidCart?: bool 122 privacyPolicyRequired?: bool 123 placeorder: { 124 lock: { 125 type: *"memory" | "redis" 126 if type == "redis" { 127 redis: Redis 128 } 129 } 130 contextstore: { 131 type: *"memory" | "redis" 132 if type == "redis" { 133 redis: Redis 134 } 135 } 136 states: { 137 placeorder: { 138 cancelOrdersDuringRollback: bool | *false 139 } 140 } 141 } 142 }` 143 } 144 145 // FlamingoLegacyConfigAlias mapping 146 func (m *Module) FlamingoLegacyConfigAlias() map[string]string { 147 return map[string]string{ 148 "checkout.useDeliveryForms": "commerce.checkout.useDeliveryForms", 149 "checkout.usePersonalDataForm": "commerce.checkout.usePersonalDataForm", 150 "checkout.skipReviewAction": "commerce.checkout.skipReviewAction", 151 "checkout.skipStartAction": "commerce.checkout.skipStartAction", 152 "checkout.showReviewStepAfterPaymentError": "commerce.checkout.showReviewStepAfterPaymentError", 153 "checkout.showEmptyCartPageIfNoItems": "commerce.checkout.showEmptyCartPageIfNoItems", 154 "checkout.redirectToCartOnInvalideCart": "commerce.checkout.redirectToCartOnInvalidCart", 155 "checkout.privacyPolicyRequired": "commerce.checkout.privacyPolicyRequired", 156 } 157 } 158 159 type routes struct { 160 controller *controller.CheckoutController 161 } 162 163 // Inject required controller 164 func (r *routes) Inject(controller *controller.CheckoutController) { 165 r.controller = controller 166 } 167 168 // Routes configuration for checkout controllers 169 func (r *routes) Routes(registry *web.RouterRegistry) { 170 // routes 171 registry.HandleAny("checkout.start", r.controller.StartAction) 172 registry.MustRoute("/checkout/start", "checkout.start") 173 174 registry.HandleAny("checkout.review", r.controller.ReviewAction) 175 registry.MustRoute("/checkout/review", `checkout.review`) 176 177 registry.HandleAny("checkout", r.controller.SubmitCheckoutAction) 178 registry.MustRoute("/checkout", "checkout") 179 180 registry.HandleAny("checkout.payment", r.controller.PaymentAction) 181 registry.MustRoute("/checkout/payment", "checkout.payment") 182 183 registry.HandleAny("checkout.success", r.controller.SuccessAction) 184 registry.MustRoute("/checkout/success", "checkout.success") 185 186 registry.HandleAny("checkout.expired", r.controller.ExpiredAction) 187 registry.MustRoute("/checkout/expired", "checkout.expired") 188 189 registry.HandleAny("checkout.placeorder", r.controller.PlaceOrderAction) 190 registry.MustRoute("/checkout/placeorder", "checkout.placeorder") 191 } 192 193 // Depends on other modules 194 func (m *Module) Depends() []dingo.Module { 195 return []dingo.Module{ 196 new(cart.Module), 197 new(payment.Module), 198 new(flamingo.SessionModule), 199 } 200 } 201 202 type apiRoutes struct { 203 apiController *controller.APIController 204 } 205 206 func (r *apiRoutes) Inject(apiController *controller.APIController) { 207 r.apiController = apiController 208 } 209 210 func (r *apiRoutes) Routes(registry *web.RouterRegistry) { 211 registry.MustRoute("/api/v1/checkout/placeorder", "checkout.api.placeorder") 212 registry.HandleGet("checkout.api.placeorder", r.apiController.CurrentPlaceOrderContextAction) 213 registry.HandlePut("checkout.api.placeorder", r.apiController.StartPlaceOrderAction) 214 registry.HandleDelete("checkout.api.placeorder", r.apiController.ClearPlaceOrderAction) 215 216 registry.MustRoute("/api/v1/checkout/placeorder/cancel", "checkout.api.placeorder.cancel") 217 registry.HandlePost("checkout.api.placeorder.cancel", r.apiController.CancelPlaceOrderAction) 218 219 registry.MustRoute("/api/v1/checkout/placeorder/refresh", "checkout.api.placeorder.refresh") 220 registry.HandlePost("checkout.api.placeorder.refresh", r.apiController.RefreshPlaceOrderAction) 221 222 registry.MustRoute("/api/v1/checkout/placeorder/refresh-blocking", "checkout.api.placeorder.refreshblocking") 223 registry.HandlePost("checkout.api.placeorder.refreshblocking", r.apiController.RefreshPlaceOrderBlockingAction) 224 }