Проверьте, отменен ли пользователь SKPaymentTransaction

Как я могу проверить, была ли кнопка отмены пользователем нажата (либо когда его спросили, хочет ли он купить что-либо или, может быть, если он уже купил этот SKProduct, хочет ли он его загрузить)?

На данный момент я просто получаю SKPaymentTransactionStateFailed в paymentQueue: updatedTransactions: метод как после отмены нажатия кнопок пользователя, так и, например, при отсутствии Интернета. Любой способ дифференцировать эти два случая?

Ответ 1

Проверьте установленное свойство ошибки SKPaymentTransaction. Кроме того, вы можете использовать класс Apple Reachability для определения доступности Интернета до начала транзакции.

ошибка Объект, описывающий ошибку, возникшую при обработке транзакции. (Только для чтения)

@property (nonatomic, readonly) Ошибка NSError * обсуждение Свойство error undefined, за исключением случаев, когда для параметра transactionState установлено значение SKPaymentTransactionStateFailed. Ваше приложение может прочитать свойство ошибки, чтобы определить, почему транзакция не удалась.

Наличие Доступен в iOS 3.0 и более поздних версиях. Объявлено в SKPaymentTransaction.h

Ответ 2

Этот код работает для меня:

if (transaction.error.code != SKErrorPaymentCancelled) {
    NSLog(@"Other error");
} else {
   NSLog(@"User canceled");
}

Ответ 3

Ответ Эллен прекрасен. На всякий случай кто-то задается вопросом о других случаях

switch (transaction.error.code) {
        case SKErrorUnknown:
            //Unknown error
            break;
        case SKErrorClientInvalid:
            // client is not allowed to issue the request, etc.
            break;
        case SKErrorPaymentCancelled:
            // user cancelled the request, etc.
            break;
        case SKErrorPaymentInvalid:
            // purchase identifier was invalid, etc.
            break;
        case SKErrorPaymentNotAllowed:
            // this device is not allowed to make the payment
            break;
        default:
            break;
}

Ответ 4

Здесь рабочий код Swift 3.0:

  if let error = transaction.error as? NSError {

                if error.domain == SKErrorDomain {
                    // handle all possible errors
                    switch (error.code) {
                    case SKError.unknown.rawValue:
                        print("Unknown error")

                    case SKError.clientInvalid.rawValue:
                        print("client is not allowed to issue the request")

                    case SKError.paymentCancelled.rawValue:
                        print("user cancelled the request")

                    case SKError.paymentInvalid.rawValue:
                        print("purchase identifier was invalid")

                    case SKError.paymentNotAllowed.rawValue:
                        print("this device is not allowed to make the payment")

                    default:
                        break;
             }
  }

Ответ 5

Возможно, вы используете учебный код Ray Wunderlich для покупки приложений. Там говорится:

- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers {

if ((self = [super init])) {

    // Store product identifiers
    _productIdentifiers = productIdentifiers;

    // Check for previously purchased products
    _purchasedProductIdentifiers = [NSMutableSet set];
    for (NSString * productIdentifier in _productIdentifiers) {
        BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productIdentifier];
        if (productPurchased) {
            [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; // CHECK THIS
            [_purchasedProductIdentifiers addObject:productIdentifier];
            NSLog(@"Previously purchased: %@", productIdentifier);
        } else {
            NSLog(@"Not purchased: %@", productIdentifier);
        }
    }

Там вы можете видеть, что addTransactionObserver вызывается только в том случае, если Продукт уже обработан. Если вы переместите эту строку кода перед запросом if, вы получите желаемый результат.

[[SKPaymentQueue defaultQueue] addTransactionObserver:self]; // MOVE HERE
if (productPurchased) {
    [_purchasedProductIdentifiers addObject:productIdentifier];
    NSLog(@"Previously purchased: %@", productIdentifier);
} else {
    NSLog(@"Not purchased: %@", productIdentifier);
}                

В методе failTransaction теперь вы можете вызвать

 [[NSNotificationCenter defaultCenter] postNotificationName:IAPHelperProductPurchasedNotification object:nil userInfo:nil];

Теперь вы можете проверить значение nil, отправленное уведомлением в текущем виде

Ответ 6

Swift 2.2

В случае, когда вы получите ответ .Failed в paymentQueue, было бы неплохо обработать все возможные ошибки.

if let error = transaction.error {
    if error.domain == SKErrorDomain {
        // handle all possible errors
        switch (error.code) {
        case SKErrorCode.Unknown.rawValue:
            print("Unknown error")
            break;
        case SKErrorCode.ClientInvalid.rawValue:
            print("client is not allowed to issue the request")
            break;
        case SKErrorCode.PaymentCancelled.rawValue:
            print("user cancelled the request")
            break;
        case SKErrorCode.PaymentInvalid.rawValue:
            print("purchase identifier was invalid")
            break;
        case SKErrorCode.PaymentNotAllowed.rawValue:
            print("this device is not allowed to make the payment")
            break;
        default:
            break;
        }
    }
}

Ответ 7

Swift 4.2

if let error = transaction.error,
 (error as? SKError)?.code != SKError.paymentCancelled {
 // Here it is failed for sure!
}