Skip to content

Commit 5f3669d

Browse files
authored
refactor: determine stripe checkout mode dynamically (#2986)
1 parent 391feac commit 5f3669d

File tree

5 files changed

+128
-70
lines changed

5 files changed

+128
-70
lines changed

services/skus/model/model.go

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -449,21 +449,16 @@ type OrderItemRequest struct {
449449

450450
// CreateOrderRequestNew includes information needed to create an order.
451451
type CreateOrderRequestNew struct {
452-
Email string `json:"email" validate:"required,email"`
453-
CustomerID string `json:"customer_id"` // Optional.
454-
Currency string `json:"currency" validate:"required,iso4217"`
455-
StripeMetadata *OrderStripeMetadata `json:"stripe_metadata"`
456-
RadomMetadata *OrderRadomMetadata `json:"radom_metadata"`
457-
PaymentMethods []string `json:"payment_methods"`
458-
Discounts []string `json:"discounts"`
459-
Items []OrderItemRequestNew `json:"items" validate:"required,gt=0,dive"`
460-
Metadata map[string]string `json:"metadata"`
461-
Locale string `json:"locale" validate:"omitempty,bcp47_language_tag"`
462-
PricingInterval string `json:"pricing_interval" validate:"omitempty,oneof=one-off"`
463-
}
464-
465-
func (r *CreateOrderRequestNew) IsOneOffPayment() bool {
466-
return r.PricingInterval == "one-off"
452+
Email string `json:"email" validate:"required,email"`
453+
CustomerID string `json:"customer_id"` // Optional.
454+
Currency string `json:"currency" validate:"required,iso4217"`
455+
StripeMetadata *OrderStripeMetadata `json:"stripe_metadata"`
456+
RadomMetadata *OrderRadomMetadata `json:"radom_metadata"`
457+
PaymentMethods []string `json:"payment_methods"`
458+
Discounts []string `json:"discounts"`
459+
Items []OrderItemRequestNew `json:"items" validate:"required,gt=0,dive"`
460+
Metadata map[string]string `json:"metadata"`
461+
Locale string `json:"locale" validate:"omitempty,bcp47_language_tag"`
467462
}
468463

469464
// OrderItemRequestNew represents an item in an order request.

services/skus/model/model_test.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,49 +1958,3 @@ func TestOrderItem_IsSearchAnnual(t *testing.T) {
19581958
func ptrTo[T any](v T) *T {
19591959
return &v
19601960
}
1961-
1962-
func TestCreateOrderRequestNew_IsOneOffPayment(t *testing.T) {
1963-
type tcGiven struct {
1964-
req *model.CreateOrderRequestNew
1965-
}
1966-
1967-
type tcExpected struct {
1968-
res bool
1969-
}
1970-
1971-
type testCase struct {
1972-
name string
1973-
given tcGiven
1974-
exp tcExpected
1975-
}
1976-
1977-
tests := []testCase{
1978-
{
1979-
name: "pricing_interval_none",
1980-
given: tcGiven{
1981-
req: &model.CreateOrderRequestNew{},
1982-
},
1983-
},
1984-
1985-
{
1986-
name: "pricing_interval_one_off",
1987-
given: tcGiven{
1988-
req: &model.CreateOrderRequestNew{
1989-
PricingInterval: "one-off",
1990-
},
1991-
},
1992-
exp: tcExpected{
1993-
res: true,
1994-
},
1995-
},
1996-
}
1997-
1998-
for i := range tests {
1999-
tc := tests[i]
2000-
2001-
t.Run(tc.name, func(t *testing.T) {
2002-
actual := tc.given.req.IsOneOffPayment()
2003-
should.Equal(t, tc.exp.res, actual)
2004-
})
2005-
}
2006-
}

services/skus/service.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,11 +2163,6 @@ func (s *Service) createStripeSession(ctx context.Context, req *model.CreateOrde
21632163
return "", err
21642164
}
21652165

2166-
csm := string(stripe.CheckoutSessionModeSubscription)
2167-
if req.IsOneOffPayment() {
2168-
csm = string(stripe.CheckoutSessionModePayment)
2169-
}
2170-
21712166
sreq := createStripeSessionRequest{
21722167
orderID: oid,
21732168
email: req.Email,
@@ -2179,7 +2174,7 @@ func (s *Service) createStripeSession(ctx context.Context, req *model.CreateOrde
21792174
discounts: buildStripeDiscounts(req.Discounts),
21802175
metadata: req.Metadata,
21812176
Locale: req.Locale,
2182-
csMode: csm,
2177+
csMode: determineStripeCheckoutSessionMode(req.Items),
21832178
}
21842179

21852180
return createStripeSession(ctx, s.stripeCl, sreq, s.stripeLocaleValid)
@@ -3110,6 +3105,14 @@ func buildStripeDiscounts(discounts []string) []*stripe.CheckoutSessionDiscountP
31103105
return result
31113106
}
31123107

3108+
func determineStripeCheckoutSessionMode(items []model.OrderItemRequestNew) string {
3109+
if len(items) == 1 && items[0].Period == "one-off" {
3110+
return string(stripe.CheckoutSessionModePayment)
3111+
}
3112+
3113+
return string(stripe.CheckoutSessionModeSubscription)
3114+
}
3115+
31133116
func handleRedeemFnError(ctx context.Context, w http.ResponseWriter, kind string, cred *cbr.CredentialRedemption, err error) *handlers.AppError {
31143117
msg := err.Error()
31153118

services/skus/service_nonint_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4285,6 +4285,13 @@ func TestService_createStripeSession(t *testing.T) {
42854285
{
42864286
name: "success_mode_payment",
42874287
given: tcGiven{
4288+
req: &model.CreateOrderRequestNew{
4289+
Items: []model.OrderItemRequestNew{
4290+
{
4291+
Period: "one-off",
4292+
},
4293+
},
4294+
},
42884295
cl: &xstripe.MockClient{
42894296
FnCreateSession: func(ctx context.Context, params *stripe.CheckoutSessionParams) (*stripe.CheckoutSession, error) {
42904297
if *params.Mode != string(stripe.CheckoutSessionModePayment) {
@@ -4296,9 +4303,6 @@ func TestService_createStripeSession(t *testing.T) {
42964303
return result, nil
42974304
},
42984305
},
4299-
req: &model.CreateOrderRequestNew{
4300-
PricingInterval: "one-off",
4301-
},
43024306
ord: &model.Order{},
43034307
},
43044308
exp: tcExpected{

services/skus/service_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,3 +793,105 @@ func TestTimeChunking(t *testing.T) {
793793
})
794794
}
795795
}
796+
797+
func TestDetermineStripeCheckoutSessionMode(t *testing.T) {
798+
type tcGiven struct {
799+
items []model.OrderItemRequestNew
800+
}
801+
802+
type tcExpected struct {
803+
csm string
804+
}
805+
806+
type testCase struct {
807+
name string
808+
given tcGiven
809+
exp tcExpected
810+
}
811+
812+
tests := []testCase{
813+
{
814+
name: "no_items",
815+
exp: tcExpected{
816+
csm: "subscription",
817+
},
818+
},
819+
820+
{
821+
name: "one_item_empty_period",
822+
given: tcGiven{
823+
items: []model.OrderItemRequestNew{{}},
824+
},
825+
exp: tcExpected{
826+
csm: "subscription",
827+
},
828+
},
829+
830+
{
831+
name: "one_item_period_subscription",
832+
given: tcGiven{
833+
items: []model.OrderItemRequestNew{{
834+
Period: "subscription",
835+
}},
836+
},
837+
exp: tcExpected{
838+
csm: "subscription",
839+
},
840+
},
841+
842+
{
843+
name: "one_item_period_one_off",
844+
given: tcGiven{
845+
items: []model.OrderItemRequestNew{{
846+
Period: "one-off",
847+
}},
848+
},
849+
exp: tcExpected{
850+
csm: "payment",
851+
},
852+
},
853+
854+
{
855+
name: "multiple_items_period_subscription",
856+
given: tcGiven{
857+
items: []model.OrderItemRequestNew{
858+
{
859+
Period: "subscription",
860+
},
861+
{
862+
Period: "subscription",
863+
},
864+
},
865+
},
866+
exp: tcExpected{
867+
csm: "subscription",
868+
},
869+
},
870+
871+
{
872+
name: "multiple_items_period_one_off",
873+
given: tcGiven{
874+
items: []model.OrderItemRequestNew{
875+
{
876+
Period: "one-off",
877+
},
878+
{
879+
Period: "one-off",
880+
},
881+
},
882+
},
883+
exp: tcExpected{
884+
csm: "subscription",
885+
},
886+
},
887+
}
888+
889+
for i := range tests {
890+
tc := tests[i]
891+
892+
t.Run(tc.name, func(t *testing.T) {
893+
actual := determineStripeCheckoutSessionMode(tc.given.items)
894+
should.Equal(t, tc.exp.csm, actual)
895+
})
896+
}
897+
}

0 commit comments

Comments
 (0)