Using SDKs

SDK Initialization

Initialize the Glassfy SDK

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

  Glassfy.initialize(apiKey: "YOUR_API_KEY", watcherMode: false)

  [...]

  // optionally login your user
  Glassfy.login(user: "youruser")

}
[...]
ContentView()
	.onAppear() {
		Glassfy.initialize(apiKey: "YOUR_API_KEY", watcherMode: false)
  }
[...]
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  [Glassfy initializeWithAPIKey:@"YOU_API_KEY" watcherMode:NO];

  [...]

  // optionally login your user
  [Glassfy loginUser:@"youruser" withCompletion:nil];
}
class App : Application() {
  override fun onCreate() {
    super.onCreate()
    
    Glassfy.initialize(this, "YOUR_API_KEY", false, null)
  }
}
public class App extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    Glassfy.initialize(this, "YOUR_API_KEY", false, null);
  }
}
try {

  await Glassfy.initialize('YOU_API_KEY',watcherMode: false);

} catch (e) {
  // error
  [...]
}
try {

  await Glassfy.initialize('YOU_API_KEY', false);

} catch (e) {
  // initialization error
}
try {

  await Glassfy.initialize({ apiKey: 'YOU_API_KEY', watcherMode: false });

} catch (e) {
  // initialization error
}

Fetch offerings

Fetch all offers previously created in the dashboard. The offerings completion block returns an Offerings object or an error.

Glassfy.offerings { (offerings, err) in
    if let offering = offerings?["premium"] {
        // display your offering's skus
        for sku in offering.skus {
            // sku.extravars
            // sku.product.localizedTitle
            // sku.product.localizedDescription
            // sku.product.price
        }
    }
}
[Glassfy offeringsWithCompletion:^(GYOfferings *offers, NSError *err) {
    GYOffering *offering = offers[@"premium"];
    if (offering) {
        // display your offering's skus
        for (GYSku *sku in offering.skus) {
            // sku.extravars
            // sku.product.localizedTitle
            // sku.product.localizedDescription
            // sku.product.price
        }
    }
}];
Glassfy.offerings() { offers, err ->
    offers?.all
        ?.firstOrNull { it.offeringId == "premium" }
        ?.also {
            // display your offering's skus
            for (sku in it.skus) {
                // sku.extravars
                // sku.product.title
                // sku.product.description
                // sku.product.price
            }
        }
}
Glassfy.offerings(new OfferingsCallback() {
    @Override
    public void onResult(@Nullable Offerings offers, @Nullable GlassfyError err) {
        Offering offering = null;
        if (offers != null) {
            for (Offering o : offers.getAll()) {
                if (o.getOfferingId().equals("premium")) {
                    offering = o;
                }
            }
        }
        if (offering != null) {
            // display your offering's skus
            for (Sku sku : offering.getSkus()) {
                // sku.getExtravars();
                // sku.getProduct().getTitle();
                // sku.getProduct().getDescription();
                // sku.getProduct().getPrice();
            }
        }
    }
});
try {
    var offerings = await Glassfy.offerings();
    var offering = offerings.all
        ?.singleWhere((offering) => offering.offeringId == 'premium');

    offering?.skus?.forEach((sku) {
        // sku.product.description
        // sku.product.price
    });
} catch (e) {
  // initialization error
  [...]
}
try {
    let offering = Glassfy.offerings().all.find((o) => o.offeringId === 'premium');

    offering?.skus.forEach((sku) => {
      // sku.extravars
      // sku.product.description;
      // sku.product.price
    });
} catch (e) {
  [...]
}
try {
    let offering = Glassfy.offerings().all.find((o) => o.offeringId === 'premium');

    offering?.skus.forEach((sku) => {
      // sku.extravars
      // sku.product.description;
      // sku.product.price
    });
} catch (e) {
  [...]
}

🚧

App Store

If all the SKUs in your offering are not returned to your app please be sure to follow the instructions at this guide

Fetch SKU

