revenuecat webhook ve tabloları yanlış oluşturmuş olabilirim. bunu düzenle. paused durumunu ele almadım ve user is_premium alanını ele alamadım. günlük çalışan command tanımlamam gerekiyor. süresi biten abonelikleri kontrol edip işlem yapan.

   public function up(): void
    {
        Schema::create('subscription_events', function (Blueprint $table) {
            $table->id();
            $table->string('event_id');
            $table->string('type');
            $table->timestamp('event_timestamp')->nullable();
            $table->json('payload');

            $table->foreignId('subscription_id')->nullable()->constrained()->onDelete('set null');
            $table->foreignId('user_id')->constrained()->onDelete('cascade');

            $table->timestamps();
        });
    }
  
 public function up(): void
    {
        Schema::create('subscriptions', function (Blueprint $table) {
            $table->id();
            $table->string('app_user_id')->index();
            $table->string('original_app_user_id')->nullable();
            $table->string('store')->nullable();
            $table->string('environment')->nullable();
            $table->string('product_id');
            $table->json('entitlement_ids')->nullable();
            $table->string('period_type')->nullable();
            $table->timestamp('purchased_at')->nullable();

            $table->timestamp('expiration_at')->nullable();
            $table->string('transaction_id')->nullable();
            $table->string('original_transaction_id')->nullable();
            $table->boolean('is_trial_conversion')->default(false);
            $table->boolean('is_active')->default(true);

            $table->foreignId('user_id')->constrained()->onDelete('cascade');
            $table->timestamps();

            $table->unique(['user_id', 'product_id', 'is_active']);
        });
    }

     Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->uuid('app_user_id')->unique()->nullable();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();

            $table->string('username')->unique();
            $table->string('avatar')->nullable();
            $table->timestamp('avatar_updated_at')->nullable();
            $table->boolean('is_uploaded_avatar')->default(false)->avatar_updated_at();
            $table->boolean('is_premium')->default(false);


final class RevenueCatWebhookController extends Controller
{
    use ApiResponses;

    public function handle(Request $request)
    {
        Log::info('RevenueCat Webhook Received', $request->all());

        $payload = $request->all();
        $data = $payload['event'] ?? [];
        $eventType = $data['type'] ?? null;
        $revenuecatAppUserId = $data['app_user_id'] ?? null;

        if (! $eventType) {
            Log::warning('Invalid webhook payload.');

            return $this->error('Invalid payload', 400);
        }

        $user = User::where('app_user_id', $revenuecatAppUserId)->first();

        if (! $user && $eventType !== SubscriptionEventTypeEnum::TRANSFER->value) {
            Log::warning("User with RevenueCat app user ID {$revenuecatAppUserId} not found.");

            return $this->error('User not found', 404);
        }

        $event = SubscriptionEvent::create([
            'user_id' => $user->id,
            'event_id' => $data['id'] ?? null,
            'type' => $eventType,
            'event_timestamp' => isset($data['event_timestamp_ms']) ? Carbon::createFromTimestampMs($data['event_timestamp_ms']) : now(),
            'payload' => $data,
        ]);

        // Handle the event types
        switch ($eventType) {
            case SubscriptionEventTypeEnum::INITIAL_PURCHASE->value:
                $this->handleInitialPurchase($user, $data);
                break;
            case SubscriptionEventTypeEnum::NON_RENEWING_PURCHASE->value:
                $this->handleNonRenewingPurchase($user, $data);
                break;
            case SubscriptionEventTypeEnum::RENEWAL->value:
                $this->handleRenewal($user, $data);
                break;
            case SubscriptionEventTypeEnum::CANCELLATION->value:
                $this->handleCancellation($user, $data);
                break;
            case SubscriptionEventTypeEnum::BILLING_ISSUE->value:
                $this->handleBillingIssue($user, $data);
                break;
            case SubscriptionEventTypeEnum::EXPIRATION->value:
                $this->handleExpiration($user, $data);
                break;
            case SubscriptionEventTypeEnum::PRODUCT_CHANGE->value:
                $this->handleProductChange($user, $data);
                break;
            case SubscriptionEventTypeEnum::SUBSCRIPTION_EXTENDED->value:
                $this->handleSubscriptionExtended($user, $data);
                break;
            case SubscriptionEventTypeEnum::TRANSFER->value:
                $this->handleTransfer($data);
                break;
                // Add other cases as necessary
            default:
                Log::info("Unhandled event type: {$eventType}");
                break;
        }

        return $this->success('Subscription updated successfully');
    }

