Pay
Unity3D
Outline
Access Guide
FAQ
Android
Outline
Access Guide
FAQ
IOS
Outline
Access Guide
FAQ
Others
Data Structure
System Tools
Pay / IOS / Outline

Outline

Tencent Games uses Midas to pay in a unified way. Midas is the official mobile payment SDK provided by Tencent and can provide Q-currency, Q-card, TenPay, bank card and WeChat payment, mobile prepaid cards, phone fee and other payment channels. It provides native Android and iap (Apple Official Edition) payment SDK and a full set of payment services, including support for marketing campaigns. Here is only a brief introduction for it. For details, please refer to Midas wiki.

Access Guide

1 Preconditions

1) Complete access to MSDK login

When making the payment, fill in some token information like pf, pfkey, openid, pay_token (required at the time of mobile QQ login) and accessToken (required at the time of WeChat login). All the information is got after the successful login. Please refer to login function and How to get token information . In addition, you need to pass in offerid, which should be applied for at http://midas.qq.com.

2) Complete other requirements of Midas

For details, please refer to Preparations for access to Midas

2 Configure the game's payment information

It is required to register and configure the game coin payment mode and the item direct purchase mode for the game at Midas’ website. Refer to IOS payment configuration details.

3 Access to Midas SDK and joint debugging

iOS needs to import Midas IAPSDK.framework package and configure SDK dependencies, etc.

1) Import Midas SDK resources

You should download Midas iOS's sdk from Midas official website.

Import MidasIAPSDK.framework in Midas SDK

a) Import MidasIAPSDK.framework package. 

b) Select MidasIAPSDK.framework and import it.

After these resources are imported, the structure is like the figure below:

2) Import the resource bundle. Find MidasIAPSDK.bundle file in Finder

To ensure that the resources in bundle are correctly called, you should confirm that there is MidasIAPSDK.bundle in the project setting after the resource bundle is imported. Violation of this rule will lead to SDK's failure in getting resources in bundle, and further result in UI errors. The UI is shown in the figure below after bundle has been successfully imported.

3) Configure the project

System frameworks and libraries which Midas SDK depends on include: libz.dylib, Foundation.framework, MobileCoreService.framework, SystemConfiguration.framework and StoreKit.framework. In Build Phase, you should add these dependencies into the target project. Since this SDK mainly adopts In-App Purchase function in StoreKit, it is needed open the In-App Purchase function in "Capabilities" in the figure above.

Please refer to Access to Midas iOS SDK.

2 Call MidasSDK interface

1) Set parent window handle

a)Function description

Set Parent window handle, so that MidasSDK displays the mall page or launches H5 page.

b)Interface declaration

- (void)setParentViewController:(UIViewController *)parent

c)Parameter description

Parameter name Parameter type Description
parent UIViewController * Parent window handle

d)Return value

None

e)Demo code

 [[IAPPayHelper getIntanceIapHelp] setParentViewController:UIViewController];

2) Realize and set payment callback Delegate

a)Function description

Set IAP payment callback notification object to obtain payment result's callback.

b)Interface declaration

@property (nonatomic, assign) id<IAPPayDelegate> Delegate

c)Parameter description For IAPPayDelegate header file, refer to Midas official website IAPPayDelegate explanation.

d)Return value

None

e)Demo code

//...
@interface LoginSucceedVC ()<IAPPayDelegate>
//...
@end
//...
[[IAPPayHelper getIntanceIapHelp] setDelegate:self];
-(void)parameterWrong:(NSString*)parameterLog
{
    //Set payment ending scene
    WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), -1, -1);
    NSLog(@"callback:parameterWrong:%@",parameterLog);
}
//log callback
-(void)log:(NSString*)message
{
    NSLog(@"callback:logMessage:%@",message);
}

//Login state expires
-(void)onLoginExpiry:(RequestInfo*)info
{
    //Set payment ending scene
    WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), -1, -1);
    NSLog(@"callback:login expire");
}

//Callback for placing an order successfully
-(void)onOrderFinish:(NSString*)billno withRequestInfo:(RequestInfo*)info
{
    //Set payment scenes
    WGPlatform::GetInstance()->WGStartGameStatus((unsigned char*)"MSDKPayIng");
    NSLog(@"callback:order succ");
}

