Skip to content

Commit

Permalink
fix: unify use of expiry time
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelbrm committed Jul 19, 2024
1 parent 9a185fb commit ca62479
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 84 deletions.
10 changes: 7 additions & 3 deletions services/skus/appstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func parseAppStoreSrvNotification(vrf *assnCertVerifier, spayload string) (*appS
return result, nil
}

func parseTxnInfo(pubKey *ecdsa.PublicKey, spayload appstore.JWSTransaction) (*appstore.JWSTransactionDecodedPayload, error) {
func parseTxnInfo(pubKey *ecdsa.PublicKey, spayload appstore.JWSTransaction) (*appStoreTransaction, error) {
raw, err := jose.ParseSigned(string(spayload))
if err != nil {
return nil, err
Expand All @@ -210,7 +210,7 @@ func parseTxnInfo(pubKey *ecdsa.PublicKey, spayload appstore.JWSTransaction) (*a
return nil, err
}

return result, nil
return (*appStoreTransaction)(result), nil
}

//nolint:unused
Expand Down Expand Up @@ -329,12 +329,16 @@ func shouldCancelOrderIOS(info *appstore.JWSTransactionDecodedPayload, now time.

type appStoreTransaction appstore.JWSTransactionDecodedPayload

func (x *appStoreTransaction) expiresTime() time.Time {
return time.UnixMilli(x.ExpiresDate).UTC()
}

func (x *appStoreTransaction) hasExpired(now time.Time) bool {
if x == nil {
return false
}

return x.ExpiresDate > 0 && now.After(time.UnixMilli(x.ExpiresDate))
return x.ExpiresDate > 0 && now.After(x.expiresTime())
}

func (x *appStoreTransaction) isRevoked(now time.Time) bool {
Expand Down
14 changes: 0 additions & 14 deletions services/skus/playstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,6 @@ func (x *playStoreDevNotification) pkg() string {
return x.PackageName
}

func (x *playStoreDevNotification) isBeforeCutoff() bool {
ems, err := x.EventTimeMilli.Int64()
if err != nil {
return true
}

cot := time.Date(2024, time.July, 1, 0, 0, 0, 0, time.UTC)

// Assumption: server time is UTC.
event := time.UnixMilli(ems)

return event.Before(cot)
}

func (x *playStoreDevNotification) purchaseToken() (string, bool) {
switch {
case x.SubscriptionNtf != nil:
Expand Down
41 changes: 0 additions & 41 deletions services/skus/playstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,47 +661,6 @@ func TestPlayStoreDevNotification_effect(t *testing.T) {
}
}

func TestPlayStoreDevNotification_isBeforeCutoff(t *testing.T) {
type testCase struct {
name string
given *playStoreDevNotification
exp bool
}

tests := []testCase{
{
name: "invalid_time",
given: &playStoreDevNotification{EventTimeMilli: "garbage"},
exp: true,
},

{
name: "before",
given: &playStoreDevNotification{EventTimeMilli: "1719791940000"},
exp: true,
},

{
name: "exact",
given: &playStoreDevNotification{EventTimeMilli: "1719792000000"},
},

{
name: "after",
given: &playStoreDevNotification{EventTimeMilli: "1722470400000"},
},
}

for i := range tests {
tc := tests[i]

t.Run(tc.name, func(t *testing.T) {
acutal := tc.given.isBeforeCutoff()
should.Equal(t, tc.exp, acutal)
})
}
}

func TestPlayStoreDevNotification_purchaseToken(t *testing.T) {
type tcExpected struct {
val string
Expand Down
16 changes: 10 additions & 6 deletions services/skus/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,24 @@ func (v *receiptVerifier) validateGoogleTime(ctx context.Context, req model.Rece
return model.ReceiptData{}, fmt.Errorf("failed to fetch subscription purchase: %w", err)
}

psub := (*playStoreSubPurchase)(sub)
if psub.hasExpired(now) {
if sub.hasExpired(now) {
return model.ReceiptData{}, errGPSSubPurchaseExpired
}

if psub.isPending() {
if sub.isPending() {
return model.ReceiptData{}, errGPSSubPurchasePending
}

return newReceiptDataGoogle(req, psub), nil
return newReceiptDataGoogle(req, sub), nil
}

func (v *receiptVerifier) fetchSubPlayStore(ctx context.Context, pkgName, subID, token string) (*androidpublisher.SubscriptionPurchase, error) {
return v.playStoreCl.VerifySubscription(ctx, pkgName, subID, token)
func (v *receiptVerifier) fetchSubPlayStore(ctx context.Context, pkgName, subID, token string) (*playStoreSubPurchase, error) {
sub, err := v.playStoreCl.VerifySubscription(ctx, pkgName, subID, token)
if err != nil {
return nil, err
}

return (*playStoreSubPurchase)(sub), nil
}

func findInAppBySubID(iap []appstore.InApp, subID string, now time.Time) (*wrapAppStoreInApp, bool) {
Expand Down
19 changes: 4 additions & 15 deletions services/skus/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"sync"
"time"

"github.com/awa/go-iap/appstore"
"github.com/getsentry/sentry-go"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
Expand All @@ -27,7 +26,6 @@ import (
"github.com/stripe/stripe-go/v72/checkout/session"
"github.com/stripe/stripe-go/v72/client"
"github.com/stripe/stripe-go/v72/sub"
"google.golang.org/api/androidpublisher/v3"
"google.golang.org/api/idtoken"
"google.golang.org/api/option"

Expand Down Expand Up @@ -115,7 +113,7 @@ type tlv2Store interface {
type vendorReceiptValidator interface {
validateApple(ctx context.Context, req model.ReceiptRequest) (model.ReceiptData, error)
validateGoogle(ctx context.Context, req model.ReceiptRequest) (model.ReceiptData, error)
fetchSubPlayStore(ctx context.Context, pkgName, subID, token string) (*androidpublisher.SubscriptionPurchase, error)
fetchSubPlayStore(ctx context.Context, pkgName, subID, token string) (*playStoreSubPurchase, error)
}

type gpsMessageAuthenticator interface {
Expand Down Expand Up @@ -1678,15 +1676,15 @@ func (s *Service) processAppStoreNotification(ctx context.Context, ntf *appStore
return tx.Commit()
}

func (s *Service) processAppStoreNotificationTx(ctx context.Context, dbi sqlx.ExtContext, ntf *appStoreSrvNotification, txn *appstore.JWSTransactionDecodedPayload) error {
func (s *Service) processAppStoreNotificationTx(ctx context.Context, dbi sqlx.ExtContext, ntf *appStoreSrvNotification, txn *appStoreTransaction) error {
ord, err := s.orderRepo.GetByExternalID(ctx, dbi, txn.OriginalTransactionId)
if err != nil {
return err
}

switch {
case ntf.shouldRenew():
expt := time.UnixMilli(txn.ExpiresDate).UTC().Add(24 * time.Hour)
expt := txn.expiresTime().Add(24 * time.Hour)
paidt := time.Now()

return s.renewOrderWithExpPaidTimeTx(ctx, dbi, ord.ID, expt, paidt)
Expand All @@ -1709,15 +1707,6 @@ func (s *Service) processPlayStoreNotification(ctx context.Context, ntf *playSto
return nil
}

// Temporary. Clean up after the initial rollout.
//
// Refuse to handle any events issued prior to 2024-07-01.
// This is to avoid unexpected effects from past events (in case we get them),
// and to avoid complicating the downstream logic.
if ntf.isBeforeCutoff() {
return nil
}

tx, err := s.Datastore.RawDB().BeginTxx(ctx, nil)
if err != nil {
return err
Expand Down Expand Up @@ -1745,7 +1734,7 @@ func (s *Service) processPlayStoreNotificationTx(ctx context.Context, dbi sqlx.E
return err
}

expt := time.UnixMilli(sub.ExpiryTimeMillis).UTC().Add(24 * time.Hour)
expt := sub.expiresTime().Add(24 * time.Hour)
paidt := time.Now()

return s.renewOrderWithExpPaidTimeTx(ctx, dbi, ord.ID, expt, paidt)
Expand Down
10 changes: 5 additions & 5 deletions services/skus/service_nonint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ func TestService_processPlayStoreNotificationTx(t *testing.T) {
func TestService_processAppStoreNotificationTx(t *testing.T) {
type tcGiven struct {
ntf *appStoreSrvNotification
txn *appstore.JWSTransactionDecodedPayload
txn *appStoreTransaction
orepo *repository.MockOrder
prepo *repository.MockOrderPayHistory
}
Expand All @@ -553,7 +553,7 @@ func TestService_processAppStoreNotificationTx(t *testing.T) {
name: "get_order_error",
given: tcGiven{
ntf: &appStoreSrvNotification{val: &appstore.SubscriptionNotificationV2DecodedPayload{}},
txn: &appstore.JWSTransactionDecodedPayload{OriginalTransactionId: "123456789000001"},
txn: &appStoreTransaction{OriginalTransactionId: "123456789000001"},
orepo: &repository.MockOrder{
FnGetByExternalID: func(ctx context.Context, dbi sqlx.QueryerContext, extID string) (*model.Order, error) {
return nil, model.Error("something_went_wrong")
Expand All @@ -573,7 +573,7 @@ func TestService_processAppStoreNotificationTx(t *testing.T) {
Subtype: appstore.SubTypeV2BillingRecovery,
},
},
txn: &appstore.JWSTransactionDecodedPayload{
txn: &appStoreTransaction{
OriginalTransactionId: "123456789000001",
ExpiresDate: 1704067200000,
},
Expand All @@ -600,7 +600,7 @@ func TestService_processAppStoreNotificationTx(t *testing.T) {
Subtype: appstore.SubTypeV2AutoRenewDisabled,
},
},
txn: &appstore.JWSTransactionDecodedPayload{
txn: &appStoreTransaction{
OriginalTransactionId: "123456789000001",
ExpiresDate: 1704067201000,
},
Expand All @@ -619,7 +619,7 @@ func TestService_processAppStoreNotificationTx(t *testing.T) {
Subtype: appstore.SubTypeV2Accepted,
},
},
txn: &appstore.JWSTransactionDecodedPayload{
txn: &appStoreTransaction{
OriginalTransactionId: "123456789000001",
ExpiresDate: 1704067201000,
},
Expand Down

0 comments on commit ca62479

Please sign in to comment.