Xamarin integration for iOS

The iOS mobile SDK is delivered as a .framework file that allows for easy integration with both native and cross-platform development tools. If you’re using Xamarin to generate your apps, you must complete the following preparatory steps before you integrate with the iOS Mobile SDK.

To incorporate the AffiniPay Mobile SDK for iOS into your Xamarin application, do one of the following:

After you complete the tasks in one of these sections, you can integrate with iOS.

Create a binding and add a reference to it

You can create a binding and add a reference to it in your Xamarin application solution.

Create a project

  1. In Microsoft Visual Studio, open a Xamarin application solution.
  2. Add a new project and choose the iOS bindings library template.

Create a binding

  1. Copy the AffiniPaySDK.framework file from AffiniPay to the binding project directory.
  2. In the ApiDefinition.cs file in that same directory, add the following code block to the namespace block.

    // @interface AFPAmountResult : NSObject
     [BaseType(typeof(NSObject))]
     interface AFPAmountResult
     {
         // @property (retain, nonatomic) NSString * amount;
         [Export("amount", ArgumentSemantic.Retain)]
         string Amount { get; set; }
    
         // -(id)initWithAmount:(NSString *)amount;
         [Export("initWithAmount:")]
         IntPtr Constructor(string amount);
     }
    
     // @interface AFPCustomerInfo : NSObject
     [BaseType(typeof(NSObject))]
     interface AFPCustomerInfo
     {
         // @property (retain, nonatomic) NSString * name;
         [Export("name", ArgumentSemantic.Retain)]
         string Name { get; set; }
    
         // @property (retain, nonatomic) NSString * email;
         [Export("email", ArgumentSemantic.Retain)]
         string Email { get; set; }
    
         // @property (retain, nonatomic) NSString * address1;
         [Export("address1", ArgumentSemantic.Retain)]
         string Address1 { get; set; }
    
         // @property (retain, nonatomic) NSString * address2;
         [Export("address2", ArgumentSemantic.Retain)]
         string Address2 { get; set; }
    
         // @property (retain, nonatomic) NSString * city;
         [Export("city", ArgumentSemantic.Retain)]
         string City { get; set; }
    
         // @property (retain, nonatomic) NSString * state;
         [Export("state", ArgumentSemantic.Retain)]
         string State { get; set; }
    
         // @property (retain, nonatomic) NSString * country;
         [Export("country", ArgumentSemantic.Retain)]
         string Country { get; set; }
    
         // @property (retain, nonatomic) NSString * postalCode;
         [Export("postalCode", ArgumentSemantic.Retain)]
         string PostalCode { get; set; }
    
         // @property (retain, nonatomic) NSString * phone;
         [Export("phone", ArgumentSemantic.Retain)]
         string Phone { get; set; }
    
         // @property (retain, nonatomic) NSString * reference;
         [Export("reference", ArgumentSemantic.Retain)]
         string Reference { get; set; }
    
         // -(NSDictionary *)toDictionary;
         [Export("toDictionary")]
         NSDictionary ToDictionary { get; }
    
         // +(AFPCustomerInfo *)fromDictionary:(NSDictionary *)dict;
         [Static]
         [Export("fromDictionary:")]
         AFPCustomerInfo FromDictionary(NSDictionary dict);
     }
    
     // @interface AFPChargeParams : NSObject
     [BaseType(typeof(NSObject))]
     interface AFPChargeParams
     {
         // @property (retain, nonatomic) AFPCustomerInfo * customerInfo;
         [Export("customerInfo", ArgumentSemantic.Retain)]
         AFPCustomerInfo CustomerInfo { get; set; }
    
         // @property (retain, nonatomic) NSString * publicKey;
         [Export("publicKey", ArgumentSemantic.Retain)]
         string PublicKey { get; set; }
    
         // @property (retain, nonatomic) NSString * amount;
         [Export("amount", ArgumentSemantic.Retain)]
         string Amount { get; set; }
    
         // -(id)initWithPublicKey:(NSString *)publicKey amount:(NSString *)amount customerInfo:(AFPCustomerInfo *)customerInfo;
         [Export("initWithPublicKey:amount:customerInfo:")]
         IntPtr Constructor(string publicKey, string amount, AFPCustomerInfo customerInfo);
     }
    
     // @interface AFPChargeResult : NSObject
     [BaseType(typeof(NSObject))]
     interface AFPChargeResult
     {
         // @property (retain, nonatomic) NSString * oneTimeToken;
         [Export("oneTimeToken", ArgumentSemantic.Retain)]
         string OneTimeToken { get; set; }
    
         // @property (retain, nonatomic) NSString * amount;
         [Export("amount", ArgumentSemantic.Retain)]
         string Amount { get; set; }
    
         // @property (retain, nonatomic) NSString * accountId;
         [Export("accountId", ArgumentSemantic.Retain)]
         string AccountId { get; set; }
    
         // @property (retain, nonatomic) NSDictionary * posFields;
         [Export("posFields", ArgumentSemantic.Retain)]
         NSDictionary PosFields { get; set; }
    
         // @property (retain, nonatomic) NSString * paymentDataSource;
         [Export("paymentDataSource", ArgumentSemantic.Retain)]
         string PaymentDataSource { get; set; }
    
         // -(id)initWithOneTimeToken:(NSString *)oneTimeToken accountId:(NSString *)accountId amount:(NSString *)amount posFields:(NSDictionary *)posFields paymentDataSource:(NSString *)paymentDataSource;
         [Export("initWithOneTimeToken:accountId:amount:posFields:paymentDataSource:")]
         IntPtr Constructor(string oneTimeToken, string accountId, string amount, NSDictionary posFields, string paymentDataSource);
     }
    
     // @interface AFPCustomerInfoParams : NSObject
     [BaseType(typeof(NSObject))]
     interface AFPCustomerInfoParams
     {
         // @property (retain, nonatomic) NSArray * mandatoryFields;
         [Export("mandatoryFields", ArgumentSemantic.Retain)]
         NSObject[] MandatoryFields { get; set; }
    
         // @property (retain, nonatomic) AFPCustomerInfo * customerPrefill;
         [Export("customerPrefill", ArgumentSemantic.Retain)]
         AFPCustomerInfo CustomerPrefill { get; set; }
    
         // -(id)initWithMandatoryFields:(NSArray *)mandatoryFields;
         [Export("initWithMandatoryFields:")]
          IntPtr Constructor(NSObject[] mandatoryFields);
    
         // -(id)initWithMandatoryFields:(NSArray *)mandatoryFields customerPrefill:(AFPCustomerInfo *)customerPrefill;
         [Export("initWithMandatoryFields:customerPrefill:")]
         IntPtr Constructor(NSObject[] mandatoryFields, AFPCustomerInfo customerPrefill);
    
         // -(BOOL)containsMandatoryField:(NSUInteger)item;
         [Export("containsMandatoryField:")]
         bool ContainsMandatoryField(nuint item);
     }
    
     // @interface AFPCustomerInfoResult : NSObject
     [BaseType(typeof(NSObject))]
     interface AFPCustomerInfoResult
     {
         // @property (retain, nonatomic) AFPCustomerInfo * customerInfo;
         [Export("customerInfo", ArgumentSemantic.Retain)]
         AFPCustomerInfo CustomerInfo { get; set; }
     }
    
     // @interface AFPSignatureParams : NSObject
     [BaseType(typeof(NSObject))]
     interface AFPSignatureParams
     {
         // @property (retain, nonatomic) NSString * transactionId;
         [Export("transactionId", ArgumentSemantic.Retain)]
         string TransactionId { get; set; }
    
         // @property (retain, nonatomic) NSString * amount;
         [Export("amount", ArgumentSemantic.Retain)]
         string Amount { get; set; }
    
         // @property (retain, nonatomic) NSString * merchant;
         [Export("merchant", ArgumentSemantic.Retain)]
         string Merchant { get; set; }
    
         // @property (retain, nonatomic) UIImage * image;
         [Export("image", ArgumentSemantic.Retain)]
         UIImage Image { get; set; }
    
         // -(id)initWithTransactionId:(NSString *)transactionId amount:(NSString *)amount merchant:(NSString *)merchant;
         [Export("initWithTransactionId:amount:merchant:")]
         IntPtr Constructor(string transactionId, string amount, string merchant);
    
         // -(id)initWithTransactionId:(NSString *)transactionId amount:(NSString *)amount merchant:(NSString *)merchant image:(UIImage *)image;
         [Export("initWithTransactionId:amount:merchant:image:")]
         IntPtr Constructor(string transactionId, string amount, string merchant, UIImage image);
     }
    
     // @interface AFPSignatureResult : NSObject
     [BaseType(typeof(NSObject))]
     interface AFPSignatureResult
     {
         // @property (retain, nonatomic) NSString * signatureString;
         [Export("signatureString", ArgumentSemantic.Retain)]
         string SignatureString { get; set; }
     }
    
     // @interface AFPNavigationController : UINavigationController <UINavigationControllerDelegate>
     [BaseType(typeof(UINavigationController))]
     interface AFPNavigationController : IUINavigationControllerDelegate
     {
     }
    
     // typedef void (^voidBlock_t)();
     delegate void voidBlock_t();
    
     // typedef void (^cancelBlock_t)();
     delegate void cancelBlock_t();
    
     // typedef void (^longBlock_t)(long);
     delegate void longBlock_t(nint arg0);
    
     // typedef void (^doubleBlock_t)(double);
     delegate void doubleBlock_t(double arg0);
    
     // typedef void (^boolBlock_t)(BOOL);
     delegate void boolBlock_t(bool arg0);
    
     // typedef BOOL (^boolReturnBlock_t)();
     delegate bool boolReturnBlock_t();
    
     // typedef void (^nsintegerBlock_t)(NSInteger);
     delegate void nsintegerBlock_t(nint arg0);
    
     // typedef void (^stringBlock_t)(NSString * _Nullable);
     delegate void stringBlock_t([NullAllowed] string arg0);
    
     // typedef void (^dictionaryBlock_t)(NSDictionary * _Nullable);
     delegate void dictionaryBlock_t([NullAllowed] NSDictionary arg0);
    
     // typedef void (^dictionaryBlock_nonnull_t)(NSDictionary * _Nonnull);
     delegate void dictionaryBlock_nonnull_t(NSDictionary arg0);
    
     // typedef void (^errorBlock_t)(NSError * _Nullable);
     delegate void errorBlock_t([NullAllowed] NSError arg0);
    
     // typedef void (^mutableRequestBlock_t)(NSMutableURLRequest * _Nullable);
     delegate void mutableRequestBlock_t([NullAllowed] NSMutableUrlRequest arg0);
    
     // typedef void (^amountNextBlock_t)(AFPAmountResult * _Nullable);
     delegate void amountNextBlock_t([NullAllowed] AFPAmountResult arg0);
    
     // typedef void (^customerInfoNextBlock_t)(AFPCustomerInfoResult * _Nullable);
     delegate void customerInfoNextBlock_t([NullAllowed] AFPCustomerInfoResult arg0);
    
     // typedef void (^chargeNextWithCompletionBlock_t)(AFPChargeResult * _Nullable, boolBlock_t _Nullable);
     delegate void chargeNextWithCompletionBlock_t([NullAllowed] AFPChargeResult arg0, [NullAllowed] boolBlock_t arg1);
    
     // typedef void (^chargeNextBlock_t)(AFPChargeResult * _Nullable);
     delegate void chargeNextBlock_t([NullAllowed] AFPChargeResult arg0);
    
     // typedef void (^signatureNextWithCompletionBlock_t)(AFPSignatureResult * _Nullable, boolBlock_t _Nullable);
     delegate void signatureNextWithCompletionBlock_t([NullAllowed] AFPSignatureResult arg0, [NullAllowed] boolBlock_t arg1);
    
     // typedef void (^signatureNextBlock_t)(AFPSignatureResult * _Nullable);
     delegate void signatureNextBlock_t([NullAllowed] AFPSignatureResult arg0);
    
     // @interface AFPAmountVC : UIViewController
     [BaseType(typeof(UIViewController))]
     interface AFPAmountVC
     {
         // +(id)amountWithNext:(amountNextBlock_t _Nullable)next;
         [Static]
         [Export("amountWithNext:")]
         NSObject AmountWithNext([NullAllowed] amountNextBlock_t next);
     }
    
     // @interface AFPCustomerInfoVC : UIViewController
     [BaseType(typeof(UIViewController))]
     interface AFPCustomerInfoVC
     {
         // +(id)customerInfoWithParams:(AFPCustomerInfoParams * _Nonnull)params next:(customerInfoNextBlock_t _Nullable)next;
         [Static]
         [Export("customerInfoWithParams:next:")]
         NSObject CustomerInfoWithParams(AFPCustomerInfoParams @params, [NullAllowed] customerInfoNextBlock_t next);
     }
    
     // @interface AFPCardEntryVC : UIViewController
     [BaseType(typeof(UIViewController))]
     interface AFPCardEntryVC
     {
         // +(id)cardEntryWithParams:(AFPChargeParams * _Nonnull)params nextWithCompletionBlock:(chargeNextWithCompletionBlock_t _Nullable)next;
         [Static]
         [Export("cardEntryWithParams:nextWithCompletionBlock:")]
         NSObject CardEntryWithParams(AFPChargeParams @params, [NullAllowed] chargeNextWithCompletionBlock_t next);
    
         // +(id)cardEntryWithParams:(AFPChargeParams * _Nonnull)params next:(chargeNextBlock_t _Nullable)next;
         [Static]
         [Export("cardEntryWithParams:next:")]
         NSObject CardEntryWithParams(AFPChargeParams @params, [NullAllowed] chargeNextBlock_t next);
    
         // -(void)finish:(BOOL)success;
         [Export("finish:")]
         void Finish(bool success);
     }
    
     // @interface AFPSignatureVC : UIViewController
     [BaseType(typeof(UIViewController))]
     interface AFPSignatureVC
     {
         // +(id)signatureWithParams:(AFPSignatureParams * _Nonnull)params nextWithCompletionBlock:(signatureNextWithCompletionBlock_t _Nullable)next;
         [Static]
         [Export("signatureWithParams:nextWithCompletionBlock:")]
         NSObject SignatureWithParams(AFPSignatureParams @params, [NullAllowed] signatureNextWithCompletionBlock_t next);
    
         // +(id)signatureWithParams:(AFPSignatureParams * _Nonnull)params next:(signatureNextBlock_t _Nullable)next;
         [Static]
         [Export("signatureWithParams:next:")]
         NSObject SignatureWithParams(AFPSignatureParams @params, [NullAllowed] signatureNextBlock_t next);
    
         // -(void)finish:(BOOL)success;
         [Export("finish:")]
         void Finish(bool success);
     }
    
     // @interface AffiniPaySDK : NSObject
     [BaseType(typeof(NSObject))]
     interface AffiniPaySDK
     {
         // +(void)initialize:(NSString *)gatewayUrl;
         [Static]
         [Export("initialize:")]
         void Initialize(string gatewayUrl);
    
         // +(NSString * _Nullable)getGatewayUrl;
         [Static]
         [NullAllowed, Export("getGatewayUrl")]
         string GatewayUrl { get; }
    
         // +(NSString * _Nonnull)version;
         [Static]
         [Export("version")]
         string Version { get; }
    
         // +(AFPAmountVC * _Nullable)getAmountVC:(amountNextBlock_t _Nullable)next;
         [Static]
         [Export("getAmountVC:")]
         [return: NullAllowed]
         AFPAmountVC GetAmountVC([NullAllowed] amountNextBlock_t next);
    
         // +(AFPCustomerInfoVC * _Nullable)getCustomerInfoVC:(AFPCustomerInfoParams * _Nonnull)params next:(customerInfoNextBlock_t _Nullable)next;
         [Static]
         [Export("getCustomerInfoVC:next:")]
         [return: NullAllowed]
         AFPCustomerInfoVC GetCustomerInfoVC(AFPCustomerInfoParams @params, [NullAllowed] customerInfoNextBlock_t next);
    
         // +(AFPCardEntryVC * _Nullable)getCardEntryVC:(AFPChargeParams * _Nonnull)params next:(chargeNextBlock_t _Nullable)next;
         [Static]
         [Export("getCardEntryVC:next:")]
         [return: NullAllowed]
         AFPCardEntryVC GetCardEntryVC(AFPChargeParams @params, [NullAllowed] chargeNextBlock_t next);
    
         // +(AFPCardEntryVC * _Nullable)getCardEntryVC:(AFPChargeParams * _Nonnull)params nextWithCompletionBlock:(chargeNextWithCompletionBlock_t _Nullable)next;
         [Static]
         [Export("getCardEntryVC:nextWithCompletionBlock:")]
         [return: NullAllowed]
         AFPCardEntryVC GetCardEntryVC(AFPChargeParams @params, [NullAllowed] chargeNextWithCompletionBlock_t next);
    
         // +(AFPSignatureVC * _Nullable)getSignatureVC:(AFPSignatureParams * _Nonnull)params nextWithCompletionBlock:(signatureNextWithCompletionBlock_t _Nullable)next;
         [Static]
         [Export("getSignatureVC:nextWithCompletionBlock:")]
         [return: NullAllowed]
         AFPSignatureVC GetSignatureVC(AFPSignatureParams @params, [NullAllowed] signatureNextWithCompletionBlock_t next);
    
         // +(AFPSignatureVC * _Nullable)getSignatureVC:(AFPSignatureParams * _Nonnull)params next:(signatureNextBlock_t _Nullable)next;
         [Static]
         [Export("getSignatureVC:next:")]
         [return: NullAllowed]
         AFPSignatureVC GetSignatureVC(AFPSignatureParams @params, [NullAllowed] signatureNextBlock_t next);
    
         // +(void)tokenTest:(NSDictionary * _Nonnull)a b:(dictionaryBlock_t _Nullable)b c:(errorBlock_t _Nullable)c;
         [Static]
         [Export("tokenTest:b:c:")]
         void TokenTest(NSDictionary a, [NullAllowed] dictionaryBlock_t b, [NullAllowed] errorBlock_t c);
     }

  3. In the Structs.cs file, add the following to the using block which appear at the top of your file:

    using ObjCRuntime;

  4. Also in the Structs.cs file, add the following code block to the namespace block:

    [Native]
       public enum AFPCustomerInfoType: uint
       {
           Name = 0,
           Address1 = 1,
           Address2 = 2,
           Phone = 3,
           Email = 4,
           State = 5,
           Country = 6,
           Postalcode = 7,
           Reference = 8,
           City = 9,
           Max = 10
       }

Add a reference to the binding project

  1. In Microsoft Visual Studio, add a native reference to AffiniPaySDK.framework.
  2. Add a reference to the binding project.

Create a DLL and and add a reference to it

If you don’t already have a DLL with a known namespace, you will create a binding project, create a DLL, and then reference the DLL in your application solution.

Create a new solution

In Microsoft Visual Studio, create a new solution.

Complete the steps in the “Create a binding” section

First, create a binding using the steps in the Create a binding section. Then, continue with the next step.

Create a DLL

Build the project. <PROJECT_NAME>.dll will be generated in the <PROJECT_ROOT>/obj/<CONFIGURATION>/ directory, where:

Complete the steps in the “Add a reference to the DLL” section

Add a reference in your application solution to the DLL you created using the steps in the Add a reference to a DLL section.

Add a reference to a DLL

If you have a DLL with a known namespace, you can add a reference to it in your application solution.

  1. Copy the DLL to your application solution.
  2. Add a native reference to your DLL. (Edit the references of your iOS project. In the .Net Assembly tab, click Browse and select the DLL.)

Xamarin limitations

Xamarin.iOS limitations are well documented on the Microsoft docs site.

To avoid issues with limitations with reverse callbacks: