flamingo.me/flamingo-commerce/v3@v3.11.0/checkout/interfaces/graphql/dto/states.go (about) 1 package dto 2 3 import ( 4 "fmt" 5 "net/url" 6 7 "flamingo.me/flamingo-commerce/v3/checkout/domain/placeorder/process" 8 "flamingo.me/flamingo-commerce/v3/checkout/domain/placeorder/states" 9 ) 10 11 type ( 12 // StateProvider returns a state instance 13 StateProvider func() map[string]State 14 15 // State representation for graphql 16 State interface { 17 MapFrom(process.Context) 18 } 19 20 // StateMapper to create dto states from context states 21 StateMapper struct { 22 stateProvider StateProvider 23 } 24 25 // Failed state 26 Failed struct { 27 Name string 28 Reason process.FailedReason 29 } 30 // Success state 31 Success struct { 32 Name string 33 } 34 // Wait state 35 Wait struct { 36 Name string 37 } 38 // WaitForCustomer state 39 WaitForCustomer struct { 40 Name string 41 } 42 // ShowIframe state 43 ShowIframe struct { 44 Name string 45 URL string 46 } 47 // ShowHTML state 48 ShowHTML struct { 49 Name string 50 HTML string 51 } 52 // Redirect state 53 Redirect struct { 54 Name string 55 URL string 56 } 57 // PostRedirect state 58 PostRedirect struct { 59 Name string 60 URL string 61 Parameters []FormParameter 62 } 63 // FormParameter holds redirect related form data 64 FormParameter struct { 65 Key string 66 Value []string 67 } 68 69 // ShowWalletPayment state 70 ShowWalletPayment struct { 71 Name string 72 PaymentMethod string 73 PaymentRequestAPI PaymentRequestAPI 74 } 75 76 // TriggerClientSDK state 77 TriggerClientSDK struct { 78 Name string 79 URL string 80 Data string 81 } 82 83 // PaymentRequestAPI holds all data needed to create a PaymentRequest 84 PaymentRequestAPI struct { 85 MethodData string 86 Details string 87 Options string 88 MerchantValidationURL *string 89 CompleteURL string 90 } 91 ) 92 93 var ( 94 _ State = new(Failed) 95 _ State = new(Success) 96 _ State = new(Wait) 97 _ State = new(WaitForCustomer) 98 _ State = new(ShowIframe) 99 _ State = new(ShowHTML) 100 _ State = new(Redirect) 101 _ State = new(PostRedirect) 102 _ State = new(ShowWalletPayment) 103 _ State = new(TriggerClientSDK) 104 ) 105 106 // MapFrom the internal process state to the graphQL state fields 107 func (s *Failed) MapFrom(pctx process.Context) { 108 s.Name = pctx.CurrentStateName 109 s.Reason = pctx.FailedReason 110 } 111 112 // MapFrom the internal process state to the graphQL state fields 113 func (s *ShowWalletPayment) MapFrom(pctx process.Context) { 114 s.Name = pctx.CurrentStateName 115 if stateData, ok := pctx.CurrentStateData.(states.ShowWalletPaymentData); ok { 116 s.PaymentMethod = stateData.UsedPaymentMethod 117 s.PaymentRequestAPI = PaymentRequestAPI{ 118 CompleteURL: func() string { 119 if stateData.PaymentRequestAPI.CompleteURL == nil { 120 return "" 121 } 122 return stateData.PaymentRequestAPI.CompleteURL.String() 123 }(), 124 MerchantValidationURL: func() *string { 125 if stateData.PaymentRequestAPI.MerchantValidationURL == nil { 126 return nil 127 } 128 result := stateData.PaymentRequestAPI.MerchantValidationURL.String() 129 return &result 130 }(), 131 Details: stateData.PaymentRequestAPI.Details, 132 Options: stateData.PaymentRequestAPI.Options, 133 MethodData: stateData.PaymentRequestAPI.Methods, 134 } 135 } 136 } 137 138 // MapFrom the internal process state to the graphQL state fields 139 func (s *Success) MapFrom(pctx process.Context) { 140 s.Name = pctx.CurrentStateName 141 } 142 143 // MapFrom the internal process state to the graphQL state fields 144 func (s *Wait) MapFrom(pctx process.Context) { 145 s.Name = pctx.CurrentStateName 146 } 147 148 // MapFrom the internal process state to the graphQL state fields 149 func (s *WaitForCustomer) MapFrom(pctx process.Context) { 150 s.Name = pctx.CurrentStateName 151 } 152 153 // MapFrom the internal process state to the graphQL state fields 154 func (s *ShowIframe) MapFrom(pctx process.Context) { 155 s.Name = pctx.CurrentStateName 156 if stateData, ok := pctx.CurrentStateData.(*url.URL); ok { 157 s.URL = stateData.String() 158 } 159 } 160 161 // MapFrom the internal process state to the graphQL state fields 162 func (s *ShowHTML) MapFrom(pctx process.Context) { 163 s.Name = pctx.CurrentStateName 164 if stateData, ok := pctx.CurrentStateData.(string); ok { 165 s.HTML = stateData 166 } 167 } 168 169 // MapFrom the internal process state to the graphQL state fields 170 func (s *Redirect) MapFrom(pctx process.Context) { 171 s.Name = pctx.CurrentStateName 172 if stateData, ok := pctx.CurrentStateData.(*url.URL); ok { 173 s.URL = stateData.String() 174 } 175 } 176 177 // MapFrom the internal process state to the graphQL state fields 178 func (s *PostRedirect) MapFrom(pctx process.Context) { 179 s.Name = pctx.CurrentStateName 180 if stateData, ok := pctx.CurrentStateData.(states.PostRedirectData); ok { 181 s.URL = stateData.URL.String() 182 parameters := make([]FormParameter, 0, len(stateData.FormFields)) 183 for key, p := range stateData.FormFields { 184 parameters = append(parameters, FormParameter{ 185 Key: key, 186 Value: p.Value, 187 }) 188 } 189 s.Parameters = parameters 190 } 191 } 192 193 // MapFrom the internal process state to the graphQL state fields 194 func (t *TriggerClientSDK) MapFrom(pctx process.Context) { 195 t.Name = pctx.CurrentStateName 196 if stateData, ok := pctx.CurrentStateData.(states.TriggerClientSDKData); ok { 197 t.URL = stateData.URL.String() 198 t.Data = stateData.Data 199 } 200 } 201 202 // Inject dependencies 203 func (sm *StateMapper) Inject(stateProvider StateProvider) *StateMapper { 204 sm.stateProvider = stateProvider 205 206 return sm 207 } 208 209 // Map a context into a state 210 func (sm *StateMapper) Map(pctx process.Context) (State, error) { 211 resultState, found := sm.stateProvider()[pctx.CurrentStateName] 212 if !found { 213 return nil, fmt.Errorf("couldn't map the internal process state %q to a GraphQL state", pctx.CurrentStateName) 214 } 215 216 resultState.MapFrom(pctx) 217 return resultState, nil 218 }