I'm trying to start multiple auto renewable purchase of subscriptions in once for one user, I'm curious how it is handled by Apple
I append transactions like this:
func startTransactions(purchaseIDs: Array<String>) {
if (SKPaymentQueue.canMakePayments()) {
purchaseIDs.forEach { id in
let transactionRequest = SKMutablePayment()
transactionRequest.productIdentifier = id
SKPaymentQueue.default().add(transactionRequest)
}
}
}
and I have this method
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
}
}
What i want to know if multiple SKPaymentQueue.default().add(transactionRequest) in a row results in one transaction of does it results in multiple transactions (one per product)
Thanks in advance for your help
Post
Replies
Boosts
Views
Activity
We have a webapp that has a page that allows users to link its Garmin Connect account with his/her account but when I open the Garmin page in the WkWebview I've this page that I cannot interact with the buttons but the only quick fix I've found is to open the URL in a SFSafariViewController , sadly this requires us to re-log the user before opening the URL (with a token) that’s why I'm not happy with this solution (and I want to avoid using other things than our wkwebview).
In my ViewController I have this method
func runOauth(){
self.loadingLabel.isHidden=true
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.oauth2!.afterAuthorizeOrFail = self.callBackOAuth
var url:URL?
do{
//the url for authorizing the user, kronos://oauth/callback" is called after the OAuth finish
url = try appDelegate.oauth2!.authorizeURL(withRedirect:"kronos://oauth/callback", scope: "auth",params: ["tg":"addon/kronos/main","idx":"login.OAuth","formId":"iOS"])
do{
let authorizer = appDelegate.oauth2!.authorizer as! OAuth2Authorizer
safariVC = try authorizer.authorizeSafariEmbedded(from: self,at: url!)
}catch let error {
DispatchQueue.main.async {
print("ERROR authorizing\(error)")
}
}
}catch let error {
DispatchQueue.main.async {
print("ERROR creating OAuth URL \(error)")
}
- }
}
This afterAuthorizeOrFail method is called in background
func callBackOAuth(authParameters:OAuth2JSON!, error: OAuth2Error!){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
if (error == nil && appDelegate.oauth2!.accessToken != nil){
//OAuth succeed in
//we store the token and its experation date in keychain
self.keychain!.set(appDelegate.oauth2!.accessToken!,forKey:"Token")
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let myString = formatter.string(from: appDelegate.oauth2!.accessTokenExpiry!)
self.keychain!.set(myString,forKey:"ExpiryDate")
appDelegate.reloadView()
}else if (error != nil){//OAUth failed
print("OAuth error \(String(describing: error))")
}else{//Another error
print("Cannot login")
self.showMessage(msg: "Login error", title: "Error")
self.runOauth()
}
}
And I want to wait the end of callBackOAuth to call handleRedirectURL here in AppDelegate
func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
let site=components?.host
print("Application")
if site == "oauth"{//OAuth terminated
if components?.path == "/callback" {
let viewController = self.window?.rootViewController as! ViewController
print("oauth")
self.oauth2!.handleRedirectURL(url)
viewController.hideSafariView()
}
}else if site == "logoff"{//User logoff
print("logoff")
}
return true
}
Does someone has a solution?
In swift I'm calling successfully a callback URL which revoke a token after the user is logout, and right after I call this to enable re-logging
func runOauth(){
self.loadingLabel.isHidden=true
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.oauth2!.logger = OAuth2DebugLogger(.debug)
//code executed when OAuth have finished
appDelegate.oauth2!.afterAuthorizeOrFail = self.callBackOAuth
var url:URL?
do{
//the url for authorizing the user, kronos://oauth/callback" is called after the OAuth finish
url = try appDelegate.oauth2!.authorizeURL(withRedirect:"kronos://oauth/callback", scope: "auth",params: ["tg":"addon/kronos/main","idx":"login.OAuth","formId":"iOS"])
do{
let authorizer = appDelegate.oauth2!.authorizer as! OAuth2Authorizer
//launch OAuth in embeded view "SafariVC"
print("Safari embeded")
safariVC = try authorizer.authorizeSafariEmbedded(from: self,at: url!)
}catch let error {
DispatchQueue.main.async {
print("ERROR authorizing\(error)")
//self.runOauth()
}
}
}catch let error {
DispatchQueue.main.async {
print("ERROR creating OAuth URL \(error)")
//self.runOauth()
}
}
}
But it re-log the user automatically when loading logging page, I've tried this:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let authorizer = appDelegate.oauth2!.authorizer as! OAuth2Authorizer
authorizer.oauth2.forgetTokens()
Does someone have a solution?
Hello,
We have a page in PHP showing the price of our subscriptions displayed in a WKWebView and we want to display the localized prices
we successfully implemented
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse)
And I'm curious to know if, with a URLRequest, we can call a callback method which stores in $_SESSION the prices when the user login. And more precisely the $_SESSION of the currently displayed WKWebView (this is that specific thing we want to achieve)
Hello there,
Our App has been rejected with this message :
Additionally, the following are still missing in your app’s binary:
– A functional link to the Terms of Use (EULA)
– A functional link to the privacy policy
And from your app's metadata:
– A functional link to the Terms of Use (EULA)
Can someone please help us to fix those errors steps by steps, I'm not sure to understand well how to do this in App Store Connect Help
Hello there,
I've implemented signing with apple and successfully retrieve access_token but if the user either don't share his email or use an email already used on our website we want to kind of dissociate the user with our app / cancel sign with apple, so I'm curious if this is possible in php (with curl for example) and if it is, how?
Thanks in advance
Hello there,
I've another question about signing with apple more precisely how to create the jw token in php after sign with apple, here is what I do:
$header = json_encode(array(
'kid' => $keyId,
));
$decodedTokenData = json_decode(base64_decode(str_replace('_', '/', str_replace('-','+',explode('.', $_POST['id_token'])[1]))),true);
$payload = json_encode(array(
'iss' => $teamid,
'iat' => time(),
'exp' => time() + 86400*180,
'aud' => $decodedTokenData['aud'],
'sub' => $decodedTokenData['sub'],
));
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, 'abC123!', true);
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
$jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
curl -X POST https://appleid.apple.com/auth/token -d '{"client_id":$CLIENTID,"client_secret":$jwt,"code": $_POST['code'],"grant_type":"authorization_code","redirect_uri":$URL}'
and I've got a
{"error":"invalid_client"}
i don't know what is wrong
Thanks in advance for your help
Hello thereI'm trying to open an URL in and embeded safari on iOS.My issue is that I've a blank pageHere is what I've got so fareAppDelegateimport UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}View controllerimport UIKit
import WebKit
import SafariServices
class ViewController: UIViewController {
@IBOutlet weak var KronosWebsite: WKWebView!
override func loadView() {
KronosWebsite = WKWebView()
self.view = KronosWebsite
}
override func viewDidLoad() {
super.viewDidLoad()
openGoogle()
}
func openGoogle(){
let url2=URL(string: "http://www.google.com")
let web = SFSafariViewController(url: url2!)
let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
if var topController = keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
do{
topController.present(web, animated: true, completion: nil)
}catch let error {
DispatchQueue.main.async {
print("ERROR \(error)")
}
}
}
}
}Thanks in advanceI've upload the project here:https://github.com/camillegallet/testSwiftSafariEmbeded
EDIT:It is fixed The issue was that I used a wrong WKWebview (not the one on the storyboard) Changing that fix my issueHello there,is there someone who can help me with the OAuth2 library in swift I'm doing that to handle the end of OAuthappDelegate.oauth2!.afterAuthorizeOrFail = { authParameters, error in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let myString = formatter.string(from: appDelegate.oauth2!.accessTokenExpiry!)
print("t \(appDelegate.oauth2!.accessToken)")
print("td \(myString)")
//login me here with oauth2.accessToken
}In this block I want to log into my website with an url like that : "http://my-website.com/authme.php?token=\(oauth2!.accessToken!)"I've try webview.load and no success. If I open the URL in another method everything work like a charmI think it is due to the fact that afterAuthorizeOrFail seems to be called in backgroundHere is how afterAuthorizeOrFail is called didFail and didAuthorize which only differences are the arguments of the function in those methodspublic final func didFail(with error: OAuth2Error?) {
var finalError = error
if let error = finalError {
logger?.debug("OAuth2", msg: "\(error)")
}
else {
finalError = OAuth2Error.requestCancelled
}
callOnMainThread() {
self.didAuthorizeOrFail?(nil, finalError)
self.didAuthorizeOrFail = nil
self.internalAfterAuthorizeOrFail?(true, finalError)
self.afterAuthorizeOrFail?(nil, finalError)
}
}Here is the source file with this method https://github.com/p2/OAuth2/blob/master/Sources/Base/OAuth2Base.swiftand callOnMainThread is that:public func callOnMainThread(_ callback: (() -> Void)) {
if Thread.isMainThread {
callback()
}
else {
DispatchQueue.main.sync(execute: callback)
}
}Here is the source file with this method https://github.com/p2/OAuth2/blob/master/Sources/Base/OAuth2Requestable.swiftAnd here is how I do the request let requrl=URL(string: "http://my-website.com/authme.php?token=\(oauth2!.accessToken!)")
do{
let request = try URLRequest(url: requrl!,method: .post)
self.webView!.load(request)
}catch let error {
DispatchQueue.main.async {
print("ERROR loading site \(error)")
}
}Thanks in advance
I'm making an iOS web app and I want to save credentials to keep session opened. It is the first time I dev an iOS appFor the moment I only do that:class ViewController: UIViewController {
@IBOutlet weak var KronosWebsite: WKWebView!
let myUrl = URL(string:"https://mobi.kronos-sport.com")
override func viewDidLoad() {
super.viewDidLoad()
let myRequest = URLRequest(url : myUrl!)
KronosWebsite.load(myRequest)
}
}