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.
Post
Replies
Boosts
Views
Activity
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?
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?
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.
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: NIXGCSqGSIb3DQEHAqCAMIACRQExDzANBglghkgBZQMEAgv5IXkqhZiG0wLBBwGggCSABIIBSDGnAUQDwIBAAIBAAQHDAVYY2vN4LLAgEBAgEBBAMCAQAwGwIBAgIBAQQTDBFjb20ucXVpemNoYW1waW9uczALAgEDAgEBBAMMATEwEAIBBAIBAQQIa/9t2AoAAAAwHAIBBQIBVQQU+5kbpjF0admfn1nbdh01nWKFPkUwCgIBCAIBAQQCFgAwIgIBDAIBAQQaFhgyMDIxLTAyLTE3VDIzOjM5OjQzKzExMDAwdgIBEQIBAQRuMWwwDAICBqUCAQEEAwIBATAsAgIGpgIBAQQjDCFjb20uZ2FtZXRvd25hcHAuZ2FtZVJlZ2lzdHJhdGlvbjUwDQICBqcCAQEEBAwCNDMwHwICBqgCAQEEFhYUMjAyMS0wMi0xN1QyMzozOTo0M1owIgIBFQIvAQQaFhg0MDAxLTAxLTAxVDExOjkLoSKzExMDAAAAAAAACgggN4MIIDdDCCAlygAwIBAgIBATANBgkqhkiG9w0BAQsFADBfMREwDwYDVQQDDAhTdG9yZUtpdDERMA8GA1UECgwIU3RvcmVLaXQxETAPBgNVBAsMCFN0b3JlS2l0MQswCQYDVQQGEwJVUzEXMBUGCSqGSIb3DQEJARYIU3RvcmVLaXQwHhcNMjAwNDAxMTc1MjM1WhcNNDAwMzI3MTc1MjM1WjBfMREwDwYDVQQDDAhTdG9yZUtpdDERMA8GA1UECgwIU3RvcmVLaXQxETAPBgNVBAsMCFN0b3JlS2l0MQswCQYDVQQGEwJVUzEXMBUGCSqPO9b3DQEJARYIU3RvcmVLaXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbf5A8LHMP25cmS5O7CvihIT7IYdkkyF4fdT7ak9sxGpGAub/lDMs8uw5EYib6BCm2Sedv4BvmDWjNJW7Ddgj1SguuenQ8xKkLs89iD/u0vPfbhF4o60cN8e2LrPWfsAk4o257yyZQChrhidFydgs5TMtPbsCzX7eVurmoXUp0q+9vQaV+CY26PT3NcFfY7e/V2nfIkwQc7wmIeGXOgfKNcucHGm4mEvcysQ27OJBrBsT8DeWVUM2RyLol9FaJjOFx20pF8y0ZlgNWgaZE7nV3W1PPeKxduj5fUCtcKYzdwtcqF98itNfkeKivqG2nwdpoLWbMzykLUCzjwvvmXxLBAgMBAAGjOzA5MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKEMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA2SIBAQCyAOA88ejpYr3A1h1Anle5OJB3dlLSqEtwbrhnmfuzilWf7x0ouF8q0XOfNUc3u0bTdhDy8GnszWKZcflgioIOMS9i2cluatsM2Wt2MKaeEgP6czBJw3Gz2Q8bYBZM4zKNgYqERuNSc4I/2bARyhL61rBKwlWLKWqCQN7MjHc6IV4SM7AxRIRag8Mri8Fym96ZH8gLHXmTLES0/3jH14NfbhY16B85H9jq5eaK8Mq2NCy4dVaDTkbb2coqRKD1od4bZm9XrMK4JjO9urDjm1p67dAgT2HPXBR0cRdjaXcf2pYGt5gdjdS7P+sGV0MFS+KD/WJyNcrHR7sK5EFpz1PMYIBjzCCAYsCAQEwZDBfMREwDwYDVQQDDAhTdG9yZUtpdDERMA8GA1UECgwIU3RvcmVLaXQxETAPBgNVBAsML3N0b3JlS2l0MQswCQYDVQQGEwJVUzEXMBUGCSqGSIb3DQEJARYIU3RvcmVLaXQCAQEwDQYJYIZIAWUDBAIBBQAwDQYJKo0hvcNAQELBQAEggEACJ1l561c34xJ+WOEW7b+jsMfWLUN/KDQGgYymDuRPSxJTeRUfWPGIieIiIycReJVl9Y0EfYVSOhLhsWlD9vAPRaw9043q21sYopfR2JcGDpL7OUimmetNmzXNilPpSeQ4hsule2eZQ9770q29xQ/vg6dXooBabR2q620QkFr3T2vsWu1nktSguQunaOPFtsh8rAr+TFI605Gy2BuLTMefqt9SjxEJfzDcQ7wfCMWjSWYx/g/EhMVBR4rXSUFsd9//PM7GcT+cqmM/NaFFIvMRfsqEGMtx81HX55X1jitnh9nhthNQuJhlDpamP6V5sg0nDCtD3W9j8pnkL3sgtIfYdQAAAAAAAA==
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?
I am trying to create a production certificate for my iOS app, with Push Notifications enabled.
So when I go to "Create a New Certificate",
Certificates, Identifiers & Profiles > Create a New Certificate
I tick this checkbox under "Software":
iOS App Development
Sign development versions of your iOS app.
However, when I scroll down to "Services" and check this checkbox:
Apple Push Notification service SSL (Sandbox & Production)
Establish connectivity between your notification server, the Apple Push Notification service sandbox, and production environments to deliver remote notifications to your app. When utilizing HTTP/2, the same certificate can be used to deliver app notifications, update ClockKit complication data, and alert background VoIP apps of incoming activity. A separate certificate is required for each app you distribute.
It then removes the other checkbox! Indicating that I'm unable to check both at the same time.
Why is this and how can I fix it? I need both ticked as my certificate is for a production app with push notifications.
PS: I only have one development Certificate in my account at the moment.
I'm trying to create a Certificate for my first production app, and I'm not sure which box to tick below. My app uses remote notifications via FCM (Firebase Cloud Messaging), which is connected to APN.
The two options:
Apple Push Notification service SSL (Sandbox)
Establish connectivity between your notification server and the Apple Push Notification service sandbox environment to deliver remote notifications to your app. A separate certificate is required for each app you develop.
Apple Push Notification service SSL (Sandbox & Production)
Establish connectivity between your notification server, the Apple Push Notification service sandbox, and production environments to deliver remote notifications to your app. When utilizing HTTP/2, the same certificate can be used to deliver app notifications, update ClockKit complication data, and alert background VoIP apps of incoming activity. A separate certificate is required for each app you distribute.
What is the difference between those two? Is the first one only for development builds?
Thanks.