- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在向应用程序添加一个非消耗性功能。一切正常,除了购买操作请求登录,成功后几乎立即紧跟另一个登录表。如果第二次登录成功,则订单进入完成,否则失败。诊断打印跟踪(下方)显示 UpdateTransactions Observer 将“处理中”事件视为队列中的单个事件,然后是两个登录表,然后是“已购买”事件。调用时观察者队列中只有一个项目,这一切似乎都发生在 Apple 内部,过程结束。恢复功能正常工作。此行为发生在我的设备本地以及我的 TestFlight beta 人员身上。有谁知道发生了什么?
Buy button tapped
Entered delegate Updated transactions with n = 1 items
TransactionState = 0
Updated Tranaction: purch in process
At this point, the signin sheet appears, pw entered, then a ping and DONE is checked
a few seconds later, the signin re-appears, pw again re-entered and again success signaled on sheet
Entered delegate Updated transactions with n = 1 items
TransactionState = 1
Update Transaction : Successful Purchase
下面是我相当普通的 IAP 管理器类的代码:
class IAPManager: NSObject {
// MARK: - Properties
static let shared = IAPManager()
// MARK: - Init
private override init() {
super.init()
}
//MARK: - Control methods
func startObserving() {
SKPaymentQueue.default().add(self)
}
func stopObserving() {
SKPaymentQueue.default().remove(self)
}
func canMakePayments() -> Bool {
return SKPaymentQueue.canMakePayments()
}
func peelError(err: SKError) -> String {
let userInfo = err.errorUserInfo
let usr0 = userInfo["NSUnderlyingError"] as! NSError
let usr1 = (usr0.userInfo["NSUnderlyingError"] as! NSError).userInfo
let usr2 = usr1["NSLocalizedDescription"] as? String
return usr2 ?? "\nreason not available"
}
//MARK: - Generic Alert for nonVC instances
func simpleAlert(title:String, message:String) -> Void {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let ok = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(ok)
if #available(iOS 13.0, *) {
var topWindow = UIApplication.shared.currentWindow
if topWindow == nil {
topWindow = UIApplication.shared.currentWindowInactive
}
let topvc = topWindow?.rootViewController?.presentedViewController
topvc?.present(alert, animated: false, completion: nil)
if var topController = UIApplication.shared.keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
// topController.present(alert, animated: false, completion: nil)
}
} else {
var alertWindow : UIWindow!
alertWindow = UIWindow.init(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController.init()
alertWindow.windowLevel = UIWindow.Level.alert + 1
alertWindow.makeKeyAndVisible()
alertWindow.rootViewController?.present(alert, animated: false)
}
}
// MARK: - Purchase Products
func buy(product:String) -> Bool {
if !canMakePayments() {return false}
let paymentRequest = SKMutablePayment()
paymentRequest.productIdentifier = product
SKPaymentQueue.default().add(paymentRequest)
return true
}
func restore() -> Void {
SKPaymentQueue.default().restoreCompletedTransactions()
}
}
// MARK: - Methods Specific to my app
func enableBigD() -> Void {
let glob = Globals.shared
let user = UserDefaults.standard
.........
//Post local notification signal that purch success/restored (to change UI in BuyView)
NotificationCenter.default.post(name: Notification.Name(rawValue: NotificationNames.kNotificationBuyDictEvent), object: nil)
}
// MARK: - SKPaymentTransactionObserver
extension IAPManager: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
//Debugging Code
print("Entered delegate Updated transactions with n = \(transactions.count) items")
for tx in transactions {
print(" TransactionState = \(tx.transactionState.rawValue)")
}
// END debugging code
transactions.forEach { (transaction) in
switch transaction.transactionState {
case .purchased:
enableBigD()
print("Update Transaction : Successful Purchase")
SKPaymentQueue.default().finishTransaction(transaction)
simpleAlert(title: "Purchase Confirmed", message: "Thank You!")
case .restored:
print("Update Transaction : Restored Purchase")
enableBigDict()
SKPaymentQueue.default().finishTransaction(transaction)
simpleAlert(title: "Success", message: "Your access has been restored!")
case .failed:
print("Updated Tranaction: FAIL")
if let err = transaction.error as? SKError {
let reason = peelError(err: err)
simpleAlert(title: "Purchase Problem", message: "Sorry, the requested purchase did not complete.\nThe reason was: \n\(err.localizedDescription) because:\(reason)")
}
UserDefaults.standard.set(false, forKey: Keys.kHasPaidForDict)
SKPaymentQueue.default().finishTransaction(transaction)
case .deferred:
print("Updated Transaction: purch deferred ")
if let err = transaction.error as? SKError {
print("purch deferred \(err.localizedDescription)")
}
break
case .purchasing:
print("Updated Tranaction: purch in process ")
break
@unknown default:
print("Update Transaction: UNKNOWN STATE!")
break
}
}
}
func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
let err = error.localizedDescription
let reason = peelError(err: error as! SKError)
let fullerr = "The Restore request had a problem. If it persists after retrying, Please send us a note with the Code through the Feedback button in Settings. The Error Code is: \(err) because \(reason)"
simpleAlert(title: "Restore Problem", message: fullerr)
}
} //end Extension of Queue Observer
//MARK: - Extension on UIAppl to get current Window in Scene-based iOS14 environment
// https://stackoverflow.com/questions/57009283/how-get-current-keywindow-equivalent-for-multi-window-scenedelegate-xcode-11
extension UIApplication {
var currentWindow: UIWindow? {
connectedScenes
.filter(({$0.activationState == .foregroundActive}))
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
}
var currentWindowInactive: UIWindow? {
connectedScenes
.filter(({$0.activationState == .foregroundInactive}))
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
}
}
最佳答案
是的,我刚刚写了一篇关于这个的文章。 (尚未发布。)基本上这是整个应用程序内购买用于测试的方式中的一个错误。您只需要忽略对话循环出现两次的事实。
如果您退出 paymentQueue(_:updatedTransactions:)
实现(您已经完成了,除非您应该使用 OSLog 而不是 print
),您会发现那里的一切都在正确发生。它对对话的双循环一无所知,这一切都完全不发生在进程之外。
只有当您是 TestFlight 测试员或使用沙箱测试员帐户时才会出现此问题。
所以,由于这个问题不会影响代码的工作,而且当真正的用户这样做时它不会发生,你只需要闭上眼睛继续工作。不要担心,并警告您的 TestFlight 用户并告诉他们不要担心。
关于iOS 14 应用内购买请求登录/验证两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64991656/
我正在尝试为我的用户提供使用 Google 或 Facebook 登录的选项。到目前为止,我找到了一个实现 Google 登录流程的示例,但如果我可以在同一 Activity 中实现类似的 Faceb
我有一个网页,它对用户是否登录很敏感。我使用的是 Google 登录 Javascript SDK。当用户到达此页面时,我想显示一个插页式广告(“正在加载...”),然后 1)如果用户已登录则呈现页面
我用 digitalocean 创建了一个 droplet,并使用 apt install mariadb-server 命令安装了 mariadb。现在我想使用 php 连接到我的服务器,我使用这个
这个问题在这里已经有了答案: Inno Setup - Signing fails with "Sign Tool failed with exit code 0x1" (2 个回答) 3年前关闭。
我正在尝试使用他们的新 API 实现 google 登录:https://developers.google.com/identity/sign-in/web/ 登录和注销工作正常。我的问题是我不知道
我的应用程序具有谷歌登录、Facebook 登录和 braintree 集成。 我已将以下代码放入 appdelegate.swift 中: func application(_ applicatio
我有一个 Flask 应用程序,最近在我的登录/退出表单中实现了 Flask-Login: @account.route('/sign-in', methods=['POST', 'GET']) de
friend 们,我是初学者级别的 ios swift 学习者。我一直在尝试在我的试用应用程序中进行谷歌登录。根据来自谷歌开发人员和其他教程的资源,我成功地使用 UIView 进行了登录。然后我试图在
我正在使用 Ionic 在 Codeigniter/Ion_Auth/codeigniter-restclient 之上构建登录系统,当我尝试从“ionic 服务器”登录时,登录可以正常工作,但对 L
在 Docker 文件中我有这个 FROM ubuntu RUN apt update && apt -y upgrade RUN apt install -y sudo # Setup ops us
对于 Java 开发,我使用 Slf4j 和 Logback。 Logger logger = LoggerFactory.getLogger(HelloWorld.class); logger.de
在 Scala 应用程序中进行日志记录的好方法是什么?与语言哲学一致的东西,不会使代码困惑,并且维护成本低且不引人注目。以下是基本要求列表: 简单 不会使代码困惑。 Scala 以其简洁而著称。我不希
我正在尝试将我的登录名转换为 Retrofit2 我的旧 LoginActivity: public class LoginActivity extends Activity { private st
我正在尝试让 google+ 登录在 android 上运行。我的问题是,每当我使用 eclipse 运行它时,google 开发站点上提供的示例都能完美运行。当我签署 apk 并在我的设备上手动安装
这个问题已经有答案了: JS Simple but Safe Login? [closed] (1 个回答) 已关闭 6 年前。 我正在尝试使用 JavaScript 创建登录页面。它实际上只是一个带
其他章节请看: react 高效高质量搭建后台系统 系列 登录 本篇将完成 登录模块 。效果和 spug 相同: 需求 如下:
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 1 年前。
我在使用 ReactJs 中的 facebook-login 组件时遇到问题,代码与文档中的完全一样,但仍然无法正常工作。你能帮我找出我做错了什么吗? import React, { Componen
我有一个项目,其中包含许多具有自己的日志记录的“工具”类。这些日志文件是在应用程序启动时创建的,但在使用之前一直为空。 是否可以告诉logback在启动时不应该创建空文件?但是仅在使用它们时? 不知何
我正在创建一个需要用户授权才能访问某些功能的网站。我目前正在研究用户如何创建帐户以及如何利用 session 来授权他们的登录。用户信息存储在名为 user 的 MySQL 表中,其中可能包括用户名和
我是一名优秀的程序员,十分优秀!