    protected function handleRenewal(User $user, array $data)
    {
        $subscription = Subscription::where('user_id', $user->id)
            ->where('product_id', $data['product_id'])
            ->orderBy('created_at', 'desc')
            ->first();

        if ($subscription) {
            $newExpirationAt = isset($data['expiration_at_ms']) ? Carbon::createFromTimestampMs($data['expiration_at_ms']) : null;

            $subscription->update([
                'expiration_at' => $newExpirationAt,
                'is_active' => true,
            ]);

            Log::info("Subscription renewed for user ID {$user->id}, subscription ID {$subscription->id}.");
        } else {
            $this->handleInitialPurchase($user, $data);
        }
    }

    protected function handleCancellation(User $user, array $data)
    {
        $subscription = Subscription::where('user_id', $user->id)
            ->where('transaction_id', $data['transaction_id'])
            ->orderBy('created_at', 'desc')
            ->first();

        if ($subscription) {
            $subscription->update([
                'is_active' => false,
            ]);

            Log::info("Subscription cancelled for user ID {$user->id}, subscription ID {$subscription->id}.");
        } else {
            Log::warning("Subscription not found for cancellation, user ID {$user->id}.");
        }
    }

    protected function handleExpiration(User $user, array $data)
    {
        $subscription = Subscription::where('user_id', $user->id)
            ->where('transaction_id', $data['transaction_id'])
            ->orderBy('created_at', 'desc')
            ->first();

        if ($subscription) {
            $subscription->update([
                'is_active' => false,
            ]);

            Log::info("Subscription expired for user ID {$user->id}, subscription ID {$subscription->id}.");
        } else {
            Log::warning("Subscription not found for expiration, user ID {$user->id}.");
        }
    }

    protected function handleProductChange(User $user, array $data)
    {
        $newProductId = $data['new_product_id'] ?? null;

        if (! $newProductId) {
            Log::warning('Product change event received without new_product_id');

            return;
        }

        // Deactivate the old subscription
        $oldSubscription = Subscription::where('user_id', $user->id)
            ->where('transaction_id', $data['transaction_id'])
            ->orderBy('created_at', 'desc')
            ->first();

        if ($oldSubscription) {
            $oldSubscription->update(['is_active' => false]);
        }

        // Create a new subscription for the new product
        $purchasedAt = isset($data['purchased_at_ms']) ? Carbon::createFromTimestampMs($data['purchased_at_ms']) : null;
        $expirationAt = isset($data['expiration_at_ms']) ? Carbon::createFromTimestampMs($data['expiration_at_ms']) : null;

        $subscription = Subscription::create([
            'user_id' => $user->id,
            'app_user_id' => $data['app_user_id'] ?? null,
            'original_app_user_id' => $data['original_app_user_id'] ?? null,
            'store' => $data['store'] ?? null,
            'environment' => $data['environment'] ?? null,
            'product_id' => $newProductId,
            'entitlement_ids' => $data['entitlement_ids'] ?? null,
            'period_type' => $data['period_type'] ?? null,
            'purchased_at' => $purchasedAt,
            'expiration_at' => $expirationAt,
            'transaction_id' => $data['transaction_id'] ?? null,
            'original_transaction_id' => $data['original_transaction_id'] ?? null,
            'is_trial_conversion' => $data['is_trial_conversion'] ?? false,
            'is_active' => true,
        ]);

        $event = SubscriptionEvent::where('id', $subscription->id)->first();
        if ($event) {
            $event->update(['subscription_id' => $subscription->id]);
        }

        Log::info("Product changed for user ID {$user->id}, new subscription ID {$subscription->id}.");
    }

    protected function handleSubscriptionExtended(User $user, array $data)
    {
        $subscription = Subscription::where('user_id', $user->id)
            ->where('transaction_id', $data['transaction_id'])
            ->orderBy('created_at', 'desc')
            ->first();

        if ($subscription) {
            $newExpirationAt = isset($data['expiration_at_ms']) ? Carbon::createFromTimestampMs($data['expiration_at_ms']) : null;
            if ($newExpirationAt && $newExpirationAt->gt($subscription->expiration_at)) {
                $subscription->update([
                    'expiration_at' => $newExpirationAt,
                    'is_active' => true,
                ]);

                Log::info("Subscription extended for user ID {$user->id}, subscription ID {$subscription->id}.");
            } else {
                Log::warning("Received subscription extended event but new expiration is not greater than current, user ID {$user->id}.");
            }
        } else {
            Log::warning("Subscription not found for extension, user ID {$user->id}.");
        }
    }

    private function handleTransfer(array $data)
    {

        $from = $data['transferred_from'][0] ?? null;
        $to = $data['transferred_to'][0] ?? null;

        $user = User::where('app_user_id', $from)->first();
        $newUser = User::where('app_user_id', $to)->first();

        if ($newUser && $user) {
            $subscriptions = Subscription::where('user_id', $user->id)->get();
            foreach ($subscriptions as $subscription) {
                $subscription->update(['user_id' => $newUser->id]);
            }

            Log::info("Subscriptions transferred from user ID {$user->id} to user ID {$newUser->id}.");
        } else {
            Log::warning("User not found for transfer, from: {$from}, to: {$to}.");
        }

        SubscriptionEvent::create([
            'user_id' => $user->id,
            'event_id' => $data['id'] ?? null,
            'type' => SubscriptionEventTypeEnum::TRANSFER->value,
            'event_timestamp' => isset($data['event_timestamp_ms']) ? Carbon::createFromTimestampMs($data['event_timestamp_ms']) : now(),
            'payload' => $data,
        ]);
    }

    private function handleInitialPurchase(User $user, array $data)
    {
        $purchasedAt = isset($data['purchased_at_ms']) ? Carbon::createFromTimestampMs($data['purchased_at_ms']) : null;
        $expirationAt = isset($data['expiration_at_ms']) ? Carbon::createFromTimestampMs($data['expiration_at_ms']) : null;

        $subscription = Subscription::create([
            'user_id' => $user->id,
            'app_user_id' => $data['app_user_id'] ?? null,
            'original_app_user_id' => $data['original_app_user_id'] ?? null,
            'store' => $data['store'] ?? null,
            'environment' => $data['environment'] ?? null,
            'product_id' => $data['product_id'] ?? null,
            'entitlement_ids' => $data['entitlement_ids'] ?? null,
            'period_type' => $data['period_type'] ?? null,
            'purchased_at' => $purchasedAt,
            'expiration_at' => $expirationAt,
            'transaction_id' => $data['transaction_id'] ?? null,
            'original_transaction_id' => $data['original_transaction_id'] ?? null,
            'is_trial_conversion' => $data['is_trial_conversion'] ?? false,
            'is_active' => true,
        ]);

        $event = SubscriptionEvent::where('id', $subscription->id)->first();
        if ($event) {
            $event->update(['subscription_id' => $subscription->id]);
        }

        Log::info("Subscription created for user ID {$user->id}, subscription ID {$subscription->id}.");
    }

