{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-docs/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"iOS","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"ios","__idx":0},"children":["iOS"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A native wrapper for the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/in-person-payments/pay-in-person/integration-guide/js-library"},"children":["JS library"]},", for POS applications targeting iOS 13+. The"," ","library is a thin wrapper around the iClient JavaScript library, using a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["WKWebView"]}," (or, for"," ","older integrations, a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UIWebView"]},") in place of a browser page. There are no changes to how a"," ","transaction is initiated or to the underlying JavaScript API — only to how the WebView is set up."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The original Tyro iOS SDK was based on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UIWebView"]},", which iOS no longer supports: new app"," ","submissions using it stopped being accepted, and updates to existing apps were blocked, in"," ","December 2020. The current implementation uses ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["WKWebView"]}," instead, via a new ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TyroClientUniversal"]}," ","framework added to the POS application."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before you begin development, check the certification criteria:"," ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/assets/certification_criteria_iclient_retail_hospitality.7bf0b2b5462961db882fcba1f1e9ddbec0d942cc7ee96278907994599bebf62a.d564e73d.pdf"},"children":["Certification Criteria Document"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Downloads:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/assets/possimulator.90a10096ef0950254515b26ab3f7801af25c7cd21d5c9f34aaa89d65793625a1.fbf1555a.zip"},"children":["POS simulator"]}," — an example project demonstrating the framework"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/assets/tyroclientuniversal.framework.b6aeb23f9f8c0aba621d36df4f5105507d4d6e882d7858ac5d23db1953fad241.fbf1555a.zip"},"children":["TyroClientUniversal framework"]}," — just the framework"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/assets/iclient-api.57e262928075df78cfa8a01bd63db2f4b79b8d58736bbb024a56daa62cd686fe.fbf1555a.zip"},"children":["iClient API docs"]}," — unzip, then open ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["doc/index.html"]},"; the iOS"," ","integration reference is under ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TYRO.IClientEmbedded"]}," in the left-hand navigation"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"objective-c-purchase-example","__idx":1},"children":["Objective-C purchase example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The main change from a standard web integration is how the WebView is initiated."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["WKWebView SDK:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"objectivec","header":{"controls":{"copy":{}}},"source":"#import <TyroClientUniversal/TyroClient.h>\n#import \"PaymentsViewController.h\"\n#import \"PosConfiguration.h\"\n\n@interface PaymentsViewController ()\n\n@property(weak, nonatomic) IBOutlet UITextField *amountField;\n@property(weak, nonatomic) IBOutlet UITextField *cashoutAmountField;\n@property(weak, nonatomic) IBOutlet UITextField *refundAmountField;\n@property(weak, nonatomic) IBOutlet UITextField *openTabAmountField;\n@property(weak, nonatomic) IBOutlet UITextField *closeTabAmountField;\n@property(weak, nonatomic) IBOutlet UITextField *closeTabCompletionReferenceField;\n@property(weak, nonatomic) IBOutlet UITextField *voidTabCompletionReferenceField;\n\n@property(strong, nonatomic) IBOutlet WKWebView *mainWebView;\n@property(weak, nonatomic) IBOutlet UITextView *merchantReceiptTextView;\n@property(weak, nonatomic) IBOutlet UITextView *customerReceiptTextView;\n\n@property(nonatomic, strong) PosConfiguration *posConfiguration;\n@property(nonatomic, strong) TyroClient *client;\n@property (weak, nonatomic) IBOutlet UISwitch *enableSurcharge;\n\n@end\n\n@implementation PaymentsViewController\n\n- (void) viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    self.posConfiguration = [PosConfiguration sharedInstance];\n    \n    WKPreferences * preferences = [[WKPreferences alloc] init];\n    preferences.javaScriptEnabled = true;\n    WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];\n    configuration.preferences = preferences;\n    self.mainWebView = [[WKWebView alloc] initWithFrame:self.mainWebView.frame configuration:configuration];\n    \n    [self.view addSubview:self.mainWebView];\n\n    self.client = [[TyroClient alloc] initWithWebView:self.mainWebView\n                                      webViewDelegate:self\n                                               apiKey:self.posConfiguration.apiKey\n                                     posProductVendor:self.posConfiguration.posProductVendor\n                                       posProductName:self.posConfiguration.posProductName\n                                    posProductVersion:self.posConfiguration.posProductVersion];\n    \n    self.client.baseUrl = self.posConfiguration.iclientBaseUrl;\n}\n","lang":"objectivec"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["UIWebView SDK:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"objectivec","header":{"controls":{"copy":{}}},"source":"#import <TyroClientUniversal/TyroClient.h>\n#import \"PaymentsViewController.h\"\n#import \"PosConfiguration.h\"\n\n@interface PaymentsViewController ()\n\n@property(weak, nonatomic) IBOutlet UITextField *amountField;\n@property(weak, nonatomic) IBOutlet UITextField *cashoutAmountField;\n@property(weak, nonatomic) IBOutlet UITextField *refundAmountField;\n@property(weak, nonatomic) IBOutlet UITextField *openTabAmountField;\n@property(weak, nonatomic) IBOutlet UITextField *closeTabAmountField;\n@property(weak, nonatomic) IBOutlet UITextField *closeTabCompletionReferenceField;\n@property(weak, nonatomic) IBOutlet UITextField *voidTabCompletionReferenceField;\n\n@property(strong, nonatomic) IBOutlet UIWebView *mainWebView;\n@property(weak, nonatomic) IBOutlet UITextView *merchantReceiptTextView;\n@property(weak, nonatomic) IBOutlet UITextView *customerReceiptTextView;\n\n@property(nonatomic, strong) PosConfiguration *posConfiguration;\n@property(nonatomic, strong) TyroClient *client;\n\n@end\n\n@implementation PaymentsViewController\n\n- (void) viewWillAppear:(BOOL)animated {\n    [super viewWillAppear:animated];\n    self.posConfiguration = [PosConfiguration sharedInstance];\n    self.mainWebView = [[UIWebView alloc] initWithFrame:self.mainWebView.frame];\n    [self.view addSubview:self.mainWebView];\n\n    self.client = [[TyroClient alloc] initWithWebView:self.mainWebView\n                                      webViewDelegate:self\n                                               apiKey:self.posConfiguration.apiKey\n                                     posProductVendor:self.posConfiguration.posProductVendor\n                                       posProductName:self.posConfiguration.posProductName\n                                    posProductVersion:self.posConfiguration.posProductVersion];\n    \n    self.client.baseUrl = self.posConfiguration.iclientBaseUrl;\n}\n","lang":"objectivec"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"initiating-a-transaction","__idx":2},"children":["Initiating a transaction"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Initiating a transaction remains the same regardless of which WebView the POS uses:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"objectivec","header":{"controls":{"copy":{}}},"source":"- (IBAction)initiatePurchase {\n    [self.amountField resignFirstResponder];\n    [self clearReceipts];\n\n    NSDictionary *parameters = @{\n            @\"amount\" : self.amountField.text,\n            @\"cashout\" : self.cashoutAmountField.text,\n            @\"integratedReceipt\" : self.posConfiguration.integratedReceipt ? @\"true\" : @\"false\"};\n\n    if ([self.amountField.text isEqualToString:@\"error\"]) {\n        [self.client performOperation:@\"invalid-operation\"\n                           parameters:parameters\n              receiptReceivedCallback:[self receiptReceivedCallback]\n          transactionCompleteCallback:[self transactionCompleteCallback]];\n    } else {\n        [self.client performOperation:@\"purchase\"\n                           parameters:parameters\n              receiptReceivedCallback:[self receiptReceivedCallback]\n          transactionCompleteCallback:[self transactionCompleteCallback]];\n    }\n}\n","lang":"objectivec"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"headless-pairing","__idx":3},"children":["Headless pairing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pairTerminal(mid, tid)"]}," is compulsory when implementing the iOS SDK with your POS. This"," ","function establishes the connection with the terminal, and returns the integration key for you to"," ","store in memory."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Parameters:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mid"]}," (String) — Tyro Merchant ID (MID)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tid"]}," (String) — Tyro Terminal ID (TID)"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Example:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"objectivec","header":{"controls":{"copy":{}}},"source":"[self.client performOperation: @\"pairTerminal\" parameters: @{@\"mid\" : @\"22323\", @\"tid\": @\"3\" } receiptReceivedCallback: nil transactionCompleteCallback: ^(NSDictionary *result) {NSLog(@\"Paired terminal: %@\", result);}];\n","lang":"objectivec"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The POS must display the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message"]}," fields on the POS UI gracefully. The POS must"," ","store the MID, TID and integration key in the POS app's own database, and pass them when"," ","processing a transaction."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For further information on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["WKWebView"]}," functionality, see"," ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://developer.apple.com/documentation/webkit/wkwebview?language=objc"},"children":["Apple's documentation"]},"."]}]}]},"headings":[{"value":"iOS","id":"ios","depth":1},{"value":"Objective-C purchase example","id":"objective-c-purchase-example","depth":2},{"value":"Initiating a transaction","id":"initiating-a-transaction","depth":3},{"value":"Headless pairing","id":"headless-pairing","depth":3}],"frontmatter":{"title":"iOS","seo":{"title":"iOS"}},"lastModified":"2026-09-22T01:37:20.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/in-person-payments/pay-in-person/integration-guide/js-library/ios","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}