Fetch the SKU previously created in the dashboard. The sku completion block returns a Sku object or an error.

Glassfy.sku(id: "premium_weekly") { sku, err in
    if let sku = sku {
        // sku.extravars
        // sku.product.localizedTitle
        // sku.product.localizedDescription
        // sku.product.price
    }
}
[Glassfy skuWithId:@"premium_weekly" completion:^(GYSku *sku, NSError *err) {
    if (sku != nil) {
        // sku.extravars
        // sku.product.localizedTitle
        // sku.product.localizedDescription
        // sku.product.price
    }
}];
Glassfy.sku("premium_weekly") { sku, err ->
    sku?.also {
        // sku.extravars
        // sku.product.title
        // sku.product.description
        // sku.product.price
    }
}
Glassfy.sku("premium_weekly", new SkuCallback() {
    @Override
    public void onResult(@Nullable Sku sku, @Nullable GlassfyError err) {
        if (sku != null) {
            // sku.getExtravars();
            // sku.getProduct().getTitle();
            // sku.getProduct().getDescription();
            // sku.getProduct().getPrice();
        }
    }
});
try {
    var sku = await Glassfy.skuWithId('premium_weekly');
    // sku.product.description
    // sku.product.price
} catch (e) {
  // initialization error
  [...]
}
try {
    let sku = Glassfy.skuWithId('premium_weekly');
    // sku.extravars
    // sku.product.description;
    // sku.product.price
} catch (e) {
  [...]
}
try {
    let sku = Glassfy.skuWithId({ identifier: "premium_weekly" });
    // sku.extravars
    // sku.product.description;
    // sku.product.price
} catch (e) {
  [...]
}

Make purchases

To start the purchase process, you need to get a Sku reference using an offer or directly from the identifier. The purchase completion block returns a Transaction or an error.

Glassfy.purchase(sku: premiumSku) { (transaction, e) in
    // update app status accondingly
    if let p = transaction?.permissions["aPermission"] {
        if p.isValid {
            // unlock aFeature
        } else {
            // lock aFeature
        }
    }
}
[Glassfy purchaseSku:premiumSku completion:^(GYTransaction *transaction, NSError *err) {
    GYPermissions *permissions = transaction.permissions;
    if (permissions) {
        GYPermission *p = permissions[@"aPermission"];
        if (p.isValid) {
            // unlock aFeature
        }
        else {
            // lock aFeature
        }
    }
}];
Glassfy.purchase(activity, sku) { transaction, err ->
    // update app status accordingly
    transaction?.permissions
        ?.all
        ?.firstOrNull { it.permissionId == "aPermission" }
        ?.also {
            if (it.isValid) {
                // unlock aFeature
            } else {
                // lock aFeature
            }
        }
}
Glassfy.purchase(activity, sku, new PurchaseCallback() {
    @Override
    public void onResult(@Nullable Transaction t, @Nullable GlassfyError err) {
        // update app status accordingly
        Permission permission = null;
        if (t != null) {
            for (Permission p : t.getPermissions().getAll()) {
                if (p.getPermissionId().equals("aPermission")) {
                    permission = p;
                }
            }
        }
        if (permission != null) {
            if (permission.isValid()) {
              // unlock aFeature
            } else {
              // lock aFeature
            }
        }
    }
});
try {
    var transaction = await Glassfy.purchaseSku(sku);

    var p = transaction.permissions?.all?.singleWhere((permission) => permission.permissionId == 'premium');
    if (p?.isValid==true) {
        // unlock aFeature
    }
    else {
        // lock aFeature
    }
} catch (e) {
  // initialization error
  [...]
}
try {
    const transaction = await Glassfy.purchaseSku(premiumSku );
    const permission = transaction.permissions.all.find((p) => p.permissionId === "aPermission");
    if (permission && permission.isValid) {
        // unlock aFeature
    }
} catch (e) {
  // initialization error
  [...]
}
try {
    const transaction = await Glassfy.purchaseSku({ sku: premiumSku });
    const permission = transaction.permissions.all.find((p) => p.permissionId === "aPermission");
    if (permission && permission.isValid) {
        // unlock aFeature
    }

} catch (e) {
  // initialization error
  [...]
}

