应用内购买错误现已修复,但对于以前受影响的用户仍会崩溃

Posted

技术标签:

【中文标题】应用内购买错误现已修复,但对于以前受影响的用户仍会崩溃【英文标题】:In App Purchase bug now fixed, but still crashing for previously affected users 【发布时间】:2016-03-05 12:43:03 【问题描述】:

我的游戏可以免费下载,并且有一个 IAP 可以解锁整个游戏。它在少数用户购买后立即崩溃,通过在我的函数开头添加这两行来修复崩溃:

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) 
  *my original code*

这是解决问题的线程:In App Purchase causes occasional crash

但是,尽管新用户不再出现此问题,但对于最初受此错误影响的用户,即使更新到修复版本后,该应用仍会崩溃。我认为从最初的崩溃开始,他们设备上的某个地方存在损坏的设置,因为我有一个用户在他的另一台设备上下载了游戏,他能够恢复 IAP 并正常玩游戏。

这是一个崩溃报告:

Incident Identifier: B7B61633-1BE4-4AB2-99ED-A207B2E88525
CrashReporter Key:   2b01761b32c1d23c1adf755f83cc58464c9e7e77
Hardware Model:      iPhone5,2
Process:             MyApp [551]
Path:                /private/var/mobile/Containers/Bundle/Application/43D176E1-395E-4BF5-A0D5-3602068AADA6/MyApp.app/MyApp
Identifier:          com.MyName.MyApp
Version:             5 (1.1)
Code Type:           ARM (Native)
Parent Process:      launchd [1]

Date/Time:           2016-03-02 02:10:42.42 +0000
Launch Time:         2016-03-02 02:10:27.27 +0000
OS Version:          ios 9.2.1 (13D15)
Report Version:      105

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000000e7ffdefe
Triggered by Thread:  0

Breadcrumb Trail: (reverse chronological seconds)
14     GC Framework: startAuthenticationForExistingPrimaryPlayer


Global Trace Buffer (reverse chronological seconds):
13.238455    CFNetwork                  0x0000000023da3e45 TCP Conn 0x16ede9d0 SSL Handshake DONE
13.532519    CFNetwork                  0x0000000023da3d7f TCP Conn 0x16ede9d0 starting SSL negotiation
13.534444    CFNetwork                  0x0000000023e231a5 TCP Conn 0x16ede9d0 complete. fd: 11, err: 0
13.537454    CFNetwork                  0x0000000023e242a7 TCP Conn 0x16ede9d0 event 1. err: 0
13.643210    CFNetwork                  0x0000000023e24325 TCP Conn 0x16ede9d0 started
13.648224    CFNetwork                  0x0000000023da3e45 TCP Conn 0x16ed89f0 SSL Handshake DONE
13.982238    CFNetwork                  0x0000000023da3d7f TCP Conn 0x16ed89f0 starting SSL negotiation
13.982896    CFNetwork                  0x0000000023e231a5 TCP Conn 0x16ed89f0 complete. fd: 6, err: 0
13.984447    CFNetwork                  0x0000000023e242a7 TCP Conn 0x16ed89f0 event 1. err: 0

Thread 0 name:
Thread 0 Crashed:
0   MyApp                       0x002028ac _TFFC11MyApp9IAPHelper12paymentQueueFS0_FTCSo14SKPaymentQueue19updatedTransactionsGSaCSo20SKPaymentTransaction__T_U_FT_T_ + 7504 (IAPHelper.swift:0)
1   libdispatch.dylib               0x23447dd6 _dispatch_call_block_and_release + 10 (init.c:760)
2   libdispatch.dylib               0x234514e6 _dispatch_after_timer_callback + 66 (queue.c:3293)
3   libdispatch.dylib               0x23447dc2 _dispatch_client_callout + 22 (init.c:819)
4   libdispatch.dylib               0x2345a6d2 _dispatch_source_latch_and_call + 2042 (inline_internal.h:1063)
5   libdispatch.dylib               0x23449d16 _dispatch_source_invoke + 738 (source.c:755)
6   libdispatch.dylib               0x2344c1fe _dispatch_main_queue_callback_4CF + 394 (inline_internal.h:1043)
7   CoreFoundation                  0x2386cfc4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8 (CFRunLoop.c:1613)
8   CoreFoundation                  0x2386b4be __CFRunLoopRun + 1590 (CFRunLoop.c:2718)
9   CoreFoundation                  0x237bdbb8 CFRunLoopRunSpecific + 516 (CFRunLoop.c:2814)
10  CoreFoundation                  0x237bd9ac CFRunLoopRunInMode + 108 (CFRunLoop.c:2844)
11  GraphicsServices                0x24a37af8 GSEventRunModal + 160 (GSEvent.c:2245)
12  UIKit                           0x27aa9fb4 UIApplicationMain + 144 (UIApplication.m:3681)
13  MyApp                       0x001898f4 main + 180 (AppDelegate.swift:12)
14  libdyld.dylib                   0x23470872 start + 2 (start_glue.s:64)

