Skip to content

iOS SDK FAQs

1. Common Issues During Integration

1.1 What is the minimum configuration to integrate the SDK?

Answer: The FinClip Mini Program SDK supports iOS 9 and above. Versions lower than iOS 9 are not supported.

1.2 Does it support bitcode?

Answer: Versions prior to 2.34.5 do not support bitcode. It is supported from version 2.34.5 onwards (including 2.34.5). Support for bitcode was removed starting from version 2.36.13.

1.3 The project reports an error, saying a certain category method cannot be found. What should I do?

Answer: This is because -ObjC was not configured. The SDK creates a Category, so you need to add -ObjC in Other Linker Flags under Build Setting.

1.4 What parameters must be configured when initializing the SDK?

Answer: For SDK versions lower than 2.34.1, sdkSecret, sdkKey, apiServer, and apiPrefix must all be configured. For SDK versions greater than or equal to 2.34.1, we have optimized it by removing apiPrefix, thus sdkSecret, sdkKey, and apiServer are required.

objective-c
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"Enter your SDK Key here";
storeConfig.sdkSecret = @"Enter your SDK secret here";
storeConfig.apiServer = @"Enter your server address here"; // Example: https://api.finclip.com;
storeConfig.apiPrefix = @"/api/v1/mop"; // apiPrefix is not required for versions above 2.34.1
FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];

[[FATClient sharedClient] initWithConfig:config error:nil];

Additionally, if currentUserId is configured, data will be cached in that directory, facilitating data loading for different accounts during account switching.

1.5 Why do the registered custom Mini Program APIs not work?

Answer: When registering custom APIs, we check whether the Mini Program SDK has been initialized successfully. If it has not initialized successfully, then the registration of the custom APIs will not succeed.

Therefore, ensure that the Mini Program is successfully initialized before registering custom APIs.

1.6 Does the Mini Program support landscape or forced landscape mode?

Answer: Yes.

To enable landscape and portrait switching for the Mini Program, check the options of Portrait, Landscape Left, and Landscape Right under General -> Deployment Info -> Device Orientation in the iOS project settings.

Then, configure [pageOrientation] in the Mini Program's app.json file. Its value can be one of: auto / portrait / landscape.

Alternatively, you can also set [pageOrientation] in the corresponding json configuration of each page.

For iPads, to allow the device to support switching between landscape and portrait modes, set resizable in app.json. The value is of boolean type.

1.7 How to configure the number of Mini Programs for batch update in the SDK?

Answer: In FATConfig, there is a property called appletIntervalUpdateLimit, which defaults to 3. This means that during background version checks, it will only check the three most recently used Mini Programs. You can modify appletIntervalUpdateLimit when initializing the SDK, with a range from 0 to 50.

1.8 How to try the major version of the SDK?

Answer: Some functions may affect existing modules, so we have placed them in the major version of the SDK. Users who need these features can integrate the major SDK in advance for trial or early development of their Mini Programs.

The major version of the SDK may include some features that are not thoroughly tested and have unstable performance. There are two ways to experience the major version SDK: manual integration and pod integration.

For manual integration, follow the same procedure as the stable version: download the SDK, add it to your project, modify the project settings, etc., which will not be elaborated here.

Regarding pod integration, here are the key points! Due to the instability of the major version, it cannot be uploaded to the cocoa pods source, so we have uploaded the major version SDK to our own repository source. The steps are as follows:

1. Add FinClip repository source

source 'https://git.finogeeks.com/cocoapods/FinPods'

Note: If you haven't added a cocoa pods source in your previous podfile, you need to add it.

# Add one of the following sources as per your actual situation
source 'GitHub - CocoaPods/Specs: The CocoaPods Master Repo'
source 'https://cdn.cocoapods.org/'

2. Specify SDK version in the podfile

pod 'FinApplet', '2.37.0-alpha20220416v03'
pod 'FinAppletExt', '2.37.0-alpha20220416v03'

3. pod install Install the dependencies or update them using pod update.

2. Common Issues During Use

2.1 How to start the Mini Program?

Answer: Just call the following API:

objective-c
[[FATClient sharedClient] startRemoteApplet:appId startParams:startParams InParentViewController:viewController completion:^(BOOL result, NSError *error) {
        NSLog(@"result:%d---error:%@", result, error);
}];

2.2 Are there common error codes and troubleshooting methods for when the Mini Program fails to open?

Answer: The following are the 8 common error messages encountered when failing to open a Mini Program:

  1. appId or appTitle is nil. This is due to not configuring appId when starting the Mini Program, or not configuring the Mini Program name while editing basic information in the background.
  2. copyResources failed. This occurs when moving the downloaded Mini Program package or base library package to the running directory fails. This is often due to issues with the compiled Mini Program zip package or base library zip package.
  3. service.html not found! This indicates that the service.html is missing in the compiled Mini Program zip package, which might be caused by problems in the compilation process.
  4. copy app file failed! This occurs when moving the downloaded Mini Program zip package to the cache directory fails. Such issues are rare.
  5. Service exception, failed to obtain Mini Program details. This usually indicates a failure in calling the API to obtain Mini Program details, often due to issues in the backend service or Mini Program configuration. Remember to check that apiPrefix is configured correctly as api/v1/mop.
  6. Cooperation terminated. This situation generally occurs when the management backend terminates cooperation with the corresponding application (related to this bundleId). For specifics, please consult the open platform or backend administrator.
  7. Service unavailable. This generally occurs when the Mini Program has not yet been associated with an application or when there are issues in the backend.
  8. Service exception, returning abnormal Mini Program detail data. This usually indicates an error in the backend service, resulting in invalid return data format.

2.3 How to add WeChat sharing functionality to the Mini Program?

Answer: There are three main methods:

  1. Change the forward functionality to WeChat sharing;
  2. Create a custom WeChat sharing interface and have the Mini Program call it.
  3. Directly reference the sharing SDK, you can search with integration SDK documentation**

2.3.1 Change the forward functionality to WeChat sharing

The FinClip Mini Program SDK will pass the forwarding event through the delegate, so you only need to set an implementing object for [FATClient sharedClient].buttonOpenTypeDelegate.

Then, you can obtain the forwarding information in the following delegate method:

objective-c
/** Forwarding event
 When you click the forward menu in the upper right corner of the Mini Program, the shareAppMessage method in the Mini Program will be triggered, which then calls back to the native method
 @param contentInfo Relevant information about the Mini Program, which contains the Mini Program ID, name, icon, and screenshot (5:4), etc.
 {
    appAvatar = "Mini Program icon URL";
    appDescription = "Mini Program description";
    appId = "Mini Program ID";
    appInfo =  {}; // Users can customize fields in appInfo; the content will be forwarded.
    appStartParams =     {
        path = "The path of the Mini Program page when clicked to forward";
    };
    appThumbnail = "URL/path of the Mini Program cover image, which can be a web or local path with an aspect ratio of 5:4";
    appTitle = "Mini Program name";
    userId = "Mini Program developer ID";
}
 @param completion Callback executed after completion; if you wish to inform the Mini Program of the forwarding result after the forwarding operation, you need to call this block.
 */
- (BOOL)forwardAppletWithInfo:(NSDictionary *)contentInfo completion:(void (^)(FATExtensionCode code, NSDictionary *result))completion;

Here, appInfo is a new attribute added to onShareAppMessage, allowing various key-value pairs to be defined.

Finally, simply call the WeChat sharing SDK's interface to share the Mini Program.

2.3.2 Create a custom WeChat sharing interface and have the Mini Program call it.

Since the FinClip Mini Program SDK allows for the customization of Mini Program APIs, you can first define a sharing API. After initializing the Mini Program SDK, you can register a Mini Program API like so:

objective-c
    [[FATClient sharedClient] registerExtensionApi:@"shareToWechat" handle:^(id param, FATExtensionApiCallback callback) {
       // Here you can get param, which is the object passed in from the Mini Program.

       // Then call the WeChat sharing interface to share.

        callback(FATExtensionCodeSuccess, nil);
    }];

Simultaneously, create the FinClipConf.js file in the root directory of the Mini Program with the following sample configuration:

objective-c
module.exports = {
  extApi:[
    { // Standard interaction API
      name: 'shareToWechat', // Name of the extended API which must be implemented by the Native side
      params: { // Parameter format for the extended API; you can list only the necessary attributes
        path: '',
        title: '',
        description: ''
      }
    }
  ]
}

Finally, call the custom WeChat sharing interface in the Mini Program:

objective-c
ft.shareToWechat

2.4 Why can't the request, uploadFile, or downloadFile interfaces be called? There is no trace of the interface call in the packet capture.

Answer: If the three interfaces above cannot be called, you will generally see the error message: url not in domain list.

This is because the domain name for the Mini Program was not configured in the backend. The method for configuring domain names is similar to that of WeChat, and domain names for request/uploadFile/downloadFile need to be configured separately.

Answer: If you receive the message non-business domain xxxxxxx cannot be opened, please reconfigure when using webView to open a link, this is because the business domain needs to be configured in the management platform. This business domain is the domain for loading links in the webView.

2.6 How to set the transition animation style when starting the Mini Program?

Answer: Currently, there are two animation styles available when starting the Mini Program:

  1. Present style;
  2. Similar to a push animation style.

You can set transitionStyle when calling the following start function. The enumeration values available are: FATTranstionStyleUp, FATTranstionStylePush.

objective-c
[[FATClient sharedClient] startRemoteApplet:appId startParams:appStartParams InParentViewController:self transitionStyle:FATTranstionStyleUp completion:^(BOOL result, NSError *error) {
    NSLog(@"result:%d---error:%@", result, error);
}];

2.7 How to register a custom Mini Program API?

Answer: Please search with iOS Custom Mini Program API Registration for the relevant operations.

2.8 How to get a screenshot of the current page of the Mini Program?

Answer: Call the following function to get a screenshot of the current page of the Mini Program (the screenshot is in 5:4 ratio).

objective-c
UIImage *coverImage = [[FATClient sharedClient] getCurrentAppletImage];

2.9 Does the more button menu at the upper right of the Mini Program support customization? If yes, how to implement it?

Answer: Yes.

You need to implement two delegate methods. First, create a custom class FATClientHelper that implements the FATAppletMoreMenuDelegate protocol.

objective-c
#import <Foundation/Foundation.h>
#import <FinApplet/FinApplet.h>

@interface FATClientHelper : NSObject<FATAppletMoreMenuDelegate>

+ (instancetype)shareInstance;

@end

Then, after the SDK initializes successfully, set the SDK's delegate to the FATClientHelper object.

Sample code:

objective-c
[[FATClient sharedClient] initWithConfig:config error:nil];

[FATClient sharedClient].moreMenuDelegate = [FATClientHelper shareInstance];

Finally, implement the following protocol method in FATClientHelper:

objective-c
// Return the menu objects to be injected, which must implement the FATAppletMenuProtocol protocol
// There are two types of menu objects (Common type by default):
// 1. OnMiniProgram type: requires backend configuration + Mini Program configuration, displays a collection of menus with the same menuId
// 2. Common type: displayed when configured
// PS: This is compatible with older versions. If the backend has not been upgraded, or if it has been upgraded and not configured, ensure that the menuId of the menu object is of type NSString.

- (NSArray<id<FATAppletMenuProtocol>> *)customMenusInApplet:(FATAppletInfo *)appletInfo atPath:(NSString *)path
{
    FATCustomMenuModel *favModel1 = [[FATCustomMenuModel alloc] init];
    favModel1.menuId = @"WXShareAPPFriends";
    favModel1.menuTitle = @"Share to WeChat Friends";
    favModel1.menuIconImage = [UIImage imageNamed:@"minipro_list_wx_chat"];
    favModel1.menuType = FATAppletMenuStyleOnMiniProgram;

    FATCustomMenuModel *favModel2 = [[FATCustomMenuModel alloc] init];
    favModel2.menuId = @"WXShareAPPMoments";
    favModel2.menuTitle = @"Share to WeChat Moments";
    favModel2.menuIconImage = [UIImage imageNamed:@"minipro_list_wx_monents"];
    favModel2.menuType = FATAppletMenuStyleOnMiniProgram;

    FATCustomMenuModel *favModel3 = [[FATCustomMenuModel alloc] init];
    favModel3.menuId = @"Restart";
    favModel3.menuTitle = @"Restart";
    favModel3.menuIconImage = [UIImage imageNamed:@"minipro_list_restart"];
    favModel3.menuType = FATAppletMenuStyleCommon;

    return @[favModel1, favModel2, favModel3];
}

// Event when the custom menu is clicked (old version, used when the backend is not upgraded or not configured after the upgrade)
- (void)customMenu:(id<FATAppletMenuProtocol>)customMenu inApplet:(FATAppletInfo *)appletInfo didClickAtPath:(NSString *)path
{
    NSLog(@"Clicked on %@", customMenu.menuTitle);
    NSLog(@"path = %@", path);
}

// Event when the custom menu is clicked (new version, used when backend and Mini Program are configured)
- (void)clickCustomItemMenuWithInfo:(NSDictionary *)contentInfo completion:(void (^)(FATExtensionCode, NSDictionary *))completion
{
    /**
    contentInfo contains
    {
         @"title": @"title",
         @"description": @"description",
         @"imageUrl": @"image path",
         @"path": @"the path of the Mini Program page when clicked",
         @"menuId": @"identifier of the clicked menu button",
         @"params": self.params     // Original parameter data provided by the Mini Program
    }
    */
    // Callback from the Mini Program to inform it of the click event handling status
    completion(FATExtensionCodeSuccess, contentInfo);
}

2.10 Does the Mini Program support completely hiding the navigation bar on certain pages? If yes, how to implement it?

Answer: Yes.

Similar to WeChat, Alipay, and Baidu Mini Programs, the navigationStyle can have two values: default/custom. The FinClip Mini Program SDK adds a new value hide, resulting in three values: default/custom/hide.

Therefore, to hide the navigation bar on the desired page, set the navigationStyle to hide.

2.11 How to set custom rules for a Canary Release?

Answer: The Mini Program SDK includes a protocol method in FATAppletConfigurationDelegate:

objective-c
- (NSDictionary *)grayExtensionWithAppletId:(NSString *)appletId

Implement this protocol method.

Sample code:

objective-c
/// Mini Program Canary Release Extension Parameters
/// @param appletId Mini Program ID
- (NSDictionary *)grayExtensionWithAppletId:(NSString *)appletId
{
    NSDictionary *grayExtension = @{@"key1":@"value1"};
//    if ([appletId isEqualToString:@"5e017a61c21ecf0001343e31"]) {
//        grayExtension = @{@"fckey1":@"fcvalue1"};
//    }
    return grayExtension;
}

The Mini Program SDK will call this protocol method to obtain the Canary extension parameters when loading the Mini Program, which will be forwarded to the backend service for matching relevant rules.

Note

Since the FinClip Mini Program does not provide a user system, when creating a Canary Release and selecting "Release to Specified Users", you need to pass the user information from the app to the Mini Program via custom API. The Mini Program can only release to specified users when user IDs are passed via custom APIs (the default rule ID is xUserId).

2.12 What to do if the Mini Program fails to load a webpage?

Answer: If the Mini Program fails to load a webpage, you can enable the SDK's log log switch. Error information will also be returned in the webView's binderror callback.

For example, if you see the following error message:

objective-c
Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection."

This analysis indicates that the network address uses the HTTP protocol. You need to configure Allow Arbitrary Loads to YES in the app project’s info.plist under App Transport Security Settings.

2.13 Does the Mini Program SDK support adapting to dark mode?

Answer: Yes.

When the Mini Program SDK is initialized, in the FATUIConfig class, there is a property that can be set: uiconfig.autoAdaptDarkMode = YES;. The dark mode adaptation in the Mini Program SDK includes the More menu page, about page, and feedback page. The color of the Mini Program's navigation bar is not affected by dark mode.

2.14 Does the Mini Program SDK support disabling permission requests?

Our APP is a financial app, and controlling permissions, especially sensitive permissions (like location), is very important. We hope that the SDK does not actively request permissions, but rather that the APP requests them at appropriate times. Is this possible?

Answer: Yes.

The Mini Program SDK's config class has a property disableAuthorize that can control the requesting of permissions.

If this property is not configured or set to NO, when the Mini Program SDK uses permissions that have not yet been authorized by the user, it will ask the user for permission; if this property is set to YES (config.disableAuthorize = YES;), then when the Mini Program SDK requires an API that has not yet been authorized by the user, it will return failure in the API failure callback, with errMsg containing the reason for failure (e.g., chooseImage:fail indicates no access to the gallery).

Additionally, the config class of the Mini Program SDK also has a property appletAutoAuthorize, which controls the Mini Program's requests for permissions from the SDK. If this property is not configured or set to NO, when a user needs to use a specific permission in the Mini Program, a prompt asking for user authorization will pop up. If the user agrees, the Mini Program will request permission from the SDK; if the user refuses, it will not request permission from the SDK and will return failure, with errMsg containing the reason for failure (e.g., chooseImage:fail indicates no access to the gallery); if this property is set to YES, it indicates that permission will be automatically requested from the SDK without prompting.

2.15 Is it possible to replace the return button icon? How to replace it?

Answer: Yes.

Just place a png image in the project and name it fin_btn_navi_back, ensuring it is accessible through the main bundle.

2.16 Does it support opening Safari within the Mini Program?

Answer: Yes.

Although our SDK does not have the API to open the mobile Safari and load a specific URL, the SDK supports registering custom APIs, so by injecting a custom H5 API, this functionality can be achieved. Since there are two scenarios for injecting custom APIs—registering APIs for Mini Programs and registering APIs for H5 in Mini Programs—the SDK provides separate functions for these two scenarios, and their handling processes differ, so they will be discussed separately.

Opening Safari in H5 within the Mini Program First, after initializing the SDK, register a custom API with the following code snippet:

objective-c
[[FATClient sharedClient] fat_registerWebApi:@"openInSafari" handle:^(id param, FATExtensionApiCallback callback) {
    NSString *url = param[@"url"];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];

    callback(FATExtensionCodeSuccess, nil);
}];

Then, include the FinClip Mini Program jssdk in your H5 page.

Finally, call the registered custom API within the logic of the H5:

objective-c
window.FinChatJSBridge.invoke('openInSafari', {url:'https://www.finclip.com'}, (result) => {
    console.log(result)
});

Opening Safari from the Mini Program First, register a custom API for the Mini Program as follows:

objective-c
[[FATClient sharedClient] registerExtensionApi:@"openInSafari" handle:^(id param, FATExtensionApiCallback callback) {
    NSString *url = param[@"url"];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];

    callback(FATExtensionCodeSuccess, nil);
}];

Then, in the root FinClipConf.js file of the Mini Program, configure the custom API.

objective-c
module.exports = {
  extApi:[
    {
      name: 'openInSafari',
      params: {
        url: ''
      }
    }
  ]
}

Finally, you can call this custom API in the Mini Program:

objective-c
ft.openInSafari({
    url:'https://www.baidu.com',
    success: function (res) {
        console.log("startRecord success");
        console.log(res);
    },
    fail: function (res) {
        console.log("startRecord fail");
        console.log(res);
    }
});

2.17 Is it possible to get the launch parameters for the Mini Program? How to obtain it?

Answer: Yes. However, the Mini Program can only obtain the query parameters from the launch parameters.

The parameters in the query will be converted to JSON, which can be accessed in the Mini Program's lifecycle events onLaunch(options) and onShow(options) through the options.

For example, if the Mini Program is launched with the following parameters:

objective-c
    NSDictionary *startParam = @{
        @"query":@"key1=value1&key2=value2",
        @"path":@"pages/showToast/showToast"
    };
    [[FATClient sharedClient] startRemoteApplet:@"afdfddfdfdf" startParams:startParam InParentViewController:self completion:nil];

Then the startup parameters can be accessed in the lifecycle events of the Mini Program:

objective-c
onLaunch(options) {
    console.log("App onLaunch =====>" + JSON.stringify(options))
    //options.query.key1
    //options.path
},

 onShow(options) {
    // Do something when show.
    console.log("App onShow =====>" + JSON.stringify(options))
    //options.query.key1
    //options.path
  },

2.18 Can the SDK set the UserAgent? How to set it?

Answer: Yes.

In FATUIConfig, there is a configuration item appendingCustomUserAgent. The content you set will be appended to the userAgent of the webView corresponding to the Mini Program page.

Example:

objective-c
FATUIConfig *uiConfig = [[FATUIConfig alloc] init];//[FATClientHelper uiConfig];
uiConfig.progressBarColor = [UIColor redColor];
// Add userAgent content
uiConfig.appendingCustomUserAgent = @"custom agent";

[[FATClient sharedClient] initWithConfig:config uiConfig:uiConfig error:nil];

2.19 How to implement third-party login in the Mini Program?

1. Integrate the FinClip Mini Program SDK

The developer first needs to integrate the FinClip Mini Program SDK. For the integration guide, please search with FinClip Mini Program Open Platform iOS Integration Documentation. The Open Platform has detailed iOS integration documentation, so it won't be elaborated here.

2. Customize Mini Program interfaces to realize authorization login, obtain user information, check login status, etc.

To enable the Mini Program to access data outside the Mini Program, it is essential to register custom interfaces. The details on creating custom interfaces can be search with FinClip Mini Program Open Platform - Custom Mini Program Interfaces. The parameters in the example below are determined by the developer and are just for illustration.

  • Custom login interface for authorization
objective-c
@property (nonatomic,strong) FATExtensionApiCallback callBack;

[[FATClient sharedClient] registerExtensionApi:@"login" handle:^(id param, FATExtensionApiCallback callback) {
  self.callBack = callback;
  // Proceed with third-party login.
  [self thirdLogin];
}];

- (void)thirdLogin {
  // To Do: Handle third-party login logic. After obtaining the result, callback the information you want to send to the Mini Program, the developer can determine what information is sent, FinClip only facilitates passing, and will not save it.

  // For example, reference the documentation for WeChat third-party login: https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Development_Guide.html

  self.callBack(FATExtensionCodeSuccess, @{@"code": @"success", @"openid": @"XXXXXXXXXXXXXXXXX"});
}
  • Custom getUserProfile interface for obtaining user information
objective-c
[[FATClient sharedClient] registerExtensionApi:@"getUserProfile" handle:^(id param, FATExtensionApiCallback callback) {
    NSDictionary *userInfo = @{@"nickName": @"Zhang San", @"avatarUrl": @"", @"gender": @1, @"country": @"China", @"province": @"Guangdong", @"city": @"Shenzhen",@"language": @"zh_CN"};
    NSDictionary *resDic = @{@"userInfo": userInfo};
    callback(FATExtensionCodeSuccess, resDic);
}];
  • Custom checkSession interface for verifying user tokens
objective-c
[[FATClient sharedClient] registerExtensionApi:@"checkSession" handle:^(id param, FATExtensionApiCallback callback) {
  // For Example
  if ([param[@"code"] intValue] == 1) {
      // To Do something
  }
}];

2.20 Is it possible to replace the text "Mini Program" in the SDK with another name?

Answer: Yes.

The FATUIConfig class contains a configuration item appletText, and the content you set will replace the original text "Mini Program".

Example:

objective-c
FATUIConfig *uiConfig = [[FATUIConfig alloc] init];//[FATClientHelper uiConfig];
// Replace "Mini Program" with "x App"
uiConfig.appletText = @"x App";

[[FATClient sharedClient] initWithConfig:config uiConfig:uiConfig error:nil];

2.21 Will the SDK compress the reported data during reporting?

Answer: By default, the SDK does not compress the reported data. If you want to enable compression, you can do so by setting the enableApmDataCompression parameter to YES during SDK initialization.

Example:

objective-c
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"Enter your SDK Key here";
storeConfig.sdkSecret = @"Enter your SDK secret here";
storeConfig.apiServer = @"Enter your server address here"; // Example: https://api.finclip.com;
FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];
config.enableApmDataCompression = YES;

2.22 Does it support disabling the Mini Program API for obtaining supervision information?

Answer: Yes.

By default, the SDK allows the Mini Program to call the API to obtain supervision information (getSuperviseInfo). If you want to disable it, you can set disableGetSuperviseInfo to YES during SDK initialization.

Example:

objective-c
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"Enter your SDK Key here";
storeConfig.sdkSecret = @"Enter your SDK secret here";
storeConfig.apiServer = @"Enter your server address here"; // Example: https://api.finclip.com;
FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];
config.disableGetSuperviseInfo = YES;

After disabling, the Mini Program will receive a callback: getSuperviseInfo:fail disabled when calling getSuperviseInfo.

2.23 Does it support opening the experience version of the Mini Program?

Answer: Yes.

The platform supports configuring experience versions and experience members for the Mini Program. Members with experience permissions can open the experience version of the Mini Program.

Steps to use the experience version Mini Program:

  1. Upload the Mini Program on the platform and configure the experience version. For configuration details, search the Mini Program Development - Debugging.

  2. Pass the user ID during the SDK initialization:

objective-c
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"Enter your SDK Key here";
storeConfig.sdkSecret = @"Enter your SDK secret here";
storeConfig.apiServer = @"Enter your server address here"; // Example: https://api.finclip.com;
FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];
config.currentUserId = @"userId";

Only when the passed user ID is in the experience member list configured for the Mini Program can you open the experience version Mini Program; otherwise, when opening the Mini Program, it will prompt "No experience permission".

  1. Call the interface provided by the SDK to open the Mini Program. For interfaces, search the Open Mini Program via QR Code.

2.24 Does it support offline Mini Programs to improve the startup speed on the first launch?

Answer: Starting from version 2.35.1, it is possible to configure the file paths for the offline Mini Program package and the offline base library package. On the first launch, the local offline Mini Program will be opened while checking for updates to pull the latest version of the Mini Program in preparation for the next opening.

To obtain the offline Mini Program and offline library package, refer to the following image:

Sample code:

    FATAppletRequest *request = [[FATAppletRequest alloc] init];
    // You can get appletId from the Mini Program list on https://www.finclip.com/mop/mechanism/#/Applet/my
    request.appletId = @"61ee725a8bc99400018e1f7c";
    request.apiServer = @"https://api.finclip.com";
    // The offline Mini Program zip package can be downloaded from My Mini Programs -> Mini Program List -> Details -> Export Offline Package
    request.offlineMiniprogramZipPath = [[NSBundle mainBundle] pathForResource:@"hahahhah" ofType:@"zip"];
    // The offline base library can be downloaded from My Mini Programs -> Mini Program List -> Details -> Export Offline Package -> Mini Program Library
    request.offlineFrameworkZipPath = [[NSBundle mainBundle] pathForResource:@"framework-2.12.3" ofType:@"zip"];

    [[FATClient sharedClient] startAppletWithRequest:request InParentViewController:self.window.rootViewController completion:^(BOOL result, FATError *error) {
        NSLog(@"Opened Mini Program 11:%@", error);
    } closeCompletion:^{
        NSLog(@"Closed Mini Program 11");
    }];

2.25 Does it support using WebRTC features on iOS versions below 14.3?

Answer: It supports this. The platform implements WebRTC's related functionalities for iOS versions above 9 by repackaging the GoogleWebRTC library.

Steps to use it:

  1. Add the dependency for the WebRTC-SDK in the Podfile of your Xcode project:
bash
pod 'FinAppletWebRTC'
  1. Include the WebRTC-SDK header file:
objective-c
#import <FinAppletWebRTC/FinAppletWebRTC.h>
  1. Register the WebRTC component:
objective-c
// WebRTC initialization
[FATWebRTCComponent registerComponent]

After completing the above steps, you can call the WebRTC APIs provided by us in the Mini Program to implement the necessary functionalities.

2.26 What is the role of MapSDK and how to use it?

Answer: MapSDK supports the Map component and location APIs. It relies on the expanded SDK to supplement the map and location functionalities. The map and location capabilities depend on third-party map, positioning, and search SDKs. It supports both Gaode Map | Gaode Location and Baidu Map | Baidu Location, using whichever has been initialized last by default.

Steps to use:

  1. Add the dependency for MapSDK in your Xcode project's Podfile:
bash
// If you need to use Baidu Map SDK, add this extension SDK.
pod 'FinAppletBDMap'
// If you need to use Gaode Map SDK, add this extension SDK.
pod 'FinAppletGDMap'
  1. Include the MapSDK header file:
objective-c
// Likewise, if using Baidu Map, import this header file
#import <FinAppletBDMap/FinAppletBDMap.h>
// If using Gaode Map, import this header file
#import <FinAppletGDMap/FinAppletGDMap.h>
  1. Register the MapSDK component:
objective-c
// Prepare for Map SDK initialization
// If using Baidu Map, use this API to initialize
[FATBDMapComponent setBDMapAppKey:@"Your Application Key"]
// If using Gaode Map, use this API to initialize
[FATGDMapComponent setGDMapAppKey:@"Your Application Key"]
  1. Call the map component or location API in the Mini Program.

2.27 Why is FinClip Mini Program SDK a dynamic library? Can a static library be delivered?

Answer: Since Apple allowed third parties to create dynamic libraries, many third-party SDKs are now dynamic libraries. Using dynamic libraries can significantly reduce the size of the final executable file. To ensure minimal growth in app size, FinClip Mini Program SDK has consistently provided dynamic libraries. Additionally, given that customer apps vary widely and the third-party libraries they utilize differ, using static libraries could lead to various conflict issues during compilation or runtime. Due to the limited resources and focus of the FinClip R&D team, they cannot simultaneously maintain both static and dynamic libraries; hence only dynamic libraries are packaged during regular updates.

If you absolutely insist on needing a static library, we can accommodate this by packaging a static library separately. We have also written demo tests that successfully run the FinClip static library. However, if any conflicts or issues arise with the Host App, timely resolution cannot be guaranteed.

Furthermore, static libraries must be integrated manually, with the following steps:

1. Add SDK to the project

Of course, if you do not need the APIs from FinAppletExt.framework, you can skip adding FinAppletExt.framework and FinAppletExt.bundle.

Note

When manually integrating FinAppletBDMap (Baidu Map) or FinAppletGDMap (Gaode Map), you must manually add the bundle resource files from the framework (FinAppletBDMap.bundle or FinAppletGDMap.bundle) into the project.

2 Modify project configuration

1)Add dependencies for system dynamic libraries:

2)Add -ObjC in Build Settings -> Other Linker Flags.

Note

When manually integrating FinAppletBDMap (Baidu Map) or FinAppletGDMap (Gaode Map), the default embed type is set to Do Not Embed (TARFGETS --- General --- Frameworks, Libraries, and Embedded Content). When manually integrating Gaode Map, you must include the three libraries: AMap3DMap-NO-IDFA, AMapLocation-NO-IDFA, and AMapSearch-NO-IDFA while for Baidu Map, you must include BMKLocationKit, BaiduMapKit/Map, and BaiduMapKit/Search.

3 Open the project

Double-click xxxx.xcodeproj to open the project.

4 Configure archive script

The SDK includes an x86_64 architecture for easier debugging during development with the simulator. However, when packaging and uploading to the app market, an error will occur if an SDK with the x86_64 architecture is used. Therefore, a script is configured to automatically remove the simulator architecture during packaging, allowing development and debugging with the simulator while ensuring normal submission to the app market.

Of course, you can also request a version of the SDK that does not include the simulator.

The script contents are as follows:

objective-c
#!/bin/sh

# Strip invalid architectures

strip_invalid_archs() {
    binary="$1"
    echo "current binary ${binary}"
    # Get architectures for current file
    archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
    stripped=""
    for arch in $archs; do
        if ! [[ "${ARCHS}" == *"$arch"* ]]; then
            if [ -f "$binary" ]; then
                # Strip non-valid architectures in-place
                lipo -remove "$arch" -output "$binary" "$binary" || exit 1
                stripped="$stripped $arch"
            fi
        fi
    done
    if [[ "$stripped" ]]; then
        echo "Stripped $binary of architectures:$stripped"
    fi
}

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
    FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
    FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
    echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

    strip_invalid_archs "$FRAMEWORK_EXECUTABLE_PATH"
done

2.28 Does the Mini Program support customizing more menus?

Answer: Yes, it supports this feature.

By implementing the FATAppletMoreMenuDelegate method applet:(FATAppletInfo *)appletInfo didClickMoreBtnAtPath:(NSString *)path, a custom more menu can be presented.

objective-c
/**
 This event triggers when the 【...】 button in the top right corner is clicked, where you can show your designed more menu view.
 Therefore, when this delegate event is implemented, it will not trigger the following two custom menu events.
 @param appletInfo Mini Program Information
 @param path Mini Program page path, e.g., pages/index/index
 */
- (void)applet:(FATAppletInfo *)appletInfo didClickMoreBtnAtPath:(NSString *)path;

If you implement a custom more menu but wish to redirect users to settings, about, feedback, or want to implement forwarding functionality, you can achieve this through related APIs offered by FATMoreMenuHelper.

objective-c
/// Trigger forwarding event to obtain Mini Program information used for forwarding. Once obtained, the callback - (void)forwardAppletWithInfo:(NSDictionary *)contentInfo completion:(void (^)(FATExtensionCode, NSDictionary *))completion will be triggered.
/// @param appletId Mini Program ID
+ (void)invokeForwardMenuAction:(NSString *)appletId;


/// Open the Mini Program's feedback page
/// @param appletId Mini Program ID
+ (void)goToFeedbackPage:(NSString *)appletId;


/// Open the Mini Program's about page
/// @param appletId Mini Program ID
+ (void)goToAboutPage:(NSString *)appletId;


/// Open the Mini Program's settings page
/// @param appletId Mini Program ID
+ (void)goToSettingPage:(NSString *)appletId;


/// Open/close Mini Program debug mode. If config sets enableAppletDebug to true, the operation to open/close debug mode will be ineffective.
/// @param appletId Mini Program ID
/// @param enable Whether to allow debug mode
+ (void)setEnableAppletDebug:(NSString *)appletId enable:(BOOL)enable;


/// Check if the Mini Program has debug mode enabled
/// @param appletId Mini Program ID
+ (BOOL)isEnableAppletDebug:(NSString *)appletId;


