RNInAppPurchaseModule icon indicating copy to clipboard operation
RNInAppPurchaseModule copied to clipboard

关于2021年7~9月xcode13用这个库的一些坑的总结

Open RickoNoNo3 opened this issue 4 years ago • 1 comments

RCTKeyForInstance 报错

这是作者自己定义的一个小方法, 我猜作者本来想通过这个来减轻一下内存冗余和不同次原生调用之间的冲突, 结果没想到其实有的情况下这个Instance的地址自己会变掉, 导致获取到的key不对, 进而导致在map里找不到对应元素.

解决方法: 把这个方法删掉, 所有调用的地方直接拿出其参数, 放在原位. 相当于在map里直接存取字符串. 有些地方参数不是字符串的用一些别的方法转成字符串(如hash)

downloadable 问题

报错位置的 downloadable 改成 isDownloadable

removePurchase时报was mutated while being enumerated错误.

检查发现是代码里的语法错误. 进行如下修改后问题解决:

RCT_EXPORT_METHOD(removePurchase:(NSDictionary *)purchase) {
  NSMutableArray *iapUnverifyOrdersArray = [NSMutableArray array];
  if ([[NSUserDefaults standardUserDefaults] objectForKey:kIapUnverifyOrders] != nil) {
    [iapUnverifyOrdersArray addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:kIapUnverifyOrders]];
  }
  // 这里修复了在遍历时直接修改数组元素报的错
  // ++++++++
  NSArray* array = [NSArray arrayWithArray: iapUnverifyOrdersArray];
  for (NSDictionary *unverifyPurchase in array) {
  // ++++++++
  // --------
  // for (NSDictionary *unverifyPurchase in iapUnverifyOrdersArray) {
  // --------
    if ([unverifyPurchase[@"transactionIdentifier"] isEqualToString:purchase[@"transactionIdentifier"]]) {
      [iapUnverifyOrdersArray removeObject:unverifyPurchase];
    }
  }
  [[NSUserDefaults standardUserDefaults] setObject:[iapUnverifyOrdersArray copy] forKey:kIapUnverifyOrders];
  [[NSUserDefaults standardUserDefaults] synchronize];
}

恢复购买(restorePurchase) 只能获取到 productId 的问题

进行如下修改:

- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
  NSString *key = (@"restoreRequest");
  RCTResponseSenderBlock callback = _callbacks[key];
  if (callback) {
    NSMutableArray *productsArrayForJS = [NSMutableArray array];
    for(SKPaymentTransaction *transaction in queue.transactions){
      if(transaction.transactionState == SKPaymentTransactionStateRestored) {
        // 原来这里只传productId, 改为传递transactionId, productId, originalTransactionId(如有)
        // 当然也可以自由增减业务需要的字段, 一般这三个就可以唯一确定任何一种内购商品了.
        // ++++++++++++
        NSDictionary *transactionInfo = @{
          @"transactionIdentifier": transaction.transactionIdentifier,
          @"productIdentifier": transaction.payment.productIdentifier,
          @"originalTransactionIdentifier": transaction.originalTransaction == NULL ? @"" : transaction.originalTransaction.transactionIdentifier,
                                   };
        [productsArrayForJS addObject:transactionInfo];
        // ++++++++++++
        // ------------
        // [productsArrayForJS addObject:transaction.payment.productIdentifier];
        // ------------
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
      }
    }
    callback(@[[NSNull null], productsArrayForJS]);
    [_callbacks removeObjectForKey:key];
  } else {
    RCTLogWarn(@"No callback registered for restore product request.");
  }
}

恢复购买事务的transactionId是新的, 其originalTransationId代表该账号的以前购买过的同一商品订单. 一般商品的originalTransationId就是买的时候的订单号, 续期订阅的是首次购买的订单号

RickoNoNo3 avatar Sep 03 '21 08:09 RickoNoNo3

more step: for (NSDictionary *unverifyPurchase in array) { // ++++++++ // -------- // for (NSDictionary *unverifyPurchase in iapUnverifyOrdersArray) { // -------- if ([unverifyPurchase[@"transactionIdentifier"] isEqualToString:purchase[@"transactionIdentifier"]]) { [iapUnverifyOrdersArray removeObject:unverifyPurchase]; break; } }

github984527 avatar Nov 16 '21 08:11 github984527