In-App purchase SKProduct not received from SKProductsRequest - swift

I had 3 In-App purchases (non-renewable subscriptions) in the App store connect account, all Approved and retrieved in the code successfully
Then I added one more free non-renewable subscription In-App purchase, submitted to the app store New In-App purchase is Approved, all agreements are active, tax and banking info is ok, product identifier in the code is the same as in the App Store connect
I request all four products in SKProductsRequest But in the productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) I receive three old In-App purchase SKProducts, but product identifier of the new In-App purchase is received in invalidProductIdentifiers
func fetchProducts() {
let request = SKProductsRequest(productIdentifiers: ["mentalmind.kz.free", "mentalmind.kz.threemonth", "mentalmind.kz.sixmonth", "mentalmind.kz.oneyear"])
request.delegate = self
request.start()
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
print("received products: \(response.products.map({ $0.productIdentifier }))")
print("invalid product ids: \(response.invalidProductIdentifiers)")
DispatchQueue.main.async {
self.products = response.products
}
}
Console output:
received products: ["mentalmind.kz.oneyear", "mentalmind.kz.sixmonth", "mentalmind.kz.threemonth"]
invalid product ids: ["mentalmind.kz.free"]
Is it Apple's fault, or you have any code recommendations for me?

Unfortunately I do not know what was the issue, Apple support did not help me
But I created new In-App Purchase with cheapest price, but not free and it worked fine in the App Store Connect
May be problem was because the In-App purchase was free

Related

Problem with in-app purchases in apple watch Swift

I have been trying in vain for several days to make a test purchase of a subscription from the watch, but nothing works out for me, all the methods that I found have been tried, and these are: apphud, rebooting devices, logging out with Apple ID, another Apple ID, test / not test apple id, sandbox is logged in, the appstore is also logged in, the card is linked, but, unfortunately, every time I try to buy, I get an error message: "Unable to Purchase App. Sign in with your Apple ID from the Apple Watch app on your iPhone".
Moreover, when I do all the same from the phone, everything works fine, and the purchase is made.
There is an option to try revenuecat, but honestly, I don't think it will be different from apphud. There is also an assumption that it is simply IMPOSSIBLE to make a test purchase from the watch.
Here is a piece of my code from in app manager (recipes are coming):
func startProducts() {
let bundle = appBundleID
let products = Set([
bundle + ".1m",
bundle + ".1y"
])
request = SKProductsRequest(productIdentifiers: Set(products))
request?.delegate = self
request?.start()
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
guard firstRequestFinish else {
return
}
firstRequestFinish = false
defer {
finishProducts()
}
if response.invalidProductIdentifiers.count > 0 {
print("Invalid Products IDs: \(response.invalidProductIdentifiers)")
}
self.allProducts = response.products
let subscriptions = (response.products.compactMap { item in
return IAProduct(id: item.productIdentifier,
title: item.localizedTitle,
price: item.price,
localePrice: item.localizedPrice,
locale: item.priceLocale)
}.sorted { item1, item2 in
return item1.price.doubleValue < item2.price.doubleValue
})
self.availableSubscriptions = subscriptions
if subscriptions.count > 0 {
print("Available products IDs: \(subscriptions.map({ item in return item.id }))")
}
self.monthProduct = subscriptions.first { item in
return item.id.contains(".1m")
}
self.yearProduct = subscriptions.first { item in
return item.id.contains(".1y")
}
delegate?.inappWasLoaded()
}
I would be glad for any advice! Many thanks to everyone who will take part in the discussion of this issue.

How to update FCM token

I am having the same issue where the key gets generated 2 times.
As stated here: https://github.com/firebase/firebase-ios-sdk/issues/6813
My question is how I can always keep my token updated with the Messaging didReceiveRegistrationToken: callback?
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
let deviceToken:[String: String] = ["token": fcmToken ?? ""]
print("Device token: ", deviceToken)
}
}
The last comment from a contributor on github says:
This is expected. We recently discover that sometimes, the APNS token is collected from Apple with a slight delay after first token request was issued, so client has to issue a second token request with the apns token mapping in it. So you are getting that scenario which is why you are getting the token callback twice.
It wasn't happening before because there was a bug that the second
token request is not triggered and was recently fixed in https://github.com/firebase/firebase-ios-sdk/pull/6669.
This should not affect your work as long as you always keep your token updated with the Messaging didReceiveRegistrationToken: callback."(charlotteliang)
So you should be fine as long as you update the token on every didReceiveRegistrationToken call. You can do that as the documentation describes: https://firebase.google.com/docs/cloud-messaging/ios/client#monitor-token-refresh.
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase registration token: \(String(describing: fcmToken))")
let dataDict: [String: String] = ["token": fcmToken ?? ""]
NotificationCenter.default.post(
name: Notification.Name("FCMToken"),
object: nil,
userInfo: dataDict
)
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}

Facebook Graph API user_friends does not return friends list swift

