diff --git a/src/Hermes/DeveloperNotificationReceivedHandler.php b/src/Hermes/DeveloperNotificationReceivedHandler.php index 4a1e833..fcc5b3e 100644 --- a/src/Hermes/DeveloperNotificationReceivedHandler.php +++ b/src/Hermes/DeveloperNotificationReceivedHandler.php @@ -20,6 +20,7 @@ use Psr\Log\LoggerAwareTrait; use ReceiptValidator\GooglePlay\Acknowledger; use ReceiptValidator\GooglePlay\SubscriptionResponse; +use ReceiptValidator\GooglePlay\Validator; use Tomaj\Hermes\Handler\HandlerInterface; use Tomaj\Hermes\Handler\RetryTrait; use Tomaj\Hermes\MessageInterface; @@ -32,44 +33,19 @@ class DeveloperNotificationReceivedHandler implements HandlerInterface public const INFO_LOG_LEVEL = 'google_developer_notifications'; - private $developerNotificationsRepository; - - private $googlePlaySubscriptionTypesRepository; - - private $googlePlayValidatorFactory; - - private $paymentGatewaysRepository; - - private $paymentMetaRepository; - - private $paymentsRepository; - - private $subscriptionsRepository; - - private $subscriptionMetaRepository; - - private $subscriptionResponseProcessor; + private $googlePlayValidator; public function __construct( - SubscriptionResponseProcessorInterface $subscriptionResponseProcessor, - DeveloperNotificationsRepository $developerNotificationsRepository, - GooglePlaySubscriptionTypesRepository $googlePlaySubscriptionTypesRepository, - GooglePlayValidatorFactory $googlePlayValidator, - PaymentGatewaysRepository $paymentGatewaysRepository, - PaymentMetaRepository $paymentMetaRepository, - PaymentsRepository $paymentsRepository, - SubscriptionsRepository $subscriptionsRepository, - SubscriptionMetaRepository $subscriptionMetaRepository + private SubscriptionResponseProcessorInterface $subscriptionResponseProcessor, + private DeveloperNotificationsRepository $developerNotificationsRepository, + private GooglePlaySubscriptionTypesRepository $googlePlaySubscriptionTypesRepository, + private GooglePlayValidatorFactory $googlePlayValidatorFactory, + private PaymentGatewaysRepository $paymentGatewaysRepository, + private PaymentMetaRepository $paymentMetaRepository, + private PaymentsRepository $paymentsRepository, + private SubscriptionsRepository $subscriptionsRepository, + private SubscriptionMetaRepository $subscriptionMetaRepository ) { - $this->developerNotificationsRepository = $developerNotificationsRepository; - $this->googlePlaySubscriptionTypesRepository = $googlePlaySubscriptionTypesRepository; - $this->googlePlayValidatorFactory = $googlePlayValidator; - $this->paymentGatewaysRepository = $paymentGatewaysRepository; - $this->paymentMetaRepository = $paymentMetaRepository; - $this->paymentsRepository = $paymentsRepository; - $this->subscriptionsRepository = $subscriptionsRepository; - $this->subscriptionMetaRepository = $subscriptionMetaRepository; - $this->subscriptionResponseProcessor = $subscriptionResponseProcessor; } public function handle(MessageInterface $message): bool @@ -83,7 +59,7 @@ public function handle(MessageInterface $message): bool } // validate and load google subscription - $googlePlayValidator = $this->googlePlayValidatorFactory->create(); + $googlePlayValidator = $this->googlePlayValidator ?: $this->googlePlayValidatorFactory->create(); $gSubscription = $googlePlayValidator ->setPackageName($developerNotification->package_name) ->setPurchaseToken($developerNotification->purchase_token) @@ -167,6 +143,12 @@ public function handle(MessageInterface $message): bool return true; } + // Useful in tests + public function setGooglePlayValidator(Validator $googlePlayValidator): void + { + $this->googlePlayValidator = $googlePlayValidator; + } + private function developerNotification(MessageInterface $message): ActiveRow { $payload = $message->getPayload(); @@ -282,10 +264,17 @@ private function createPayment(SubscriptionResponse $subscriptionResponse, Activ $recurrentCharge = true; - // Handle case when first subscription type is different from renewals. - // Note: currently, this only handles Introductory price (in Google console) of "Single payment" type, not "Recurring payment" type. + // Handle case when introductory subscription type is different from renewals. if ($subscriptionType->next_subscription_type_id) { - $subscriptionType = $subscriptionType->next_subscription_type; + $googleSubscriptionType = $this->googlePlaySubscriptionTypesRepository->findByGooglePlaySubscriptionId($developerNotification->subscription_id); + if ($googleSubscriptionType->offer_periods) { + $usedOfferPeriods = $this->getUsedOfferPeriods($subscriptionResponse->getRawResponse()->getOrderId()); + if ($usedOfferPeriods >= $googleSubscriptionType->offer_periods) { + $subscriptionType = $subscriptionType->next_subscription_type; + } + } else { + $subscriptionType = $subscriptionType->next_subscription_type; + } } } @@ -473,4 +462,18 @@ public function processCancelReason(SubscriptionResponse $subscriptionResponse, return $cancelData; } + + private function getUsedOfferPeriods($orderId): int + { + $matches = []; + // Order ID for renewal payments ends with '..0', e.g. 'GPA.1111-1111-1111-11111..0' + preg_match('/\.\.(\d+)$/', $orderId, $matches); + + if (isset($matches[1])) { + // Renewal starts from 0; first renewal order id ends with '..0'; initial payment has no sufix + return (int)$matches[1] + 1; + } + + return 0; + } } diff --git a/src/Models/Repositories/GooglePlaySubscriptionTypesRepository.php b/src/Models/Repositories/GooglePlaySubscriptionTypesRepository.php index f62b44f..88228a3 100644 --- a/src/Models/Repositories/GooglePlaySubscriptionTypesRepository.php +++ b/src/Models/Repositories/GooglePlaySubscriptionTypesRepository.php @@ -9,11 +9,12 @@ class GooglePlaySubscriptionTypesRepository extends Repository { protected $tableName = 'google_play_billing_subscription_types'; - final public function add(string $googlePlaySubscriptionId, ActiveRow $subscriptionType) + final public function add(string $googlePlaySubscriptionId, ActiveRow $subscriptionType, ?int $offerPeriods = null) { return $this->getTable()->insert([ 'subscription_id' => $googlePlaySubscriptionId, 'subscription_type_id' => $subscriptionType->id, + 'offer_periods' => $offerPeriods, ]); } diff --git a/src/Tests/Hermes/DeveloperNotificationReceivedHandlerOfferPeriodsTest.php b/src/Tests/Hermes/DeveloperNotificationReceivedHandlerOfferPeriodsTest.php new file mode 100644 index 0000000..7904ff6 --- /dev/null +++ b/src/Tests/Hermes/DeveloperNotificationReceivedHandlerOfferPeriodsTest.php @@ -0,0 +1,477 @@ +developerNotificationReceivedHandler = $this->inject(DeveloperNotificationReceivedHandler::class); + + $this->developerNotificationsRepository = $this->getRepository(DeveloperNotificationsRepository::class); + $this->googlePlaySubscriptionTypesRepository = $this->getRepository(GooglePlaySubscriptionTypesRepository::class); + $this->purchaseTokensRepository = $this->getRepository(PurchaseTokensRepository::class); + + $this->paymentsRepository = $this->getRepository(PaymentsRepository::class); + $this->paymentMetaRepository = $this->getRepository(PaymentMetaRepository::class); + $this->subscriptionTypesRepository = $this->getRepository(SubscriptionTypesRepository::class); + $this->subscriptionTypeBuilder = $this->inject(SubscriptionTypeBuilder::class); + $this->subscriptionsRepository = $this->getRepository(SubscriptionsRepository::class); + $this->usersRepository = $this->getRepository(UsersRepository::class); + + + // add event handler to create subscription + + /** @var Emitter $emitter */ + $emitter = $this->inject(Emitter::class); + // clear initialized handlers (we do not want duplicated listeners) + $emitter->removeAllListeners(\Crm\PaymentsModule\Events\PaymentChangeStatusEvent::class); + $emitter->addListener( + \Crm\PaymentsModule\Events\PaymentChangeStatusEvent::class, + $this->inject(\Crm\PaymentsModule\Events\PaymentStatusChangeHandler::class) + ); + } + + public function tearDown(): void + { + /** @var Emitter $emitter */ + $emitter = $this->inject(Emitter::class); + $emitter->removeAllListeners(\Crm\PaymentsModule\Events\PaymentChangeStatusEvent::class); + + parent::tearDown(); + } + + // Make sure everything works fine so we don't have to test it everytime. + public function testFirstPurchaseSuccess() + { + $this->assertEquals(0, $this->paymentsRepository->totalCount()); + $this->assertEquals(0, $this->subscriptionsRepository->totalCount()); + $this->assertEquals(0, $this->paymentMetaRepository->totalCount()); + + $purchaseToken = md5('random'); + $orderId = 'GPA.1111-1111-1111-11111'; + $googleSubscriptionType = $this->getGooglePlaySubscriptionTypeWeb(); + $startTimeMillisPurchase = new DateTime('2030-04-27 19:20:57'); + $expiryTimeMillisPurchase = new DateTime('2030-05-27 19:20:57'); + + $developerNotificationFirstPurchase = $this->preparePayment($purchaseToken, $orderId, $startTimeMillisPurchase, $expiryTimeMillisPurchase, $googleSubscriptionType); + + // developer notification marked as processed + $developerNotificationFirstPurchaseUpdated = $this->developerNotificationsRepository->find($developerNotificationFirstPurchase->id); + $this->assertEquals( + DeveloperNotificationsRepository::STATUS_PROCESSED, + $developerNotificationFirstPurchaseUpdated->status + ); + + // payment, payment_meta and subscription created + $this->assertEquals(1, $this->paymentsRepository->totalCount()); + $this->assertEquals(1, $this->subscriptionsRepository->totalCount()); + $this->assertEquals(3, $this->paymentMetaRepository->totalCount()); + + // payment status & subscription_type checks + $payment = $this->paymentsRepository->getTable()->fetch(); + $this->assertEquals(PaymentsRepository::STATUS_PREPAID, $payment->status); + $this->assertEquals($googleSubscriptionType->subscription_type_id, $payment->subscription_type_id); + + // check payment meta against order id and purchase token + $purchaseTokenFirstPurchase = $this->purchaseTokensRepository->findByPurchaseToken($purchaseToken); + $this->assertEquals( + $purchaseTokenFirstPurchase->purchase_token, + $this->paymentMetaRepository->findByPaymentAndKey($payment, 'google_play_billing_purchase_token')->value + ); + $this->assertEquals( + $developerNotificationFirstPurchase->id, + $this->paymentMetaRepository->findByPaymentAndKey($payment, 'google_play_billing_developer_notification_id')->value + ); + $this->assertEquals( + $orderId, + $this->paymentMetaRepository->findByPaymentAndKey($payment, 'google_play_billing_order_id')->value + ); + + // check subscription type & start/end times against Google play validation response + $subscription = $this->subscriptionsRepository->getTable()->fetch(); + $this->assertEquals($googleSubscriptionType->subscription_type_id, $subscription->subscription_type_id); + $this->assertEquals($startTimeMillisPurchase, $payment->subscription_start_at); + $this->assertEquals($expiryTimeMillisPurchase, $payment->subscription_end_at); + $this->assertEquals($startTimeMillisPurchase, $subscription->start_time); + $this->assertEquals($expiryTimeMillisPurchase, $subscription->end_time); + $this->assertEquals($subscription->id, $payment->subscription_id); + } + + // offer_periods set NULL equals offer_periods set 1 when next_subscription_type set for subscription type. + public function testOfferPeriodsSetNull() + { + /* ************************************************************ * + * FIRST PURCHASE ********************************************* * + * ************************************************************ */ + + $purchaseToken = md5('random'); + $orderId = 'GPA.1111-1111-1111-11111'; + $googleSubscriptionType = $this->getGooglePlaySubscriptionTypeWeb(); + $startTimeMillisPurchase = new DateTime('2030-04-27 19:20:57'); + $expiryTimeMillisPurchase = new DateTime('2030-05-27 19:20:57'); + + $this->preparePayment($purchaseToken, $orderId, $startTimeMillisPurchase, $expiryTimeMillisPurchase, $googleSubscriptionType); + + $this->assertEquals(1, $this->paymentsRepository->totalCount()); + $this->assertEquals(1, $this->subscriptionsRepository->totalCount()); + $this->assertEquals(3, $this->paymentMetaRepository->totalCount()); + + /* ************************************************************ * + * SECOND PURCHASE ********************************************* * + * ************************************************************ */ + + $orderId = 'GPA.1111-1111-1111-11111..0'; + $startTimeMillisPurchase = new DateTime('2030-05-27 19:20:57'); + $expiryTimeMillisPurchase = new DateTime('2030-06-27 19:20:57'); + + $developerNotificationSecondPurchase = $this->preparePayment($purchaseToken, $orderId, $startTimeMillisPurchase, $expiryTimeMillisPurchase, $googleSubscriptionType); + + // developer notification marked as processed + $developerNotificationSecondPurchaseUpdated = $this->developerNotificationsRepository->find($developerNotificationSecondPurchase->id); + $this->assertEquals( + DeveloperNotificationsRepository::STATUS_PROCESSED, + $developerNotificationSecondPurchaseUpdated->status + ); + + // new payment, subscription & payment_meta + $this->assertEquals(2, $this->paymentsRepository->totalCount()); + $this->assertEquals(2, $this->subscriptionsRepository->totalCount()); + $this->assertEquals(6, $this->paymentMetaRepository->totalCount()); + + $payments = $this->paymentsRepository->getTable()->order('created_at')->fetchAll(); + reset($payments); + $paymentSecondPurchase = next($payments); + + $subscriptionTypeAfterOfferPeriods = $this->getSubscriptionTypeAfterOfferPeriods(); + + // check new payment (second) & meta against second purchase + $this->assertEquals(PaymentsRepository::STATUS_PREPAID, $paymentSecondPurchase->status); + $this->assertEquals($subscriptionTypeAfterOfferPeriods->id, $paymentSecondPurchase->subscription_type_id); + + $subscriptionSecondPurchase = $paymentSecondPurchase->subscription; + $this->assertEquals($subscriptionTypeAfterOfferPeriods->id, $subscriptionSecondPurchase->subscription_type_id); + $this->assertEquals($startTimeMillisPurchase, $paymentSecondPurchase->subscription_start_at); + $this->assertEquals($expiryTimeMillisPurchase, $paymentSecondPurchase->subscription_end_at); + $this->assertEquals($startTimeMillisPurchase, $subscriptionSecondPurchase->start_time); + $this->assertEquals($expiryTimeMillisPurchase, $subscriptionSecondPurchase->end_time); + } + + public function testOfferPeriodsSetInt() + { + /* ************************************************************ * + * FIRST PURCHASE ********************************************* * + * ************************************************************ */ + + $purchaseToken = md5('random'); + $orderId = 'GPA.1111-1111-1111-11111'; + $googleSubscriptionType = $this->getGooglePlaySubscriptionTypeWeb(2); + $startTimeMillisPurchase = new DateTime('2030-04-27 19:20:57'); + $expiryTimeMillisPurchase = new DateTime('2030-05-27 19:20:57'); + + $this->preparePayment($purchaseToken, $orderId, $startTimeMillisPurchase, $expiryTimeMillisPurchase, $googleSubscriptionType); + + // After first purchase + $this->assertEquals(1, $this->paymentsRepository->totalCount()); + $this->assertEquals(1, $this->subscriptionsRepository->totalCount()); + $this->assertEquals(3, $this->paymentMetaRepository->totalCount()); + + /* ************************************************************ * + * SECOND PURCHASE ********************************************* * + * ************************************************************ */ + + $orderId = 'GPA.1111-1111-1111-11111..0'; + $startTimeMillisPurchase = new DateTime('2030-05-27 19:20:57'); + $expiryTimeMillisPurchase = new DateTime('2030-06-27 19:20:57'); + + $this->preparePayment($purchaseToken, $orderId, $startTimeMillisPurchase, $expiryTimeMillisPurchase, $googleSubscriptionType); + + // After second purchase + $this->assertEquals(2, $this->paymentsRepository->totalCount()); + $this->assertEquals(2, $this->subscriptionsRepository->totalCount()); + $this->assertEquals(6, $this->paymentMetaRepository->totalCount()); + + // Check second payment still has offer period subscription type + $payments = $this->paymentsRepository->getTable()->order('created_at')->fetchAll(); + reset($payments); + $paymentSecondPurchase = next($payments); + + // check new payment (second) & meta against second purchase + $this->assertEquals(PaymentsRepository::STATUS_PREPAID, $paymentSecondPurchase->status); + $this->assertEquals($googleSubscriptionType->subscription_type_id, $paymentSecondPurchase->subscription_type_id); + + /* ************************************************************ * + * THIRD PURCHASE ********************************************* * + * ************************************************************ */ + + $orderId = 'GPA.1111-1111-1111-11111..1'; + $startTimeMillisPurchase = new DateTime('2030-06-27 19:20:57'); + $expiryTimeMillisPurchase = new DateTime('2030-07-27 19:20:57'); + + $developerNotificationThirdPurchase = $this->preparePayment($purchaseToken, $orderId, $startTimeMillisPurchase, $expiryTimeMillisPurchase, $googleSubscriptionType); + + // After third purchase + $this->assertEquals(3, $this->paymentsRepository->totalCount()); + $this->assertEquals(3, $this->subscriptionsRepository->totalCount()); + $this->assertEquals(9, $this->paymentMetaRepository->totalCount()); + + // developer notification marked as processed + $developerNotificationThirdPurchaseUpdated = $this->developerNotificationsRepository->find($developerNotificationThirdPurchase->id); + $this->assertEquals( + DeveloperNotificationsRepository::STATUS_PROCESSED, + $developerNotificationThirdPurchaseUpdated->status + ); + + $payments = $this->paymentsRepository->getTable()->order('created_at')->fetchAll(); + reset($payments); + next($payments); + $paymentThirdPurchase = next($payments); + $subscriptionTypeAfterOfferPeriods = $this->getSubscriptionTypeAfterOfferPeriods(); + + // check third payment & meta against third purchase + $this->assertEquals(PaymentsRepository::STATUS_PREPAID, $paymentThirdPurchase->status); + $this->assertEquals($subscriptionTypeAfterOfferPeriods->id, $paymentThirdPurchase->subscription_type_id); + + $subscriptionSecondPurchase = $paymentThirdPurchase->subscription; + $this->assertEquals($subscriptionTypeAfterOfferPeriods->id, $subscriptionSecondPurchase->subscription_type_id); + $this->assertEquals($startTimeMillisPurchase, $paymentThirdPurchase->subscription_start_at); + $this->assertEquals($expiryTimeMillisPurchase, $paymentThirdPurchase->subscription_end_at); + $this->assertEquals($startTimeMillisPurchase, $subscriptionSecondPurchase->start_time); + $this->assertEquals($expiryTimeMillisPurchase, $subscriptionSecondPurchase->end_time); + } + + /* **************************************************************** * + * HELPER METHODS + * **************************************************************** */ + + private function injectSubscriptionResponseIntoGooglePlayValidatorMock(string $expectedGoogleValidatorSubscriptionResponse): void + { + /** @var Validator|MockInterface $googlePlayValidatorMocked */ + $googlePlayValidatorMocked = Mockery::mock(Validator::class); + $googlePlayValidatorMocked->shouldReceive('setPackageName->setPurchaseToken->setProductId->validateSubscription') + ->andReturn(new SubscriptionResponse(new SubscriptionPurchase( + Json::decode($expectedGoogleValidatorSubscriptionResponse, Json::FORCE_ARRAY) + ))) + ->getMock(); + + $this->developerNotificationReceivedHandler->setGooglePlayValidator($googlePlayValidatorMocked); + } + + private function getUser(): ActiveRow + { + if ($this->user !== null) { + return $this->user; + } + + $this->user = $this->usersRepository->findBy('email', 'test@example.com'); + if (!$this->user) { + $this->user = $this->usersRepository->add('test@example.com', 'password'); + } + + return $this->user; + } + + private function getGooglePlaySubscriptionTypeWeb(?int $offerPeriods = null): ActiveRow + { + if ($this->googlePlaySubscriptionTypeWeb !== null) { + return $this->googlePlaySubscriptionTypeWeb; + } + + $googlePlaySubscriptionIdWeb = 'test.package.dennikn.test.web'; + $subscriptionTypeCodeWeb = 'google_inapp_web'; + + $subscriptionTypeWeb = $this->subscriptionTypesRepository->findByCode($subscriptionTypeCodeWeb); + if (!$subscriptionTypeWeb) { + $subscriptionTypeWeb = $this->subscriptionTypeBuilder->createNew() + ->setName('Google Pay test subscription WEB month') + ->setUserLabel('Google Pay test subscription WEB month') + ->setPrice(6.99) + ->setCode($subscriptionTypeCodeWeb) + ->setLength(31) + ->setActive(true) + ->setNextSubscriptionTypeIdFromCode($this->getSubscriptionTypeAfterOfferPeriods()->code) + ->save(); + } + $this->googlePlaySubscriptionTypeWeb = $this->googlePlaySubscriptionTypesRepository->findByGooglePlaySubscriptionId($googlePlaySubscriptionIdWeb); + if (!$this->googlePlaySubscriptionTypeWeb) { + $this->googlePlaySubscriptionTypeWeb = $this->googlePlaySubscriptionTypesRepository->add( + $googlePlaySubscriptionIdWeb, + $subscriptionTypeWeb, + $offerPeriods + ); + } + + return $this->googlePlaySubscriptionTypeWeb; + } + + private function getSubscriptionTypeAfterOfferPeriods() + { + $subscriptionTypeCode = 'google_inapp_after_offer_periods'; + + $subscriptionType = $this->subscriptionTypesRepository->findByCode($subscriptionTypeCode); + if (!$subscriptionType) { + $subscriptionType = $this->subscriptionTypeBuilder->createNew() + ->setName('Google Pay test subscription after offer periods') + ->setUserLabel('Google Pay test subscription after offer periods') + ->setPrice(6.99) + ->setCode($subscriptionTypeCode) + ->setLength(31) + ->setActive(true) + ->save(); + } + + return $subscriptionType; + } + + private function preparePayment($purchaseTokenString, $orderIdPurchase, $startTimeMillisPurchase, $expiryTimeMillisPurchase, $googleSubscriptionType) + { + $purchaseToken = $this->purchaseTokensRepository->add( + $purchaseTokenString, + $this->googlePlayPackage, + $googleSubscriptionType->subscription_id + ); + $developerNotificationPurchase = $this->developerNotificationsRepository->add( + $purchaseToken, + new DateTime(), + DeveloperNotificationsRepository::NOTIFICATION_TYPE_SUBSCRIPTION_PURCHASED + ); + $hermesMessagePurchase = new HermesMessage( + 'developer-notification-received', + [ + 'developer_notification_id' => $developerNotificationPurchase->getPrimary(), + ], + ); + + $priceAmountMicrosPurchase = $googleSubscriptionType->subscription_type->price * 1000000; + // acknowledgementState: 1 -> set to acknowledged so we don't need to mock acknowledgement service + // autoRenewing: true -> first purchase set to create recurrent payment + $googleResponsePurchase = <<format('Uv')}", + "externalAccountId": null, + "familyName": null, + "givenName": null, + "kind": "androidpublisher#subscriptionPurchase", + "linkedPurchaseToken": null, + "obfuscatedExternalAccountId": "{$this->getUser()->id}", + "obfuscatedExternalProfileId": null, + "orderId": "{$orderIdPurchase}", + "paymentState": 1, + "priceAmountMicros": "{$priceAmountMicrosPurchase}", + "priceCurrencyCode": "EUR", + "profileId": null, + "profileName": null, + "promotionCode": null, + "promotionType": null, + "purchaseType": null, + "startTimeMillis": "{$startTimeMillisPurchase->format('Uv')}", + "userCancellationTimeMillis": null +} +JSON; + + $this->injectSubscriptionResponseIntoGooglePlayValidatorMock($googleResponsePurchase); + + $this->developerNotificationReceivedHandler->handle($hermesMessagePurchase); + + return $developerNotificationPurchase; + } +} diff --git a/src/Tests/Hermes/DeveloperNotificationReceivedHandlerUpgradeTest.php b/src/Tests/Hermes/DeveloperNotificationReceivedHandlerUpgradeTest.php index 57a394f..12e7fd9 100644 --- a/src/Tests/Hermes/DeveloperNotificationReceivedHandlerUpgradeTest.php +++ b/src/Tests/Hermes/DeveloperNotificationReceivedHandlerUpgradeTest.php @@ -5,7 +5,6 @@ use Crm\ApplicationModule\Hermes\HermesMessage; use Crm\ApplicationModule\Tests\DatabaseTestCase; use Crm\GooglePlayBillingModule\Hermes\DeveloperNotificationReceivedHandler; -use Crm\GooglePlayBillingModule\Model\GooglePlayValidatorFactory; use Crm\GooglePlayBillingModule\Repository\DeveloperNotificationsRepository; use Crm\GooglePlayBillingModule\Repository\GooglePlaySubscriptionTypesRepository; use Crm\GooglePlayBillingModule\Repository\PurchaseDeviceTokensRepository; @@ -46,8 +45,6 @@ class DeveloperNotificationReceivedHandlerUpgradeTest extends DatabaseTestCase private ?ActiveRow $googlePlaySubscriptionTypeStandard = null; private ?ActiveRow $user = null; - private static GooglePlayValidatorFactory $googlePlayValidatorFactoryMocked; - private DeveloperNotificationReceivedHandler $developerNotificationReceivedHandler; private DeveloperNotificationsRepository $developerNotificationsRepository; @@ -100,18 +97,15 @@ protected function requiredSeeders(): array ]; } - public static function setUpBeforeClass(): void - { - self::$googlePlayValidatorFactoryMocked = Mockery::mock(GooglePlayValidatorFactory::class); - } + //public static function setUpBeforeClass(): void + //{ + // self::$googlePlayValidatorFactoryMocked = Mockery::mock(GooglePlayValidatorFactory::class); + //} public function setUp(): void { parent::setUp(); - // switch google play validator factory to mocked one; this is used by DeveloperNotificationReceivedHandler - $this->container->removeService('googlePlayValidatorFactory'); - $this->container->addService('googlePlayValidatorFactory', self::$googlePlayValidatorFactoryMocked); $this->developerNotificationReceivedHandler = $this->inject(DeveloperNotificationReceivedHandler::class); $this->developerNotificationsRepository = $this->getRepository(DeveloperNotificationsRepository::class); @@ -174,7 +168,7 @@ public function testSuccess() $startTimeMillisFirstPurchase = new DateTime('2030-04-27 19:20:57'); $expiryTimeMillisFirstPurchase = new DateTime('2030-05-27 19:20:57'); $priceAmountMicrosFirstPurchase = $this->getGooglePlaySubscriptionTypeWeb()->subscription_type->price * 1000000; - // acknowledgementState: 1 -> set to acknowledged so we don't need to mock acknowledgement service + // acknowledgementState: 1 -> set to acknowledged, so we don't need to mock acknowledgement service // autoRenewing: true -> first purchase set to create recurrent payment $googleResponseFirstPurchase = <<getMock(); - - // set response into mock - self::$googlePlayValidatorFactoryMocked - ->shouldReceive('create') - ->andReturn($googlePlayValidatorMocked) - ->once(); + $this->developerNotificationReceivedHandler->setGooglePlayValidator($googlePlayValidatorMocked); } private function getUser(): ActiveRow diff --git a/src/migrations/20221108225704_add_offer_periods.php b/src/migrations/20221108225704_add_offer_periods.php new file mode 100644 index 0000000..d200d81 --- /dev/null +++ b/src/migrations/20221108225704_add_offer_periods.php @@ -0,0 +1,14 @@ +table('google_play_billing_subscription_types') + ->addColumn('offer_periods', 'integer', ['null' => true]) + ->update(); + } +}