Upgrade subscription on Android

To start the purchase process, you need to get a Sku reference using an offer or directly from the identifier and the active Sku using the activeSkus permissions.

val skuToUpgrade = SubscriptionUpdate(currentSkuToUpgrade)
Glassfy.purchase(activity, newSku, skuToUpgrade) { result, error -> 
  [...]
}
const transaction = await Glassfy.purchaseSku({ sku: newSku, , skuToUpgrade:currentSkuToUpgrade });
var purchase = await Glassfy.purchaseSku(newSku,currentSku);

Check permissions

Check all the current user's permission and lock or unlock your app feature accordingly. The permissions completion block returns a permissions object or an error.

Glassfy.permissions { permissions, err in
    guard let permissions = permissions else { return }
    for p in permissions.all {
        switch (p.permissionId) {
        case "aPermission":
            if (p.isValid) {
                // unlock aFeature
            }
            break;
        default:
            print("Permission not handled");
            break;
        }
    }
}
[Glassfy permissionsWithCompletion:^(GYPermissions *permissions, NSError *err) {
    if (permissions) {
        GYPermission *p = permissions[@"aPermission"];
        if (p.isValid) {
            // unlock aFeature
        }
        else {
            // lock aFeature
        }

    }
}];
Glassfy.permissions { permission, err ->
    // update app status accordingly
    permission?.all?.forEach {
        when (it.permissionId) {
            "premium" ->
                if (it.isValid) {
                    // unlock aFeature
                } 
            else -> println("Permission not handled");
        }
    }
}
Glassfy.permissions(new PermissionsCallback() {
    @Override
    public void onResult(@Nullable Permissions permission, @Nullable GlassfyError error) {
        // update app status accondingly
        if (permission != null) {
            for (Permission p: permission.getAll()) {
                switch (p.getPermissionId()) {
                case "premium":
                    if (p.isValid()) {
                        // unlock aFeature
                    } 
                    break;
                default:
                    Log.d(TAG, "Permission not handled");
                }
            }
        }
    }
});
try {
var permission = await Glassfy.permissions();
      permission.all?.forEach((p)=> {
        if (p.permissionId == "premium" && p.isValid==true) {
          // unlock aFeature
        }
      });
} catch (e) {
  // initialization error
  [...]
}
try {
    const permissions = await Glassfy.permissions();
    permissions.all.forEach((p)=>{
        switch (p.permissionId) {
            case "premium":
                if (permission.isValid) {
                    // unlock 
                }
                break;
        
            default:
                break;
        }
    });

} catch (e) {
  // initialization error
  [...]
}
try {
    const permissions = await Glassfy.permissions();
    permissions.all.forEach((p)=>{
        switch (p.permissionId) {
            case "premium":
                if (permission.isValid) {
                    // unlock 
                }
                break;
        
            default:
                break;
        }
    });

} catch (e) {
  // initialization error
  [...]
}

🚧

Offline permission checking

Glassfy does not cache the status of the permission in your device and require internet connection to check for the permission status.

If your app could be used without internet connection please implement a caching strategy for the permission status (eg: allow the use of the app up to 24 hours then require the internet connection)

Restore purchases

Restoring purchases is a way for a user to restore their in-app purchases and subscriptions.

Glassfy automatically keeps track of purchases but it's still recommended to have a button in your application to invoke the restore purchases code. The restorePurchases completion block returns a Permissions object or an error.