I am trying to get our app approved for user_friends permission from Facebook. They asked to implement the feature and demonstrate how the usage will be implemented.
Here is what I did in code:
fileprivate func getFBFriends() {
let params = ["fields": "id, first_name, last_name, name, email, picture, user_friends"]
let graphRequest = GraphRequest(graphPath: "/me/friends", parameters: params)
let connection = GraphRequestConnection()
connection.add(graphRequest, completion: { (connection, result, error) in
if error == nil {
if let userData = result as? [String:Any] {
print(userData)
}
} else {
print("Error Getting Friends");
}
self.dispatchGroup.leave()
})
connection.start()
}
I am using test users created in Facebook developer portal.
My app is in live mode. I tried switching from live to development as well.
I added test users as friends and logged into app using facebook for all the users.
Response from Facebook Graph API Explorer:
{
"data": [
],
"summary": {
"total_count": 3
}
}
PS: I have already checked if I have AccessToken or not. The problem is, I get only the count but no friends. All posted answers for same question, didn't solve my problem.
There are multiple bugs logged against this issue:
https://developers.facebook.com/support/bugs/712344266793255
https://developers.facebook.com/support/bugs/721152122632278
No progress has been reported by the Facebook team so far. I'd suggest that you also comment on the aforementioned pages to help Facebook prioritize the bug.
The issue seems to finally have been resolved. Check here for details: https://developers.facebook.com/support/bugs/334477245374676/?join_id=f3b4be2272df3a4

Cannot receive results from Square Point of Sale in a small Swift app

I have written a small app in Swift using Xcode 12.5 by following the information and code samples provided here ... https://github.com/square/SquarePointOfSaleSDK-iOS
The app polls a server to see if there is a charge to be made. The output from the server is in JSON format. When a charge comes in, the JSON results are providing a customer id, amount to be charged, and a note to the Square Point of Sale SDK.
Using the SCCAPIRequest example from the GitHub page ...
// Replace with your app's URL scheme.
let callbackURL = URL(string: "<#T##Your URL Scheme##String#>://")!
// Your client ID is the same as your Square Application ID.
// Note: You only need to set your client ID once, before creating your first request.
SCCAPIRequest.setApplicationID(<#T##Application ID##String#>)
do {
// Specify the amount of money to charge.
let money = try SCCMoney(amountCents: 100, currencyCode: "USD")
// Create the request.
let apiRequest =
try SCCAPIRequest(
callbackURL: callbackURL,
amount: money,
userInfoString: nil,
locationID: nil,
notes: "Coffee",
customerID: nil,
supportedTenderTypes: .all,
clearsDefaultFees: false,
returnsAutomaticallyAfterPayment: false,
disablesKeyedInCardEntry: false,
skipsReceipt: false
)
// Open Point of Sale to complete the payment.
try SCCAPIConnection.perform(apiRequest)
} catch let error as NSError {
print(error.localizedDescription)
}
The app successfully switches to Square POS, displays the amount due, and knows which customer I am wanting to charge (via customer id). I can process the payment and Square POS switches back to my app just fine.
This is where I am running in to trouble. I am also using the UIApplication delegate method example on that same page. Under the comment "Handle a successful request" ...
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
guard SCCAPIResponse.isSquareResponse(url) else {
return
}
do {
let response = try SCCAPIResponse(responseURL: url)
if let error = response.error {
// Handle a failed request.
print(error.localizedDescription)
} else {
// Handle a successful request.
}
} catch let error as NSError {
// Handle unexpected errors.
print(error.localizedDescription)
}
return true
}
I have added the following ...
print("Transaction successful: \(response)")
From what I understand, the response should include the transaction id, and anything that was passed along in the userInfoString. It appears that this code example isn't even firing when Square POS returns to my app. I cannot see anything in the Xcode console.
I have assigned a callback URL within Xcode using the documentation on the link above, and it's also added in the Square Developer Portal under the Point of Sale API.
What am I missing? Where should the UIApplication delegate method be placed, in AppDelegate.swift or should it reside in ViewController.swift, or somewhere else? Any insight would be greatly appreciated.
#ElTomato provided me with the hint that I needed to solve the problem I was having. I needed to delete SceneDelegate.swift, remove Application Scene Manifest from Info.plist, and remove some code from AppDelegate.swift
I found detailed instructions on THIS site ...
iOS 13: Swift - 'Set application root view controller programmatically' does not work
Thank you kindly for the fantastic help #ElTomato

Swift In-App purchases sandbox tester error

I am implementing the In-App purchases function today, and I just followed the tutorial step by step, created sandbox testers, wrote the code, and it says
<SKPaymentQueue: 0x282e50860>: Payment completed with error: Error Domain=ASDServerErrorDomain Code=3502 "This item is not available." UserInfo={NSLocalizedDescription=This item is not available.
Why is "This item is not available."? I searched the relevant information online, but there is no answer for it.
Here is my code
#IBAction func purchaseButtonPressed(_ sender: UIButton) {
print("PRESSED")
purchaseApp()
}
func purchaseApp() {
let productID = "com.crazycat.Reborn.FullFuctionalities"
if SKPaymentQueue.canMakePayments() {
let paymentRequest = SKMutablePayment()
paymentRequest.productIdentifier = productID
SKPaymentQueue.default().add(paymentRequest)
} else {
print("Can't make payments")
}
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
if transaction.transactionState == .purchased {
print("Thanks for shopping")
} else if transaction.transactionState == .failed {
print("purchase Failed")
}
}
}
I had the same issue.
Please make sure your paid application agreement in Appstore connect is Active and not Expired. Check if there are any warnings in the App Store connect. Complete all of the bank, tax, and contact information on your App Store Connect Paid Apps Agreements.
Then relaunch the app from Xcode on your physical device.
The transaction should be successful then.
Check below points
Use the same test account you specified in developer console.
Make sure the In-App product shows a status of Ready to Submit on the developer console.
Make sure the In-App product id matches what your using in your app.