Thread 1 name:
Thread 1:
0   libsystem_kernel.dylib          0x23543320 kevent_qos + 24
1   libdispatch.dylib               0x2345794e _dispatch_mgr_invoke + 254 (source.c:2542)
2   libdispatch.dylib               0x23449a2e _dispatch_mgr_thread + 38 (source.c:2573)

Thread 2:
0   libsystem_kernel.dylib          0x2354288c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x235e0e18 _pthread_wqthread + 1036 (pthread.c:1999)
2   libsystem_pthread.dylib         0x235e09fc start_wqthread + 8 (pthread_asm.s:147)

Thread 3:
0   libsystem_kernel.dylib          0x2354288c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x235e0e18 _pthread_wqthread + 1036 (pthread.c:1999)
2   libsystem_pthread.dylib         0x235e09fc start_wqthread + 8 (pthread_asm.s:147)

Thread 4:
0   libsystem_kernel.dylib          0x2354288c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x235e0e18 _pthread_wqthread + 1036 (pthread.c:1999)
2   libsystem_pthread.dylib         0x235e09fc start_wqthread + 8 (pthread_asm.s:147)

Thread 5 name:
Thread 5:
0   libsystem_kernel.dylib          0x2352dbf8 mach_msg_trap + 20 (syscall_sw.h:105)
1   libsystem_kernel.dylib          0x2352d9f8 mach_msg + 40 (mach_msg.c:103)
2   CoreFoundation                  0x2386cf1c __CFRunLoopServiceMachPort + 136 (CFRunLoop.c:2345)
3   CoreFoundation                  0x2386b2a2 __CFRunLoopRun + 1050 (CFRunLoop.c:2607)
4   CoreFoundation                  0x237bdbb8 CFRunLoopRunSpecific + 516 (CFRunLoop.c:2814)
5   CoreFoundation                  0x237bd9ac CFRunLoopRunInMode + 108 (CFRunLoop.c:2844)
6   CFNetwork                       0x23e049e6 +[NSURLConnection(Loader) _resourceLoadLoop:] + 486 (NSURLConnection.mm:325)
7   Foundation                      0x240c632c __NSThread__start__ + 1144 (NSThread.m:1134)
8   libsystem_pthread.dylib         0x235e2c7e _pthread_body + 138 (pthread.c:656)
9   libsystem_pthread.dylib         0x235e2bf2 _pthread_start + 110 (pthread.c:692)
10  libsystem_pthread.dylib         0x235e0a08 thread_start + 8 (pthread_asm.s:162)

Thread 6 name:
Thread 6:
0   libsystem_kernel.dylib          0x23541f14 __select + 20
1   CoreFoundation                  0x238723c0 __CFSocketManager + 572 (CFSocket.c:2128)
2   libsystem_pthread.dylib         0x235e2c7e _pthread_body + 138 (pthread.c:656)
3   libsystem_pthread.dylib         0x235e2bf2 _pthread_start + 110 (pthread.c:692)
4   libsystem_pthread.dylib         0x235e0a08 thread_start + 8 (pthread_asm.s:162)

Thread 7:
0   libsystem_kernel.dylib          0x2354288c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x235e0e18 _pthread_wqthread + 1036 (pthread.c:1999)
2   libsystem_pthread.dylib         0x235e09fc start_wqthread + 8 (pthread_asm.s:147)

Thread 0 crashed with ARM Thread State (32-bit):
r0: 0x00000000    r1: 0x00000000      r2: 0x39c940b0      r3: 0x00000000
r4: 0x00000000    r5: 0x00631376      r6: 0x00000000      r7: 0x0040dcf4
r8: 0x0064e984    r9: 0x00000000     r10: 0x00000001     r11: 0x16d54600
ip: 0xf64d8965    sp: 0x0040db34      lr: 0x002011f0      pc: 0x002028ac
cpsr: 0x60000010

Binary Images:
<not included for reasons of brevity>

下面是导致崩溃的函数:

