手机网络游戏SDK集成指南
小米游戏中心手机网络游戏SDK接入包括有服务器和客户端两部分。
有任何技术问题,欢迎到游戏开发者论坛吐槽,寻求帮助。
赶快适配小米平板吧! 小米平板接入最佳实践
在继续看文档之前,建议您先把随本文档一起分发的两个Demo程序安装到手机上,(SDK_Demo_OfflineGame.apk和SDK_Demo_OnlineGame.apk,上面SDK中已包含),这两个程序完整演示了小米游戏SDK的工作流程,有助于您快速理解我们SDK支付的整个流程。
修订记录:
v3.3.7 接口无变化
1 网络游戏流程概述
网络游戏开发者需要管理用户登录,并且需要记录用户登录状态,用户每次启动游戏时,必须调用 miLogin()来判断用户会话是否超时,在游戏过程中如果需要充值可以调用 miUniPayOnline()。
注意:在调用miLogin()函数之前,需要1)在开发者站申请并绑定有效的appId/appKey、2)配置应用内支付模块。
1.1网游用户开户及登录流程
注意:
UID 不是小米 ID,但与小米 ID 有对照关系;
请开发者一定要使用这个 UID 作为用户标识,不要使用本机IMEI或IMSI
未来游戏平台支持一个小米ID对应多个UID,从而实现用户在单款游戏中创建多角色的功能。
1.2 网游用户使用米币充值流程
2 SDK调用方法
对于开发者来说,只需要按以下操作引入代码即可完成网络游戏支付流程。
2.1初始化
在小米开发者创建应用并获取 AppId 、AppKey和AppSecretKey,创建应用时packageName必须以“.mi”为后缀。
将 SDK 包中的 MiGameCenterSDKService.apk 放到应用工程的的 assets 目录下, SDK 的 jar 包放到工程的 libs 下,在 buildpath 中引用,然后对 SDK 进行初始化。
注意: 需要检查下面的一致性,如果不一致会导致调用登录和其它 SDK 接口失败
1.游戏的包名是否与提供给小米后台数据配置的包名一致;
2.AppId与 AppKey是否与申请的一致。
然后在Application.onCreate中调用以下初始化方法
MiAppInfo appInfo = new MiAppInfo();
appInfo.setAppId("请申请获得");
appInfo.setAppKey("请申请获得");
appInfo.setAppType(MiGameType.online); // 网游
MiCommplatform.Init( this, appInfo );
SDK 所需要的权限
2.2 小米账户登录调用代码
//可以通过实现OnLoginProcessListener接口来捕获登录结果
MiCommplatform.getInstance().miLogin( context, new OnLoginProcessListener(){
@Override
publicvoidfinishLoginProcess( intcode,MiAccountInfoarg1) {
switch( code ) {
case MiErrorCode.MI_XIAOMI_GAMECENTER_SUCCESS:
// 登陆成功
//获取用户的登陆后的 UID(即用户唯一标识)
long uid = arg1.getUid();
//获取用户的登陆的 Session(请参考 3.3用户session验证接口)
String session = arg1.getSessionId();//若没有登录返回 null
//请开发者完成将uid和session提交给开发者自己服务器进行session验证
break;
case MiErrorCode.MI_XIAOMI_GAMECENTER_ERROR_LOGIN_FAIL:
// 登陆失败
break;
case MiErrorCode.MI_XIAOMI_GAMECENTER_ERROR_CANCEL:
// 取消登录
break;
case MiErrorCode.MI_XIAOMI_GAMECENTER_ERROR_ACTION_EXECUTED:
// 登录操作正在进行中
break;
default :
// 登录失败
break;
}
}
2.3 虚拟币充值调用
MiBuyInfoOnline online = new MiBuyInfoOnline();
online.setCpOrderId(UUID.randomUUID().toString()); //订单号唯一(不为空)
online.setCpUserInfo( “cpUserInfo ” ); //此参数在用户支付成功后会透传给CP的服务器
online.setMiBi( 10 ); //必须是大于1的整数, 10代表10米币,即10元人民币(不为空)
//用户信息※必填※
Bundle mBundle = new Bundle();
mBundle.putString( GameInfoField.GAME_USER_BALANCE, "1000" ); //用户余额
mBundle.putString( GameInfoField.GAME_USER_GAMER_VIP, "vip0" ); //vip 等级
mBundle.putString( GameInfoField.GAME_USER_LV, "20" ); //角色等级
mBundle.putString( GameInfoField.GAME_USER_PARTY_NAME, "猎人" ); //工会,帮派
mBundle.putString( GameInfoField.GAME_USER_ROLE_NAME, "meteor" ); //角色名称
mBundle.putString( GameInfoField.GAME_USER_ROLEID, "123456" ); //角色id
mBundle.putString( GameInfoField.GAME_USER_SERVER_NAME, "峡谷" ); //所在服务器
MiCommplatform.getInstance().miUniPayOnline(activity, online, mBundle
new OnPayProcessListener(){
@Override
public void finishPayProcess( int code ) {
switch( code ) {
case MiErrorCode.MI_XIAOMI_GAMECENTER_SUCCESS:
// 购买成功
break;
case MiErrorCode.MI_XIAOMI_GAMECENTER_ERROR_PAY_CANCEL:
// 取消购买
break;
case MiErrorCode.MI_XIAOMI_GAMECENTER_ERROR_PAY_FAILURE:
// 购买失败
break;
case MiErrorCode.MI_XIAOMI_GAMECENTER_ERROR_ACTION_EXECUTED:
//操作正在进行中
break;
default :
// 购买失败
break;
}
}
});
参数说明:
参数名称
用途
备注
cpOrderId
开发方订单号
必填参数。20~100字符以内,要求必须由开发者的业务服务器生成,因订单支付成功后游戏平台服务器会直接将支付结果通知给开发者的业务服务器,通知参数的cpOrderId是重要信息。
cpUserInfo
给网游透传参数
必填参数。用于透传用户信息,当用户支付成功后我们会将此参数透传给开发者业务服务器(不能为null或“”)
mibi
购买米币的数量
必填参数。且数量是int型,即最少只能购买1米币对应的虚拟币.
3 服务器接口
请开发者以小米游戏中心服务器通知的结果为准为用户进行虚拟币充值。
3.1 订单支付结果通知接口
流程说明:
在订单支付成功后,小米游戏平台服务器会将支付结果通知给开发者预先提供的服务器上。若开发者所提供的服务器地址不可用,在一定时间段内游戏平台服务器会按照周期进行轮训(前10次,每分钟通知1次;10次后每小时通知1次)。
具体流程如下:
注:由于是异步通知模型,(3)和(4)不一定是按序号产生。因此(4)和(5)需要进行轮询处理或者使用接口进行支付结果查询。
相比后面提到的开发者主动查询订单的模式,我们推荐使用此模式。
接口及参数说明:
接口地址:请随《游戏SDK申请表》一起提交
请求方法:GET
请求参数:
参数名称
重要性
说明
appId
必须
游戏ID
cpOrderId
必须
开发商订单ID
cpUserInfo
可选
开发商透传信息
uid
必须
用户ID
orderId
必须
游戏平台订单ID
orderStatus
必须
订单状态,TRADE_SUCCESS 代表成功
payFee
必须
支付金额,单位为分,即0.01 米币。
productCode
必须
商品代码
productName
必须
商品名称
productCount
必须
商品数量
payTime
必须
支付时间,格式 yyyy-MM-dd HH:mm:ss
orderConsumeType
可选
订单类型:10:普通订单11:直充直消订单
partnerGiftConsume
必选
使用游戏券金额 (如果订单使用游戏券则有,long型),如果有则参与签名
signature
必须
签名,签名方法见后面说明
返回参数说明:
参数名称
重要性
说明
errcode
必须
状态码,
200 成功
1506 cpOrderId 错误
1515 appId 错误
1516 uid 错误
1525 signature 错误
3515 订单信息不一致,用于和 CP 的订单校验
errMsg
可选
错误信息
注意:对于同一个订单号的多次通知,开发商要自己保证只处理一次发货。
3.2 主动查询订单支付状态接口
流程说明:
此接口由小米游戏中心为开发者提供。
接口及参数说明:
接口地址:http://mis.migc.xiaomi.com/api/biz/service/queryOrder.do
请求方法:GET
请求参数说明:
名称
重要性
说明
appId
必须
游戏ID
cpOrderId
必须
开发商订单ID
uid
必须
用户ID
signature
必须
签名,签名方法见后面说明
正确返回参数说明:
参数名称
重要性
说明
appId
必须
游戏ID
cpOrderId
必须
开发商订单ID
cpUserInfo
可选
开发商透传信息
uid
必须
用户ID
orderId
必须
游戏平台订单ID
orderStatus
必须
订单状态,TRADE_SUCCESS代表成功WAIT_BUYER_PAY代表未支付REPEAT_PURCHASE订购关系已经存在
payFee
必须
支付金额,单位为分,即0.01 米币。
productCode
必须
商品代码
productName
必须
商品名称
productCount
必须
商品数量
payTime
必须
支付时间,格式 yyyy-MM-dd HH:mm:ss
orderConsumeType
可选
订单类型:10:普通订单11:直充直消订单
signature
必须
签名,签名方法见后面说明
错误返回参数说明:
参数名称
重要性
说明
errcode
必须
状态码1506 cpOrderId 错误1515 appId 错误1516 uid 错误1525 signature 错误
errMsg
可选
错误信息
3.3 用户session验证接口
流程说明:
此接口由小米游戏中心为开发者提供,用于验证登录账户的有效性。
注意:用户的唯一标识是通过SDK获得的uid,而不是 Session,Session 用于校验 登录验证的有效性,必须经过SDK、游戏中心服务器、开发者服务器进行三方验证,如果 Session失效,需要重新调用miLogin()进行登录。
接口及参数说明:
接口地址:http://mis.migc.xiaomi.com/api/biz/service/verifySession.do
请求方法:GET
请求参数说明:
参数名称
重要性
说明
appId
必须
游戏ID
session
必须
用户sessionID
uid
必须
用户ID
signature
必须
签名,签名方法见后面说明
返回参数说明:
参数名称
重要性
说明
errcode
必须
状态码200 验证正确1515 appId 错误1516 uid 错误1520 session 错误1525 signature 错误
errMsg
可选
错误信息
3.4接口格式说明:
输入参数: ?参数1=值1&参数2=值2&….&参数n=值n,如果遇到文本参数值,需要 根据情况对参数值做 UrlEncode。
返回参数:采用 json 格式,如:{“返回参数 1″:”返回值 1″,”返回参数 2″:”返回值 2″,….” 返回参数 n”:” 返回值 n”}
3.5签名方法说明:
3.5.1 生成带签名字符串
表中各参数按字母顺序排序(不包含 signature),如果第一个字母相同,按第二个字母排序,依次类推。排序后拼接成par1=val1&par2=val2&par3=val3的格式,所生成的字符串即为待签名的字符串。没有值的参数请不要参与签名。由于有些数据根据HTTP协议需求,需要进行URLencoding,这样接收方才可以
接收到正确的参数,但如果这个参数参与签名,那么待签名字符串必须是字符串原值而非URLencoding 的值。
3.5.2 签名算法
以AppSecretKey作为key,使用hmac-sha1带密钥(secret)的哈希算法对代签字符串进行签名计算,签名的结果由16进制表示。
4.FAQ
4.1APK打包及发布
需要注意,SDK 包是以 jar 包提供给开发者,此 jar 包本身已为混淆状态,您在混淆 自己游戏的 APK 包时,需要在 proguard.cfg 里加入,以避免二次混淆.
-keep public class com.xiaomi.gamecenter.sdk.ui.actlayout.ViewAliPayWeb$PayObject{*;} -keepclasseswithmembers class * {
public (...);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
4.2服务器签名函数
Hmac-SHA1 算法 java 实现参考:
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HmacSHA1Encryption {
private static final String MAC_NAME = "HmacSHA1" ;
private static final String ENCODING = "UTF-8";
/**
* 使用 HMAC-SHA1 签名方法对对 encryptText 进行签名
* @param encryptText 被签名的字符串
* @param encryptKey 密钥
* @return 返回被加密后的字符串
* @throws Exception
*/
public static String HmacSHA1Encrypt( String encryptText, String encryptKey ) throws Exception{
byte[] data = encryptKey.getBytes( ENCODING );
SecretKey secretKey = new SecretKeySpec( data, MAC_NAME );
Mac mac = Mac.getInstance ( MAC_NAME );
mac.init( secretKey );
byte[] text = encryptText.getBytes( ENCODING );
byte[] digest = mac.doFinal( text );
StringBuilder sBuilder = bytesToHexString ( digest );
return sBuilder.toString();
}
/**
* 转换成Hex
* @param bytesArray
*/
public static StringBuilder bytesToHexString( byte[] bytesArray ){
if ( bytesArray == null ){
return null;
}
StringBuilder sBuilder = new StringBuilder();
for ( byte b : bytesArray ){
String hv = String.format("%02x", b);
sBuilder.append( hv );
}
return sBuilder;
}
/**
* 使用 HMAC-SHA1 签名方法对对 encryptText 进行签名
* @param encryptData 被签名的字符串
* @param encryptKey 密钥
* @return 返回被加密后的字符串
* @throws Exception
*/
public static String HmacSHA1Encrypt( byte[] encryptData, String encryptKey ) throws Exception{
byte[] data = encryptKey.getBytes( ENCODING );
SecretKey secretKey = new SecretKeySpec( data, MAC_NAME );
 Mac mac = Mac.getInstance ( MAC_NAME );
mac.init( secretKey );
byte[] digest = mac.doFinal( encryptData );
StringBuilder sBuilder = bytesToHexString ( digest );
return sBuilder.toString();
}
}
其他参考