Glassfy.restorePurchases { permissions, error
// update app status accondingly
    if let permissions = permission?.all {
        for p in permissions {
            switch p.permissionId {
            case "aPermission":
                if p.isValid {
                    // unlock aFeature
                } else {
                    // lock aFeature
                }
            default:
                print("Permission not handled");
            }
        }
    }                          
}
[Glassfy restorePurchasesWithCompletion:^(GYPermissions *permissions, NSError *err) {

    if (permissions) {
        GYPermission *p = permissions[@"aPermission"];
        if (p.isValid) {
            // unlock aFeature
        }
        else {
            // lock aFeature
        }
    }
}];
try {
  var permissions = await Glassfy.restorePurchases();
  for (var p in permissions.all ?? []) {
    debugPrint("${p.permissionId} is ${p.isValid}");
    // Use permissionId and isValid to lock and unlock features
  }
} catch (error) {
  debugPrint("Failed to restore purchases $error");
}
try {
  var permissions = await Glassfy.restorePurchases();
  for (var p in permissions.all ?? []) {
    console.log(`${p.permissionId} is ${p.isValid}`);
    // Use permissionId and isValid to lock and unlock features
  }
} catch (error) {
  console.log("Failed to restore purchases $error");
}
try {
  var permissions = await Glassfy.restorePurchases();
  for (var p in permissions.all ?? []) {
    console.log(`${p.permissionId} is ${p.isValid}`);
    // Use permissionId and isValid to lock and unlock features
  }
} catch (error) {
  console.log("Failed to restore purchases $error");
}

User properties

Save and retrieve user properties. Read the UserProperties object documentation for more details.

// Save push notification device token
Glassfy.setDeviceToken(remoteDeviceToken) { err in
    // handle err
}

// Save user email
Glassfy.setUserProperty(email: userEmail) { err in
    // handle err
}

// Save extra user properties
Glassfy.setUserProperty(extra: extra) { err in
    // handle err
}

// Fetch user properties
Glassfy.userProperties { properties, err in
    // handle err
    if let p = properties {
        // p.email
        // p.token
        // p.extra
    }
}
// Save push notification device token
[Glassfy setDeviceToken:remoteDeviceToken completion:^(NSError *err) {
    // handle err
}];

// Save user email
[Glassfy setEmailUserProperty:userEmail completion:^(NSError *err) {
    // handle err
}];

// Save extra user properties
[Glassfy setExtraUserProperty:extra completion:^(NSError *err) {
    // handle err
}];

// Fetch user properties
[Glassfy getUserProperties:^(GYUserProperties *p, NSError *err) {
    // handle err
    if (p != nil) {
        // p.email
        // p.token
        // p.extra
    }
}];
// Save push notification device token
await Glassfy.setDeviceToken("token");

// Save user email
await Glassfy.setEmailUserProperty("[email protected]");
Map<String, dynamic> extraProp = {
"property1": "value1",
"property2": "value2",
};

// Save extra user properties
await Glassfy.setExtraUserProperty(extraProp);

// Fetch user properties
var extraProperties = await Glassfy.getExtraUserProperty();
// Save push notification device token
Glassfy.setDeviceToken("mytoken");

// Save extra user properties
Glassfy.setExtraUserProperty(extraProperty);

// Fetch user properties
let extraProperty = Glassfy.getUserProperty();
// Save push notification device token
Glassfy.setDeviceToken({ token: "mytoken" });

// Save extra user properties
Glassfy.setExtraUserProperty({ extra: extraProperty });

// Fetch user properties
let extraProperty = Glassfy.getUserProperty();

Custom identifier

To identify the user you can set a custom identifier. Read the Identify the subscriber documentation for more details. You can use null disconnect the identifier.

Glassfy.connectCustomSubscriber("my_custom_identifier") { error in
    // handle error.
}
[Glassfy connectCustomSubscriber:@"my_custom_identifier" withCompletion:nil];
await Glassfy.connectCustomSubscriber("my_custom_identifier");
await Glassfy.connectCustomSubscriber('my_custom_identifier');
await Glassfy.connectCustomSubscriber({ subscriberId: 'my_custom_identifier' });
Glassfy.connectCustomSubscriber("my_custom_identifier") { error ->
    // handle error.
}
Glassfy.connectCustomSubscriber("my_custom_identifier", new ErrorCallback() {
    @Override
    public void onResult(@Nullable GlassfyError error) {
        // handle error.   
    }
});

