npm package: @hmscore/hms-js-iap
Description: HMS JS IAP
Latest version: 5.2.0-300

# JSB IAP
JSSDK enables communication between HUAWEI In-App Purchases and both React Native, Cordova and Ionic platforms. This plugin exposes capabilities provided by HUAWEI In-App Purchases.

## Contents

- [1. Introduction](#1-introduction)
- [2. Installation Guide](#2-installation-guide)
  - [Creating a Project in App Gallery Connect](#creating-a-project-in-appgallery-connect)
  - [Configuring the Signing Certificate Fingerprint](#configuring-the-signing-certificate-fingerprint)
  - [React-Native Integration](#react-native-integration)
  - [Cordova Integration](#cordova-integration)
  - [Ionic Integration](#ionic-integration)
    - [Ionic with Cordova Runtime](#ionic-with-cordova-runtime)
    - [Ionic with Capacitor Runtime](#ionic-with-capacitor-runtime)
- [3. API Reference](#3-api-reference)
  - [HMSIAP](#hmsiap)
    - [Public Method Summary](#public-method-summary)
  - [Data Types](#data-types)
    - [Result](#result)
    - [OwnedPurchasesReq](#ownedpurchasesreq)
    - [ProductInfoReq](#productinforeq)
    - [PurchaseIntentReq](#purchaseintentreq)
    - [ConsumeOwnedPurchaseReq](#consumeownedpurchasereq)
    - [StartIapActivityReq](#startiapactivityreq)
    - [IsEnvReadyResult](#isenvreadyresult)
    - [IsSandboxActivatedResult](#issandboxactivatedresult)
    - [OwnedPurchasesResult](#ownedpurchasesresult)
    - [ProductInfoResult](#productinforesult)
    - [ProductInfo](#productinfo)
    - [PurchaseIntentResult](#purchaseintentresult)
    - [ConsumeOwnedPurchaseResult](#consumeownedpurchaseresult)
  - [Constants](#constants)
    - [PriceType](#pricetype)
    - [StartIapActivityReqType](#startiapactivityreqtype)
  - [Result Codes](#result-codes)
- [4. Configuration and Description](#4-configuration-and-description)
- [5. Questions or Issues](#5-questions-or-issues)
- [6. Licensing and Terms](#6-licensing-and-terms)

## 1. Introduction

## 2. Installation Guide

### Creating a Project in AppGallery Connect

Creating an app in AppGallery Connect is required in order to communicate with the Huawei services. To create an app, perform the following steps:

**Step 1.** Sign in to [AppGallery Connect](https://developer.huawei.com/consumer/en/service/josp/agc/index.html)  and select **My projects**.

**Step 2.** Select your project from the project list or create a new one by clicking the **Add Project** button.

**Step 3.** Go to **Project Setting** > **General information**, and click **Add app**.
If an app exists in the project and you need to add a new one, expand the app selection area on the top of the page and click **Add app**.

**Step 4.** On the **Add app** page, enter the app information, and click **OK**.

- A signing certificate fingerprint is used to verify the authenticity of an app when it attempts to access an HMS Core service through the HMS Core SDK. Before using HMS Core (APK), you must locally generate a signing certificate fingerprint and configure it in AppGallery Connect. Ensure that the JDK has been installed on your computer.

### Configuring the Signing Certificate Fingerprint

**Step 1.** Go to **Project Setting > General information**. In the **App information** field, click the icon next to SHA-256 certificate fingerprint, and enter the obtained **SHA256 certificate fingerprint**.

**Step 2.** After completing the configuration, click check mark.

### React-Native Integration

**Step 1:** Sign in to [AppGallery Connect](https://developer.huawei.com/consumer/en/service/josp/agc/index.html) and select **My projects**.

**Step 2:** Find your app project, and click the desired app name.

**Step 3:** Go to **Project Setting** > **General information**. In the **App information** section, click **agconnect-service.json** to download the configuration file.

**Step 4:** Create a React Native project if you do not have one.

**Step 5:** Copy the **agconnect-service.json** file to the **android/app** directory of your React Native project.

**Step 6:** Copy the signature file that generated in [Generating a Signing Certificate](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#3) section, to the android/app directory of your React Native project.

**Step 7:** Check whether the **agconnect-services.json** file and signature file are successfully added to the **android/app** directory of the React Native project.

**Step 8:** Open the **AndroidManifest.xml** file, add the following lines, and replace the value **<app_id>** with the value you found in the **agconnect-services.json** file.

```xml
<application>
...
     <meta-data
            android:name="com.huawei.hms.client.appid"
            android:value="appid=<app_id>" />
</application>
```

**Step 9:** Open the **build.gradle** file in the **android** directory of your React Native project.

- Go to **buildscript** then configure the Maven repository address and agconnect plugin for the HMS SDK.

```groovy
buildscript {    
  repositories {        
    google()        
    jcenter()        
    maven { url 'https://developer.huawei.com/repo/' }   
  }    

  dependencies {        
    /*          
      * <Other dependencies>        
      */   
    classpath 'com.huawei.agconnect:agcp:1.4.2.301'    
  }
}
```

- Go to **allprojects** then configure the Maven repository address for the HMS SDK.

```groovy
allprojects {
  repositories {
    /*          
      * <Other repositories>        
      */  
    maven { url 'https://developer.huawei.com/repo/' }
  }
}
```

**Step 10:** Open the **build.gradle** file in the **android/app** directory of your React Native project.

- Package name must match with the **package_name** entry in **agconnect-services.json** file.

```groovy
defaultConfig {
  applicationId "<package_name>"
  minSdkVersion 19
  /*
   * <Other configurations>
   */
}
```

```groovy
android {
  /*
   * <Other configurations>
   */

  signingConfigs {
    config {
      storeFile file('<keystore_file>.jks')
      storePassword '<keystore_password>'
      keyAlias '<key_alias>'
      keyPassword '<key_password>'
    }
  }

  buildTypes {
    debug {
      signingConfig signingConfigs.config
    }
    release {
      signingConfig signingConfigs.config
      minifyEnabled enableProguardInReleaseBuilds
      ...
    }
  }
}
```

**Step 11:** Open the **build.gradle** file in the **android/app** directory of your React Native project.

- Configure build dependencies.

```groovy
buildscript {
  ...
  dependencies {
    /*
    * <Other dependencies>
    */
    implementation ('com.huawei.hms:rn-adapter:5.2.0.300'){
        exclude group: 'com.facebook.react'
    } 
    ...    
  }
}
```

**Step 12:** Import the following class to the **MainApplication.java** file of your project.

```java
import com.huawei.hms.jsb.adapter.rn.RnJSBReactPackage;
```

Then, add the **RnJSBReactPackage()** to your **getPackages** method. In the end, your file will be similar to the following:

```java
@Override
protected List<ReactPackage> getPackages() {
    List<ReactPackage> packages = new PackageList(this).getPackages();
    packages.add(new RnJSBReactPackage()); // <-- Add this line 
    return packages;
}
...
```

**Step 13:** Download js-sdk using command below.

```bash
npm i @hmscore/hms-js-iap
```

**Step 14:** Import **HMSIAP** in App.js as following line.

```js
import HMSIAP from "@hmscore/hms-js-iap";
```

**Step 15:** Call HMSIAP's init method to initialize. 

```js
import { NativeModules, DeviceEventEmitter } from "react-native";
...

HMSIAP.init(NativeModules, DeviceEventEmitter);
```

**Step 16:** Run your project.

- Run the following command to the project directory.

```bash
react-native run-android  
```

### Cordova Integration

**Step 1:** Install Cordova CLI if haven't done before.

```bash
npm install -g cordova
```

**Step 2:** Create a new Cordova project or use the existing one.

- To create new Cordova project, you can use **`cordova create path [id [name [config]]] [options]`** command. For more details please follow [CLI Reference - Apache Cordova](https://cordova.apache.org/docs/en/latest/reference/cordova-cli/index.html#cordova-create-command).

**Step 3:** Update the widget **`id`** property which is specified in the **`config.xml`** file. It must be same with **package_name** value of the **`agconnect-services.json`** file.

**Step 4:** Add the **Android platform** to the project if haven't done before.

```bash
cordova platform add android
```

**Step 5:**  Download plugin using command below.

```bash
cordova plugin add @hmscore/hms-js-iap
```

**Step 6:** Copy **`agconnect-services.json`** file to **`<project_root>/platforms/android/app`** directory.

**Step 7:** Add **`keystore(.jks)`** and **`build.json`** files to your project's root directory.

- You can refer to 3rd and 4th steps of [Generating a Signing Certificate](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#2) Codelab tutorial page for generating keystore file.

- Fill **`build.json`** file according to your keystore information. For example:

    ```json
    {
        "android": {
            "debug": {
                "keystore": "<keystore_file>.jks",
                "storePassword": "<keystore_password>",
                "alias": "<key_alias>",
                "password": "<key_password>"
            },
            "release": {
                "keystore": "<keystore_file>.jks",
                "storePassword": "<keystore_password>",
                "alias": "<key_alias>",
                "password": "<key_password>"
            }
        }
    }
    ```

**Step 8:**  Import the following class to the **MainActivity.java** file of your project. You can find this file in **`platforms/android/app/src/main/java/<your_package_name>`** directory.

```java
import com.huawei.hms.jsb.adapter.cordova.CordovaJSBInit;
```

**Step 9:** In the same file, add **CordovaJSBInit.initJSBFramework(this)** line after the **super.onCreate(savedInstanceState)** method call.

- In the end, your file will be similar to the following:

    ```java
    ...

    import com.huawei.hms.jsb.adapter.cordova.CordovaJSBInit;

    public class MainActivity extends CordovaActivity
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            CordovaJSBInit.initJSBFramework(this);

            ...
        }
        ...
    }
    ```

**Step 10:** Open the **AndroidManifest.xml** file, add the following lines, and replace the value **<app_id>** with the **app_id** value that can be found in the **agconnect-services.json** file.

```xml
<application>
...
     <meta-data
            android:name="com.huawei.hms.client.appid"
            android:value="appid=<app_id>" />
</application>
```

**Step 11:**  Run the app

  ```bash
  cordova run android
  ```

### Ionic Integration

Install Ionic CLI and other required tools if haven't done before.

```bash
npm install -g @ionic/cli cordova-res native-run
```

#### Ionic with Cordova Runtime

**Step 1:** Enable the **Cordova integration** if haven't done before.

```bash
ionic integrations enable cordova
```

**Step 2:** Update the widget **`id`** property which is specified in the **`config.xml`** file. It must be same with **package_name** value of the **`agconnect-services.json`** file.

**Step 3:** Add the **Android platform** to the project if haven't done before.

```bash
ionic cordova platform add android
```

**Step 4:** Install `HMS IAP Plugin` to the project.

```bash
ionic cordova plugin add @hmscore/hms-js-iap
```

**Step 5:** Copy **`agconnect-services.json`** file to **`<project_root>/platforms/android/app`** directory.

**Step 6:** Add **`keystore(.jks)`** and **`build.json`** files to your project's root directory.

- You can refer to 3rd and 4th steps of [Generating a Signing Certificate](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#2) Codelab tutorial page for generating keystore file.

- Fill **`build.json`** file according to your keystore information. For example:

    ```json
    {
        "android": {
            "debug": {
                "keystore": "<keystore_file>.jks",
                "storePassword": "<keystore_password>",
                "alias": "<key_alias>",
                "password": "<key_password>"
            },
            "release": {
                "keystore": "<keystore_file>.jks",
                "storePassword": "<keystore_password>",
                "alias": "<key_alias>",
                "password": "<key_password>"
            }
        }
    }
    ```

**Step 7:**  Import the following class to the **MainActivity.java** file of your project. You can find this file in **`platforms/android/app/src/main/java/<your_package_name>`** directory.

```java
import com.huawei.hms.jsb.adapter.cordova.CordovaJSBInit;
```

**Step 8:** In the same file, add **CordovaJSBInit.initJSBFramework(this)** line after the **super.onCreate(savedInstanceState)** method call.

- In the end, your file will be similar to the following:

    ```java
    ...

    import com.huawei.hms.jsb.adapter.cordova.CordovaJSBInit;

    public class MainActivity extends CordovaActivity
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            CordovaJSBInit.initJSBFramework(this);

            ...
        }
        ...
    }
    ```

**Step 9:** Open the **AndroidManifest.xml** file, add the following lines, and replace the value **<app_id>** with the **app_id** value that can be found in the **agconnect-services.json** file.

```xml
<application>
...
     <meta-data
            android:name="com.huawei.hms.client.appid"
            android:value="appid=<app_id>" />
</application>
```

**Step 10:** Run the application.

```bash
ionic cordova run android --device
```

#### Ionic with Capacitor Runtime

**Step 1:** Enable the **Capacitor integration** if haven't done before.

```bash
ionic integrations enable capacitor
```

**Step 2:** Initialize **Capacitor** if haven't done before.

```bash
npx cap init [appName] [appId]
```

- For more details please follow [Initialize Capacitor with your app information](https://capacitorjs.com/docs/getting-started/with-ionic#initialize-capacitor-with-your-app-information).

**Step 3:** Update the **`appId`** property which is specified in the **`capacitor.config.json`** file according to your project. It must be same with **package_name** value of the **`agconnect-services.json`** file.

**Step 4:** Install `HMS IAP plugin` to the project.

```bash
npm install @hmscore/hms-js-iap
```

**Step 5:** Build Ionic app to generate resource files.

```bash
ionic build
```

**Step 6:** Add the **Android platform** to the project.

```bash
npx cap add android
```

**Step 7:** Copy **`keystore(.jks)`** and **`agconnect-services.json`** files to **`<project_root>/android/app`** directory.

- You can refer to 3rd and 4th steps of [Generating a Signing Certificate](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#2) Codelab tutorial page for generating keystore file.

**Step 8:** Open the **`build.gradle`** file in the **`<project_root>/android/app`** directory.

- Add `signingConfigs` entry to the **android** section and modify it according to your keystore.

- Enable `signingConfig` configuration for **debug** and **release** flavors.

```groovy
...

android {

    ...

    // Modify signingConfigs according to your keystore
    signingConfigs {
        config {
            storeFile file('<keystore_file>.jks')
            storePassword '<keystore_password>'
            keyAlias '<key_alias>'
            keyPassword '<key_password>'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.config // Enable signingConfig for debug flavor
        }
        release {
            signingConfig signingConfigs.config // Enable signingConfig for release flavor
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

...
```

- Add **apply plugin:'com.huawei.agconnect** to top of your build gradle file in the **`<project_root>/android/app`** directory.

**Step 9:** Open the **`build.gradle`** file in the **`<project_root>/android`** directory. Add **Huawei's maven repositories** and **agconnect classpath** to the file.

```groovy
buildscript {
    repositories {
        /*
            <Other repositories>
        */
        maven { url 'https://developer.huawei.com/repo/' }
    }
    dependencies {
        /*
            <Other dependencies>
        */
        classpath 'com.huawei.agconnect:agcp:1.4.2.301'
    }
}

/*
    <Other build.gradle entries>
*/

allprojects {
    repositories {
        /*
            <Other repositories>
        */
        maven { url 'https://developer.huawei.com/repo/' }
    }
}
```

**Step 10:** Import the following class to the **MainActivity.java** file of your project. You can find this file in **`android/app/src/main/java/<your_package_name>`** directory.

```java
import com.huawei.hms.js.iap.HMSIAP;
```

**Step 11:** In the same file, add **add(HMSIAP.class);** line to the **ArrayList**.

- In the end, your file will be similar to the following:

  ```java
  ...
  import com.huawei.hms.js.iap.HMSIAP;
  public class MainActivity extends BridgeActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Initializes the Bridge
    this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
        add(HMSIAP.class);
    }});
  }
  ...
  ```

**Step 12:** Open the **AndroidManifest.xml** file, add the following lines, and replace the value **<app_id>** with the **app_id** value that can be found in the **agconnect-services.json** file.

```xml
<application>
...
     <meta-data
            android:name="com.huawei.hms.client.appid"
            android:value="appid=<app_id>" />
</application>
```

**Step 13:** Updates dependencies, and copy any web assets to your project.

```bash
npx cap sync
```

**Step 14:** Open the project in Android Studio and run it.

```bash
npx cap open android
```

## 3. API Reference
### **HMSIAP**

#### Public Method Summary

| Method                                                    | Return Type                                  | Description                                                  |
| --------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------ |
| [isEnvReady()](#hmsiapisenvready)                         | [Promise<Result\<IsEnvReadyResult>>](#isenvreadyresult)           | Checks whether the currently signed-in HUAWEI ID is located in a country or region where HUAWEI IAP is available. |
| [isSandboxActivated()](#hmsiapissandboxactivated)         | [Promise<Result\<IsSandboxActivatedResult>>](#issandboxactivatedresult)   | Checks whether the signed-in HUAWEI ID and the app APK version meet the requirements of the sandbox testing. |
| [obtainOwnedPurchases(ownedPurchasesReq)](#hmsiapobtainownedpurchasesownedpurchasesreq)                   | [Promise<Result\<OwnedPurchasesResult>>](#ownedpurchasesresult)       | Queries information about all purchased products, including consumables, non-consumables, and subscriptions. |
| [obtainProductInfo(productInfoReq)](#hmsiapobtainproductinfoproductinforeq)                         | [Promise<Result\<ProductInfoResult>>](#productinforesult)          | Obtains product details configured in AppGallery Connect.    |
| [createPurchaseIntent(purchaseIntentReq)](#hmsiapcreatepurchaseintentpurchaseintentreq)                   | [Promise<Result\<PurchaseIntentResult>>](#purchaseintentresult)       | Creates orders for products managed by the PMS, including consumables, non-consumables, and subscriptions. |
| [consumeOwnedPurchase(consumeOwnedPurchaseReq)](#hmsiapconsumeownedpurchaseconsumeownedpurchasereq)             | [Promise<Result\<ConsumeOwnedPurchaseResult>>](#consumeownedpurchaseresult) | Consumes a consumable after it is delivered to a user who has completed payment. |
| [obtainOwnedPurchaseRecord(ownedPurchasesReq)](#hmsiapobtainownedpurchaserecordownedpurchasesreq)              | [Promise<Result\<OwnedPurchasesResult>>](#ownedpurchasesresult)       | Obtains the historical consumption information about a consumable or all subscription receipts of a subscription. |
| [startIapActivity(startIapActivityReq)](#hmsiapstartiapactivitystartiapactivityreq)                     | Promise<Result\<void>>    |  Displays HUAWEI IAP-related screens, including the subscription editing screen and subscription management screen. |


### 3.1.2 Public Methods

##### HMSIAP.isEnvReady()

Checks whether the currently signed-in HUAWEI ID is located in a country or region where HUAWEI IAP is available.

| Return Type                        | Description                                                  |
| ---------------------------------- | ------------------------------------------------------------ |
| [Promise<Result\<IsEnvReadyResult>>](#isenvreadyresult) | IsEnvReadyResult object which represents environment check results. |

Call Example

```js
HMSIAP.isEnvReady()
    .then((res) => {
        console.log(res.data)
    })
    .catch((err) => {
        console.log(err)
    });
```

##### HMSIAP.isSandboxActivated()

Checks whether the signed-in HUAWEI ID and the app APK version meet the requirements of the sandbox testing.

| Return Type                                | Description                                                  |
| ------------------------------------------ | ------------------------------------------------------------ |
| [Promise<Result\<IsSandboxActivatedResult>>](#issandboxactivatedresult) | IsSandboxActivatedResult object which represents sandbox check results. |

Call Example

```js
HMSIAP.isSandboxActivated()
    .then((res) => {
        console.log(res.data)
    })
    .catch((err) => {
        console.log(err)
    });
```

Example Response

```js
{
    "errMsg": "Sandbox is activated",
    "isSandboxApk": true,
    "isSandboxUser": true,
    "returnCode": 0,
    "versionFrMarket": "0",
    "versionInApk": "1"
}
```

##### HMSIAP.obtainOwnedPurchases(ownedPurchasesReq)

Queries information about all purchased in-app products, including consumables, non-consumables, and auto-renewable subscriptions.

| Parameter         | Type              | Description                                      |
| ----------------- | ----------------- | ------------------------------------------------ |
| ownedPurchasesReq | [OwnedPurchasesReq](#ownedpurchasesreq) | Request object for the obtainOwnedPurchases API. |


| Return Type                            | Description                                                  |
| -------------------------------------- | ------------------------------------------------------------ |
| [Promise<Result\<OwnedPurchasesResult>>](#ownedpurchasesresult) | OwnedPurchasesResult object which represents purchased product information. |

Call Example

```js
const ownedPurchasesReq = {
    priceType: HMSIAP.PriceType.IN_APP_CONSUMABLE
}

HMSIAP.obtainOwnedPurchases(ownedPurchasesReq)
    .then((res) => {
        console.log(res.data)
    })
    .catch((err) => {
        console.log(err)
    });
```

Example Response

```js
{
    "continuationToken": "",
    "errMsg": "success",
    "inAppPurchaseDataList": [
        {
            "autoRenewing": false,
            "orderId": "202102211638216856838c6c...",
            "packageName": "com.huawei...",
            "applicationId": 000,
            "kind": 0,
            "productId": "5.0.2.300.1",
            "productName": "Consumable - 5.0.2.300",
            "purchaseTime": 000,
            "purchaseTimeMillis": 000,
            "purchaseState": 0,
            "developerPayload": "testPurchase",
            "purchaseToken": "00000177c574e263d0bdfc9356...",
            "consumptionState": 0,
            "confirmed": 0,
            "purchaseType": 0,
            "currency": "TRY",
            "price": 100,
            "country": "TR",
            "payOrderId": "sandbox2021022117382...",
            "payType": "34",
            "sdkChannel": "1"
        },
        {
            "autoRenewing": false,
            "orderId": "202102211614306525163a95...",
            "packageName": "com.huawei...",
            "applicationId": 000,
            "kind": 0,
            "productId": "5.0.2.300.1.2",
            "productName": "Second Consumable",
            "purchaseTime": 000,
            "purchaseTimeMillis": 000,
            "purchaseState": 0,
            "developerPayload": "testPurchase",
            "purchaseToken": "00000177c55fe39add10fcb...",
            "consumptionState": 0,
            "confirmed": 0,
            "purchaseType": 0,
            "currency": "TRY",
            "price": 200,
            "country": "TR",
            "payOrderId": "sandbox202102211715...",
            "payType": "34",
            "sdkChannel": "1"
        }
    ],
    "inAppSignatureList": [
        "KKbLc6x1Q4+mp7DnlAxiE7Zmj...",
        "YcMXNjNlwOmcctzPgmueRT+ZP..."
    ],
    "itemList": [
        "5.0.2.300.1",
        "5.0.2.300.1.2"
    ],
    "returnCode": 0
}
```

##### HMSIAP.obtainProductInfo(productInfoReq)

Obtains in-app product details configured in AppGallery Connect.

| Parameter      | Type           | Description                                   |
| -------------- | -------------- | --------------------------------------------- |
| productInfoReq | [ProductInfoReq](#productinforeq) | Request object for the obtainProductInfo API. |

| Return Type                         | Description                                                |
| ----------------------------------- | ---------------------------------------------------------- |
| [Promise<Result\<ProductInfoResult>>](#productinforesult) | ProductInfoResult object which represents product details. |

Call Example

```js
const productInfoReq = {
    skuIds: ['5.0.2.300.3', '5.0.2.300.3.2'],
    priceType: HMSIAP.PriceType.IN_APP_SUBSCRIPTION
}

HMSIAP.obtainProductInfo(productInfoReq)
    .then((res) => {
        console.log(res.data)
    })
    .catch((err) => {
        console.log(err)
    });
```

Example Response

```js
{
    "errMsg": "success",
    "returnCode": 0,
    "skuList": [
        {
            "currency": "TRY",
            "microsPrice": 000,
            "originalLocalPrice": "",
            "originalMicroPrice": 0,
            "price": "TRY 1.00",
            "priceType": 2,
            "productDesc": "subs test product",
            "productId": "5.0.2.300.3",
            "productName": "Subs - 5.0.2.300",
            "status": 0,
            "subsGroupId": "5EFB723679D3427494B...",
            "subsGroupTitle": "",
            "subsIntroductoryPeriodCycles": 0,
            "subsIntroductoryPriceMicros": 0,
            "subsProductLevel": 1,
            "subscriptionPeriod": "P1W"
        },
        {
            "currency": "TRY",
            "microsPrice": 000,
            "originalLocalPrice": "",
            "originalMicroPrice": 0,
            "price": "TRY 1.00",
            "priceType": 2,
            "productDesc": "test subs",
            "productId": "5.0.2.300.3.2",
            "productName": "Subs 2 - 5.0.2.300",
            "status": 0,
            "subsGroupId": "5EFB723679D342749...",
            "subsGroupTitle": "",
            "subsIntroductoryPeriodCycles": 0,
            "subsIntroductoryPriceMicros": 0,
            "subsProductLevel": 1,
            "subscriptionPeriod": "P6M"
        }
    ]
}
```

##### HMSIAP.createPurchaseIntent(purchaseIntentReq)

Creates orders for PMS products, including consumables, non-consumables, and subscriptions.

| Parameter         | Type              | Description                                      |
| ----------------- | ----------------- | ------------------------------------------------ |
| purchaseIntentReq | [PurchaseIntentReq](#purchaseintentreq) | Request object for the createPurchaseIntent API. |

| Return Type                            | Description                                                  |
| -------------------------------------- | ------------------------------------------------------------ |
| [Promise<Result\<PurchaseIntentResult>>](#purchaseintentresult) | PurchaseResultInfo which represents purchase intent results. |

Call Example

```js
const purchaseIntentReq = {
    productId: "subscription4",
    priceType: HMSIAP.PriceType.IN_APP_SUBSCRIPTION,
    developerPayload: "testPurchase",
}

HMSIAP.createPurchaseIntent(purchaseIntentReq)
    .then((res) => {
        console.log(res.data)
    })
    .catch((err) => {
        console.log(err)
    });
```

Example Response

```js
{
    "errMsg": "success",
    "retCode": 0
}
```

##### HMSIAP.consumeOwnedPurchase(consumeOwnedPurchaseReq)

Consumes a consumable after it is delivered to a user who has completed payment.

| Parameter               | Type                    | Description                                      |
| ----------------------- | ----------------------- | ------------------------------------------------ |
| consumeOwnedPurchaseReq | [ConsumeOwnedPurchaseReq](#consumeownedpurchasereq) | Request object for the consumeOwnedPurchase API. |

| Return Type                                  | Description                                                  |
| -------------------------------------------- | ------------------------------------------------------------ |
| [Promise<Result\<ConsumeOwnedPurchaseResult>>](#consumeownedpurchaseresult) | ConsumeOwnedPurchaseResult which represents consume details. |

Call Example

```js
const consumeOwnedPurchaseReq = {
    developerChallenge: "developerChallenge",
    purchaseToken: "000001778c016d06d5f3907d13a5f5544d8f8a1114...."
}

HMSIAP.consumeOwnedPurchase(consumeOwnedPurchaseReq)
    .then((res) => {
        console.log(res.data)
    })
    .catch((err) => {
        console.log(err)
    });
```

Example Response

```js
{
    "consumedPurchaseData": "{\"autoRenewing\":false,\"orderId\":\"202102211614306525163a9...\",\"packageName\":\"com.huawei...\",\"applicationId\":10253...,\"kind\":0,\"productId\":\"5.0.2.300.1.2\",\"productName\":\"Second Consumable\",\"purchaseTime\":161392413...,\"purchaseTimeMillis\":000,\"purchaseState\":0,\"developerPayload\":\"testPurchase\",\"purchaseToken\":\"00000177c55fe39add10fcbfedab93...\",\"developerChallenge\":\"developerChallenge\",\"responseCode\":\"0\",\"consumptionState\":1,\"confirmed\":1,\"purchaseType\":0,\"currency\":\"TRY\",\"price\":200,\"country\":\"TR\",\"payOrderId\":\"sandbox2021022117153...\",\"payType\":\"34\",\"sdkChannel\":\"1\"}",
    "dataSignature": "hjYGHuFLL+pDe58cuKYkzs/4n0M0dVde0lrau0ZvqxNCd...",
    "errMsg": "success",
    "returnCode": 0
}
```

##### HMSIAP.obtainOwnedPurchaseRecord(ownedPurchasesReq)

Obtains the historical consumption information about a consumable or all subscription receipts of a subscription.

| Parameter         | Type              | Description                                           |
| ----------------- | ----------------- | ----------------------------------------------------- |
| ownedPurchasesReq | [OwnedPurchasesReq](#ownedpurchasesreq) | Request object for the obtainOwnedPurchaseRecord API. |

| Return Type                            | Description                                                  |
| -------------------------------------- | ------------------------------------------------------------ |
| [Promise<Result\<OwnedPurchasesResult>>](#ownedpurchasesresult) | OwnedPurchasesResult which represents historical consumption details. |

Call Example

```js
const ownedPurchasesReq = {
    priceType: HMSIAP.PriceType.IN_APP_CONSUMABLE
}

HMSIAP.obtainOwnedPurchaseRecord(ownedPurchasesReq)
    .then((res) => {
        console.log(res.data)
    })
    .catch((err) => {
        console.log(err)
    });
```

Example Response

```js
{
    "continuationToken": "",
    "errMsg": "success",
    "inAppPurchaseDataList": [
        {
            "autoRenewing": true,
            "subIsvalid": false,
            "orderId": "1614062541500...",
            "lastOrderId": "1613910602138...",
            "packageName": "com.huawei...",
            "applicationId": 000,
            "productId": "subscription4",
            "kind": 2,
            "productName": "Auto-Renewable 4",
            "productGroup": "22F57CD1C8424200A66FD29720844920",
            "purchaseTime": 000,
            "oriPurchaseTime": 000,
            "purchaseState": 0,
            "developerPayload": "testPurchase",
            "purchaseToken": "000001778a43bcbbb7554bf0a8784bda...",
            "purchaseType": 0,
            "currency": "TRY",
            "price": 200,
            "country": "TR",
            "subscriptionId": "1612932431035...",
            "quantity": 1,
            "daysLasted": 15,
            "numOfPeriods": 16,
            "numOfDiscount": 0,
            "expirationDate": 000,
            "retryFlag": 1,
            "introductoryFlag": 0,
            "trialFlag": 0,
            "renewStatus": 1,
            "renewPrice": 200,
            "cancelledSubKeepDays": 30,
            "payOrderId": "SandBox_1614062541500...",
            "payType": "0",
            "confirmed": 1
        },
        {
            "autoRenewing": true,
            "subIsvalid": false,
            "orderId": "1613933434282...",
            "lastOrderId": "1613920421990...",
            "packageName": "com.huawei...",
            "applicationId": 000,
            "productId": "5.0.2.300.3",
            "kind": 2,
            "productName": "Subs - 5.0.2.300",
            "productGroup": "5EFB723679D3427494B50F...",
            "purchaseTime": 000,
            "oriPurchaseTime": 000,
            "purchaseState": 0,
            "developerPayload": "testPurchase",
            "purchaseToken": "00000177c51bf39fdc9aeedd717a4...",
            "purchaseType": 0,
            "currency": "TRY",
            "price": 100,
            "country": "TR",
            "subscriptionId": "1613919679391...",
            "quantity": 1,
            "daysLasted": 46,
            "numOfPeriods": 7,
            "numOfDiscount": 0,
            "expirationDate": 000,
            "retryFlag": 1,
            "introductoryFlag": 0,
            "trialFlag": 0,
            "renewStatus": 1,
            "renewPrice": 100,
            "cancelledSubKeepDays": 30,
            "payOrderId": "SandBox_161393343428...",
            "payType": "0",
            "confirmed": 1
        }
    ],
    "inAppSignatureList": [
        "J5XpBu7N6yvBZYX0NW4wusarhUchwY6r9...",
        "YB5UYofu2X3U0gEQWQhlB3YRMS2z0oCG9..."
    ],
    "itemList": [
        "subscription4",
        "5.0.2.300.3"
    ],
    "placedInappPurchaseDataList": [],
    "placedInappSignatureList": [],
    "returnCode": 0
}
```

##### HMSIAP.startIapActivity(startIapActivityReq)

Displays pages of HUAWEI IAP, including the subscription management page and subscription editing page.

| Parameter           | Type                | Description                                  |
| ------------------- | ------------------- | -------------------------------------------- |
| startIapActivityReq | [StartIapActivityReq](#startiapactivityreq) | Request object for the startIapActivity API. |

| Return Type                              | Description |
| ---------------------------------------- | ----------- |
| Promise<Result\<void>> | Promise resolves in a successful operation. Otherwise, it throws an error. |

Call Example

```js
const startIapActivityReq = {
    type: HMSIAP.StartIapActivityReqType.TYPE_SUBSCRIBE_EDIT_ACTIVITY,
    subscribeProductId: "productId"
}

HMSIAP.obtainOwnedPurchaseRecord(startIapActivityReq)
    .then((res) => {
        console.log(res.data)
    })
    .catch((err) => {
        console.log(err)
    });
```

### Data Types

#### Result

| Name       | Type   | Description                         |
| ---------- | ------ | ----------------------------------- |
| status     | string | Result status.                      |
| resultCode | number | [Result Code](#result-codes)                         |
| data       | object | Result object according to the API. Such as [IsEnvReadyResult](#isenvreadyresult), [IsSandboxActivatedResult](#issandboxactivatedresult), [OwnedPurchasesResult](#ownedpurchasesresult), [ProductInfoResult](#productinforesult), [PurchaseIntentResult](#purchaseintentresult), [ConsumeOwnedPurchaseResult](#consumeownedpurchaseresult). |



#### OwnedPurchasesReq

Request information of the obtainOwnedPurchases or obtainOwnedPurchaseRecord API.

| Name      | Type      | Description                                                  |
| --------- | --------- | ------------------------------------------------------------ |
| priceType | [PriceType](#pricetype) | Type of a product to be queried.<br/>IN_APP_CONSUMABLE: consumable<br/>IN_APP_NONCONSUMABLE: non-consumable<br/>IN_APP_SUBSCRIPTION: auto-renewable subscription. |
| continuationToken | string | Data location flag for query in pagination mode. This parameter is <b>optional</b> for the first query. After the API is called, the returned information contains this parameter. If query in pagination mode is required for the next API call, this parameter can be set for the second query. |

#### ProductInfoReq

| Name      | Type     | Description                                                  |
| --------- | -------- | ------------------------------------------------------------ |
| priceType | [PriceType](#pricetype)   | Type of a product to be queried.<br/>IN_APP_CONSUMABLE: consumable<br/>IN_APP_NONCONSUMABLE: non-consumable<br/>IN_APP_SUBSCRIPTION: auto-renewable subscription |
| skuIds    | string[] | ID list of products to be queried. Each product ID must exist and be unique in the current app. The product ID is the same as that you set when configuring product information in AppGallery Connect. |

#### PurchaseIntentReq

| Name             | Type   | Description                                                  |
| ---------------- | ------ | ------------------------------------------------------------ |
| productId        | string | ID of a product to be paid. The product ID is the same as that you set when configuring product information in AppGallery Connect. |
| priceType        | [PriceType](#pricetype) | Type of a product to be queried.<br/>IN_APP_CONSUMABLE: consumable<br/>IN_APP_NONCONSUMABLE: non-consumable<br/>IN_APP_SUBSCRIPTION: auto-renewable subscription. |
| developerPayload | string | Information stored on the merchant side. If this parameter is set to a value, the value will be returned in the callback result to the app after successful payment. |
| reservedInfor    | string | This parameter is used to pass the extra fields set by a merchant in a JSON string in the key:value format. |

#### ConsumeOwnedPurchaseReq

| Name               | Type   | Description                                                  |
| ------------------ | ------ | ------------------------------------------------------------ |
| purchaseToken      | string | Purchase token, which is generated by the Huawei IAP server during payment and returned to the app. |
| developerChallenge | string | User-defined challenge, which uniquely identifies a consumption request. It is recorded in the purchase information and returned after the consumption is successful. |
#### StartIapActivityReq

| Name               | Type                                                | Description                                                  |
| ------------------ | --------------------------------------------------- | ------------------------------------------------------------ |
| type               | [StartIapActivityReqType](#startiapactivityreqtype) | Type of the page to be redirected to.<br/>TYPE_SUBSCRIBE_MANAGER_ACTIVITY: subscription management page<br/>TYPE_SUBSCRIBE_EDIT_ACTIVITY: subscription editing page |
| subscribeProductId | string                                              | In-app product ID. <b>Optional </b>parameter. If this parameter is passed, the app will switch to the subscription details page. Otherwise, the app will switch to the subscription management |

#### IsEnvReadyResult

| Name        | Type   | Description  |
| ----------- | ------ | ------------ |
| returnCode  | number | Result code. |

#### IsSandboxActivatedResult

| Name            | Type    | Description                                                  |
| --------------- | ------- | ------------------------------------------------------------ |
| returnCode      | number  | Result code.                                                 |
| errMsg          | string  | Result code description.                                     |
| isSandboxUser   | boolean | Indicates whether a sandbox testing ID is used.              |
| isSandboxApk    | boolean | Indicates whether the app APK version meets the requirements of sandbox testing. |
| versionInApk    | string  | App version information.                                     |
| versionFrMarket | string  | Information about the app version that is last released on HUAWEI AppGallery. |

#### OwnedPurchasesResult

| Name                        | Type     | Description                                                  |
| --------------------------- | -------- | ------------------------------------------------------------ |
| returnCode                  | number   | Result code.                                                 |
| errMsg                      | string   | Result code description.                                     |
| itemList                    | string[] | ID list of found products.                                   |
| inAppPurchaseDataList       | string[] | Information about products that have been purchased but not consumed or about all existing subscription relationships of users using the obtainOwnedPurchases method. Historical consumable information or all subscription receipts, which are returned using the obtainOwnedPurchaseRecord method. |
| inAppSignature              | string[] | Signature character string of each subscription relationship in the InAppPurchaseDataList list. |
| continuationToken           | string   | Data location flag.<br/>If a user has a large number of products and the response contains continuationToken, the app must initiate another call on the current method and pass continuationToken currently received. If product query is still incomplete, the app needs to call the API again until no continuationToken is returned, indicating that all products are returned. |
| placedInappPurchaseDataList | string[] | Subscription relationship information about a user who has performed subscription switchover. |
| placedInappSignatureList    | string[] | Signature string of each subscription relationship in the PlacedInappPurchaseDataList list. |

#### ProductInfoResult

| Name            | Type          | Description                                  |
| --------------- | ------------- | -------------------------------------------- |
| returnCode      | number        | Result code. |
| errMsg          | string        | Result code description.                     |
| skuList | [ProductInfo[]](#productinfo) | List of found products.                      |

#### ProductInfo

| Name                   | Type   | Description                                                  |
| ---------------------- | ------ | ------------------------------------------------------------ |
| productId              | string | Product ID.                                                  |
| priceType              | [PriceType](#pricetype) | Type of a product to be queried.<br/>IN_APP_CONSUMABLE: consumable<br/>IN_APP_NONCONSUMABLE: non-consumable<br/>IN_APP_SUBSCRIPTION: auto-renewable subscription. |
| price                  | string | Displayed price of a product, including the currency symbol and actual price of the product. The value is in the Currency symbolPrice format, for example, ¥0.15. The price includes the tax. |
| microsPrice            | number | Product price in micro unit, which equals to the actual product price multiplied by 1,000,000. For example, if the actual price of a product is US$1.99, the product price in micro unit is 1990000 (1.99 x 1000000). |
| originalLocalPrice     | string | Original price of a product, including the currency symbol and actual price of the product. The value is in the Currency symbolPrice format, for example, ¥0.15. The price includes the tax. |
| originalMicroPrice     | number | Original price of a product in micro unit, which equals to the original product price multiplied by 1,000,000.For example, if the original price of a product is US$1.99, the product price in micro unit is 1990000 (1.99 x 1000000). |
| currency               | string | Currency used to pay for a product. The value must comply with the ISO 4217 standard.Example: USD, CNY, and TRY |
| productName            | string | Product name, which is set during product information configuration. The name is displayed on the checkout page. |
| productDesc            | string | Description of a product, which is set during product information configuration. |
| subPeriod              | string | Unit of a subscription period, which complies with the ISO 8601 standard. For example, P1W indicates 1 week, P1M indicates 1 month, P2M indicates 2 months, P6M indicates 6 months, and P1Y indicates 1 year. This parameter is returned only when subscriptions are queried. |
| subSpecialPrice        | string | Promotional price of a subscription, including the currency symbol and actual price. The value is in the Currency symbolPrice format, for example, ¥0.15. The price includes the tax.This parameter is returned only when subscriptions are queried. |
| subSpecialPriceMicros  | number | Promotional subscription price in micro unit, which equals to the actual promotional subscription price multiplied by 1,000,000. For example, if the actual price of a product is US$1.99, the product price in micro unit is 1990000 (1.99 x 1000000).This parameter is returned only when subscriptions are queried. |
| subSpecialPeriod       | string | Promotion period unit of a subscription, which complies with the ISO 8601 standard. For example, P1W indicates 1 week, P1M indicates 1 month, P2M indicates 2 months, P6M indicates 6 months, and P1Y indicates 1 year. This parameter is returned only when subscriptions are queried. |
| subSpecialPeriodCycles | number | Number of promotion periods of a subscription. It is set when you set the promotional price of a subscription in AppGallery Connect. For details, please refer to Setting a Promotional Price.This parameter is returned only when subscriptions are queried. |
| subFreeTrialPeriod     | string | Free trial period of a subscription. It is set when you set the promotional price of a subscription in AppGallery Connect. For details, please refer to Setting a Promotional Price. |
| subGroupId             | string | ID of the subscription group to which a subscription belongs. |
| subGroupTitle          | string | Description of the subscription group to which a subscription belongs. |
| subProductLevel        | number | Level of a subscription in its subscription group.           |
| status                 | number | Product status.<br/>0: valid.<br/>1: deleted. Products in this state cannot be renewed or subscribed to.6: removed. New subscriptions are not allowed, but users who have subscribed to products can still renew them. |

#### PurchaseIntentResult

| Name             | Type   | Description              |
| ---------------- | ------ | ------------------------ |
| returnCode       | number | Result code.             |
| errMsg           | string | Result code description. |

#### ConsumeOwnedPurchaseResult

| Name                | Type   | Description                                                  |
| ------------------- | ------ | ------------------------------------------------------------ |
| consumePurchaseData | string | Consumption result data. |
| dataSignature       | string | Signature string generated after consumption data is signed using a private payment key. The signature algorithm is SHA256withRSA. |
| returnCode          | number | Result code.                                                 |
| errMsg              | string | Result code description.                                     |

### Constants
#### PriceType

| Name                                  | Value | Description      |
| ------------------------------------- | ----- | ---------------- |
| HMSIAP.PriceType.IN_APP_CONSUMABLE    | 0     | Consumables.     |
| HMSIAP.PriceType.IN_APP_NONCONSUMABLE | 1     | Non-consumables. |
| HMSIAP.PriceType.IN_APP_SUBSCRIPTION  | 2     | Subscriptions.   |


#### StartIapActivityReqType

| Name                                                         | Value | Description                   |
| ------------------------------------------------------------ | ----- | ----------------------------- |
| HMSIAP.StartIapActivityReqType.TYPE_SUBSCRIBE_MANAGER_ACTIVITY | 2     | Subscription management page. |
| HMSIAP.StartIapActivityReqType.TYPE_SUBSCRIBE_EDIT_ACTIVITY  | 3     | Subscription editing page.    |



### Result Codes

| Result Code | Descriptive Name                          | Description                                                  |
| ----------- | ----------------------------------------- | ------------------------------------------------------------ |
| 0           | STATUS_SUCCESS                            | Success.                                                     |
| –1          | STATUS_FAILURE                            | Common error code upon a failure.                            |
| 60000       | ORDER_STATE_CANCEL                        | The user cancels the payment.                                |
| 60001       | ORDER_STATE_PARAM_ERROR                   | Parameter error (including no parameter).                    |
| 60002       | ORDER_STATE_IAP_NOT_ACTIVATED             | HUAWEI IAP is not enabled.                                   |
| 60003       | ORDER_STATE_PRODUCT_INVALID               | Incorrect product information.                               |
| 60004       | ORDER_STATE_CALLS_FREQUENT                | Too frequent API calls.                                      |
| 60005       | ORDER_STATE_NET_ERROR                     | Network connection exception                                 |
| 60006       | ORDER_STATE_PMS_TYPE_NOT_MATCH            | The found product type is inconsistent with that defined in the PMS. |
| 60007       | ORDER_STATE_PRODUCT_COUNTRY_NOT_SUPPORTED | The app to which the product belongs is not released in a specified location. |
| 60020       | ORDER_VR_UNINSTALL_ERROR                  | The VR APK is not installed.                                 |
| 60050       | ORDER_HWID_NOT_LOGIN                      | The HUAWEI ID is not signed in.                              |
| 60051       | ORDER_PRODUCT_OWNED                       | A user failed to purchase a product because the user already owns the product. |
| 60052       | ORDER_PRODUCT_NOT_OWNED                   | A user failed to consume a product because the user does not own the product. |
| 60053       | ORDER_PRODUCT_CONSUMED                    | The product has been consumed and cannot be consumed again.  |
| 60054       | ORDER_ACCOUNT_AREA_NOT_SUPPORTED          | The country or region of the signed-in HUAWEI ID does not support IAP. |
| 60056       | ORDER_HIGH_RISK_OPERATIONS                | The user triggers risk control, and the transaction is rejected. |



## 4. Configuration and Description

### Configuring Obfuscation Scripts

#### React Native

In order to prevent error while release build, you may need to add following lines in **`proguard-rules.pro`** file.

```text
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
-repackageclasses
```

#### Cordova

Before building the APK, configure the obfuscation configuration file to prevent the HMS Core SDK from being obfuscated.

**NOTE**: This step is required only if you want to minify and obfuscate your app. By default obfuscation is disabled in Cordova and Ionic apps.

The obfuscation is done by **`ProGuard`.** By default, in Cordova and Ionic apps ProGuard is disabled. Even though ProGuard is not available, ProGuard support can be added through 3rd party ProGuard plugins. If ProGuard is enabled in your project, the Huawei Cordova IAP plugin's ProGuard rules need to be added to your project. These rules are as follows:

```text
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
-repackageclasses
```

---

## 5. Questions or Issues

If you have questions about how to use HMS samples, try the following options:

- [Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services) is the best place for any programming questions. Be sure to tag your question with **huawei-mobile-services**.
- [Huawei Developer Forum](https://forums.developer.huawei.com/forumPortal/en/home?fid=0101187876626530001) HMS Core Module is great for general questions, or seeking recommendations and opinions.
- [Huawei Developer Docs](https://developer.huawei.com/consumer/en/doc/overview/HMS-Core-Plugin) is place to official documentation for all HMS Core Kits, you can find detailed documentations in there.

---

## 6. Licensing and Terms

Huawei JS SDK is licensed under [Apache 2.0 license](LICENCE).