Can anyone please explain why we have to validate the receipt after we get an SKPaymentTransaction.purchased response in our SKPaymentTransactionObserver for a non-consumable? Can someone with a non-jailbroken device trick the OS into sending SKPaymentTransaction.purchased even though they didn't pay? If non-jail-broken devices are secure then isn't it enough to save the non-consumable purchase in the keychain without validating the receipt?
For the record the app I am working on will validate the receipts. I am just very curious as to why we have to do this.
Thank you in advance.
Post
Replies
Boosts
Views
Activity
I have an app that uses StoreKit v2. It has a Non-Consumable InApp purchase. Using a development build and 2 sandbox testers, I tested this purchase many times and it worked perfectly.
I put the same app on TestFlight and invited 2 separate testers. When they try to purchase the Non-Consumable, they get the expected popup that says the purchase is free for TestFlight users. When they press purchase, they get a popup that says: Ask Permission, A request to buy "Unlock Game" will be sent to your parent or guardian, [Cancel, Ask]. Pressing any of these buttons does nothing and the purchase fails.
They do not have any parental controls enabled. They are able to purchase other apps with no issues.
We searched for related settings in App Store Connect and TestFlight and did not find anything.
What am I doing wrong? Why do InApp purchases in TestFlight show this popup?
I sell an app on the app store.
In Texas we have to file a sales and use tax report every quarter. From what I have read, Apple collects sales tax and remits it to the proper states on our behalf. Is this correct?
If this is correct, then do I report $0 sales tax to the state of Texas since Apple already collected and remitted the sales tax?
I am using the following code to create a texture atlas at runtime using a single .png image sprite sheet:
func createSpriteTextureAtlas(atlasNumber atlas:Int, forWorld world:Int) {
//load the png file
let image = UIImage(named: "world\(world)_spritesheet\(atlas)_2048x2048.png")
//create the dictonary
var imageDictionary = [String: UIImage]()
//iterate through all rows and columns and get the subimage
var imageIndex = 0
for row in 0...7 {
for column in 0...7 {
let sourceRect = CGRect(x:column * 256, y:row * 256, width:256, height:256)
let sourceImage = image?.cgImage!.cropping(to: sourceRect)
let subImage = UIImage(cgImage: sourceImage!)
//add the sub image and name to the dictionary
imageDictionary["\(imageIndex)"] = subImage
imageIndex = imageIndex + 1
}
}
//create the texture atlas using the dictionary
spriteTextureAtlas[atlas] = SKTextureAtlas(dictionary: imageDictionary)
}
I have a different sprite sheet for every world. I made all the sprite sheets myself using the same tool. This code works 100% of the time for most images.
For some images however, the program crashes at: SKTextureAtlas(dictionary: imageDictionary) with the error: Thread 4: EXC_BAD_ACCESS (code=1, address=0x105ff2000). The stack trace says it is crashing inside: #0 0x00000002178e2d34 in -[SKTextureAtlasPacker isFullyOpaque:] ().
The crash does not happen every time and only happens for some images. The crash never happens on the simulator.
Did I make a mistake inside createSpriteTextureAtlas or is this a SpriteKit bug?
P.S. I already know that I can let Xcode make the texture atlas for me by using a folder with a .atlas extension but this is not what i want to do.