AccountableSku Info

Get details about the sku that determines a permission.

Glassfy.permissions { permission, _ in
    guard let permissions = permission?.all else { return }
    
    if let currentPermission = permissions.first(where: { permission in permission.isValid && permission.permissionId == "premium" }),
       let currentSku = currentPermission.accountableSkus.first
    {
        // check accountable sku status
        //
        // currentSku.isInIntroOfferPeriod
        // currentSku.isInTrialPeriod
        //
        // get more details if needed
        Glassfy.sku(id: currentSku.skuId, store: currentSku.store) { sku, _ in
            if let sku = sku {
                if let sku = sku as? Glassfy.Sku {
                    // you can get iOS product info including the
                    // price and the title.
                    //
                    // sku.product.price
                    // sku.product.localizedDescription
                    // sku.product.priceLocale
                } else if let sku = sku as? Glassfy.SkuPaddle {
                    // you can get Paddle product info including the
                    // price and the title.
  									//
                    // sku.name
                    // sku.recurringPrice
                    // sku.recurringPriceLocale
                }
            }
        }
    }
}
[Glassfy permissionsWithCompletion:^(GYPermissions *permissions, NSError *pErr) {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isValid == YES && permissionId == premium"];
    GYPermission *currentPermission = [[permissions.all filteredArrayUsingPredicate:predicate] firstObject];
    GYAccountableSku *currentSku = [currentPermission.accountableSkus anyObject];
    if (currentSku) {
        // check accountable sku status
        //
        // currentSku.isInIntroOfferPeriod;
        // currentSku.isInTrialPeriod;
        //
        // get more details if needed
        [Glassfy skuWithId:currentSku.skuId store:currentSku.store completion:^(GYSkuBase *sku, NSError *sErr) {
            if ([sku isKindOfClass:GYSku.class]) {
                // you can get iOS product info including the
                // price and the title.
                //
                // sku.product.price;
                // sku.product.localizedDescription;
                // sku.product.priceLocale;
            } else if ([sku isKindOfClass:GYSkuPaddle.class]) {
                // you can get Paddle product info including the
                // price and the title.
                //
                // sku.name;
                // sku.recurringPrice;
                // sku.recurringPriceLocale;
            }
                        
        }];
    }
}];

Paddle Store info

Information about user connected stores.

Glassfy.storeInfo { stores, err in
    // handle err
    if let paddleStores = stores?.filter(.paddle),
       let paddleStore = paddleStores.first as? Glassfy.StoreInfoPaddle
    {
        // paddleStore.cancelURL
        // paddleStore.updateURL
    }
}
[Glassfy storeInfo:^(GYStoresInfo *stores, NSError *err) {
    // handle err
    NSArray *paddleStores = [stores filter:GYStorePaddle];
    GYStoreInfoPaddle *paddleStore = [paddleStores firstObject];
    if ([paddleStore isKindOfClass:GYStoreInfoPaddle.class]) {
        // paddleStore.cancelURL
        // paddleStore.updateURL
    }
}];
try {
  final res = await Glassfy.storeInfo();
  res.all?.forEach((storeInfo) {
    if (storeInfo is GlassfyStoreInfoPaddle) {
      print(storeInfo.subscriptionId);
      print(storeInfo.userid);
      print(storeInfo.planId);
      print(storeInfo.subscriptionId);
      print(storeInfo.updateURL);
      print(storeInfo.cancelURL);
    }
  });
} catch (err) {
  [...]
}
try {
  const storesInfo = await Glassfy.storeInfo();
  storesInfo.all.forEach(storeInfo => {
    switch (storeInfo.store) {
      case GLASSFY_STORE.Paddle: {
        console.log(storeInfo.subscriptionId);
        console.log(storeInfo.userid);
        console.log(storeInfo.planId);
        console.log(storeInfo.subscriptionId);
        console.log(storeInfo.updateURL);
        console.log(storeInfo.cancelURL);
      }
    }
  })
} catch (err) {
  [...]
}
try {
  const storesInfo = await Glassfy.storeInfo();
  storesInfo.all.forEach(storeInfo => {
    switch (storeInfo.store) {
      case GLASSFY_STORE.Paddle: {
        console.log(storeInfo.subscriptionId);
        console.log(storeInfo.userid);
        console.log(storeInfo.planId);
        console.log(storeInfo.subscriptionId);
        console.log(storeInfo.updateURL);
        console.log(storeInfo.cancelURL);
      }
    }
  })
} catch (err) {
  [...]
}