//Callback for placing an order unsuccessfully (service error)

-(void)onOrderFailue:(RequestInfo*)info withErrorMessage:(NSString*)errorMessage withErrorCode:(int)code
{
    NSLog(@"callback:order fail");
}

//Apple payment success callback

-(void)onIAPPaymentSucess:(RequestInfo*)info
{
    //Set payment ending scene
    WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), 0, 0);
    NSLog(@"callback: iap pay succ");
}

//Failure in getting the cargo product information
//The product quantity is 0 when the product is gotten
-(void)onGetProductInfoFailue:(RequestInfo*)info
{
    //Set payment ending scene
    WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), -1, -1);
    NSLog(@"callback: get iap product info fail");
}

//Apple payment failure callback

-(void)onIAPPayFailue:(RequestInfo*)info  withError:(NSError*)error
{
    //Set payment ending scene
    WGPlatform::GetInstance()->WGEndGameStatus(((unsigned char*)"MSDKPayNotify"), -1, -1);
    NSLog(@"callback: iap pay fail, error info:%@", error);
}

//Delivery success callback

-(void)onDistributeGoodsFinish:(RequestInfo*)info
{
    NSLog(@"callback: distribute succ");
}

//Delivery failure callback (service error)
//If code=10001, supplementary delivery is needed. As for other errors, supplementary delivery is not needed
-(void)onDistributeGoodsFailue:(RequestInfo*)info withErrorMessage:(NSString*)errorMessage withErrorCode:(int)code
{
    NSLog(@"callback: distribute fail");
}

3) Register environment variables and the supplementary delivery interface

a)Function description

Register the environment variables, and simultaneously activate the supplementary delivery interface, and define passthrough fields on your own.

b)Interface declaration

-(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)Parameter description

Parameter name Parameter type Description
offerid String offerid
openid String user account id (account)
openKey String user session; paytoken for mobile QQ and accesstoken for WeChat
sessionId String user account type (uin or openid)
sessiontype String session type; mobile QQ: kp_actoken; WeChat: wc_actoken
pf String pf
pfkey String pfkey
env String payment environment; test: test environment; release: formal environment
dictExtra String extended fields defined on the business side: kAppDefineInfo, kAppDefineInfo1, kAppDefineInfo2, kAppDefineInfo3

d)Return value

Parameter type Explanation
bool yes: registration succeeds, no: registration fails

e)Demo code

NSLog(@"Register payment");
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) Payment interface

a)Function description

Directly call IAP payment.

b)Interface declaration

-(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)Parameter description

Parameter name Parameter type Description
offerid String offerid
openid String user account id (account)
openKey String user session; paytoken for mobile QQ and accesstoken for WeChat
sessionId String user account type (uin or openid)
sessiontype String session type; mobile QQ: kp_actoken; WeChat: wc_actoken
pf String pf
pfkey String pfkey
payItem String
1. If the payment mode used by app is the item purchase type, this parameter is defined by the app developer according to "Item ID Unit Price (Unit: 0.1 Yuan)Quantity"
2. If the payment mode used by app is the monthly package, it is needed to transmit the number of months opened for the monthly package (for example, QQ members)
3. If the payment mode used by app is the game coin payment mode, it is needed to transmit the number of recharging game coins 4. If the payment mode used by app is the monthly card type, it is needed to transmit the number of days for the monthly card. Note: the number of game coins in the game coin payment mode should be corresponding to the transmitted product ID, as shown in the figure below
productId String Apple's product id
IsDepositGameCoin bool Whether to deposit game coins or not; deposit game coins: true; direct purchase or monthly package: false
productType AppproductType Apple product type
zoneId String Account’s zone ID. If the game role is a support role: zoneId needs to transmit zone ID_role ID

d)Return value

None

e)Demo code

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];

// Directly call the payment interface
[[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 Access to Midas server interfaces and joint debugging

Midas provides the payment interface for the server to call, including querying the game coin balance, recharging, consignment sales, and marketing, etc. The application server should have internal and external access permissions. Please refer to Midas payment API joint debugging.

5 Precautions for online payment

It is needed to submit documents for audit and switch to the formal environment. Please refer to How to go online-IAP

FAQ