create([ 'type' => 'endcustomer', 'lemonsqueezy_variant_id' => 'pri_pkg_001', 'price' => 59, ]); $payload = [ 'data' => [ 'id' => 'ord_123', 'attributes' => [ 'total' => 5900, 'currency' => 'EUR', 'checkout_id' => 'chk_abc', 'variant_id' => 'pri_pkg_001', 'user_email' => 'buyer@example.com', ], ], 'meta' => [ 'custom_data' => [ 'type' => 'gift_card', 'purchaser_email' => 'buyer@example.com', 'recipient_email' => 'friend@example.com', 'recipient_name' => 'Friend', 'message' => 'Happy Day', ], ], ]; $service = $this->app->make(GiftVoucherService::class); $voucher = $service->issueFromLemonSqueezy($payload); $this->assertInstanceOf(GiftVoucher::class, $voucher); $this->assertSame(59.00, (float) $voucher->amount); $this->assertNotNull($voucher->coupon); $this->assertSame($voucher->code, $voucher->coupon->code); $this->assertTrue($voucher->expires_at->greaterThan(now()->addYears(4))); $this->assertTrue($voucher->coupon->packages()->whereKey($package->id)->exists()); } public function test_redeeming_coupon_marks_voucher_redeemed(): void { $voucher = GiftVoucher::factory()->create([ 'status' => GiftVoucher::STATUS_ISSUED, 'amount' => 29, ]); $coupon = Coupon::factory()->create([ 'code' => $voucher->code, 'type' => CouponType::FLAT, 'amount' => 29, 'currency' => 'EUR', 'lemonsqueezy_discount_id' => null, ]); $voucher->coupon()->associate($coupon)->save(); $service = $this->app->make(GiftVoucherService::class); $service->markRedeemed($coupon, 'txn_999'); $this->assertSame(GiftVoucher::STATUS_REDEEMED, $voucher->refresh()->status); $this->assertNotNull($voucher->redeemed_at); } public function test_it_sends_notifications_to_purchaser_and_recipient_once(): void { Mail::fake(); config()->set('gift-vouchers.reminder_days', 0); config()->set('gift-vouchers.expiry_reminder_days', 0); Package::factory()->create([ 'type' => 'endcustomer', 'lemonsqueezy_variant_id' => 'pri_pkg_001', 'price' => 29, ]); $payload = [ 'data' => [ 'id' => 'ord_456', 'attributes' => [ 'total' => 2900, 'currency' => 'EUR', 'checkout_id' => 'chk_notif', 'variant_id' => 'pri_pkg_001', 'user_email' => 'buyer@example.com', ], ], 'meta' => [ 'custom_data' => [ 'type' => 'gift_voucher', 'purchaser_email' => 'buyer@example.com', 'recipient_email' => 'friend@example.com', 'app_locale' => 'de', ], ], ]; $service = $this->app->make(GiftVoucherService::class); $voucher = $service->issueFromLemonSqueezy($payload); Mail::assertQueued(GiftVoucherIssued::class, 2); $this->assertTrue((bool) ($voucher->metadata['notifications_sent'] ?? false)); // Second call (duplicate webhook) should not resend $service->issueFromLemonSqueezy($payload); Mail::assertQueued(GiftVoucherIssued::class, 2); } public function test_it_resolves_amount_from_tier_by_variant_id(): void { config()->set('gift-vouchers.tiers', [ [ 'key' => 'gift-standard-usd', 'label' => 'Gift Classic (USD)', 'amount' => 65.00, 'currency' => 'USD', 'lemonsqueezy_variant_id' => 'pri_usd_123', ], ]); Mail::fake(); $payload = [ 'data' => [ 'id' => 'ord_usd', 'attributes' => [ 'variant_id' => 'pri_usd_123', 'currency' => 'USD', 'total' => 6500, ], ], ]; $service = $this->app->make(GiftVoucherService::class); $voucher = $service->issueFromLemonSqueezy($payload); $this->assertSame(65.00, (float) $voucher->amount); $this->assertSame('USD', $voucher->currency); } }