    private function handleNonRenewingPurchase(User $user, array $data)
    {
        $purchasedAt = isset($data['purchased_at_ms']) ? Carbon::createFromTimestampMs($data['purchased_at_ms']) : null;
        $expirationAt = isset($data['expiration_at_ms']) ? Carbon::createFromTimestampMs($data['expiration_at_ms']) : null;

        $subscription = Subscription::create([
            'user_id' => $user->id,
            'app_user_id' => $data['app_user_id'] ?? null,
            'original_app_user_id' => $data['original_app_user_id'] ?? null,
            'store' => $data['store'] ?? null,
            'environment' => $data['environment'] ?? null,
            'product_id' => $data['product_id'] ?? null,
            'entitlement_ids' => $data['entitlement_ids'] ?? null,
            'period_type' => $data['period_type'] ?? null,
            'purchased_at' => $purchasedAt,
            'expiration_at' => $expirationAt,
            'transaction_id' => $data['transaction_id'] ?? null,
            'original_transaction_id' => $data['original_transaction_id'] ?? null,
            'is_trial_conversion' => $data['is_trial_conversion'] ?? false,
            'is_active' => true,
        ]);

        // Update the event with subscription ID
        $event = SubscriptionEvent::where('id', $subscription->id)->first();
        if ($event) {
            $event->update(['subscription_id' => $subscription->id]);
        }

        Log::info("Non-renewing subscription created for user ID {$user->id}, subscription ID {$subscription->id}.");
    }

    private function handleBillingIssue(User $user, array $data)
    {
        $subscription = Subscription::where('user_id', $user->id)
            ->where('transaction_id', $data['transaction_id'])
            ->orderBy('created_at', 'desc')
            ->first();

        if ($subscription) {
            // Here you may take appropriate action, such as notifying the user
            Log::warning("Billing issue detected for user ID {$user->id}, subscription ID {$subscription->id}.");
        } else {
            Log::warning("Subscription not found for billing issue, user ID {$user->id}.");
        }
    }
}

Event Types and Fields
RevenueCat sends webhooks in response to events that occur in your app. Here these event types are defined, as well as the data contained in each webhook.

Event Types
Webhook Event Type	Description	App Store	Play Store	Amazon	Stripe	Promo
TEST	Test event issued through the RevenueCat dashboard.	✅	✅	❌	❌	❌
INITIAL_PURCHASE	A new subscription has been purchased.	✅	✅	✅	✅	❌
RENEWAL	An existing subscription has been renewed or a lapsed user has resubscribed.	✅	✅	✅	✅	❌
CANCELLATION	A subscription or non-renewing purchase has been cancelled or refunded. Note that in the event of refunds, a subscription's auto-renewal setting may still be active. See cancellation reasons for more details. Note that, for the case of subscription refunds, this event is only fired if the latest subscription period of a subscription is refunded, refunds for earlier subscription periods do not trigger this event.	✅	✅	✅	✅	✅
UNCANCELLATION	A non-expired cancelled subscription has been re-enabled.	✅	✅	✅	❌	❌
NON_RENEWING_PURCHASE	A customer has made a purchase that will not auto-renew.	✅	✅	✅	✅	✅
SUBSCRIPTION_PAUSED	The subscription has set to be paused at the end of the period. Please note: You should not revoke access when receiving a SUBSCRIPTION_PAUSED event, but only when receiving an EXPIRATION event (which will have the expiration reason SUBSCRIPTION_PAUSED).	❌	✅	❌	❌	❌
EXPIRATION	A subscription has expired and access should be removed. If you have Platform Server Notifications configured, this event will occur as soon as we are notified (within seconds to minutes) of the expiration. If you do not have notifications configured, delays may be approximately 1 hour.	✅	✅	✅	✅	✅
BILLING_ISSUE	There has been a problem trying to charge the subscriber. This does not mean the subscription has expired. Can be safely ignored if listening to CANCELLATION event + cancel_reason=BILLING_ERROR.	✅	✅	✅	✅	❌
PRODUCT_CHANGE	A subscriber has changed the product of their subscription. This does not mean the new subscription is in effect immediately. See Managing Subscriptions for more details on updates, downgrades, and crossgrades.	✅	✅	❌	✅	❌
TRANSFER	A transfer of transactions and entitlements was initiated between one App User ID(s) to another. Please note: The webhook will only be sent for the destination user despite us displaying this event in both customer histories because the event body is exactly the same for both users.	✅	✅	✅	✅	❌
SUBSCRIPTION_EXTENDED	An existing subscription has been extended (the expiration date of the current subscription period has been pushed back to the future). This event is fired when a Apple App Store or Google Play Store subscription is extended through the store's API. On the Google Play Store, this event can also sometimes fire when Google defers charging for a renewal by less than 24 hours (for unknown reasons). In this case, you will receive a SUBSCRIPTION_EXTENDED webhook, followed by either a RENEWAL or BILLING_ISSUE webhook within the next 24 hours.	✅	✅	✅	✅	❌
TEMPORARY_ENTITLEMENT_GRANT	RevenueCat was temporarily unable to validate a purchase with the respective store and has granted a short-term entitlement to the customer. This event is sent in exceptional situations (for example, a partial app store outage) and is used to avoid customers making a purchase but not getting access to their entitlement. The expiration date of the entitlement is always at most 24 hours in the future. Once the exceptional situation has been resolved and RevenueCat can validate the purchases, a regular INITIAL_PURCHASE event will be sent. If the purchase can't be validated, an EXPIRATION event with the same transaction_id is sent. Please note: because this event type is dispatched in cases of limited connectivity with the store servers, it contains less information than a regular purchase event. The following fields are guaranteed to be present: app_user_id, purchased_at_ms, expiration_at_ms, event_timestamp_ms, product_id, entitlement_ids, store, transaction_id (note: the transaction_id might be different from the store's transaction_id present in a subsequent INITIAL_PURCHASE event; depending on the store, the product_id might be different from the product_id present in the subsequent INITIAL_PURCHASE event).	✅	✅	✅	✅	❌
Events Format
Webhook events are serialized in JSON. The body of a POST request to your server will contain the serialized event, as well as the API version.

Code
{
  "api_version": "1.0",
  "event": {
    "aliases": [
      "yourCustomerAliasedID",
      "yourCustomerAliasedID"
    ],
    "app_id": "yourAppID",
    "app_user_id": "yourCustomerAppUserID",
    "commission_percentage": 0.3,
    "country_code": "US",
    "currency": "USD",
    "entitlement_id": "pro_cat",
    "entitlement_ids": [
      "pro_cat"
    ],
    "environment": "PRODUCTION",
    "event_timestamp_ms": 1591121855319,
    "expiration_at_ms": 1591726653000,
    "id": "UniqueIdentifierOfEvent",
    "is_family_share": false,
    "offer_code": "free_month",
    "original_app_user_id": "OriginalAppUserID",
    "original_transaction_id": "1530648507000",
    "period_type": "NORMAL",
    "presented_offering_id": "OfferingID",
    "price": 2.49,
    "price_in_purchased_currency": 2.49,
    "product_id": "onemonth_no_trial",
    "purchased_at_ms": 1591121853000,
    "store": "APP_STORE",
    "subscriber_attributes": {
      "$Favorite Cat": {
        "updated_at_ms": 1581121853000,
        "value": "Garfield"
      }
    },
    "takehome_percentage": 0.7,
    "tax_percentage": 0.3,
    "transaction_id": "170000869511114",
    "type": "INITIAL_PURCHASE"
  }
}

initial purchase

