flamingo.me/flamingo-commerce/v3@v3.11.0/test/integrationtest/projecttest/modules/payment/fake_gateway.go (about)

     1  package payment
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net/url"
     7  
     8  	"flamingo.me/flamingo-commerce/v3/cart/domain/cart"
     9  	"flamingo.me/flamingo-commerce/v3/cart/domain/placeorder"
    10  	"flamingo.me/flamingo-commerce/v3/payment/domain"
    11  	"flamingo.me/flamingo-commerce/v3/payment/interfaces"
    12  )
    13  
    14  const (
    15  	// FakePaymentGateway gateway code
    16  	FakePaymentGateway = "fake_payment_gateway"
    17  )
    18  
    19  type (
    20  	// FakeGateway used for testing all payment states
    21  	FakeGateway struct {
    22  		CartIsCompleted map[string]bool
    23  	}
    24  
    25  	// Method ...
    26  	Method struct {
    27  		Title  string
    28  		Status *domain.FlowStatus
    29  	}
    30  )
    31  
    32  var (
    33  	_       interfaces.WebCartPaymentGateway = &FakeGateway{}
    34  	methods                                  = map[string]Method{
    35  		domain.PaymentFlowStatusCompleted: {
    36  			Title: "Payment completed",
    37  			Status: &domain.FlowStatus{
    38  				Status: domain.PaymentFlowStatusCompleted,
    39  			},
    40  		},
    41  		domain.PaymentFlowStatusFailed: {
    42  			Title: "Payment failed",
    43  			Status: &domain.FlowStatus{
    44  				Status: domain.PaymentFlowStatusFailed,
    45  			},
    46  		},
    47  		domain.PaymentErrorAbortedByCustomer: {
    48  			Title: "Payment aborted by customer",
    49  			Status: &domain.FlowStatus{
    50  				Status: domain.PaymentErrorAbortedByCustomer,
    51  			},
    52  		},
    53  		domain.PaymentFlowStatusAborted: {
    54  			Title: "Payment aborted",
    55  			Status: &domain.FlowStatus{
    56  				Status: domain.PaymentFlowStatusAborted,
    57  			},
    58  		},
    59  		domain.PaymentFlowStatusCancelled: {
    60  			Title: "Payment canceled",
    61  			Status: &domain.FlowStatus{
    62  				Status: domain.PaymentFlowStatusCancelled,
    63  			},
    64  		},
    65  		domain.PaymentFlowStatusApproved: {
    66  			Title: "Payment approved",
    67  			Status: &domain.FlowStatus{
    68  				Status: domain.PaymentFlowStatusApproved,
    69  			},
    70  		},
    71  		domain.PaymentFlowWaitingForCustomer: {
    72  			Title: "Payment waiting for customer",
    73  			Status: &domain.FlowStatus{
    74  				Status: domain.PaymentFlowWaitingForCustomer,
    75  			},
    76  		},
    77  		domain.PaymentFlowActionShowIframe: {
    78  			Title: "Payment unapproved, iframe",
    79  			Status: &domain.FlowStatus{
    80  				Status: domain.PaymentFlowStatusUnapproved,
    81  				Action: domain.PaymentFlowActionShowIframe,
    82  				ActionData: domain.FlowActionData{
    83  					URL: &url.URL{Scheme: "https", Host: "url.com"},
    84  				},
    85  			},
    86  		},
    87  		domain.PaymentFlowActionRedirect: {
    88  			Title: "Payment unapproved, redirect",
    89  			Status: &domain.FlowStatus{
    90  				Status: domain.PaymentFlowStatusUnapproved,
    91  				Action: domain.PaymentFlowActionRedirect,
    92  				ActionData: domain.FlowActionData{
    93  					URL: &url.URL{Scheme: "https", Host: "url.com"},
    94  				},
    95  			},
    96  		},
    97  		domain.PaymentFlowActionPostRedirect: {
    98  			Title: "Payment unapproved, post-redirect",
    99  			Status: &domain.FlowStatus{
   100  				Status: domain.PaymentFlowStatusUnapproved,
   101  				Action: domain.PaymentFlowActionPostRedirect,
   102  				ActionData: domain.FlowActionData{
   103  					URL: &url.URL{Scheme: "https", Host: "url.com"},
   104  				},
   105  			},
   106  		},
   107  		domain.PaymentFlowActionShowHTML: {
   108  			Title: "Payment unapproved, html",
   109  			Status: &domain.FlowStatus{
   110  				Status: domain.PaymentFlowStatusUnapproved,
   111  				Action: domain.PaymentFlowActionShowHTML,
   112  				ActionData: domain.FlowActionData{
   113  					DisplayData: "<h2>test</h2>",
   114  				},
   115  			},
   116  		},
   117  		domain.PaymentFlowActionShowWalletPayment: {
   118  			Title: "Payment unapproved, wallet",
   119  			Status: &domain.FlowStatus{
   120  				Status: domain.PaymentFlowStatusUnapproved,
   121  				Action: domain.PaymentFlowActionShowWalletPayment,
   122  				ActionData: domain.FlowActionData{
   123  					WalletDetails: &domain.WalletDetails{
   124  						UsedPaymentMethod: "ApplePay",
   125  						PaymentRequestAPI: domain.PaymentRequestAPI{
   126  							Methods: `{"a": "b"}`,
   127  						},
   128  					},
   129  				},
   130  			},
   131  		},
   132  		"unknown": {
   133  			Title: "Payment unapproved, unknown",
   134  			Status: &domain.FlowStatus{
   135  				Status: domain.PaymentFlowStatusUnapproved,
   136  				Action: "unknown",
   137  			},
   138  		},
   139  	}
   140  )
   141  
   142  // Inject dependencies
   143  func (g *FakeGateway) Inject() *FakeGateway {
   144  	g.CartIsCompleted = make(map[string]bool)
   145  
   146  	return g
   147  }
   148  
   149  // Methods returns all payment gateway methods
   150  func (g *FakeGateway) Methods() []domain.Method {
   151  	result := make([]domain.Method, 0, len(methods))
   152  
   153  	for key, val := range methods {
   154  		result = append(result, domain.Method{Code: key, Title: val.Title})
   155  	}
   156  
   157  	return result
   158  }
   159  
   160  func (g *FakeGateway) isSupportedPaymentMethod(method string) bool {
   161  	for _, supportedMethod := range g.Methods() {
   162  		if supportedMethod.Code == method {
   163  			return true
   164  		}
   165  	}
   166  	return false
   167  }
   168  
   169  // StartFlow starts a new Payment flow
   170  func (g *FakeGateway) StartFlow(ctx context.Context, cart *cart.Cart, correlationID string, returnURL *url.URL) (*domain.FlowResult, error) {
   171  	method := ""
   172  	// just grab the first method we find and use it to decide between the different use cases
   173  	for qualifier := range cart.PaymentSelection.CartSplit() {
   174  		method = qualifier.Method
   175  		break
   176  	}
   177  
   178  	if !g.isSupportedPaymentMethod(method) {
   179  		return nil, errors.New("specified method not supported by payment gateway: " + method)
   180  	}
   181  
   182  	return &domain.FlowResult{
   183  		Status: domain.FlowStatus{
   184  			Status: domain.PaymentFlowStatusUnapproved,
   185  		},
   186  	}, nil
   187  
   188  }
   189  
   190  // FlowStatus returns a payment with a state depending on the supplied payment method
   191  func (g *FakeGateway) FlowStatus(ctx context.Context, cart *cart.Cart, correlationID string) (*domain.FlowStatus, error) {
   192  	methodCode := ""
   193  	// just grab the first method we find and use it to decide between the different use cases
   194  	for qualifier := range cart.PaymentSelection.CartSplit() {
   195  		methodCode = qualifier.Method
   196  		break
   197  	}
   198  
   199  	if !g.isSupportedPaymentMethod(methodCode) {
   200  		return nil, errors.New("specified method not supported by payment gateway: " + methodCode)
   201  	}
   202  
   203  	if g.CartIsCompleted[cart.ID] {
   204  		return &domain.FlowStatus{
   205  			Status: domain.PaymentFlowStatusCompleted,
   206  		}, nil
   207  	}
   208  
   209  	return methods[methodCode].Status, nil
   210  }
   211  
   212  // ConfirmResult mark payment as completed
   213  func (g *FakeGateway) ConfirmResult(ctx context.Context, cart *cart.Cart, cartPayment *placeorder.Payment) error {
   214  	g.CartIsCompleted[cart.ID] = true
   215  	return nil
   216  }
   217  
   218  // OrderPaymentFromFlow return fake payment
   219  func (g *FakeGateway) OrderPaymentFromFlow(ctx context.Context, cart *cart.Cart, correlationID string) (*placeorder.Payment, error) {
   220  	return &placeorder.Payment{
   221  		Gateway: FakePaymentGateway,
   222  		Transactions: []placeorder.Transaction{
   223  			{
   224  				TransactionID:     correlationID,
   225  				AdditionalData:    nil,
   226  				AmountPayed:       cart.GrandTotal,
   227  				ValuedAmountPayed: cart.GrandTotal,
   228  			},
   229  		},
   230  		RawTransactionData: nil,
   231  		PaymentID:          "",
   232  	}, nil
   233  }
   234  
   235  // CancelOrderPayment does nothing
   236  func (g *FakeGateway) CancelOrderPayment(ctx context.Context, cartPayment *placeorder.Payment) error {
   237  	return nil
   238  }