/// Get the data of custom menu items (requires the Mini Program to implement the menu items and provide additional calling parameters)
/// @param appletId Mini Program ID
/// @param menuId Icon ID
/// @param complete Result callback
+ (void)getMiniProgramTypeMenuData:(NSString *)appletId menuId:(NSString *)menuId complete:(void(^)(NSDictionary *result,FATAppletInfo *appletInfo))complete;

/// Check if the Mini Program implements custom menu functionality
/// The `onShareAppMessage` event is affected by whether the Mini Program called the `showShareMenu`/`hideShareMenu` API.
/// If the Mini Program calls `showShareMenu` and then detects this method, the value of this event will be YES regardless of whether the Mini Program has implemented the `onShareAppMessage` event.
/// If the Mini Program calls `hideShareMenu` and then detects this method, the value will be NO regardless of implementation.
/// @param appletId Mini Program ID
/// @param menuIds Custom icon ID array
/// @param complete Result callback, parameter is NSArray, elements are @{ "eventName": ##Mini Program event name##, "menuId": ##Icon ID##, "value": ##Whether the event is implemented##}
+ (void)checkMenus:(NSString *)appletId menuIds:(NSArray<NSString *> *)menuIds complete:(void(^)(NSArray *result))complete;

Example code for a custom more menu:

objective-c
// Inside the class implementing FATAppletMoreMenuDelegate, implement this delegate method to use a custom menu view; you must return YES at the end.
- (BOOL)appletInfo:(FATAppletInfo *)appletInfo didClickMoreBtnAtPath:(NSString *)path {
    // Here we use UIAlertController as an example (users can use custom views)
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"More Menu" message:@"Custom More Menu" preferredStyle:UIAlertControllerStyleActionSheet];

    UIAlertAction *forwardAction = [UIAlertAction actionWithTitle:@"Forward" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // On click, call the 【+ (void)invokeForwardMenuAction:】 method to implement the **Forward** function.
        [FATMoreMenuHelper invokeForwardMenuAction:appletInfo.appId];
    }];
    [alertVC addAction:forwardAction];

    UIAlertAction *feedbackAction = [UIAlertAction actionWithTitle:@"Feedback and Complaint" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // On click, call the 【+ (void)goToFeedbackPage:】 method to implement the redirection to the **Feedback and Complaint** page.
        [FATMoreMenuHelper goToFeedbackPage:appletInfo.appId];
    }];
    [alertVC addAction:feedbackAction];

    UIAlertAction *aboutAction = [UIAlertAction actionWithTitle:@"About" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // On click, call the 【+ (void)goToAboutPage:】 method to implement redirection to the **About** page.
        [FATMoreMenuHelper goToAboutPage:appletInfo.appId];
    }];
    [alertVC addAction:aboutAction];

    UIAlertAction *settingAction = [UIAlertAction actionWithTitle:@"Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // On click, call the 【+ (void)goToSettingPage:】 method to implement redirection to the **Settings** page.
        [FATMoreMenuHelper goToSettingPage:appletInfo.appId];
    }];
    [alertVC addAction:settingAction];

    // Get the status of the **debug mode** button
    BOOL enableDebug = [FATMoreMenuHelper isEnableAppletDebug:appletInfo.appId];
    UIAlertAction *debugAction = [UIAlertAction actionWithTitle: enableDebug ? @"Disable debug mode" : @"Enable debug mode" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // On click, call the 【+ (void)setEnableAppletDebug:enable:】 method to set the **debug mode** button's state.
        [FATMoreMenuHelper setEnableAppletDebug:appletInfo.appId enable:!enableDebug];
    }];
    [alertVC addAction:debugAction];

    // Custom menu button IDs
    NSArray *menuIds = @[ @"WXShareAPPFriends", @"WXShareAPPMoments", @"ShareSinaWeibo", @"ShareQQFriends" ];
    // Call the 【+ (void)checkMenus:menuIds:complete:】 method to check whether the input menuIds are implemented in the Mini Program.
    [FATMoreMenuHelper checkMenus:appletInfo.appId menuIds:menuIds complete:^(NSArray * _Nonnull result) {
        // Iterate over the detection results
        for (NSDictionary *dict in result) {
            NSString *title = dict[@"eventName"];
            NSString *menuId = dict[@"menuId"];
            BOOL value = [dict[@"value"] boolValue];
            UIAlertAction *customAction = [UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                // On click, call the 【+ (void)getMiniProgramTypeMenuData:menuId:complete:】 method to trigger the Mini Program to call the custom button method.
                [FATMoreMenuHelper getMiniProgramTypeMenuData:appletInfo.appId menuId:menuId complete:^(NSDictionary * _Nonnull result, FATAppletInfo * _Nonnull appletInfo) {
                    // Handle custom menu button click event callback. Please add your business logic here.
                }];
            }];
            // Set the button's click state
            customAction.enabled = value;
            [alertVC addAction:customAction];
        }

        [alertVC addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
        // Display the custom menu
        UIViewController *topVC = [[UIApplication sharedApplication] fin_topViewController];
        [topVC presentViewController:alertVC animated:YES completion:nil];
    }];

    // Return YES
    return YES;
}

2.29 Does FinClip SDK support batch updating of Mini Programs?

Answer: Yes, it supports batch updates.

After SDK initialization is complete, calling the - (void)downloadApplets:apiServer:complete: API enables pre-downloading one or more Mini Programs, thus realizing batch update functionality.

Example code:

objective-c
/**
 @brief Batch update Mini Programs
 @param appIds Array of Mini Program IDs
 @param apiServer Server address
 @param complete Callback for batch updating Mini Programs
 */
[[FATClient sharedClient] downloadApplets:##appIds## apiServer:##apiServer## complete:^(NSArray *results, FATError *error) {
    // Callback for batch updating Mini Programs
    // results is the result of the batch updates and is an array object
    // each element is: @{@"appId": ##Mini Program ID##, @"success": ##Update success##, @"needUpdate": ##Need update##}
    // Each Mini Program ID passed might already cache the latest version, hence it might not need updating, in which case, needUpdate field will be false
    // error is nil if successful
}];

2.30 Does FinClip SDK support setting languages? How to set it?

From version 2.40.0-alpha20230106v02 onwards, the FinClip iOS SDK supports setting the language type of the SDK. The language type affects the text language used in public UI components of the SDK (e.g., more panels, about, settings, feedback, etc.). Currently, the SDK only supports Simplified Chinese and English. When setting string values for other languages, they will display in Simplified Chinese. Starting from iOS version 2.42.7, we have added the customLanguagePath attribute, allowing users to configure this property for custom internationalization languages.

How to set it?
If you only need to set Simplified Chinese and English, there is a language configuration item in FATConfig that can be set during initialization.

Example code:

objective-c
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"Fill in your SDK Key here";
storeConfig.sdkSecret = @"Fill in your SDK Secret here";
storeConfig.apiServer = @"Fill in your server address here"; // e.g., https://api.finclip.com;
storeConfig.apiPrefix = @"/api/v1/mop"; // This can be omitted if version is above 2.34.1
FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];
config.language = FATPreferredLanguageSimplifiedChinese;

To set other international languages, configure the customLanguagePath property which takes precedence over the language property.

For example, for Japanese, create an internationalization file directory named jp.lproj in your iOS development project, and within that directory, create a Localizable.strings file where you paste and translate the keys from within FinApplet.framework.

objective-c
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];
// Directly place `jp.lproj` under the project directory (which is under the mainBundle), initialize it as follows.
config.customLanguagePath = "jp.lproj";
// Or, if the `jp.lproj` file is stored in a custom bundle, include the relative path
// config.customLanguagePath = "XXX.bundle/jp.lproj";

Note: The keys used for custom internationalization languages must be sourced from FinApplet.framework located at FinApplet.framework/FinApplet.bundle/zh-Hans.lproj/Localizable.strings.

2.31 Detailed explanation of landscape and portrait modes in the SDK

Currently, the public UI screens within the SDK, such as the loading page when launching a Mini Program, about, settings, feedback pages, and pages opened via the Mini Program API such as scancode, chooseLocation, and openLocation, are fixed in portrait mode.

The direction supported by Mini Program pages is determined by the pageOrientation set in the Mini Program’s app.json and page.json.

  • If pageOrientation is set to portrait, it indicates that the page only supports portrait mode.
  • If pageOrientation is set to landscape, it indicates that the page supports LandscapeLeft and LandscapeRight.
  • If pageOrientation is set to auto, it indicates that the page supports Portrait, LandscapeLeft, and LandscapeRight.

SDK view controllers can be portrait, landscape, or support rotation alongside device orientation, thus configuration within the iOS project must include selections for Portrait, LandscapeLeft, and LandscapeRight.

If your project only supports portrait:

You will need to implement the following method in AppDelegate:

objective-c
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    UIViewController *topVC = [application fat_topViewController];
    Class class = NSClassFromString(@"FATUIViewController");
    if ([topVC isKindOfClass:class]) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
     // From version 2.45.3 and onward, the following method can be used to check if it’s a FinClip view controller
    // [[FATClient sharedClient] fat_isFinclipViewController:topVC]
    return UIInterfaceOrientationMaskPortrait;
}

If your project only supports landscape:

You will also need to implement the following method in AppDelegate:

objective-c
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    UIViewController *topVC = [application fat_topViewController];
    Class class = NSClassFromString(@"FATUIViewController");
    if ([topVC isKindOfClass:class]) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
    // From version 2.45.3 and onward, the following method can be used to check if it’s a FinClip view controller
    // [[FATClient sharedClient] fat_isFinclipViewController:topVC]

    return UIInterfaceOrientationMaskLandscape;
}

If you encounter the error 'could not build module FinAppletWXExt/FinAppletShareExt', you need to adjust the settings by setting Build Settings --- Enable Modules (C and Objective-C) to NO.

2.33 After importing the sharing SDK, the sharing panel does not display

The sharing panel is hidden by default, so after importing the sharing SDK, you also need to set the FATUIConfig parameter hideShareAppletMenu to False to show the sharing panel.

2.34 Requests in H5 of the Mini Program have lost body parameters, leading to request failure

Answer: The issue of body parameters being lost in H5 often arises from the Host App intercepting the HTTP/HTTPS protocols. For example:

objective-c
// Using NSURLProtocol interception can lead to this issue
[HtmlURLProtocol HtmlURLProtocolRegisterScheme:@"http"];
[HtmlURLProtocol HtmlURLProtocolRegisterScheme:@"https"];
[NSURLProtocol registerClass:HtmlURLProtocol.class];

// Using WKBrowsingContextController for interception could also lead to this issue
[WKBrowsingContextController registerSchemeForCustomProtocol:@"https"]

The root of the issue is that when the app intercepts HTTP/HTTPS requests, the system constructs the network request in H5 into a request object, but the body is not included in this request object. Therefore, when using the intercepted request to continue sending, the server does not receive the body business parameters, resulting in request failure.

This issue can also arise even in a native app; if intercepted and then using WKWebView directly, the same problem can occur. A third-party library has provided a solution to this problem: https://github.com/karosLi/KKJSBridge , and our FinClip SDK also references this open-source library's approach to provide a solution.

The basic principle of the solution is:

  1. Injecting a segment of JS into the HTML which hooks into the network request before it is initiated and generates a requestId.
  2. Calling a native event, sending the requestId and body content to native code, where the native keeps them matched.
  3. Appending the requestId parameter to the original network request's URL.
  4. The native code intercepting the HTTP/HTTPS events obtains the URL through the NSURLRequest object and retrieves the requestId.
  5. Using the requestId, locate the corresponding body and set it into NSURLRequest (typically by creating a new NSMutableURLRequest) before sending the request.
  6. Deleting the stored requestId and body parameters.

Thus, the solution in FinClip is as follows:

  1. During SDK initialization, set whether hooking H5 network requests is allowed, as well as the requestId’s field name.
objective-c
FATConfig *config = [FATConfig configWithStoreConfigs:storeArrayM];
// Allow hooking which will inject the JS handling
config.enableH5AjaxHook = YES;
// Set the field name used for appending requestId, for example, setting requestKey to FinClip-RequestId will change the URL to https://www.exampleexample.com?FinClip-RequestId=xxxxxxx
// If this parameter is not set, the key defaults to FinClipHookBridge-RequestId.
config.h5AjaxHookRequestKey = @"FinClip-RequestId";
  1. Set the proxy for the Mini Program SDK configuration.
objective-c
[FATClient sharedClient].configurationDelegate = self;
  1. Implement the delegate method in FATAppletConfigurationDelegate that handles hooking the body content.
objective-c
#pragma mark - FATAppletConfigurationDelegate
- (void)applet:(FATAppletInfo *)appletInfo hookRequestInfo:(NSDictionary *)requestInfo
{
    NSLog(@"hookRequestInfo:%@", requestInfo);
    NSDictionary *data = requestInfo;
    NSString *requestId = data[@"requestId"];
    // Here FATAjaxBodyManager is a singleton created randomly in our demo app
    FATAjaxBodyManager *bodyManager = [FATAjaxBodyManager manager];
    bodyManager.bodyCacheDictionary[requestId] = data;
}
  1. In the class that handles the HTTP/HTTPS protocol interception, set the body (Logic in the Host App).