{
    "event": {
        "event_timestamp_ms": 1658726378679,
        "product_id": "com.subscription.weekly",
        "period_type": "NORMAL",
        "purchased_at_ms": 1658726374000,
        "expiration_at_ms": 1659331174000,
        "environment": "PRODUCTION",
        "entitlement_id": null,
        "entitlement_ids": [
            "pro"
        ],
        "presented_offering_id": null,
        "transaction_id": "123456789012345",
        "original_transaction_id": "123456789012345",
        "is_family_share": false,
        "country_code": "US",
        "app_user_id": "1234567890",
        "aliases": [
            "$RCAnonymousID:8069238d6049ce87cc529853916d624c"
        ],
        "original_app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
        "currency": "USD",
        "price": 4.99,
        "price_in_purchased_currency": 4.99,
        "subscriber_attributes": {
            "$email": {
                "updated_at_ms": 1662955084635,
                "value": "firstlast@gmail.com"
            }
        },
        "store": "APP_STORE",
        "takehome_percentage": 0.7,
        "offer_code": null,
        "type": "INITIAL_PURCHASE",
        "id": "12345678-1234-1234-1234-123456789012",
        "app_id": "1234567890"
    },
    "api_version": "1.0"
}

renewal
{
    "event": {
        "event_timestamp_ms": 1658726405017,
        "product_id": "com.subscription.weekly",
        "period_type": "NORMAL",
        "purchased_at_ms": 1658755132000,
        "expiration_at_ms": 1659359932000,
        "environment": "PRODUCTION",
        "entitlement_id": null,
        "entitlement_ids": [
            "pro"
        ],
        "presented_offering_id": null,
        "transaction_id": "123456789012345",
        "original_transaction_id": "123456789012345",
        "is_family_share": false,
        "country_code": "DE",
        "app_user_id": "1234567890",
        "aliases": [
            "$RCAnonymousID:8069238d6049ce87cc529853916d624c"
        ],
        "original_app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
        "currency": "EUR",
        "is_trial_conversion": false,
        "price": 8.14,
        "price_in_purchased_currency": 7.99,
        "subscriber_attributes": {
            "$email": {
                "updated_at_ms": 1662955084635,
                "value": "firstlast@gmail.com"
            }
        },
        "store": "APP_STORE",
        "takehome_percentage": 0.7,
        "offer_code": null,
        "type": "RENEWAL",
        "id": "12345678-1234-1234-1234-123456789012",
        "app_id": "1234567890"
    },
    "api_version": "1.0"
}

cancelletion

{
  "event": {
    "event_timestamp_ms": 1601337615995,
    "product_id": "com.revenuecat.myapp.weekly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1601417766000,
    "expiration_at_ms": 1602022566000,
    "environment": "PRODUCTION",
    "entitlement_id": "pro",
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": "defaultoffering",
    "transaction_id": "100000000000002",
    "original_transaction_id": "100000000000000",
    "app_user_id": "$RCAnonymousID:12345678-1234-1234-1234-123456789123",
    "aliases": [
      "$RCAnonymousID:12345678-1234-ABCD-1234-123456789123",
      "user_1234"
    ],
    "offer_code": "free_month",
    "original_app_user_id": "$RCAnonymousID:12345678-1234-ABCD-1234-123456789123",
    "cancel_reason": "UNSUBSCRIBE",
    "currency": "USD",
    "price": 0.0,
    "price_in_purchased_currency": 0.0,
    "subscriber_attributes": {
      "$idfa": {
        "value": "12345678-1234-1234-1234-12345678912x",
        "updated_at_ms": 1578018408238
      },
      "$appsflyerId": {
        "value": "1234567891234-1234567",
        "updated_at_ms": 1578018408238
      },
      "favorite_food": {
        "value": "pizza",
        "updated_at_ms": 1578018408238
      }
    },
    "store": "APP_STORE",
    "takehome_percentage": 0.7,
    "type": "CANCELLATION",
    "id": "12345678-ABCD-1234-ABCD-12345678912"
  },
  "api_version": "1.0"
}