extension IAPHelper: SKPaymentTransactionObserver 

  public func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) 
    let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
    dispatch_after(delayTime, dispatch_get_main_queue()) 

    for transaction in transactions 
      switch (transaction.transactionState) 
      case .Purchased:
        print("case .Purchased:")
        self.completeTransaction(transaction)
        break
      case .Failed:
        print("case .Failed:")
        self.failedTransaction(transaction)
        break
      case .Restored:
        print("case .Restored:")
        self.restoreTransaction(transaction)
        break
      case .Deferred:
        print("case .Deferred:")
        break
      case .Purchasing:
        print("case .Purchasing:")
        break
      
    
  

有人知道如何解决这个问题吗?因为我无法复制它并且不知道从哪里开始。他们已尝试从设备中删除该应用并下载更新版本,但没有任何区别。

编辑:

我想澄清一下,在尝试购买 1.0 版 IAP 的人中,大约有 10% 的人崩溃了。现在,当任何人尝试在 1.1 版中购买 IAP 时,它不会崩溃。这个问题是关于那些 1.0 版的 10% 仍然无法正常加载游戏的人,因为当 SKPayment 尝试检查他们之前是否购买过 IAP 时,它每次都会崩溃。

编辑 2:

下面是从 paymentQueue 中调用的方法:

private func completeTransaction(transaction: SKPaymentTransaction) 
  provideContentForProductIdentifier(transaction.payment.productIdentifier)
  SKPaymentQueue.defaultQueue().finishTransaction(transaction)


private func restoreTransaction(transaction: SKPaymentTransaction) 
  let productIdentifier = transaction.originalTransaction!.payment.productIdentifier
  provideContentForProductIdentifier(productIdentifier)
  SKPaymentQueue.defaultQueue().finishTransaction(transaction)


private func failedTransaction(transaction: SKPaymentTransaction) 
  NSNotificationCenter.defaultCenter().postNotificationName(IAPHelperStopSpinnerNotification, object: nil)
  if transaction.error!.code != SKErrorPaymentCancelled 
     NSNotificationCenter.defaultCenter().postNotificationName(IAPHelperTransactionFailedNotification, object: nil)
  
  SKPaymentQueue.defaultQueue().finishTransaction(transaction)

编辑 3:

我刚收到一个用户的崩溃报告,该用户的设备在进行 IAP 时崩溃,这表明最初的问题确实没有得到解决。 :-( 在更新的版本中,这些崩溃的数量已大大减少,但看起来根本原因仍然存在。我将就此提出一个新问题,提供更多详细信息,因为此页面现在变得有点混乱!

【问题讨论】:

您是否尝试过在完全相同的设备上使用完全相同的操作系统进行复制?您是否尝试过使用像 Crashlytics 这样的工具和像 CocoaLumberjack 这样更好的日志记录系统? 你没有修复崩溃,你试图解决它。你调用的方法中的代码是什么? @nhgrif 它已经在具有不同操作系统的许多不同设备上崩溃。我没有使用过 Crashlytics,也没有听说过 CocoaLumberjack - 他们有什么帮助? @wain 你指的是哪种方法?另外,你是说还有一个潜在的问题吗? 它仍然崩溃...什么表明问题已经解决...? 【参考方案1】:

当用户进行购买时,购买实际上是通过 Apple 的软件进行的,Apple 记录了购买完成,用户支付了他的钱,并且应用程序需要交付一些东西 - 当你调用 finishTransaction 时,Apple假设已交付。

如果用户进行了购买,并且您的应用在用户进行购买和您交付之间发生了崩溃,那么 Apple 仍会记住用户在没有交付的情况下进行了付款。因此,每当您开始收听付款队列时,您都会收到有关此销售的通知,此时您需要正确处理它。如果您还没有看到用户进行购买,这可能会让您的应用出乎意料。

【讨论】:

感谢您的解释。因此,当我的用户点击“恢复”并调用 restoreTransaction 时,您认为我需要在那里处理这个特定问题吗?我已将 restoreTransaction 和从支付队列中调用的其他方法添加到原始问题的底部。 另外,这如何解释受影响的用户可以在另一台设备上登录他的 iTunes 帐户,下载游戏并成功点击“恢复”。然而,在发生初始崩溃的设备上,点击恢复时它总是崩溃?有什么想法吗?

以上是关于应用内购买错误现已修复,但对于以前受影响的用户仍会崩溃的主要内容,如果未能解决你的问题,请参考以下文章

尽管没有iTunes帐户登录,iOS仍会恢复应用内购买

尽管没有登录 iTunes 帐户,iOS 仍会恢复应用内购买

从应用内购买中移除商品 [已清除出售 = 否] 仍会出现在应用中

如何修复应用内购买错误“交易错误:无法连接到 iTunes Store 代码 0”? [复制]

向应用添加应用内购买会影响已购买该应用的用户吗?

应用内购买恢复按钮