概述
腾讯游戏统一使用米大师(Midas)进行支付。米大师(Midas)是腾讯官方提供的移动端支付SDK,能够提供Q币,Q卡,财付通,银行卡,微信支付,手机充值卡,话费等支付渠道。提供原生的android和iap(苹果官方版)支付SDK,和一整套的支付服务,包括营销活动的支持。这里只做简要的介绍,详情请参考米大师wiki。
接入向导
1 前置条件
1)完成MSDK登录的接入
在进行支付时需要填入一些票据信息如pf,pfkey,openid,pay_token(手Q登录时需要) accessToken(微信登录时需要)这些信息都是在登录成功后获取到的。请参考登录功能和 如何获取票据信息。此外您还需要传入offerid,offerid请到http://midas.qq.com申请。
2)完成米大师的其他要求
详情请参考接入米大师准备工作。
2 配置游戏支付信息
需要在米大师的网站注册并配置游戏的游戏币模式、道具直购模式。请参考IOS支付配置详情。
3 接入米大师SDK与联调
IOS 需要导入MidasIAPSDK.framework包,配置SDK依赖等。
1)导入MidasSDK 资源
请您到米大师官网下载MidasIOS的sdk。
导入MidasSDK中的 MidasIAPSDK.framework。
a) 导入MidasIAPSDK.framework包。
b) 选择MidasIAPSDK.framework进行导入。
导入后就如下图所示:
2) 导入资源bundle,在Finder中找到MidasIAPSDK.bundle文件
为了保证能够正确调用bundle中的资源,导入资源bundle后,确认工程的设置中有MidasIAPSDK.bundle出现才行, 不然会造成SDK无法获取到bundle中的资源,导致界面错误。成功导入后的界面如下图所示。
3)配置工程
Midas SDK依赖的系统framework和库有:libz.dylib,Foundation.framework,MobileCoreService.framework,SystemConfiguration.framework,StoreKit.framework,请在Build Phase中将这些依赖添加到目标工程中; 因为本SDK主要采用StoreKit中的In App Purchase功能,所以,最后,要在上图的Capabilities中打开In-App Purchase功能。
请参考米大师IOS SDK接入。
2 调用MidasSDK接口
1)设置父窗口句柄
a)功能描述
设置父窗口句柄,供MidasSDK显示商城页面或者拉起H5页面。
b)接口声明
- (void)setParentViewController:(UIViewController *)parent
c)参数说明
参数名称 | 参数类型 | 说明 |
---|---|---|
parent | UIViewController * | 父窗口句柄 |
d)返回值
无
e)示例代码
[[IAPPayHelper getIntanceIapHelp] setParentViewController:UIViewController];
2)实现并设置支付回调Delegate
a)功能描述
设置IAP支付回调通知对象,获得支付结果的回调。
b)接口声明
@property (nonatomic, assign) id<IAPPayDelegate> Delegate
c)参数说明 IAPPayDelegate的头文件请参考,Midas官网IAPPayDelegate说明。
d)返回值
无
e)示例代码
//...
@interface LoginSucceedVC ()<IAPPayDelegate>
//...
@end
//...
[[IAPPayHelper getIntanceIapHelp] setDelegate:self];
-(void)parameterWrong:(NSString*)parameterLog
{
//设置支付结束场景
WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), -1, -1);
NSLog(@"callback:parameterWrong:%@",parameterLog);
}
//log的回调
-(void)log:(NSString*)message
{
NSLog(@"callback:logMessage:%@",message);
}
//登陆态失效
-(void)onLoginExpiry:(RequestInfo*)info
{
//设置支付结束场景
WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), -1, -1);
NSLog(@"callback:login expire");
}
//下单成功回调
-(void)onOrderFinish:(NSString*)billno withRequestInfo:(RequestInfo*)info
{
//设置支付中场景
WGPlatform::GetInstance()->WGStartGameStatus((unsigned char*)"MSDKPayIng");
NSLog(@"callback:order succ");
}
//下单失败回调(业务错误)
-(void)onOrderFailue:(RequestInfo*)info withErrorMessage:(NSString*)errorMessage withErrorCode:(int)code
{
NSLog(@"callback:order fail");
}
//苹果支付成功回调
-(void)onIAPPaymentSucess:(RequestInfo*)info
{
//设置支付结束场景
WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), 0, 0);
NSLog(@"callback: iap pay succ");
}
//拉取货物产品信息失败
//针对拉取产品的时候产品数量为0的时候
-(void)onGetProductInfoFailue:(RequestInfo*)info
{
//设置支付结束场景
WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), -1, -1);
NSLog(@"callback: get iap product info fail");
}
//苹果支付失败回调
-(void)onIAPPayFailue:(RequestInfo*)info withError:(NSError*)error
{
//设置支付结束场景
WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), -1, -1);
NSLog(@"callback: iap pay fail, error info:%@", error);
}
//发货成功回调
-(void)onDistributeGoodsFinish:(RequestInfo*)info
{
NSLog(@"callback: distribute succ");
}
//发货失败回调(业务错误)
//如果code=10001 则需要补发,其他错误则不需要
-(void)onDistributeGoodsFailue:(RequestInfo*)info withErrorMessage:(NSString*)errorMessage withErrorCode:(int)code
{
NSLog(@"callback: distribute fail");
}
3)注册环境变量及补发货接口
a)功能描述
注册环境变量并同时激活补发货的接口,还可以自定义透传字段。
b)接口声明
-(BOOL)registerPay:(NSString*)offerid withOpenid:(NSString*)openid
withOpenKey:(NSString*)openKey
withSessionId:(NSString*)sessionId
withSessionType:(NSString*)sessionType
withPf:(NSString*)pf withPfkey:(NSString*)pfKey
withEnv:(NSString*)env withExtra:(NSDictionary *)dictExtra
c)参数说明
参数名称 | 参数类型 | 说明 |
---|---|---|
offerid | String | offerid |
openid | String | 用户账号id(account) |
openKey | String | 用户session手Q为paytoken微信为accesstoken |
sessionId | String | 用户账户类型(uin还是openid) |
sessiontype | String | session类型手Q:kp_actoken,微信:wc_actoken |
pf | String | pf |
pfkey | String | pfkey |
env | String | 支付环境,test:测试环境,release:正式环境 |
dictExtra | String | 业务侧定义扩展字段,kAppDefineInfo,kAppDefineInfo1,kAppDefineInfo2,kAppDefineInfo3 |
d)返回值
参数类型 | 说明 |
---|---|
bool | yes:注册成功,no:注册失败 |
e)示例代码
NSLog(@"注册支付");
LoginRet ret;
WGPlatform* plat = WGPlatform::GetInstance();
int retCode = plat->WGGetLoginRecord(ret);
std::string openid = ret.open_id;
std::string paytoken;
std::string sessionId;
std::string sessionType;
if(retCode == ePlatform_QQ)
{
for(int i=0;i<ret.token.size();i++)
{
TokenRet* pToken = &ret.token[i];
if(pToken->type == eToken_QQ_Pay)
{
paytoken = pToken->value;
break;
}
}
sessionId = "openid";
sessionType = "kp_actoken";
}
else if (retCode == ePlatform_Weixin)
{
for(int i=0;i<ret.token.size();i++)
{
TokenRet* pToken = &ret.token[i];
if(pToken->type == eToken_WX_Access)
{
paytoken = pToken->value;
break;
}
}
sessionId = "hy_gameid";
sessionType = "wc_actoken";
}
else if (retCode == ePlatform_Guest)
{
for(int i=0;i<ret.token.size();i++)
{
TokenRet* pToken = &ret.token[i];
if(pToken->type == eToken_Guest_Access)
{
paytoken = pToken->value;
break;
}
}
sessionId = "hy_gameid";
sessionType = "st_dummy";
}
std::string pf = plat->WGGetPf();
std::string pfKey = plat->WGGetPfKey();
NSString *offerID = [MSDKInfoTool getOfferId];
NSDictionary *dictExtra = @{kAppExtra:@"1",kAppDefineInfo:@"1",kAppReserve1:@"1",kAppReserve2:@"1",kAppReserve3:@"1"};
[IAPPayHelper setIsEnLog:YES];
[IAPPayHelper setLocal:@"local"];
[[IAPPayHelper getIntanceIapHelp] setParentViewController:self];
[[IAPPayHelper getIntanceIapHelp] setDelegate:self];
[[IAPPayHelper getIntanceIapHelp]
registerPay:offerID
withOpenid:[NSString stringWithCString:openid.c_str() encoding:NSUTF8StringEncoding]
withOpenKey:[NSString stringWithCString:paytoken.c_str() encoding:NSUTF8StringEncoding]
withSessionId:[NSString stringWithCString:sessionId.c_str() encoding:NSUTF8StringEncoding]
withSessionType:[NSString stringWithCString:sessionType.c_str() encoding:NSUTF8StringEncoding]
withPf:[NSString stringWithCString:pf.c_str() encoding:NSUTF8StringEncoding]
withPfkey:[NSString stringWithCString:pfKey.c_str() encoding:NSUTF8StringEncoding]
withEnv:@"test"
withExtra:dictExtra];
4)支付接口
a)功能描述
直接调用IAP 支付。
b)接口声明
-(void)pay:(NSString*)offerid
withOpenid:(NSString*)openid
withOpenKey:(NSString*)openKey
withSessionId:(NSString*)sessionId
withSessionType:(NSString*)sessionType
withPf:(NSString*)pf
withPfkey:(NSString*)pfKey
withPayItem:(NSString*)payItem
withProductId:(NSString*)productId
withIsDepositGameCoin:(Boolean)isDepositGameCoin
withProductType:(AppproductType)productType
withZoneId:(NSString*)zoneId
withVarItem:(NSString*)varItem
c)参数说明
参数名称 | 参数类型 | 说明 |
---|---|---|
offerid | String | offerid |
openid | String | 用户账号id(account) |
openKey | String | 用户session手Q为paytoken微信为accesstoken |
sessionId | String | 用户账户类型(uin还是openid) |
sessiontype | String | session类型手Q:kp_actoken,微信:wc_actoken |
pf | String | pf |
pfkey | String | pfkey |
payItem | String | 1.如果应用使用道具购买类支付模式,该参数由应用方按照“物品ID单价(单位“角”)数量”定义 2.如果应用使用包月类支付模式,传开通包月的月数 (QQ会员这类) 3.如果游戏币支付模式,传充值游戏币的个数4.如果应用使用月卡类支付模式,传开通月卡天数注:游戏币模式传的游戏币个数需要与所传productID对应。如下图 |
productId | String | 苹果的产品id |
IsDepositGameCoin | bool | 是否托管,游戏币托管:true,直钩或包月:false |
productType | AppproductType | 苹果产品的类型 |
zoneId | String | 账户分区ID,若游戏为支持角色:zoneId需要传分区ID_角色ID |
d)返回值
无
e)示例代码
LoginRet ret;
int retCode = plat->WGGetLoginRecord(ret);
std::string openid = ret.open_id;
std::string paytoken;
std::string sessionId;
std::string sessionType;
if(retCode == ePlatform_QQ)
{
for(int i=0;i<ret.token.size();i++)
{
TokenRet* pToken = &ret.token[i];
if(pToken->type == eToken_QQ_Pay)
{
paytoken = pToken->value;
break;
}
}
sessionId = "openid";
sessionType = "kp_actoken";
}
else if (retCode == ePlatform_Weixin)
{
for(int i=0;i<ret.token.size();i++)
{
TokenRet* pToken = &ret.token[i];
if(pToken->type == eToken_WX_Access)
{
paytoken = pToken->value;
break;
}
}
sessionId = "hy_gameid";
sessionType = "wc_actoken";
}
else if (retCode == ePlatform_Guest)
{
for(int i=0;i<ret.token.size();i++)
{
TokenRet* pToken = &ret.token[i];
if(pToken->type == eToken_Guest_Access)
{
paytoken = pToken->value;
break;
}
}
sessionId = "hy_gameid";
sessionType = "st_dummy";
}
std::string pf = plat->WGGetPf();
std::string pfKey = plat->WGGetPfKey();
NSString *offerID = [MSDKInfoTool getOfferId];
const char * payItem = PayPayitem;
const char * productId = PayProductid;
bool isDepositGameCoin = true;
uint32_t productType = 0;
const char * zoneId = "1";
const char * varItem = "com.lightspeed.weshoothd.600*1";
NSLog(@"\n\n\nofferid:%@\nopenid:%s\npaytoken:%s\nsessionId:%s\nsessionType:%s\npayItem:%s\nproductId:%s\npf:%s\npfKey:%s\nisDepositGameCoin:%d\nproductType:%d\nzoneId:%s\nvarItem:%s\n",offerID,openid.c_str(),paytoken.c_str(),sessionId.c_str(),
sessionType.c_str(),
payItem,
productId,
pf.c_str(),
pfKey.c_str(),
isDepositGameCoin,
productType,
zoneId,
varItem);
if (![IAPPayHelper judgeIsCanPay])
{
NSLog(@"can't pay in app");
return;
}
NSLog(@"\n\nMidasVersion:%@\n\n",[IAPPayHelper getVersion]);
//[[IAPPayHelper getIntanceIapHelp] setParentViewController:self];
// 直接调用支付接口
[[IAPPayHelper getIntanceIapHelp]
pay:offerID
withOpenid:[NSString stringWithCString:openid.c_str() encoding:NSUTF8StringEncoding]
withOpenKey:[NSString stringWithCString:paytoken.c_str() encoding:NSUTF8StringEncoding]
withSessionId:[NSString stringWithCString:sessionId.c_str() encoding:NSUTF8StringEncoding]
withSessionType:[NSString stringWithCString:sessionType.c_str() encoding:NSUTF8StringEncoding]
withPf:[NSString stringWithCString:pf.c_str() encoding:NSUTF8StringEncoding]
withPfkey:[NSString stringWithCString:pfKey.c_str() encoding:NSUTF8StringEncoding]
withPayItem:[NSString stringWithCString:payItem encoding:NSUTF8StringEncoding]
withProductId:[NSString stringWithCString:productId encoding:NSUTF8StringEncoding]
withIsDepositGameCoin:isDepositGameCoin
withProductType:Consumable
withZoneId:[NSString stringWithCString:zoneId encoding:NSUTF8StringEncoding]
withVarItem:[NSString stringWithCString:varItem encoding:NSUTF8StringEncoding]];
4 米大师服务器接口接入与联调
米大师提供给了服务器调用的支付接口,包括查询游戏币余额,充值,寄售,营销等,需要应用服务器具备内外访问权限。请参考米大师支付API联调。
5 支付上线注意事项
需要提交审核,并切换正式环境。请参考如何上线-IAP。
常见问题
支付问题详见米大师IOS-FAQ。