本文档介绍了联想应用联运移动端订阅SDK接入操作指南,您可在了解文档内容后,自行接入应用联运移动端订阅SDK。
接入前准备
1请先与联想商务达成合作意向。
2.联系联想运营,提供应用和公司信息,并获取商户id、app id、key(公私钥、用于登录和支付校验)、SDK包。
以下为需提供的信息:
2.1商户名称(例:xxx公司)
2.2应用名称
2.3应用图标(建议像素:36*36,png格式)
3.登录联想开放平台,注册开发者账号。
联想开放平台地址:https://open.lenovomm.com/developer/home
隐私政策
SDK本身不会弹出任何隐私协议,隐私协议由应用内自行设计实现,并且在应用的隐私协议中附加联想应用订阅移动端SDK隐私协议。
应用接入了联想移动端订阅SDK,提供登录和支付服务,所收集信息请阅读:协议隐私
安卓端订阅SDK及接入文档下载地址:
下载地址: 联想乐云
(密码:84m8)
阅读对象说明
研发工程师、测试工程师、产品经理
接入联运服务流程
1. 联系联想运营,提供应用和公司信息,获取商户id、appid、key(公私钥、用于登录和支付校验)。
2. 接入联想联运移动端订阅SDK,SDK内包含登录、支付功能。
名词解释
名词 | 解释说明 |
移动端订阅SDK | 指本SDK,由联想提供,用于接入联想的各种基础服务 |
接入方 | 指接入该联运SDK基础服务的各种三方应用 |
应用私钥 | 商户向联运云端发起请求(支付、查询、退款等API接口),进行签名;联运云端使用应用公钥验签 |
平台公钥 | 联运向商户发起通知(支付通知、退款通知),进行签名;商户使用平台公钥验签 |
订阅SDK接入说明
配置说明
1.aar接入
(1) AndroidStudio项目需要把aar包放入libs下,在项目gradle里添加aar;
(2) 需要把sdkDemo里app下assets目录supplierconfig.json添加到项目中;
(3) 混淆配置参考sdkDemo里proguard-rules.pro文件。
2.jar接入
配置项目AndroidManifest内容
添加以下必要权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
需要配置以下内容:
<activityandroid:name="com.lenovo.intermodal.ui.PayActionActivity"android:configChanges="keyboardHidden|orientation|screenSize|navigation|locale| layoutDirection"android:exported="false"android:launchMode="singleTask"android:screenOrientation="portrait" ></activity><activityandroid:name="com.alipay.sdk.app.H5PayActivity"android:configChanges="orientation|keyboardHidden|navigation"android:exported="false"android:screenOrientation="behind" ></activity><activityandroid:name="com.alipay.sdk.app.H5AuthActivity"android:configChanges="orientation|keyboardHidden|navigation"android:exported="false"android:screenOrientation="behind"tools:ignore="MissingClass">
</activity>
初始化接口
注意:每次打开应用后,都需要调用初始化接口,才可调用联想账号登录接口或者支付接口。
接口:
void doInit(Activity context, String appId, String mchId, String privateKey, InitCallback initCallback)
InitCallback定义如下:
interface InitCallback {
void onSuccess(); //初始化成功
void onError(int errorCode, String errorMsg); //初始化失败
}
示例代码:
IntermodalClient.doInit(MainActivity.this, appId, mchId, privateKey,new IntermodalClient.InitCallback() {@Overridepublic void onSuccess() {}@Overridepublic void onError(int errorCode, String errorMsg) {}
});
联想账号接入说明
登录介绍说明
联想账号登录接口
接口定义:应用需要使用联想账号登录时调用此接口登录。
void Login(Activity context, LoginCallback callback);
示例代码:
IntermodalClient.Login(MainActivity.this, new IntermodalClient.LoginCallback() {@Overridepublic void onFinished(boolean ret, String data) {if(ret){Toast.makeText(MainActivity.this, "login success data:"+data, Toast.LENGTH_LONG).show();}else{Toast.makeText(MainActivity.this, "login error data:"+data, Toast.LENGTH_LONG).show();}}
});
联想账号登出接口
接口定义:应用内需给出退出登录的能力,调用此接口实现。
void Logout(Activity context, LogoutCallback callback);
示例代码:
IntermodalClient.Logout(MainActivity.this, new IntermodalClient.LogoutCallback() {@Overridepublic void onFinished(boolean ret, String data) {if(ret){Toast.makeText(MainActivity.this, "logout success data:"+data, Toast.LENGTH_LONG).show();}else{Toast.makeText(MainActivity.this, "logout error data:"+data, Toast.LENGTH_LONG).show();}}
});
支付接入说明
支付介绍说明
支付接入介绍:
(1) 移动端订阅SDK提供联想通用收银台,收银台内支付方式包括微信支付、支付宝支付、聚合码支付;
(2) 支付类型包括普通支付、代扣支付,支付类型可由cp根据业务需要选择性接入。
支付接口
接口定义:
void doPay(Activity context, final PayRequest request, final IPayResultCallback callback);
支付请求定义
联想账号支付请求
(1) 普通支付请求:PayRequest
请求示例代码:
private void payMbLogin(){PayRequest payRequest = new PayRequest();payRequest.mchNo(System.currentTimeMillis()+"");payRequest.attach(attach);payRequest.goodsDesc(goodsDec);payRequest.goodsName(goodsName);payRequest.goodsCode(goodsCode);payRequest.payAmount(payFee);payRequest.payNotify(notifyUrl);IntermodalClient.doPay(MainActivity.this, payRequest,new IPayResultCallback() {@Overridepublic void onPayResult(int requestCode, String signvalue, String resultInfo) {Log.d(TAG, "onPayResult requestCode:"+requestCode+", signvalue:"+signvalue+" resultInfo:"+resultInfo);}});
}
(2) 代扣支付请求:PayDKRequest
请求示例代码:
private void payDkLogin(){PayDKRequest payRequest = new PayDKRequest();payRequest.mchNo(System.currentTimeMillis()+"");payRequest.attach(attach);payRequest.goodsDesc(goodsDec);payRequest.goodsName(goodsName);payRequest.goodsCode(goodsCode);payRequest.payAmount(payFee);payRequest.payNotify(notifyUrl);payRequest.deductionFee(deductionFee);payRequest.deductionPeriod(deductionPeriod);payRequest.firstDeductionDate(firstDeductionDate);payRequest.contractUrl(contractNotify);payRequest.productId(productId);IntermodalClient.doPay(MainActivity.this, payRequest,new IPayResultCallback() {@Overridepublic void onPayResult(int requestCode, String signvalue, String resultInfo) {Log.d(TAG, "onPayResult requestCode:"+requestCode+", signvalue:"+signvalue+" resultInfo:"+resultInfo);}});}
支付结果返回
注:最终用户权益的变更以服务端支付通知的结果为准。
interface IPayResultCallback {public void onPayResult(int requestCode, String msg, String resultInfo);
}
服务端接口说明
支付通知
当用户支付完成后,联运云端将数据post到支付通知地址。商户返回SUCCESS则表示该订单支付通知,商户成功接收。商户返回其它任何字符都代表接收失败。
接收失败后联运云端会再次发送通知。通知触达10次,到达通知次数后,不会触发通知。
Post数据
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
商户ID | mchId | Y | Long | 78993434342 | |
应用ID | appId | Y | Long | 343453453445 | |
签名 | sign | Y | String | 参考签名算法 | |
签名方式 | signType | Y | String | RSA2 | 固定值RSA2 |
版本 | version | Y | String | 1.0 | 固定值1.0 |
编码 | charSet | Y | String | utf-8 | 固定值utf-8 |
随机字符 | nonce | Y | String | dsafsadfasdfasa | 随机字符串 |
商户订单号 | mchNo | Y | String | ||
交易订单号 | tradeNo | Y | Long | 9860494571601920 | 交易订单号 |
银行流水号 | serialsNo | Y | String | 2019090239230923 | 第三方支付渠道的交易流水号 |
支付金额 | payFee | Y | Int | 1 | 支付金额单位(分) |
支付状态 | payStatus | Y | String | 支付状态 1 已支付 | 支付状态 1 已支付 |
支付时间 | payTime | Y | String | 2022-03-23 19:17:56 | yyyy-MM-dd HH:mm:ss |
附加数据 | attach | N | String | Dfasas | 商户私有数据 |
商户需返回参数
SUCCESS
通知示例代码:
{"mchNo": "*********1111", "tradeNo": 969549918857856, "serialsNo": "***********2222", "payFee": 3000, "payTime": "2022-10-19 17:23:12", "payStatus": "1", "appId": 12312312, "mchId": 123123123, "sign": "T2IuyxblOnKstHf7EuJZWGBroSUzwN4n6l6yZ1zahsvGfBDn2AxAhifpPUblbMuq2XHsh9Mvg==", "signType": "RSA2", "version": "1.0", "charSet": "UTF-8", "nonce": "m1wo53f6iy"
}
查询支付结果接口
请求方式:POST
请求头参数说明:Content-Type: application/json
请求Body参数说明:
1.基础参数
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
商户ID | mchId | Y | Long | 96291345 | 分配的商户号 |
应用ID | appId | Y | Long | 11962913 | 商户号下创建的APPID |
随机字符串 | nonce | Y | String | 5K8264ILTKCH16C | 随机字符串,不长于32位 |
时间戳 | timestamp | Y | String | 1648878162182 | 时间戳(从1970-01-01T00:00:00Z开始的毫秒数) |
版本 | version | Y | String | 1.0 | 版本号 固定值1.0 |
签名 | sign | Y | String | 参考签名算法 | |
签名方式 | signType | Y | String | RSA2 | 签名方式RSA2 |
2. 业务参数说明
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
交易订单号 | tradeNo | Y | Long | 524498630711936 |
返回参数说明:
字段名 | 变量名 | 必填 | 类型 | 示例值 |
返回码 | code | Y | String | 10000 |
返回消息 | msg | Y | String | SUCCESS |
返回数据体 | data | N | String |
示例:
请求参数:
{"mchId": 233799539766016,"appId": 233799539766016,"sign": "ngAcXTBZnuuI944ae8pyMY60CpiRILjTm2uX***SEwHG19+aWotz","signType": "RSA2","timestamp": "1666593772589","nonce": "w190bfrrog1666593772585","version": "1.0","tradeNo": 977319841453440,
}
返回参数:
http状态200
{"code": 10000,"message": "Success","data": {"tradeNo": 877319841453440,"serialsNo": "4200001493202206141879749159","payStatus": 1,"payTime": "2022-06-14 11:17:48","payAmount": 1}
}
data 数据说明:
变量名 | 必填 | 类型 | 描述 |
tradeNo | Y | long | 交易订单号 |
serialsNo | N | String | 交易流水号 |
payStatus | Y | Byte | 支付状态:待支付:0,已支付:1 |
payTime | N | String | 支付时间 yyyy-MM-dd HH:mm:ss |
payAmount | Y | BigDecimal | 支付金额单位分 |
错误返回数据:
http状态码:非200
{"code":401,"message":"unauthorizedException","data":null}
{"code":500,"message":"error","data":null}
周期扣款—协议通知
用户签约、解约后,联运云端将数据post到协议通知地址。商户返回SUCCESS则表示该协议通知,商户成功接收。商户返回其它任何字符都代表接收失败。
接收失败后联运云端会再次发送通知。通知触达10次,到达通知次数后,不会触发通知。
Post数据
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
商户ID | mchId | Y | Long | 78993434342 | |
应用ID | appId | Y | Long | 343453453445 | |
签名 | sign | Y | String | 参考签名算法 | |
签名方式 | signType | Y | String | RSA2 | 固定值RSA2 |
版本 | version | Y | String | 1.0 | 固定值1.0 |
编码 | charSet | Y | String | utf-8 | 固定值utf-8 |
随机字符 | nonce | Y | String | dsafsadfasdfasa | 随机字符串 |
商户订单号 | mchNo | Y | String | ||
交易订单号 | tradeNo | Y | Long | 9860494571601920 | 交易号 |
协议状态 | status | Y | String | 状态 1 已完成 2 已解约 | |
变更时间 | changeTime | Y | String | 2022-03-23 19:17:56 | yyyy-MM-dd HH:mm:ss |
返回参数说明:
SUCCESS
通知示例代码:
{"mchNo": "4fcf9d5e-4891-4e","tradeNo": 1066044865591424,"status": "2","changeTime": "2023-03-02 10:48:56","appId": 233799539766016,"mchId": 233799539766016,"sign": "GP*********=","signType": "RSA2","version": "1.0","charSet": "UTF-8","nonce": "ft2u016vvo"
}
其他说明
商户订单号
商户支付的订单号由商户自定义生成,仅支持使用字母、数字、中划线-、下划线_、竖线|、星号*这些英文半角字符的组合,请勿使用汉字或全角等特殊字符。联运服务平台要求商户订单号保持唯一性,同一个应用ID不可重复(建议根据当前系统时间加随机序列来生成订单号)。重新发起一笔支付要使用新订单号,避免重复支付。
金额
交易金额默认为人民币交易,接口中参数支付金额单位为【分】,支付金额必须大于 0,参数值不能带小数,暂不支持外币交易。
日期时间
标准北京时间,时区为东八区;如果商户的系统时间为非标准北京时间。按照各个接口需要日期时间格式的传入。
签名算法
开发者需要自行实现签名,签名过程如下:
1. 筛选并排序
获取所有请求参数,不包括字节类型参数,如文件,字节流,剔除 sign 字段,剔除值为空
的参数,并按照第一个字符的键值 ASCII 码递增排序(字母升序排序),如果遇到相同字符
则按照第二个字符的键值 ASCII 码递增排序,以此类推。
2. 拼接
将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接
起来,此时生成的字符串为待签名字符串。
例如:appId=2018071360678029&sign_type=RSA2&version=1.0
3. 签名
使用各自语言对应的 SHA256WithRSA(对应 signType 为 RSA2)签名函数利用开发者私钥(
名词解释)对待签名字符串进行签名。
4.把生成的签名赋值给 sign 参数,拼接到请求参数中.
5.验签工具:https://cloud-rest.lenovomm.com/front-sign/
版本更新日志
V2.3.0内容变更
变更项 | 接入说明 |
1、新增移动端订阅SDK | 有接入移动端订阅SDK需求的应用可接入; |
2、PC端订阅SDK更新,修复了登录部分bug | 有用户频繁反馈登录问题的应用可集成v2.3.0版本的PC端订阅SDK。 |
常见问题
1.接入订阅 SDK
Q:帐号登录窗口是SDK 弹的吗?
A:是的,SDK 弹出的登录窗口包含了登录、注册、更改密码等功能。
Q:接入联运服务后,开发者的微信、付宝支付是否需要屏蔽,改为联运服务的支付?
A:是的。
Q:是否有接口查询支付结果?
A:支付结果可通过接入文档中的“查询支付结果接口”查询。
Q:用户在收银台支付页面支付成功后,客户端如何知道用户的支付状态?
A:在收银台页面会一直轮询用户的支付状态,支付成功后刷新页面并提醒用户;用户支付
成功后联想的服务端会主动通知应用的服务端,应用的客户端可以主动查询该状态。
Q:客户购买连续包月支付成功后,如何确认是否已完成连续包月签约,以及如何区分后续扣款通知。
A:可以通过接口文档中周期扣款-协议通知部分来确认是否完成包月签约。扣款成功的支付通知里,商户订单号是初次签约支付时的订单号。
Q:连续包月最短扣款周期是多久,扣款都有哪些条件限制?
A:目前最短扣款周期为1个月,扣款条件会受支付通道限制。目前支付宝限制每个用户的单笔扣款不超过 100 元,当日扣款不超过 1000 元,当月扣款不超过 30000 元。
2. 测试
Q:支付和退款是否有测试环境?
A:无测试环境,开发者可将商品设为一个较低的金额(比如 1 分钱)进行测试。
6.3. 发布应用
Q :联运版本的应用如何发布?
A:参与联运的应用首次上架及后续版本更新,开发者需将应用包发送给联想接口人,由联
想进行配置上架。
移动端应用订阅SDK下载
名称 | 开发者 | 版本号 | 主要功能 | 版本描述 | 更新时间 | 个人信息处理规则 | 合规使用说明 | 下载地址 |
移动端订阅SDK | 北京神奇工场科技有限公司 | V1.0.2 | 登录、支 付 | 此版本更新内容: 1、修改了隐私文档中关于IMEI获取及个性化推送的说明; 2、删除SDK读取序列号的系统方法,取消了不必要的调用;请下载解压后使用(包括Demo演示和开发文档 | 2023/12/28 | 见协议隐私 | 见联想开放平台 | 联想乐云 (密码:84m8) |
移动端应用订阅SDK合规使用说明
更新时间:2024-01-26
根据《个人信息保护法》、《数据安全法》、《网络安全法》等法律法规和监管部门规章要求,App开发运营者(以下简称为“开发者”)在提供网络产品服务时应尊重和保护最终用户的个人信息,不得违法违规收集使用个人信息,保证和承诺就个人信息处理行为获得最终用户的授权同意,遵循最小必要原则,且应当采取有效的技术措施和组织措施确保个人信息安全。为帮助开发者在使用移动端应用订阅SDK的过程中更好地落实用户个人信息保护相关要求,避免出现侵害最终用户个人信息权益的情形,特制定本合规使用说明,供开发者在接入使用移动端应用订阅SDK服务时参照自查和合理配置,不断提升个人信息保护水平。
移动端应用订阅SDK配置能力说明
1. SDK扩展业务功能的配置说明
要求内容:《SDK合规使用说明》应详细说明SDK各项扩展业务功能介绍及对应关闭的配置方式、示例。
接入说明:应用订阅移动端SDK提供的基本业务功能是为开发者应用提供联想账号登录、以及支付的技术服务,开发者可以通过接入应用订阅移动端SDK在其应用内为最终用户提供登录、支付的功能或服务。目前不涉及提供其他扩展业务功能,如后续提供其他扩展业务功能,将通过本合规使用说明向开发者详细介绍具体的扩展业务功能及其关闭配置方式和示例。
2. SDK可选个人信息的配置说明
要求内容:《SDK合规使用说明》应详细说明SDK各项可选个人信息使用目的、场景及对应关闭的配置方式、示例。
接入说明:对于应用订阅移动端SDK可选收集的个人信息的控制,开发者可以参考如下配置文档的内容进行配置操作。因相关信息的不收集将会对其对应的功能造成影响,请开发者结合业务实际需要进行合理配置。配置文档链接:
联想开放平台
应用订阅移动端SDK可选个人信息的说明:
可选个人信息类型及字段 | 使用目的 | 使用场景 | |
设备信息 | 设备唯一标识码(IMEI、OAID(针对Android Q以上版本))、Android ID、MAC地址、设备型号、制造商、系统、应用版本信息、屏幕分辨率、网络类型、运营商信息。 | 为开发者提供联想账号登录的技术服务,保障正常的登录流程。 | 若开发者的应用需要接入联想账号的登录功能,则在用户登录联想账号时使用。 |
3. SDK可按照不同频次、精度收集个人信息的配置说明
要求内容:如果SDK可按照不同频次、精度收集个人信息的,《SDK合规使用说明》应说明不同频次、精度的使用目的、场景及对应选择的配置方式、示例。
接入说明:收集频次方面,应用订阅移动端SDK的数据采集仅在App调用/最终用户触发相关功能时触发,不涉及定时逻辑等频次控制选项。收集精度方面,应用订阅移动端SDK不涉及可根据精度收集个人信息的情形。
4. SDK申请系统权限的说明
要求内容:《SDK合规使用说明》应详细说明SDK所需的系统权限与各业务功能间的关系,并说明权限申请时机。
接入说明:对于应用订阅移动端SDK可选申请的系统权限,您可以参考相关如下表格的内容,详细了解相关权限与各业务功能的关系及其申请时机,因相关权限的不申请将会对其对应的功能造成影响,您可以结合业务实际需要进行合理配置。配置文档链接:联想开放平台
权限名称 | 调用权限的目的 | 是否询问 | 可否关闭权限 | 关闭权限对相应功能的影响 |
允许访问网络 | 连接网络 | 跟随接入的三方应用询问访问 | 否 | 无法登录支付 |
获取wifi网络状态 | 连接网络 | 跟随接入的三方应用询问访问 | 否 | 无法登录支付 |
获取移动网络状态 | 连接网络 | 跟随接入的三方应用询问访问 | 否 | 无法登录支付 |
允许使用相机权限 | 扫一扫 | 使用此功能前会询问 | 是 | 无法完成扫一扫相关的功能 |
允许使用相机打开灯光 | 扫一扫 | 使用此功能前会询问 | 是 | 扫一扫时无法打开灯光 |
5. SDK初始化及业务功能调用时机
要求内容:《SDK合规使用说明》应详细说明SDK初始化及各项业务功能接口合规调用时机,如最终用户选择使用第三方登录方式后,初始化某第三方登录SDK。App应当在App登录注册页面及App首次运行时,通过弹窗、文本链接及附件等简洁明显且易于访问的方式,向最终用户告知涵盖个人信息处理主体、处理目的、处理方式、处理类型、保存期限等内容的个人信息处理规则,并且获得最终用户授权同意后才能处置最终用户数据。
接入说明:应用订阅移动端SDK初始化时会获取用户的IMEI和mac地址,请务必在用户同意您App种的隐私政策之后,再进行应用订阅移动端SDK的初始化。用户同意隐私政策之前,避免动态申请涉及用户个人信息的敏感设备权限;用户同意隐私政策前,您应避免私自采集和上报个人信息。具体的初始化时机可以详细查阅相关接入文档的内容。具体配置文档链接:
联想开放平台
6. SDK隐私政策披露要求与示例
要求内容:《SDK合规使用说明》应提供App向最终用户披露SDK隐私政策条款的示例,包括SDK名称、公司名称、处理个人信息种类及目的、采集方式、隐私政策链接等内容。
接入说明: 开发者在App集成应用订阅移动端SDK后,应用订阅移动端SDK的正常运行会收集必要的最终用户信息。 请开发者根据集成应用订阅移动端SDK的实际情况,在您App的隐私政策中,对应用订阅移动端SDK名称、公司名称、处理个人信息种类及目的、采集方式、隐私政策链接等内容进行披露。建议:确认您所接入的应用订阅移动端SDK版本和功能模块;根据上述版本和模块,从隐私政策中确定与应用订阅移动端SDK交互的数据内容;在您App的隐私政策中,以文字或列表的方式向公众披露应用订阅移动端SDK的相关信息。
披露示例(仅供参考,请以实际合作情况为准):
SDK名称:应用订阅移动端SDK
涉及个人信息:设备唯一标识码(IMEI、OAID(针对Android Q以上版本))、Android ID、MAC地址、设备型号、制造商、系统、应用版本信息、屏幕分辨率、网络类型、运营商信息、wifi状态
合作方主体:北京神奇工场科技有限公司
使用目的:是为开发者应用提供联想账号登录、以及支付的技术服务,开发者可以通过接入应用订阅移动端SDK在其应用内为最终用户提供登录、支付的功能或服务。
使用场景:向最终用户登录联想账号或者支付时使用
收集方式:SDK自行采集
隐私政策链接:协议隐私
7. 最终用户同意方式的示例
要求内容:《SDK合规使用说明》应详细说明App获取最终用户授权同意的建议方式,其中需要取得最终用户单独同意的,应显著提示并给出示例。
接入说明:App首次运行时应当有隐私弹窗,隐私弹窗中应公示简版隐私政策内容并附完整版隐私政策链接,并明确提示最终用户阅读并选择是否同意隐私政策;隐私弹窗应提供同意按钮和拒绝同意的按钮,并由最终用户主动选择。
8. 最终用户行使权利的配置说明
要求内容:最终用户对其个人信息的处理享有知情、决定、查阅、复制、补充、更正、撤回授权同意、删除、注销账号等权利。以嵌入接口形式向最终用户提供行使权利的,应提供接口调用方式、示例。
接入说明:开发者在其App中集成应用订阅移动端SDK后,应用订阅移动端SDK的正常运行会收集必要的最终用户信息。开发者应根据相关法律法规为最终用户提供行使个人信息主体权利的路径或功能, 需要应用订阅移动端SDK配合的,请与应用订阅移动端SDK及时进行联系,我们将与开发者协同妥善解决最终用户的诉求。
原文地址https://open.lenovomm.com/developer/doc?id=1672793830201233409
联想开放平台地址:联想开放平台
联想开发者专属QQ客服(工作日9:30-18:00):联想开发平台首页右侧悬浮的在线客服聊天入口可直接会话,无需添加好友。也可搜索官方客服QQ号2881414004。
联想应用商店微信公众号: