Purchases and User Info

SDK configuration to send purchases info to Appflow.ai


Ready to work

a. Configure product information in apple store

b. Add product information in appflow.ai platform

Product id

Get product id of iOS in-app purchase

Appflow.shared.getPurchaseProductIds { productIdArray, error in 
 
 }

API Reference

getPurchaseProductIds

error = nil

Success callback

error != nil

Failure callback

error: Error

code

error code

message

error message

Parameter returned: data typeInstructions

productIdArray: [string]

Returns the Appflow.ai platform configuration ProductID

Product SKU

Get the sku information of in-app purchases

Displaying products to fetch the Products sku information, you have to call method:

According to the interface getSkuDetails, you need to pass in the Set <product_Ids> of in-app purchases, the return value is a dictionary, product_id is key, value: SKProduct object

Appflow.shared.getSkuDetails(productIds: Set(productIDs)) { skuDetailInfo, error in
    
};

API Reference

getSkuDetails

error = nil

Success callback

error != nil

Failure callback

error: Error

code

error code

message

error message

Request parameter: data typeInstructions

productIds: Set

The parameter is the product ID configured in the Apple background

Returned parameter: data typeInstructions

skuDetailInfo: [String:SKProduct]

key - value, Return SKProduct

After obtaining SKProduct, you can obtain information related to in-app purchases, and developers can save them in their own projects. Subsequent payment needs to be used. SKProduct, please refer to the official documentation of Apple

Check if payment is available

let canMakePurchases = Appflow.shared.canMakePayment()

This interface returns data of type 'bool'. True: indicates that payment can be pulled up. False: indicates that payment cannot be pulled up

Making Purchase

To start the purchase process call function purchaseProduct it will take SKProduct object as a parameter.

NOTE

After the in-app purchase is completed, uploadUserInfo must be reported, which is mainly used for user data attribution.

If the developer has integrated the purchase method of AppflowSDK (Appflow.shared.purchaseSKProduct). There will be no need to process and report user information after subscription, this step has been completed automatically, (versions after V1.0.7 will be automatically reported, and versions before V1.0.7 need to be manually reported by developers) If the developer does not integrate the method of purchasing goods in AppflowSDK, the developer will need to manually handle it. After the user completes the purchase, use this method uploadUserInfo to report the user information, where UserId is not a mandatory parameter

// After V1.0.7, it will be automatically reported after subscription
Appflow.shared.purchaseSKProduct(skProduct) { transaction, subscriber, error, canceled in
    if canceled || error != nil {
        print("Canceled")
    } else {
        print("Completed")
    }
}

// Before V1.0.7, the subscription must be reported manually, otherwise it will lead to data loss
Appflow.shared.purchaseSKProduct(skProduct) { transaction, subscriber, error, canceled in
    if canceled || error != nil {
        print("Canceled")
    } else {
        // Manually report user information after subscription is complete
        Appflow.shared.uploadUserInfo()
    }
}

Note

Closure will return SKPaymentTransaction, entitlement dictionary, error if it occurred and bool to indicate if a user canceled the purchase process.

Users can use IMSubscriber.isActive to determine the subscription status. true: subscribed\purchased; false: unsubscribed\unpurchased IMSubscriber.expireAt, Return the expiration time of the current subscription. You can compare expireAt with the current time and process the subscription status

API Reference

purchaseSKProduct

error = nil

Success callback

error != nil

Failure callback, Note: A user's subscription status cannot be determined by ERROR.Please use:isActive or expireAt

error: Error

code

error code

message

error message

Request parameter: data typeInstructions

product: SKProduct

Product information

Returned parameter: data typeInstructions

transaction: SKPaymentTransaction

An object in the payment queue. [SKPaymentTransaction

isCanceled: Bool

Cancel the payment

entitlement: IMSubscriberinstructions

productId: String

product id

expireAt: Int64

Expiration time of the subscription (millisecond)

isActive: Bool

product subscription\purchase status, true: subscribed\purchased; false: unsubscribed\unpurchased

imEntitlement: [IMEntitlement]

check entitlement for current status

imSubscription: [IMSubscription]

subscription details by product_id

IMEntitlementInstructions

id: String

product group id

expireAt: Int64

Expiration time of the subscription (millisecond)

isActive: Bool

product subscription\purchase status, true: subscribed\purchased; false: unsubscribed\unpurchased

productId: String

product id

IMSubscriptionproduct Id

status: IMSubscriberStatus

SubscriptionState_State

expireAt: Int64

Expiration time of the subscription (millisecond)

cancelAt: Int64

Time to unsubscribe (millisecond)

willRenewTo: String

The next subscription ID to switch: Product ID

originalTransactions:

[IMSubscriptionOriginalTransaction] Original transactions

IMSubscriptionproduct Id

originalTxid: String

Original order note

expireAt: Int64

Expiration time of the subscription (millisecond)

startAt: Int64

Time to start the subscription (millisecond)

Checking User Status

To check if user has any active entitlements call function hasActiveSubscription

Appflow.shared.hasActiveSubscription({ [weak self] subscriber, error in
    guard let `self` = self else { return }
    var status = "pro not active"
    if error == nil {
        if subscriber.isActive {
            status = "pro active"
        }
        self.statusLabel.text = "Subcription status: \(status)"
    }
})

Users can use IMSubscriber.isActive to determine the subscription status. true: subscribed\purchased; false: unsubscribed\unpurchased IMSubscriber.expireAt, Return the expiration time of the current subscription. You can compare expireAt with the current time and process the subscription status

Restoring Purchases

To restore user purchases call restorePurchases function.

Appflow.shared.restorePurchases { (subscriber, error) in
    if error == nil {
        if subscriber.isActive {
            // Purchase restored and have active entitlment
        }else {
            // Purchase restore finished but user don't have active entitlment
        }
    }
}

Users can use IMSubscriber.isActive to determine the subscription status. true: subscribed\purchased; false: unsubscribed\unpurchased IMSubscriber.expireAt, Return the expiration time of the current subscription. You can compare expireAt with the current time and process the subscription status

Upload User Info

Introduction: If you need to associate the userId in your application with the Appflow platform, then the developer needs to choose an appropriate time to report userId to the Appflow platform, for example, when your application logs in. Where useId is the unique identifier defined in the App.

Appflow.shared.uploadUserInfo(userId: "xxx") { _, _ in   }

expand

Add a json string field in the UploadUserInfo API to support developers uploading map<string, string> type data. It supports fixed fields: username, email, phone, gender, age.

  • Field:

  • All key , value length limit is 128 , calculated according to toString characters

  • The fixed fields are username, email, phone, gender, age, please refer to the table below, gender is a number, and the meaning is shown in the table

  • There are no restrictions on the type of additional fields added by the user, both numbers and strings can be used

  • If you need to report user-related data, report it through the following methods

fieldtype

username

string

email

string

phone

string

gender

number(FEMALE = 1, MALE = 2, OTHER = 3)

age

number

//uploadUserInfo to extraAttribute
Appflow.shared.uploadUserInfo(userId: "app_user_idxxxxx", extraAttribute: extraAttribute) {[weak self] _, _ in
}

Last updated