objective-c
- (void)startLoading {
    NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
    // Set a flag on the processed request to prevent infinite loops,
    [NSURLProtocol setProperty:@YES forKey:FinClipNSURLProtocolKey inRequest:mutableReqeust];

    NSString *requestId;
    if ([mutableReqeust.URL.absoluteString containsString:[self requestIdKey]]) {
        requestId = [self fetchRequestId:mutableReqeust.URL];
        // Remove temporary request ID key-value pair
        NSString *reqeustPair = [self fetchRequestIdPair:mutableReqeust.URL];
        if (reqeustPair) {
            NSString *absString = [mutableReqeust.URL.absoluteString stringByReplacingOccurrencesOfString:reqeustPair withString:@""];
            mutableReqeust.URL = [NSURL URLWithString:absString];
        }
    }

    self.requestId = requestId;
    self.requestHTTPMethod = mutableReqeust.HTTPMethod;

    // Set body only for request types with a body
    NSArray<NSString *> *methods = @[@"POST"];
    if (mutableReqeust.HTTPMethod.length > 0 && [methods containsObject:mutableReqeust.HTTPMethod]) {
        NSDictionary *bodyReqeust = [[FATAjaxBodyManager manager].bodyCacheDictionary objectForKey:requestId];
        if (bodyReqeust) {
            // Set the cached body to the request
            [KKJSBridgeAjaxBodyHelper setBodyRequest:bodyReqeust toRequest:mutableReqeust];
        }
    }

    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
    self.customTask = [session dataTaskWithRequest:mutableReqeust];

    [self.customTask resume];
}

2.33 Does the FinClip SDK support setting custom city and district data? How to set it?

The FinClip iOS SDK, starting from version 2.43.1, supports setting custom city and district data. This allows for specifying a custom file path for loading and displaying regional data. When this property is set, the selector will attempt to load data from the specified path, which can either be a path in the app's sandbox directory or a filename included in the app bundle.

How to set it?
If you only need to set the Chinese and English languages, there is a configuration item called pickerRegionPath in FATConfig. Set this value during initialization.

Sample code:

objective-c
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"Enter your SDK Key here";
storeConfig.sdkSecret = @"Enter your SDK secret here";
storeConfig.apiServer = @"Enter your server address here"; // For example: https://api.finclip.com;
storeConfig.apiPrefix = @"/api/v1/mop"; // Not required for versions above 2.34.1
FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];
config.language = @"customData.json";

Note: If you need to pass a file from the sandbox, you must provide the complete path. Below is a sample format for the city and district data:

postalCode: postal code
name: region name
areaCode: area code
objective-c
[
    {
        "name": "Beijing",
        "postalCode": "100000",
        "areaCode": "110000",
        "city": [
            {
                "name": "Beijing",
                "postalCode": "100000",
                "areaCode": "110100",
                "area": [
                    {
                        "name": "Dongcheng District",
                        "postalCode": "100010",
                        "areaCode": "110101"
                    },
                    {
                        "name": "Xicheng District",
                        "postalCode": "100032",
                        "areaCode": "110102"
                    },
                    {
                        "name": "Chaoyang District",
                        "postalCode": "100020",
                        "areaCode": "110105"
                    },
                    {
                        "name": "Fengtai District",
                        "postalCode": "100071",
                        "areaCode": "110106"
                    },
                    {
                        "name": "Shijingshan District",
                        "postalCode": "100043",
                        "areaCode": "110107"
                    },
                    {
                        "name": "Haidian District",
                        "postalCode": "100089",
                        "areaCode": "110108"
                    },
                    {
                        "name": "Mentougou District",
                        "postalCode": "102300",
                        "areaCode": "110109"
                    },
                    {
                        "name": "Fangshan District",
                        "postalCode": "102488",
                        "areaCode": "110111"
                    },
                    {
                        "name": "Tongzhou District",
                        "postalCode": "101100",
                        "areaCode": "110112"
                    },
                    {
                        "name": "Shunyi District",
                        "postalCode": "101300",
                        "areaCode": "110113"
                    },
                    {
                        "name": "Changping District",
                        "postalCode": "102200",
                        "areaCode": "110114"
                    },
                    {
                        "name": "Daxing District",
                        "postalCode": "102600",
                        "areaCode": "110115"
                    },
                    {
                        "name": "Huairou District",
                        "postalCode": "101400",
                        "areaCode": "110116"
                    },
                    {
                        "name": "Pinggu District",
                        "postalCode": "101200",
                        "areaCode": "110117"
                    },
                    {
                        "name": "Miyun District",
                        "postalCode": "101500",
                        "areaCode": "110118"
                    },
                    {
                        "name": "Yanqing District",
                        "postalCode": "102100",
                        "areaCode": "110119"
                    }
                ]
            }
        ]
    }
]

3. Debugging

3.1 How to debug a mini program?

After integrating the mini program SDK and running the mini program in Xcode (you can also use an app packaged with the develop profile), you can open Safari on your computer. In the Safari menu under Develop, choose the running Simulator or Physical Device, then select the list of opened pages in the mini program. You can review page elements, inspect network calls, and view log messages.

3.2 How to enable vConsole?

If you need to debug the mini program, there are currently several ways to enable vConsole, allowing you to see the logs from the mini program.

Enabling the vConsole can be approached from both the SDK and the mini program.

SDK Aspect There are two places in the SDK that affect the enabling and disabling of vConsole:

  1. The appletDebugMode parameter in the initialization configuration item FATConfig.
  2. The buttons for [Open Debugging] and [Close Debugging] in the More Panel.

The appletDebugMode is an enumeration type with four current values:

  • FATAppletDebugModeDefault: Default value, behaves consistently with WeChat's vConsole controls.
  • FATAppletDebugModeEnable: Forces vConsole to be on for all mini programs (all versions), and it cannot be disabled through setEnableDebug or the debugging menu in More.
  • FATAppletDebugModeForbidden: Forces vConsole to be off for all mini programs (all versions), and it cannot be enabled through setEnableDebug or the debugging menu in More.
  • FATAppletDebugModeForbiddenRelease: Forces vConsole to be off for formal versions of mini programs; other versions behave according to FATAppletDebugModeDefault.

Mini Program Aspect The mini program can call the mini program API (ft.setEnableDebug) to enable vConsole.

However, if config.appletDebugMode is set to FATAppletDebugModeEnable, then the ft.setEnableDebug interface will not be effective. If config.appletDebugMode is set to FATAppletDebugModeForbidden, then the ft.setEnableDebug interface will also not be effective.

Note

  1. The debug mode of the mini program will be persistently stored. That is, when ft.setEanbleDebug is called to enable vConsole, the same mini program will also open vConsole the next time it is opened.
  2. The debug mode for the same mini program is persistently stored.
  3. configWithAppSecret:appKey: will be deprecated in the future, please replace it as soon as possible with configWithStoreConfigs to construct FATConfig.
  4. Starting from version 2.34.1, it is no longer necessary to configure apiPrefix, as it has already been set up internally in the interface.

Finally, it is recommended to set config.appletDebugMode to FATAppletDebugModeEnable during the app development phase; then modify it to FATAppletDebugModeDefault when the app is submitted for review. Setting it to FATAppletDebugModeDefault means that the formal version of the mini program will not display the [Open Debugging] and [Close Debugging] buttons, but it can still activate vConsole through the API (ft.setEnableDebug). Non-formal versions of the mini program can open vConsole via [Open Debugging] and ft.setEnableDebug.