Post

Replies

Boosts

Views

Activity

Validating receipt for iOS in-app purchase always returns error 21002
I am validating my consumable in-app purchase on the server-side. That is, I get the receipt from the client-side via: .onChange(of: self.storeObserver.paymentStatus) { status in switch status { case .purchasing: print("Payment status: purchasing") case .failed: self.creatingGame = false print("Payment status: failed") case .deferred: print("Payment status: deferred") case .restored: print("Payment status: restored") case .purchased: if Bundle.main.appStoreReceiptURL == nil { print("appStoreReceiptURL is nil") } if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: appStoreReceiptURL.path) { do { let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped) let receiptString = receiptData.base64EncodedString(options: []) print("receiptString: \(receiptString)") // Read receiptData createGame(receiptString: receiptString) } catch { print("Couldn't read receipt data with error: " + error.localizedDescription) } } print("Payment status: purchased") default: print("Payment status: default") } } private func createGame(receiptString: String){ let data: [String:Any?] = [ "gameName": self.gameName, "receipt": receiptString ] callFunction(name: "validateReceipt", data: data){ result, err in } print("receiptString: \(receiptString)") prints the following: Receipt data: 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 And then the receipt string is sent to the server: } As you can see above the code tries the production verifyReceipt endpoint, and if that fails it tries the sandbox endpoint. However it never tries the sandbox endpoint as a different error comes up the first try: The data in the receipt-data property was malformed or the service experienced a temporary issue. Try again. I have no idea why this error occurs. I am testing in sandbox if that makes any difference. Any idea why I keep getting this error?
9
1
7.4k
Feb ’23
My app was rejected based on: Guideline 3.2.2 - Other Business Model Issues - Unacceptable
My app allows users to compete in quizzes with other players, with each quiz having a $5 entry fee. The winner of the quiz will receive a digital gift card. The amount of the gift card depends on the number of players in the quiz. This app has gone through a long review process. It initially failed to Guideline 5.1.1: We found in our review that your app does not meet all of our requirements for apps that offer highly regulated services or handle sensitive user data. Specifically: The account that submits the app must be enrolled in the Apple Developer Program as an organization, and not as an individual. Which made me to believe it was a Gambling app (even though it's a skill-based game, not a chance-based game which is what 'Gambling' is defined as). So I established a company and then resubmitted the app. It then failed on the following guideline: Guideline 3.2.2 - Business - Other Business Model Issues - Unacceptable The primary purpose of your app is to encourage users to watch ads or perform marketing-oriented tasks, which is not appropriate for the App Store. I was then entitled to a call to explain the rejection. The reviewer said that you are not allowed to give anything of real value (money, gift cards etc) as an incentive to users. He said I could only give in-app rewards (like increased levels in the app). I found this hard to believe - as there are many pay-to-win puzzle/quiz games (Skillz alone has many of these apps: https://games.skillz.com/genres/Puzzle). So what is the best way to appeal to the App Review Board? Do I just write the same explanation I just said above? I also asked which specific dot point in 3.2.2 the app was breaching and he was not able to answer: https://developer.apple.com/app-store/review/guidelines/#unacceptable Any feedback appreciated.
0
1
1k
Jul ’21
Location permission dialog disappears after 1 second
I just want to ask my user for a one-time location permission. However, when I click the button that activates the permission dialog, it disappears after one second. This has been brought up before - https://stackoverflow.com/questions/61993353/request-user-location-permission-in-swiftui - however I am already following this advice and storing @ObservedObject var locationManager = LocationManager() as a class variable in my view. View } Model } Any idea what the problem is?
5
0
1.6k
May ’21
Am I allowed to use a custom Apple Pay button design for my iOS app?
I have looked through the different Apple Pay button types on this page: https://developer.apple.com/design/human-interface-guidelines/apple-pay/overview/buttons-and-marks/ However I need to change the text on the Button. I also would like to use a custom design to fit the style of my app. On that page, it says: Don’t create your own Apple Pay button design or attempt to mimic the system-provided button designs. However on this page, it gives an example of a custom button, implying that it is allowed: https://developer.apple.com/design/human-interface-guidelines/apple-pay/overview/offering-apple-pay/ If you use a custom button to trigger the Apple Pay payment process, make sure your custom button does not display “Apple Pay” or the Apple Pay logo. Is someone able to clarify whether I can use a custom Apple Pay button in my iOS app or not?
1
0
2.8k
Apr ’21
Click and holding a link doesn't always allow opening it in my app.
I have set up Firebase Dynamic Links, which allows users to click a link in their email which takes them to my app (and logs them in). On my iPhone running 14.4 this is working fine, I can click and hold the link and the option 'Open in My_App' pops up. However on my iPad running 14.4, when i click and hold the link in my email, the option 'Open in My_App' does not appear. How do I get it to appear? It just opens up in Safari but on my iPhone it allows me to open it in my app.
0
0
765
Mar ’21