Post

Replies

Boosts

Views

Activity

Restore purchases stopped working on macOS Catalina (Sandbox)
Hello, Environment macOS Catalina 10.15.6 Xcode 11.6, Xcode 12 beta 6 App Sandbox Problem: A call to SKPaymentQueue.default().restoreCompletedTransactions() suddenly stopped calling paymentQueue(:updatedTransactions:) and directly invokes paymentQueueRestoreCompletedTransactionsFinished(:) I have an unreleased Mac app with a few non-consumables, and one of the IAP has Apple hosted content. Until a few days ago, both the in-app purchases & restore purchases were working fine, paymentQueue(:updatedTransactions:) was called during purchase and as well as restore flow, and the content was successfully downloaded. With no code changes to StoreKit flow, the restore purchases stopped working and paymentQueue(:updatedTransactions:) is no longer called. Now, it goes straight to paymentQueueRestoreCompletedTransactionsFinished(_:).     func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {                 if (queue.transactions.count == 0) {             #if DEBUG             print ("zero restore transactions")             #endif         }        ...     } I have looked into other forum questions, - https://developer.apple.com/forums/search/?q=restore%20purchases&page=1&sortBy=newest stack overflow, TN2413 - https://developer.apple.com/library/archive/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-TROUBLESHOOTING-CALLING_THE_PAYMENT_QUEUE___S_RESTORECOMPLETEDTRANSACTIONS_METHOD_DOES_NOT_RESTORE_ANY_PRODUCTS_IN_MY_APPLICATION, and of course the documentation - https://developer.apple.com/documentation/storekit/in-app_purchase/offering_completing_and_restoring_in-app_purchases. Unfortunately, the problem persists. I've filed FB8560139. The only change I remember doing in the last few days is to install the macOS 10.15.6 supplemental update. Appreciate any help! Thanks
1
0
943
Aug ’20
AppAttest Assertion - signature verification failing
Hello, I'm implementing AppAttest for one of our apps. Though the Attestation procedure works fine, the assertion signed by the private key on the device (via generateAssertion) can't be verified at the server with the public key saved during the attestation. Environment AppAttest entitlement: development iOS 14 Server: Nodejs The client (app) and server code specific to assertion is below. Client side code (app) if let clientData = self.prepareClientData(withChallenge: challenge) { 		// generate assertion 		let clientDataHash = Data(SHA256.hash(data: clientData)) 		DCAppAttestService.shared.generateAssertion(keyId!, clientDataHash: clientDataHash) { assertion, error in 				guard error == nil else { 						print ("ERROR: Assertion not available right now") 						return 				} 				// create assertion request 				var urlRequest = URLRequest(url: URL(string: self.assertEP)!) 				urlRequest.httpMethod = "POST" 				urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") 				let clientDataString = clientData.base64EncodedString() 				let assertionString = assertion!.base64EncodedString() 				let assertRequest: [String: Any] = ["clientData": clientDataString, "assertion": assertionString] 				let jsonData: Data 				do { 						jsonData = try JSONSerialization.data(withJSONObject: assertRequest, options: []) 						urlRequest.httpBody = jsonData 				} catch { 						print (error) 						return 				} 				 				// send assertion request to server 				let task = URLSession.shared.dataTask(with: urlRequest) { data, response, error in 						guard error == nil else { 								// request sending failed, try again later 								print (error!) 								return 						} 						 						self.extractAssertionResponse(withData: data) 				} 				task.resume() 		} } Server side Assertion verification code function verifyAssertion(clientDataBuffer, assertionBuffer) { 		try { 				let assert = cbor.decodeAllSync(assertionBuffer)[0]; 				let authData = assert.authenticatorData; // buffer 				let signature = assert.signature; // buffer 				// compute client Data Hash 				let clientDataHash = crypto.createHash('sha256').update(clientDataBuffer).digest('base64'); 				let clientDataHashBuffer = Buffer.from(clientDataHash, 'base64'); 				// compute composite hash 				let compositeBuffer = Buffer.concat([authData, clientDataHashBuffer]); 				let nonce = crypto.createHash('sha256').update(compositeBuffer).digest('base64'); // base64 string 				let nonceBuffer = Buffer.from(nonce, 'base64'); 				// load public key 				let keyObj = crypto.createPublicKey(k_publicKeyPem); 				// verify signature 				let verifier = crypto.createVerify('sha256').update(nonceBuffer); 				let sign_verify = verifier.verify(keyObj, signature); 				console.log("sign_verify: ", sign_verify); 		} catch (e) { 				console.log(e); 		} } The verifier.verify() call always results in 'false'. I've tried 'hex' and 'base64' variations on the signature, but didn't work. I've verified that the sha256(publicKey) received at the server is equal to the keyId. let keybuf = Buffer.from(k_publicKeyRaw, 'base64'); let keySHA = crypto.createHash('sha256').update(keybuf).digest('base64'); let keyVerified = (keySHA === k_keyId); Also verified that the clientDataHash generated at the server is the same as clientDataHash generated within the app. Does crypto Verify not compatible with the generated signatures? If not, what's the suggested way to do it? I've tried all the encodings supported by crypto Verify.verify but none of those worked. crypto.getHashes(); Please help.
4
0
2.2k
Sep ’20
Master shared secret vs. App-specific shared secret for refund notifications
If I have generated a master shared secret and an app-specific shared secret for a non-consumable in-app purchase, which one would Apple send in the Refund notification? The refunds notification testing is not supported in sandbox, so can't really test to figure out which one to configure. I've learned that during receipt validation, either of these secrets can be used. My question is related to AppStore callbacks, specifically, the refund notification callback. Does the app-specific secret takes precedence over the master one? Can you choose which shared secret to use for App Store callbacks? Thanks
1
0
685
Mar ’21