支付
Unity3D
概述
接入向导
常见问题
Android
概述
接入向导
常见问题
IOS
概述
接入向导
常见问题
其他
数据结构
系统工具
支付 / IOS / 概述

概述

腾讯游戏统一使用米大师(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