diff --git a/satellite/console/consoleweb/consoleapi/payments.go b/satellite/console/consoleweb/consoleapi/payments.go index c637c634d..9c1b44f1f 100644 --- a/satellite/console/consoleweb/consoleapi/payments.go +++ b/satellite/console/consoleweb/consoleapi/payments.go @@ -174,7 +174,7 @@ func (p *Payments) AddCreditCard(w http.ResponseWriter, r *http.Request) { token := string(bodyBytes) - err = p.service.Payments().AddCreditCard(ctx, token) + _, err = p.service.Payments().AddCreditCard(ctx, token) if err != nil { if console.ErrUnauthorized.Has(err) { p.serveJSONError(w, http.StatusUnauthorized, err) diff --git a/satellite/console/service.go b/satellite/console/service.go index 6fb229a53..65484898a 100644 --- a/satellite/console/service.go +++ b/satellite/console/service.go @@ -331,17 +331,17 @@ func (payment Payments) AccountBalance(ctx context.Context) (balance payments.Ba } // AddCreditCard is used to save new credit card and attach it to payment account. -func (payment Payments) AddCreditCard(ctx context.Context, creditCardToken string) (err error) { +func (payment Payments) AddCreditCard(ctx context.Context, creditCardToken string) (card payments.CreditCard, err error) { defer mon.Task()(&ctx, creditCardToken)(&err) user, err := payment.service.getUserAndAuditLog(ctx, "add credit card") if err != nil { - return Error.Wrap(err) + return payments.CreditCard{}, Error.Wrap(err) } - err = payment.service.accounts.CreditCards().Add(ctx, user.ID, creditCardToken) + card, err = payment.service.accounts.CreditCards().Add(ctx, user.ID, creditCardToken) if err != nil { - return Error.Wrap(err) + return payments.CreditCard{}, Error.Wrap(err) } payment.service.analytics.TrackCreditCardAdded(user.ID, user.Email) @@ -355,12 +355,12 @@ func (payment Payments) AddCreditCard(ctx context.Context, creditCardToken strin payment.service.config.UsageLimits.Project.Paid, ) if err != nil { - return Error.Wrap(err) + return payments.CreditCard{}, Error.Wrap(err) } projects, err := payment.service.store.Projects().GetOwn(ctx, user.ID) if err != nil { - return Error.Wrap(err) + return payments.CreditCard{}, Error.Wrap(err) } for _, project := range projects { if project.StorageLimit == nil || *project.StorageLimit < payment.service.config.UsageLimits.Storage.Paid { @@ -376,12 +376,12 @@ func (payment Payments) AddCreditCard(ctx context.Context, creditCardToken strin } err = payment.service.store.Projects().Update(ctx, &project) if err != nil { - return Error.Wrap(err) + return payments.CreditCard{}, Error.Wrap(err) } } } - return nil + return card, nil } // MakeCreditCardDefault makes a credit card default payment method. diff --git a/satellite/console/service_test.go b/satellite/console/service_test.go index 8531789fb..6ca398add 100644 --- a/satellite/console/service_test.go +++ b/satellite/console/service_test.go @@ -107,7 +107,8 @@ func TestService(t *testing.T) { // stripecoinpayments.TestPaymentMethodsAttachFailure triggers the underlying mock stripe client to return an error // when attaching a payment method to a customer. - require.Error(t, service.Payments().AddCreditCard(userCtx1, stripecoinpayments.TestPaymentMethodsAttachFailure)) + _, err = service.Payments().AddCreditCard(userCtx1, stripecoinpayments.TestPaymentMethodsAttachFailure) + require.Error(t, err) // user still in free tier user, err = service.GetUser(ctx, up1Pro1.OwnerID) @@ -128,8 +129,9 @@ func TestService(t *testing.T) { userCtx1, err := sat.UserContext(ctx, user.ID) require.NoError(t, err) // add a credit card to put the user in the paid tier - err = service.Payments().AddCreditCard(userCtx1, "test-cc-token") + card, err := service.Payments().AddCreditCard(userCtx1, "test-cc-token") require.NoError(t, err) + require.NotEmpty(t, card) // user should be in paid tier user, err = service.GetUser(ctx, up1Pro1.OwnerID) require.NoError(t, err) @@ -553,7 +555,7 @@ func TestPaidTier(t *testing.T) { require.NoError(t, err) // add a credit card to the user - err = service.Payments().AddCreditCard(userCtx, "test-cc-token") + _, err = service.Payments().AddCreditCard(userCtx, "test-cc-token") require.NoError(t, err) // expect user to be in paid tier diff --git a/satellite/console/userinfo/endpoint_test.go b/satellite/console/userinfo/endpoint_test.go index 4f489cb2f..d66808eb9 100644 --- a/satellite/console/userinfo/endpoint_test.go +++ b/satellite/console/userinfo/endpoint_test.go @@ -130,7 +130,7 @@ func TestEndpointGet(t *testing.T) { userCtx, err := sat.UserContext(ctx, user.ID) require.NoError(t, err) // add a credit card to put the user in the paid tier. - err = sat.API.Console.Service.Payments().AddCreditCard(userCtx, "test-cc-token") + _, err = sat.API.Console.Service.Payments().AddCreditCard(userCtx, "test-cc-token") require.NoError(t, err) // get user info again diff --git a/satellite/payments/creditcards.go b/satellite/payments/creditcards.go index 04ad4eec9..3208eb2ac 100644 --- a/satellite/payments/creditcards.go +++ b/satellite/payments/creditcards.go @@ -17,7 +17,7 @@ type CreditCards interface { List(ctx context.Context, userID uuid.UUID) ([]CreditCard, error) // Add is used to save new credit card and attach it to payment account. - Add(ctx context.Context, userID uuid.UUID, cardToken string) error + Add(ctx context.Context, userID uuid.UUID, cardToken string) (CreditCard, error) // Remove is used to detach a credit card from payment account. Remove(ctx context.Context, userID uuid.UUID, cardID string) error diff --git a/satellite/payments/stripecoinpayments/creditcards.go b/satellite/payments/stripecoinpayments/creditcards.go index 9156c4b87..8014efea0 100644 --- a/satellite/payments/stripecoinpayments/creditcards.go +++ b/satellite/payments/stripecoinpayments/creditcards.go @@ -66,12 +66,12 @@ func (creditCards *creditCards) List(ctx context.Context, userID uuid.UUID) (car } // Add is used to save new credit card, attach it to payment account and make it default. -func (creditCards *creditCards) Add(ctx context.Context, userID uuid.UUID, cardToken string) (err error) { +func (creditCards *creditCards) Add(ctx context.Context, userID uuid.UUID, cardToken string) (_ payments.CreditCard, err error) { defer mon.Task()(&ctx, userID, cardToken)(&err) customerID, err := creditCards.service.db.Customers().GetCustomerID(ctx, userID) if err != nil { - return payments.ErrAccountNotSetup.Wrap(err) + return payments.CreditCard{}, payments.ErrAccountNotSetup.Wrap(err) } cardParams := &stripe.PaymentMethodParams{ @@ -81,7 +81,7 @@ func (creditCards *creditCards) Add(ctx context.Context, userID uuid.UUID, cardT card, err := creditCards.service.stripeClient.PaymentMethods().New(cardParams) if err != nil { - return Error.Wrap(err) + return payments.CreditCard{}, Error.Wrap(err) } attachParams := &stripe.PaymentMethodAttachParams{ @@ -90,7 +90,7 @@ func (creditCards *creditCards) Add(ctx context.Context, userID uuid.UUID, cardT card, err = creditCards.service.stripeClient.PaymentMethods().Attach(card.ID, attachParams) if err != nil { - return Error.Wrap(err) + return payments.CreditCard{}, Error.Wrap(err) } params := &stripe.CustomerParams{ @@ -102,7 +102,14 @@ func (creditCards *creditCards) Add(ctx context.Context, userID uuid.UUID, cardT _, err = creditCards.service.stripeClient.Customers().Update(customerID, params) // TODO: handle created but not attached card manually? - return Error.Wrap(err) + return payments.CreditCard{ + ID: card.ID, + ExpMonth: int(card.Card.ExpMonth), + ExpYear: int(card.Card.ExpYear), + Brand: string(card.Card.Brand), + Last4: card.Card.Last4, + IsDefault: true, + }, Error.Wrap(err) } // MakeDefault makes a credit card default payment method. diff --git a/satellite/payments/stripecoinpayments/creditcards_test.go b/satellite/payments/stripecoinpayments/creditcards_test.go index 7bfcf2d95..c653870f6 100644 --- a/satellite/payments/stripecoinpayments/creditcards_test.go +++ b/satellite/payments/stripecoinpayments/creditcards_test.go @@ -63,11 +63,13 @@ func TestCreditCards_Add(t *testing.T) { }, 1) require.NoError(t, err) - err = satellite.API.Payments.Accounts.CreditCards().Add(ctx, u.ID, tt.cardToken) + card, err := satellite.API.Payments.Accounts.CreditCards().Add(ctx, u.ID, tt.cardToken) if tt.shouldErr { require.Error(t, err) + require.Empty(t, card) } else { require.NoError(t, err) + require.NotEmpty(t, card) } cards, err := satellite.API.Payments.Accounts.CreditCards().List(ctx, u.ID) @@ -90,10 +92,10 @@ func TestCreditCards_Remove(t *testing.T) { satellite := planet.Satellites[0] userID := planet.Uplinks[0].Projects[0].Owner.ID - err := satellite.API.Payments.Accounts.CreditCards().Add(ctx, userID, "test") + _, err := satellite.API.Payments.Accounts.CreditCards().Add(ctx, userID, "test") require.NoError(t, err) - err = satellite.API.Payments.Accounts.CreditCards().Add(ctx, userID, "test2") + _, err = satellite.API.Payments.Accounts.CreditCards().Add(ctx, userID, "test2") require.NoError(t, err) cards, err := satellite.API.Payments.Accounts.CreditCards().List(ctx, userID) @@ -120,10 +122,10 @@ func TestCreditCards_RemoveAll(t *testing.T) { satellite := planet.Satellites[0] userID := planet.Uplinks[0].Projects[0].Owner.ID - err := satellite.API.Payments.Accounts.CreditCards().Add(ctx, userID, "test") + _, err := satellite.API.Payments.Accounts.CreditCards().Add(ctx, userID, "test") require.NoError(t, err) - err = satellite.API.Payments.Accounts.CreditCards().Add(ctx, userID, "test2") + _, err = satellite.API.Payments.Accounts.CreditCards().Add(ctx, userID, "test2") require.NoError(t, err) cards, err := satellite.API.Payments.Accounts.CreditCards().List(ctx, userID)