Attributions attribute

the following attributes can be set

AttributeiOSAndroid
Adjust.AdjustIDAttributionItem.Type.AdjustIDUnique Adjust ID of the device. Available after the installation has been successfully tracked.
AppsFlyerID.AppsFlyerIDAttributionItem.Type.AppsFlyerIDApp identifier generated by AppsFlyer at installation. A new ID is generated if an app is deleted,
IP Address.IPAttributionItem.Type.IPIP Address
Apple IDFA.IDFAn/aIdentifier For Advertisers - Unique to each device. Only use for advertising.
Apple IDFV.IDFVn/a
Google GAIDn/aAttributionItem.Type.GAIDIdentifier For Advertisers - Unique to each device. Only use for advertising.
App Set IDn/aAttributionItem.Type.ASIDPrivacy friendly App Set Id (Android 12+)
ANDROID_IDn/aAttributionItem.Type.AIDUnique to each combination of app-signing key, user, and device

// set single attribution attribute
Glassfy.setAttribution(type: .IDFA, value: "device_idfa") { err in
    //    [...]
}

// set attributions in block

var attributions: [Glassfy.AttributionItem] = []
attributions.append(Glassfy.AttributionItem(type: .IDFV, value: "xxx"))
attributions.append(Glassfy.AttributionItem(type: .IDFA, value: "yyy"))
Glassfy.setAttributions(attributions) { err in
    //    [...]
}
Glassfy.setAttribution(AttributionItem.Type.GAID, "bebe511e-ae2a-72ef-1756") { err ->
            // handle error
        }

val items = listOf(
    AttributionItem(AttributionItem.Type.AdjustID, "1234"),
    AttributionItem(AttributionItem.Type.IP, "0.0.0.0"),
    AttributionItem(AttributionItem.Type.AppsFlyerID, "1234567"),
)

                                                                              
Glassfy.setAttributions(items) { err ->
    // handle error
}
await Glassfy.setAttribution(GlassfyAttribution.AppsFlyerID, "1234567");
final attributions = [
   GlassfyAttributionItem(GlassfyAttribution.AdjustID, "1234"),
   GlassfyAttributionItem(GlassfyAttribution.IP, "0.0.0.0")
];
await Glassfy.setAttributions(attributions);
await Glassfy.setAttribution({ type: GLASSFY_ATTRIBUTION.AppsFlyerID, value: "56j4jkjk458989" });

const items: GlassfyAttributionItem[] = [
  {
    type: GLASSFY_ATTRIBUTION.GAID,
    value: "my_gaid"
  },
  {
    type: GLASSFY_ATTRIBUTION.AdjustID,
    value: "my_Adjust"
  },
]

await Glassfy.setAttributions({ items: items })

await Glassfy.setAttribution(GLASSFY_ATTRIBUTION.AppsFlyerID, value: "56j4jkjk458989");

const items: GlassfyAttributionItem[] = [
  {
    type: GLASSFY_ATTRIBUTION.GAID,
    value: "my_gaid"
  },
  {
    type: GLASSFY_ATTRIBUTION.AdjustID,
    value: "my_Adjust"
  },
]

await Glassfy.setAttributions( items );

Purchase History

Retrieve user's purchase history.

