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  }