# Getting Open Data from Server

Open data provided by Weixin can be fetched by Mini Programs via various client APIs. While developer server can also get such data by following the methods below:

# Method 1: The developer verifies and decrypts open data in the backend

Weixin will sign and encrypt open data. After receiving the open data, the developer can verify the signature of such data and decrypt it in the backend, to ensure that they have not been tampered with.

Signature verification and data encryption/decryption involves the user's session_key. The developer should first get session_key via the wx.login login process and save it on the server. To prevent the data from being tampered, the developer should not pass the session_key to the Mini Program client or other environments outside of the server.

# Data signature verification

To ensure the security of the user data returned via the open API, the plaintext data will be signed in Weixin. The developer can verify the signature of the data package as per the business requirements to ensure data integrity.

  1. When an API (such as wx.getUserInfo) is called to get data, it will return both rawData and signature, where signature = sha1 (rawData + session_key).
  2. The developer sends signature and rawData to the developer server for verification. The server uses the user's session_key to calculate signature2 with the same algorithm, and compares signature and signature2 to verify the data integrity.

For example, to verify the data for wx.getUserInfo:

rawData returned by the API:

{
  "nickName": "Band",
  "gender": 1,
  "language": "zh_CN",
  "city": "Guangzhou",
  "province": "Guangdong",
  "country": "CN",
  "avatarUrl": "http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0"
}

The user's session-key:

HyVFkGl5F5OQWJZZaNzBBg==

The string for signing is:

{"nickName":"Band","gender":1,"language":"zh_CN","city":"Guangzhou","province":"Guangdong","country":"CN","avatarUrl":"http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0"}HyVFkGl5F5OQWJZZaNzBBg==

The result returned when data is signed using sha1:

75e81ceda165f4ffa64f4068af58c64b8f54b88c

# The decryption algorithm for encrypted data

If an API involves sensitive data (such as openId and unionId in wx.getUserInfo), the plaintext content in the API will not include such data. To fetch the sensitive data, the developer needs to symmetrically decrypt the encrypted data (encryptedData) returned via the API. The decryption algorithm is as follows:

  1. The algorithm used for symmetrical decryption is AES-128-CBC, and the data is filled using PKCS#7.
  2. The target cryptogram for symmetrical decryption is Base64_Decode(encryptedData).
  3. The key for symmetrical decryption: aeskey = Base64_Decode(session_key), which is 16 bytes.
  4. The initialization vector of the symmetrical decryption algorithm is Base64_Decode(iv), where iv is returned by the data API.

Sample codes in multiple programming languages are provided by Weixin ((Click to download). The names of APIs used for each programming language are the same. For call methods, see examples.

In addition, to allow apps to verify the data validity, watermark will be added to sensitive data.

watermark parameters:

Parameter Type Description
appid String The appId of the Mini Program where the sensitive data belongs to. The developer can verify if this parameter is the same as his/her appId.
timestamp Int The timestamp when sensitive data is fetched. The developer can use it to check the timeliness of the data.

Example of watermark in the sensitive data of the wx.getUserInfo API:

{
    "openId": "OPENID",
    "nickName": "NICKNAME",
    "gender": GENDER,
    "city": "CITY",
    "province": "PROVINCE",
    "country": "COUNTRY",
    "avatarUrl": "AVATARURL",
    "unionId": "UNIONID",
    "watermark":
    {
        "appid":"APPID",
        "timestamp":TIMESTAMP
    }
}

Note:

  1. The json data obtained via decryption may include new fields according to specific requirements, and old fields remain unchanged and will not be deleted. The developer needs to reserve enough space.

# Validity of session_key

In case of signature validation failure or decryption failure due to incorrect session_key, the developer should note the following.

  1. When wx.login is called, the user's session_key may be updated, causing the old session_key to be invalid. (The refresh mechanism has the shortest cycle. If a user calls wx.login several times in a short time, not every call results in the refresh of session_key.) The developer should call wx.login only when they are clearly requested to log in again, and they should use the auth.code2Session API to update the session_key stored on the server.
  2. The validity period of session_key will not be shared to developers in Weixin. We will renew session_key according to the user's behaviors to use the Mini Program. The more frequently the user uses the Mini Program, the longer will be the validity period of session_key.
  3. When session_key expires, developers can re-run the login process to obtain a valid session_key. The wx.checkSession API can be used to verify the session_key, so that the Mini Program will not be logged in repeatedly.
  4. When developers implement a custom login status, they can choose to use the validity period of the session_key as that of their own login status, or use a custom timeliness policy.

# Method 2: The open data is obtained directly via cloud call

If an API (such as wx.getWeRunData) involves sensitive data, the plaintext content in the API will not include such data. However, the cloudID field of the sensitive data will be included in the returned API, and data can be obtained via the cloud function, as shown below:

1. Get cloudID

When base library 2.7.0 and later is used, if Cloud Base is activated for the Mini Program, the cloudID can be obtained via the cloudID field (the same level as encryptedData) in return value of the open data API. cloudID is valid for 5 minutes.

2. Call cloud function

When the cloud function is called, if the value of a top-level field is CloudID constructed via wx.cloud.CloudID for the incoming data parameter, the value of such field will be replaced with the open data corresponding to the cloudID. Up to 5 CloudID can be replaced in a call.

Example:

A call is initiated after the Mini Program obtains the cloudID:

wx.cloud.callFunction({
  name: 'myFunction',
  data: {
    weRunData: wx.cloud.CloudID('xxx'), // This CloudID value will be replaced via the cloud function.
    obj: {
      shareInfo: wx.cloud.CloudID('yyy'), // The CloudID of non-top fields will not be replaced and will be displayed as the original string.
    }
  }
})

Example of event received in the cloud function:

// event
{
  // The value of weRunData has been replaced with open data
  "weRunData": {
    "cloudID": "xxx",
    "data": {
      "stepInfoList": [
        {
          "step": 5000,
          "timestamp": 1554814312,
        }
      ],
      "watermark": {
        "appid": "wx1111111111",
        "timestampe": 1554815786
      }
    }
  },
  "obj": {
    // Non-top level field remains unchanged
    "shareInfo": "yyy",
  }
}

If cloudID is invalid or expires, an object with error code, error message and original cloudID will be obtained from event. See the example below:

// event
{
  "weRunData": {
    "cloudID": "xxx",
    "errCode": -601006,
    "errMsg": "cloudID expired."
  },
  // ...
}