feat(myket): add myket

This commit is contained in:
2026-05-16 23:44:08 +03:30
parent c05587474f
commit 2796ce7de7
7 changed files with 280 additions and 48 deletions

View File

@@ -0,0 +1,117 @@
<?php
namespace App\Services;
use App\Models\UserSubscriber;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class AppMarketPurchaseVerifier
{
public function verifyBazaarSubscription(string $subscriptionId, string $purchaseToken): ?Carbon
{
$packageName = config('services.app_markets.package_name');
$url = "https://pardakht.cafebazaar.ir/devapi/v2/api/applications/{$packageName}/subscriptions/{$subscriptionId}/purchases/{$purchaseToken}";
$response = Http::withHeaders([
'CAFEBAZAAR-PISHKHAN-API-SECRET' => config('services.app_markets.bazaar_secret'),
])->get($url);
if (!$response->successful()) {
Log::error('Failed to verify Bazaar subscription', [
'status' => $response->status(),
'body' => $response->body(),
]);
return null;
}
$validUntil = $response->json('validUntilTimestampMsec');
if (!$validUntil || $validUntil < now()->timestamp * 1000) {
return null;
}
return Carbon::createFromTimestampMs($validUntil);
}
public function refreshBazaarSubscriber(UserSubscriber $subscriber): bool
{
if (!$subscriber->subscription_id || !$subscriber->purchase_token) {
return false;
}
$expiredAt = $this->verifyBazaarSubscription($subscriber->subscription_id, $subscriber->purchase_token);
if (!$expiredAt) {
$subscriber->update(['expired_at' => now()]);
return false;
}
$subscriber->update([
'expired_at' => $expiredAt,
'last_verified_at' => now(),
]);
return true;
}
public function verifyMyketProduct(string $skuId, string $token): ?array
{
$packageName = config('services.app_markets.package_name');
$url = "https://developer.myket.ir/api/partners/applications/{$packageName}/purchases/products/{$skuId}/verify";
$response = Http::withHeaders([
'X-Access-Token' => config('services.app_markets.myket_access_token'),
])->post($url, [
'tokenId' => $token,
]);
if (!$response->successful()) {
Log::error('Failed to verify Myket purchase', [
'status' => $response->status(),
'body' => $response->body(),
]);
return null;
}
$data = $response->json();
if (($data['purchaseState'] ?? null) !== 0 || empty($data['purchaseTime'])) {
return null;
}
return [
'data' => $data,
'purchased_at' => Carbon::createFromTimestampMs($data['purchaseTime']),
];
}
public function refreshMyketSubscriber(UserSubscriber $subscriber): bool
{
if (!$subscriber->product_id || !$subscriber->purchase_token || !$subscriber->subscribe) {
return false;
}
$purchase = $this->verifyMyketProduct($subscriber->product_id, $subscriber->purchase_token);
if (!$purchase) {
$subscriber->update(['expired_at' => now()]);
return false;
}
$expiredAt = $purchase['purchased_at']->copy()->addDays($subscriber->subscribe->expired_day);
$subscriber->update([
'purchased_at' => $purchase['purchased_at'],
'expired_at' => $expiredAt,
'last_verified_at' => now(),
]);
return $expiredAt->greaterThanOrEqualTo(now());
}
}