Read the PurchaseHistory object documentation for more details.

Glassfy.purchaseHistory { history, err in
    guard let history else { return }
    let latestPurchase = history.all
        .sorted { $0.purchaseDate > $1.purchaseDate }
        .first
}
[Glassfy purchaseHistory:^(history, err) {
    if (history) {
        NSArray *allPurchases = [history all];
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"purchaseDate" ascending:NO];
        NSArray *sortedPurchases = [allPurchases sortedArrayUsingDescriptors:@[sortDescriptor]];
        GYPurchaseHistory *latestPurchase = [sortedPurchases firstObject];
        // Do something with the latestPurchase object
    } else {
        // Handle the error
    }
}];
Glassfy.purchaseHistory { history, err ->
    if (history != null) {
        val allPurchases = history.all
        val sortedPurchases = allPurchases.sortedByDescending { it.purchaseDate }
        val latestPurchase = sortedPurchases.firstOrNull()
        // Do something with the latestPurchase object
    } else {
        // Handle the error
    }
}
const { history, err } = await Glassfy.purchaseHistory();
if (history) {
  const allPurchases = history.all;
  const sortedPurchases = allPurchases.sort((a, b) => b.purchaseDate - a.purchaseDate);
  const latestPurchase = sortedPurchases.length > 0 ? sortedPurchases[0] : null;
  // Do something with the latestPurchase object
} else {
  // Handle the error
}
const { history, err } = await Glassfy.purchaseHistory();
if (history) {
  const allPurchases = history.all;
  const sortedPurchases = allPurchases.sort((a, b) => b.purchaseDate - a.purchaseDate);
  const latestPurchase = sortedPurchases.length > 0 ? sortedPurchases[0] : null;
  // Do something with the latestPurchase object
} else {
  // Handle the error
}

Connect Paddle License Key

Connect a Paddle License Key to the current subscriber

Read the Paddle License Key documentation for more details.

do {
    try await Glassfy.connectPaddle(licenseKey: license, force: false)
    print("Connected \(license)")
} catch {
    print("Failed to connect license key: \(error)")
}
[Glassfy connectPaddleLicenseKey:licenseKey
                           force:force
                      completion:^(NSError *error) { 
                      // Handle errors
                      }];
Glassfy.connectPaddleLicenseKey(licenseKey, force) { error ->
    // Handle error
}
try {
    await Glassfy.connectPaddleLicenseKey(licenseKey, force);
    console.log(`Connected ${licenseKey}`);
} catch (error) {
    console.log(`Error connecting license key ${error}`);
}
try {
    await Glassfy.connectPaddleLicenseKey({ licenseKey: license, force: true });
    console.log(`Connected ${licenseKey}`);
} catch (error) {
    console.log(`Error connecting license key ${error}`);
}
await Glassfy.connectPaddleLicenseKey(license, true);

Connect Glassfy Universal Code

Connect a Glassfy Universal Code to the current subscriber

Read the Universal Codes documentation for more details.

Please note to connect the universal code the subscriber must have a customID setup (see above)

do {
    try await Glassfy.connectGlassfy(universalCode: code, force: false)
    print("Connected \(code)")
} catch {
    print("Failed to connect universal code: \(error)")
}
[Glassfy connectGlassfyUniversalCode:universalCode
                               force:force
                          completion:^(NSError *error) { 
                          // Handle errors
                          }];
Glassfy.connectGlassfyUniversalCode(universalCode, force) { error ->
    // Handle error
}
try {
    await Glassfy.connectGlassfyUniversalCode(universalCode, force);
    console.log(`Connected ${universalCode}`);
} catch (error) {
    console.log(`Error connecting universal code ${error}`);
}
try {
    await Glassfy.connectGlassfyUniversalCode({ universalCode: universalCode, force: true });
    console.log(`Connected ${universalCode}`);
} catch (error) {
    console.log(`Error connecting universal code ${error}`);
}
await Glassfy.connectGlassfyUniversalCode(universalCode, true);