uncancelletion

{
    "event": {
        "event_timestamp_ms": 1663982135337,
        "product_id": "com.subscription.monthly",
        "period_type": "NORMAL",
        "purchased_at_ms": 1662643092000,
        "expiration_at_ms": 1665235092000,
        "environment": "PRODUCTION",
        "entitlement_id": null,
        "entitlement_ids": [
            "plus"
        ],
        "presented_offering_id": "plus",
        "transaction_id": "123456789012345",
        "original_transaction_id": "123456789012345",
        "is_family_share": false,
        "country_code": "US",
        "app_user_id": "1234567890",
        "aliases": [
            "$RCAnonymousID:8069238d6049ce87cc529853916d624c"
        ],
        "original_app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
        "currency": "USD",
        "price": 0.0,
        "price_in_purchased_currency": 0.0,
        "subscriber_attributes": {},
        "store": "APP_STORE",
        "takehome_percentage": 0.7,
        "offer_code": null,
        "tax_percentage": 0.0,
        "commission_percentage": 0.3,
        "type": "UNCANCELLATION",
        "id": "12345678-1234-1234-1234-123456789012",
        "app_id": "1234567890"
    },
    "api_version": "1.0"
}

subscription paused 

{
    "event": {
        "event_timestamp_ms": 1652796516000,
        "product_id": "premium",
        "period_type": "NORMAL",
        "purchased_at_ms": 1652681048845,
        "expiration_at_ms": 1655366648845,
        "environment": "PRODUCTION",
        "entitlement_id": "Premium1",
        "entitlement_ids": [
            "Premium1"
        ],
        "presented_offering_id": "premium",
        "transaction_id": "123456789012345",
        "original_transaction_id": "123456789012345",
        "is_family_share": false,
        "country_code": "US",
        "app_user_id": "1234567890",
        "aliases": [
            "$RCAnonymousID:8069238d6049ce87cc529853916d624c"
        ],
        "original_app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
        "auto_resume_at_ms": 1657951448845,
        "currency": "USD",
        "price": 0.0,
        "price_in_purchased_currency": 0.0,
        "subscriber_attributes": {
            "$email": {
                "updated_at_ms": 1662955084635,
                "value": "firstlast@gmail.com"
            }
        },
        "store": "PLAY_STORE",
        "takehome_percentage": 0.85,
        "offer_code": null,
        "type": "SUBSCRIPTION_PAUSED",
        "id": "12345678-1234-1234-1234-123456789012",
        "app_id": "1234567890"
    },
    "api_version": "1.0"
}

non renewing purchase

{
    "event": {
        "event_timestamp_ms": 1658726522314,
        "product_id": "2100_tokens",
        "period_type": "NORMAL",
        "purchased_at_ms": 1658726519000,
        "expiration_at_ms": null,
        "environment": "PRODUCTION",
        "entitlement_id": null,
        "entitlement_ids": [
            "pro"
        ],
        "presented_offering_id": "coins",
        "transaction_id": "123456789012345",
        "original_transaction_id": "123456789012345",
        "is_family_share": false,
        "country_code": "CA",
        "app_user_id": "1234567890",
        "aliases": [
            "$RCAnonymousID:8069238d6049ce87cc529853916d624c"
        ],
        "original_app_user_id": "$RCAnonymousID:87c6049c58069238dce29853916d624c",
        "currency": "CAD",
        "price": 25.487,
        "price_in_purchased_currency": 32.99,
        "subscriber_attributes": {
            "$email": {
                "updated_at_ms": 1662955084635,
                "value": "firstlast@gmail.com"
            }
        },
        "store": "APP_STORE",
        "takehome_percentage": 0.85,
        "offer_code": null,
        "type": "NON_RENEWING_PURCHASE",
        "id": "12345678-1234-1234-1234-123456789012",
        "app_id": "1234567890"
    },
    "api_version": "1.0"
}