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。