360安卓应用接入文档
版本号 |
修改时间 |
内容 |
修改人 |
确认人 |
0.5 |
2012-09-19 |
初稿 |
东玮、蔡文华、张玉智、佘帅 |
|
360应用开放平台 2012年09月19日
1. 概述
目前360开放平台为接入的应用提供登录服务与支付服务。安卓应用接入,需要先在http://dev.app.360.cn/上提交一个手机应用,获得app key与app secret后,按文档描述的流程,调通相关接口,即可完成接入。
2. 基本技术流程
接入分为登录授权流程与支付流程。通过登录授权流程,安卓应用可以获得当前用户的access token, 以此可获得当前用户的登录信息等。获得用户id后,应用可以接入360的支付系统。同时SDK也增加了用户试玩流程,应用接入SDK传递不同参数,即可直接获得试玩用户信息。
具体登录授权流程如图:
图1.安卓应用接入的登录授权与支付流程
3. 登录授权流程
3.1 流程介绍
图1中,1-8步为登录授权流程,详细描述如下:
(1). 应用调用SDK登录相关接口
(2).SDK展示服务端的页面,引导用户完成登录、授权
(3).服务端返回auth code或access token给SDK
(4).SDK返回auth code或access token给应用
(5).应用使用auth code直接调用360服务端接口换取access token。如果应用在(1)选择了token模式,可以跳过此步。token模式安全性较差,可能会造成access token泄露,一般只推荐无服务端的应用使用。
(6).应用使用access token直接调用360服务端接口获得用户信息
(7).需要把360PaySDK_Project工程里drawable-hdpi目标下qihoo_pay_game_icon.jpg图片
换成应用自己风格的图片。
图2登录页 图3 授权页
3.2 接口介绍
3.2.1 登录接口
接口名:
接口调用方法:应用客户端调用SDK
简介:
此接口对应图1的1-4步,应用通过调用SDK,SDK会引导用户进行登录与授权。最终, code模式会返回auth code,token模式会直接返回access token。
推荐应用接入code模式,本模式安全性高。具体参见3.1(5),(6)步骤说明
参数说明:
参数 |
必选 |
参数说明 |
key |
true |
参数为应用申请的key值 |
Response_type |
true |
参数可以token或code,具体参见3.1(5)(6)步骤说明 |
state |
false |
参数可以自定义,并登录成功后返回,如果没有就不填写 |
Display |
true |
参数必需为mobile.pay_v2 |
Redirect_uri |
true |
参数必需为oob |
Scope |
true |
参数为basic |
使用说明:
(1). 配置AndroidManifest.xml
您需要在您的工程AndroidManifest.xml里面添加权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
添加activity:
<activity
android:name="com.qihoopay.android.activity.QiHooPayOrderInfo"
android:screenOrientation="portrait" >
</activity>
<activity
android:name="com.qihoopay.android.activity.QiHooLoginWeb"
android:configChanges="orientation|keyboardHidden|navigation"
android:screenOrientation="portrait" >
</activity>
<activity
android:name="com.qihoopay.android.activity.QiHooPayWeb"
android:configChanges="orientation|keyboardHidden|navigation"
android:screenOrientation="portrait" >
</activity>
(2). 将资源工程360PaySDK_Project以lib工程的方式增加到您的工程里或者直接把360PaySDK_Project工程里的所有资源直接复制到您的工程相应的包里面。
(3). 将qihoo_pay_sdk_client.jar包加入到您的工程libs目录下,如果没有就建一个libs目录。
(4). 360帐号登录:
QiHooLoginInfologinInfo = newQiHooLoginInfo();
loginInfo.setClient_id(key);// 此参数为应用申请的key值
loginInfo.setResponse_type("token"); //参数可以token或code
loginInfo.setState("state");//可以自定义参数,如果不需要自定义不设置
loginInfo.setDisplay("mobile.pay_v2"); // 此参数为mobile.pay_v2
loginInfo.setRedirect_uri("oob"); //此参数为oob
loginInfo.setScope("basic"); //此参数为basic
QiHooPay.login(QiHooPayMain.this, loginInfo);
登录返回结果:
@Override
protectedvoidonActivityResult(intrequestCode, intresultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (data == null) {
return;
}
switch (requestCode) {
caseQiHooPay.LOGIN_RESULT_CODE:
String result = data.getStringExtra(QiHooPay.LOGIN_RESULT_BACK);
JSONObjectresultJson;
try {
resultJson = newJSONObject(result);
//判断是否为试玩模式,试玩将直接返回试玩用户信息给应用
if ((Boolean) resultJson.get("trials_mode")) {
//得到试玩模式的用户信息
getTrialsInfo(resultJson);
} else {
//得到登录模式的用户信息
getLoginInfo(resultJson);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
privatevoidgetLoginInfo(JSONObjectresultJson) throwsJSONException {
// 如果loginInfo.setResponse_type("token"),参数为token则返回结果为token
String token = resultJson.getString("code");//token不为空代表登录成功
// 如果loginInfo.setResponse_type("code"),参数为code则返回结果为code
// String code = data.getStringExtra(QiHooPay.LOGIN_RESULT_BACK_CODE);
if (!TextUtils.isEmpty(token)) {
JSONObjectuserJson = newQiHooPayMobileSecurePayHelper(this)
.sendHttpRequest("https://openapi.360.cn/user/me.json?access_token="
+ token);
if (userJson == null)
return;
try {
userId = userJson.getString("id");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
privatevoidgetTrialsInfo(JSONObjectresultJson) throwsJSONException {
String name = resultJson.getString("name");// 试玩用户名
userId = resultJson.getString("id");// 试玩用户id,用来支付用的
String avatar = resultJson.getString("avatar");// 试玩用户图像url
}
3.2.2 获取access token
当应用选择code模式时,3.2.1将得到auth code,需要此步骤将auth code更换为access token。
接口名:/oauth2/token
接口调用方法:应用服务端调用360服务端
具体请参见文档:
2.1.3通过Authorization Code获取Access Token
3.2.3 获取用户信息
接口名:/user/me
接口调用方法:应用服务端调用360服务端
具体请参见文档:
http://wiki.dev.app.360.cn/index.php?title=PHP_API%E6%96%87%E6%A1%A3
特殊说明:获取用户信息后,应用需要保存自身账号与360账号绑定关系,或者完全使用360的账号系统。在支付时,需要使用本步骤保存的用户id
4. 支付
4.1 流程介绍
图1中,9-14步为支付流程,详细描述如下:
(9).应用调用SDK支付接口
(10).SDK展示支付页面,引导用户完成支付流程
(11).服务端回调应用加钱接口
(12)(13).应用调用服务端订单确认接口,服务端返回确认结果
(14).应用为用户加钱,并返回ok给360服务端
图4 支付渠道选择页
4.2 接口介绍
4.2.1 支付接口
接口名:
接口调用方法:应用客户端调用SDK
参数说明:
QiHooPayInfo
参数 |
必选 |
参数说明 |
数据格式 |
QiHooPayInfo类的参数1 |
true |
支付产品名称 |
50位varchar(utf8) |
QiHooPayInfo类的参数2 |
true |
总价,单位:分,支付产品总价 |
10字节unsigned int |
app_key |
true |
应用App key(加入签名) |
100位varchar |
private_key |
true |
参数为APP_SECRET的值 如果参数sign_attr = 1 ,1表示签名密钥使用处理过的APP_SECRET,APP_SECRET处理方法:md5(app_secret+”#”+app_key) 如果sign_attr不填,不处理APP_SECRET。 |
|
notify_uri |
true |
应用加钱接口uri,此字段为必传字段 |
255位varchar |
product_id |
true |
支付产品id |
36位varchar |
app_user_name |
false |
用户在应用内的用户名, 如果mode=1,此字段为必传字段 |
50位varchar(utf8) |
app_user_id |
false |
用户在应用内的用户id,如果mode=1,此字段为必传字段 |
50位varchar(utf8) |
false |
应用扩展信息1,应用可以利用此字段传递应用内部订单号 |
255位varchar(utf8) |
|
app_ext2 |
false |
应用扩展信息2 |
255位varchar(utf8) |
user_qihoo_id |
true |
360账号id |
20字节unsigned bigint |
sign_attr |
false |
如果参数sign_attr = 1 ,1表示签名密钥使用处理过的APP_SECRET,APP_SECRET处理方法:md5(app_secret+”#”+app_key) 如果sign_attr不填,不处理APP_SECRET。 |
非必选参数,可以不加入充值请求的url,如果加入充值请求的url,这些参数的值可以为空。
必选参数,必须加入充值请求的url,而且参数值必须不为空,不为0
签名算法在前端sdk接入时候,sdk给于了封装,但是在后端支付成功后,服务间进行通信时候,需要应用自行按照签名算法校验开发平台的通知参数的合法性,具体签名算法可参见附录.
关于应用方订单号的问题:我们不校验应用方的的订单号是否重复,我们通知应用方加钱时,会提供我们的订单号,有可能应用方收到两笔成功订单,两笔订单有不同的360订单号,但是有同一个应用订单号,这种情况表示是两个不同的订单,请应用为两个订单加钱。另外如果360订单号是同一个,通知了应用两次,请应用只加一次钱。
使用说明:
在点击支付按钮加入下面类似代码,参数可以由开发者自己定义:
QiHooPayInfopayInfo = newQiHooPayInfo("愤怒小鸟注册码360版本", "1");
payInfo.setAppKey("8689e00460eabb1e66277eb4232fde6f");
payInfo.setProductId("1");
payInfo.setNotifyUri("http://www.example.com/notify.php");
payInfo.setAppUserName("小宝");
payInfo.setAppUserId("1888");
payInfo.setQiHooUserId("48318605");//通过登录成功后返回的参数去取得奇虎用户id
payInfo.setPrivate_key("6b74b02c23942045f6f5778de306b693");// 与Key对应的密钥
// 调用支付方法
QiHooPay.pay(this, payInfo);
下面是关于所有参数说明
/**
* @paramproductName
* 支付产品名称
* @param amount
* 需要支付的总价,单位:分,比如amount=100则价格为1元
*/
publicQiHooPayInfo(String productName, String amount) {
this.productName = productName;
this.amount = amount;
}
/**
* @paramappKey
* 应用App key
*/
publicvoidsetAppKey(String appKey) {
this.appKey = appKey;
}
/**
* @paramnotifyUri
* 应用加钱接口uri
*/
publicvoidsetNotifyUri(String notifyUri) {
this.notifyUri = notifyUri;
}
/**
* @paramreturnUri
* 可以为null,如果不为null,则在支付成功页上点击“确定”后,反调此地址
有则加入签名。在支付成功页上点击“确定”,如果提交的是一个地址,就跳转到相应地址,如果是javascript_callback, 我们触发SDK去回调应用指定的一个js函数(页面无法回调,因为有跨域问题)
*/
publicvoidsetReturnUri(String returnUri) {
this.returnUri = returnUri;
}
/**
* @paramproductId
* 支付产品id
*/
publicvoidsetProductId(String productId) {
this.productId = productId;
}
/**
* @paramappUserName
* 用户在应用内的用户名
*/
publicvoidsetAppUserName(String appUserName) {
this.appUserName = appUserName;
}
/**
* @paramappUserId
* 用户在应用内的用户id
*/
publicvoidsetAppUserId(String appUserId) {
this.appUserId = appUserId;
}
4.2.2 应用加钱接口
接口调用方法: 此接口由应用方提供,360服务端调用应用方接口
具体请参见文档:
http://wiki.dev.app.360.cn/index.php?title=%E5%BA%94%E7%94%A8%E6%94%AF%E4%BB%98%E6%96%87%E6%A1%A3#3.3.E3.80.81.E5.BA.94.E7.94.A8.E5.8A.A0.E9.92.B1.E6.8E.A5.E5.8F.A3 (线上的文档描述了具体的流程,但是参数有所改变,以下均是如此)
手机支付的参数如下:
参数 |
必选 |
参数说明 |
数据格式 |
app_key |
true |
应用App key(加入签名) |
100位varchar |
product_id |
true |
支付产品id |
36位varchar |
amount |
true |
总价,单位:分 |
10字节unsigned int |
app_uid |
true |
用户在应用内的用户id |
50位varchar(utf8) |
app_ext1 |
false |
应用扩展信息1,应用可以利用此字段传递应用内部订单号 |
255位varchar(utf8) |
app_ext2 |
false |
应用扩展信息2 |
255位varchar(utf8) |
user_id |
false |
360账号id |
20字节unsigned bigint |
order_id |
true |
应用平台接口生成的订单号,唯一,排重 |
100位varchar |
gateway_flag |
false |
如果支付返回成功,返回success,如果支付过程断路,返回空,如果支付失败,返回fail |
10位varchar |
sign_type |
true |
签名算法 |
目前仅支持sign_type=md5 |
sign_return |
true |
应用回传给订单核实接口的参数,不加入签名校验计算 |
|
sign |
true |
提取的签名(签名方法如下),不加入签名校验计算 |
应用接收到支付平台回调的请求,参见附录的签名算法对参数进行签名,然后和平台传递的签名sign比较,从而校验平台请求的合法性.
(校验时候需要去掉sign_return这个参数,该参数不加入签名的计算)。
4.2.3 订单核实接口
接口调用方法:应用服务端调用360服务端
具体请参见文档:
本接口由360服务端提供,目的是让应用收到支付通知时候,前来确认加钱请求是否合法
目前测试地址为:
https://testol.openapi.360.cn/pay/verify_mobile_notification.json?参数
上线后为:
https://openapi.360.cn/pay/verify_mobile_notification.json?参数
参数如下:
参数 |
必选 |
参数说明 |
数据格式 |
app_key |
true |
应用App key |
100位varchar |
product_id |
true |
支付产品id |
36位varchar |
amount |
true |
总价,单位:分 |
10字节unsigned int |
app_uid |
true |
用户在应用内的用户id (pay_mode=21) |
50位varchar(utf8) |
order_id |
true |
应用平台接口生成的订单号,唯一,排重 |
100位varchar |
sign_type |
true |
签名算法 |
目前仅支持sign_type=md5 |
sign_return |
true |
应用回传给订单核实接口的参数 |
sign_return |
client_id |
true |
应用id,同app_key |
该参数为第三方应用增加 |
client_secret |
true |
应用密钥。同app_secret(注意不加处理) |
该参数为第三方应用增加 |
本表除client_id和client_secret为第三方应用增加外,其他参数按照平台给应用的参数原封返回即可。
订单核实接口返回为json
{
"ret":"verified"
}
表示支付成功。
{
"ret":"invalid"
}
表示支付失败。
应用在完成以上两个接口的流程后,输出一个 ok(小写)的字样给360服务器端,360服务器端即会标识此次支付流程完毕。
4.2.4 补单、对账机制
请参见:
http://wiki.dev.app.360.cn/index.php?title=%E5%BA%94%E7%94%A8%E6%94%AF%E4%BB%98%E6%96%87%E6%A1%A3
5. 附录:
5.1 签名算法:
签名算法不区分前后端,只要在需要签名的地方,均采用如下的算法,和语言,平台,逻辑均无关系
1. 非必选参数,可以不加入充值请求的url,如果加入充值请求的url,这些参数的值可以为空。
必选参数,必须加入充值请求的url,而且参数值必须不为空,不为0
2. 所有不为空,不为0的参数都需要加入签名,计算签名前保证参数为utf-8编码,并且不需要urlencode.
3.对所有不为空的参数按照名称字母升序排列(ksort).不用包含sign参数
4.使用符号#拼装经过ksort之后的value部分。再使用#连接上平台提供给应用的app_secret,使用md5进行签名,赋值给sign
5.拼装url进行传递(这个时候需要对value部分进行urlencode)
范例如下:
// 准备签名参数 $input = array(…); /* 去掉为空的字段 */ foreach($input as $k=>$v) { if(empty($v)){ unset($input[$k]); } } ksort($input);//对参数按照key进行排序 $sign_str = implode('#',$input);//第四步 $sign_str = $sign_str.'#'.$sign_key;//拼装密钥(如果是签名,密钥为约定处理后的密钥) $sign = md5($sign_str); $input['sign'] = $sign;//得到签名 /* 第五步得到url传递即可*/ //这里地址就是一个演示的接口地址 $url = 'https://openapi.360.cn/page/pay?'.http_build_query($input);header("Location:".$url); exit; |