تحویل خریدهای مصرفی

تحویل یکتای مصرفی با handler اندروید یا sync و confirm دستی، commit موجودی و تفاوت iOS و وب.

SDK تأیید خرید و مسیر تحویل را مدیریت می‌کند، اما موجودی اپ شما را نمی‌داند. DELIVERY_REQUIRED به معنی انتظار برای تحویل است، نه اضافه‌شدن سکه/اعتبار به حساب.

قرارداد grant ماندگار

در یک تراکنش پایگاه داده میزبان، موجودی و کلید یکتای تحویل را با هم commit کنید. کلید باید به app، مشتری اصلی، source و deliveryId وابسته باشد. تکرار همان delivery باید بدون افزودن مجدد موفق شود. فلگ حافظه یا ثبت جداگانه در preferences این ضمانت را ایجاد نمی‌کند. مقدار اعتبار را از کاتالوگ معتبر خودتان تعیین کنید؛ SDK مقدار آن را حدس نمی‌زند.

در مثال‌ها grantOnce تابع متعلق به اپ شما است و باید همین تراکنش را پیاده کند. هویت مالک را داخل تراکنش کنترل کنید و هنگام تغییر حساب، کارهای ناهم‌زمان تحویل را متوقف/هماهنگ کنید.

Android: handler خودکار

آن را پیش از configure ثبت کنید:

import 'package:inappify_sdk/inappify_sdk.dart';

Future<InappifySdkResult<void>> registerAndroidDelivery(
  Future<void> Function(InappifyConsumableDelivery) grantOnce,
) => InappifySdk.setConsumableDeliveryHandler((delivery) async {
  try {
    await grantOnce(delivery); // Durable, scoped, idempotent host transaction.
    return InappifyDeliveryResult.delivered;
  } catch (_) {
    return InappifyDeliveryResult.retryLater;
  }
});
import com.inappify.sdk.*

fun registerDelivery(
    client: InappifyV2Client,
    grantOnce: suspend (InappifyConsumableDelivery) -> Unit,
): InappifyListenerRegistration = client.setConsumableDeliveryHandler { delivery ->
    try {
        grantOnce(delivery) // Commit durable inventory before returning.
        InappifyDeliveryResult.DELIVERED
    } catch (cancelled: kotlinx.coroutines.CancellationException) {
        throw cancelled
    } catch (_: Exception) {
        InappifyDeliveryResult.RETRY_LATER
    }
}

پس از commit فقط delivered/DELIVERED برگردانید؛ SDK خودش acknowledge و ادامه مصرف/گزارش را انجام می‌دهد. داخل handler confirmDelivery را صدا نزنید. خطا، نبود handler یا retryLater کار را pending نگه می‌دارد. ثبت Kotlin یک registration قابل close دارد؛ فلاتر برای حذف handler مقدار null می‌گیرد.

مسیر دستی روی iOS Direct یا Android بدون handler

import 'package:inappify_sdk/inappify_sdk.dart';

Future<void> fulfillManually({
  required Future<void> Function(InappifyConsumableDelivery) grantOnce,
  required bool Function() stillSameCustomer,
}) async {
  final result = await InappifySdk.syncPendingConsumables();
  if (!result.isSuccess || !stillSameCustomer()) return;
  for (final delivery in result.data?.pendingDeliveries ??
      <InappifyConsumableDelivery>[]) {
    if (!stillSameCustomer()) return;
    await grantOnce(delivery);
    if (!stillSameCustomer()) return;
    final confirmed = await InappifySdk.confirmDelivery(delivery.deliveryId);
    if (!confirmed.isSuccess) return; // Keep the committed grant; never re-credit.
  }
}

این flow فقط وقتی مالک موازی handler ندارید استفاده شود. stillSameCustomer کمک میزبان است و جای کنترل owner داخل تراکنش inventory را نمی‌گیرد. روی Kotlin همان الگو با client.syncPendingConsumables() و client.confirmDelivery(deliveryId) اجرا می‌شود؛ ID از نوع Long است.

شکست confirm نباید grant قبلی را حذف یا تکرار کند. SDK checkpointها را نگه می‌دارد؛ مصرف native فقط برای مصرفی است و نباید اشتراک/غیرمصرفی را consume کنید.

JavaScript مستقیم

import type { ConsumableDelivery, InAppify } from '@inappifylabs/web-sdk';
import { DeliveryResult } from '@inappifylabs/web-sdk';

export function registerDelivery(
  client: InAppify,
  grantOnce: (delivery: ConsumableDelivery) => Promise<void>,
) {
  return client.setConsumableDeliveryHandler(async (delivery) => {
    try {
      await grantOnce(delivery);
      return DeliveryResult.DELIVERED;
    } catch {
      return DeliveryResult.RETRY_LATER;
    }
  }); // Returns an unregister function.
}

export async function synchronizeDeliveries(client: InAppify) {
  return client.syncPendingConsumables();
}

handler ثبت‌شده باید نتیجه صریح DeliveryResult.DELIVERED بدهد. بدون handler، syncPendingConsumables() خلاصه و pendingDeliveries می‌دهد؛ ابتدا grant ماندگار، سپس client.confirmDelivery(id). registration تابع unregister می‌دهد. مسیر قدیمی inline handler برای سازگاری وجود دارد، اما در کد جدید الگوی صریح بالا را انتخاب کنید.

محدودیت پلتفرم

iOS handler بومی ندارد و مسیر دستی Direct را دارد. پل Flutter Web 0.2.1 متدهای native handler/sync/confirm را ارائه نمی‌کند؛ داشتن این قابلیت در JS مستقیم، پشتیبانی facade فلاتر نیست. برای دورزدن آن client JS دوم نسازید. از جدول پلتفرم‌ها استفاده کنید.

آزمون ضروری

تحویل تکراری، قطع اپ پس از commit و پیش از confirm، شکست confirm، restart و تغییر حساب را آزمایش کنید. در همه این حالت‌ها هر delivery حداکثر یک grant موجودی داشته باشد و تأیید پیش از commit رخ ندهد.

دسترسی و بازیابی · عیب‌یابی