IAP实现之一掉单优化处理 — cocos2dx
前两片文章分别介绍了苹果内购的两种验证方式处理,那么在内购的过程中,会不可避免的出现些掉单情况,比如网络不好,程序闪退,或者使用外挂恶意刷单等种种突发原因,导致玩家支付成功却未能实现后台验证加货币的情况,以下介绍的方案只是优化中的一种。
1.在收到内购支付成功回调函数中,发送receipt-data至服务器的同时,将订单号和receipt-data缓存到本地。
2.服务器验证完毕后返回给客户端回调函数处理删除缓存中该订单号和recepit-data。
3.同时,根据实际情况(比如像在打开商城界面的时候,刷新),在程序某个地方调用遍历缓存数据,重新发起这些缓存数据至服务器验证。
具体流程代码实现:
1.缓存
iapUnhandledOrderAddData
- (void)iapDealReceiptFun:(SKPaymentTransaction *)transaction{
NSData *receipt;
// [[UIDevice currentDevice].systemVersion floatValue] < 6.0
if ([[UIDevice currentDevice].systemVersion floatValue] < 6.9f) {
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] appStoreReceiptURL]];//苹果推荐
NSError *error = nil;
receipt = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
}
else {
receipt = transaction.transactionReceipt;
}
if (!receipt) {
/* No local receipt -- handle the error. */
}
//因为此处可能会多次调用原因不明所以加判断只调用一次
else if (receipt && self.startContentService) {
/**
服务器要做的事情:
接收ios端发过来的购买凭证。
判断凭证是否已经存在或验证过,然后存储该凭证。
将该凭证发送到苹果的服务器验证,并将验证结果返回给客户端。
如果需要,修改用户相应的会员权限
*/
NSString *recepitNStr = [receipt base64EncodedStringWithOptions:0];
CCHelp* cppHelper = GetCCHelp();
cppHelper->iapUnhandledOrderAddData(PayInstance::GetPayInstance()->getCurOrderIdStr().c_str(), [recepitNStr UTF8String]);
cppHelper->purchaseRecepit(PayInstance::GetPayInstance()->getCurOrderIdStr().c_str(),[recepitNStr UTF8String]);
}
}
void CCHelp::iapUnhandledOrderAddData(const char* orderStr,const char* recepitDataStr)
{
std::string writeFilePath = FileUtils::getInstance()->getWritablePath();
std::string m_IapCacheStr = writeFilePath + "iapLostcache.plist";
ValueMap m_CacheMap;
if(FileUtils::getInstance()->isFileExist(m_IapCacheStr)){
m_CacheMap = FileUtils::getInstance()->getValueMapFromFile(m_IapCacheStr);
}
else{
//创建缓存文件并存入测试数据
//创建目录
//FileUtils::getInstance()->createDirectory(m_IapCacheStr);
Value firstValue = Value("recepitdata_1");
m_CacheMap.insert(std::make_pair("orderstr_1",firstValue));
m_CacheMap.insert(std::make_pair("orderstr_2",Value("")));
//初次写入 创建文件
FileUtils::getInstance()->writeToFile(m_CacheMap,m_IapCacheStr);
}
ValueMap::iterator iter;
for(iter = m_CacheMap.begin() ; iter != m_CacheMap.end() ; ++iter)
{
std::string orderCurStr = iter->first;
if(YYCompareStr(orderStr, orderCurStr.c_str())){
return;
}
}
Value curValue = Value(recepitDataStr);
m_CacheMap.insert(std::make_pair(orderStr,curValue));
bool writeResult = FileUtils::getInstance()->writeToFile(m_CacheMap,m_IapCacheStr);
if(writeResult){
CCLOG("write success!");
}
else{
CCLOG("write error!");
}
}
void CCHelp::iapUnhandledOrderDeleteData(const char* orderStr)
{
std::string writeFilePath = FileUtils::getInstance()->getWritablePath();
std::string m_IapCacheStr = writeFilePath + "iapLostcache.plist";
ValueMap m_CacheMap;
if(FileUtils::getInstance()->isFileExist(m_IapCacheStr)){
m_CacheMap = FileUtils::getInstance()->getValueMapFromFile(m_IapCacheStr);
ValueMap::iterator iter;
for(iter = m_CacheMap.begin() ; iter != m_CacheMap.end() ;)
{
std::string orderCurStr = iter->first;
if(YYCompareStr(orderStr, orderCurStr.c_str())){
//缓存中找到订单号
iter = m_CacheMap.erase(iter);
CCLOG("erase success!");
//写入plist问价
FileUtils::getInstance()->writeToFile(m_CacheMap,m_IapCacheStr);
return;
}
else{
++iter;
}
}
}
else{
CCLOG("no orderstr erase!");
return;
}
}
3.遍历缓存验证receipt-data
void CCHelp::iapUnhandledOrderRecovery()
{
std::string writeFilePath = FileUtils::getInstance()->getWritablePath();
std::string m_IapCacheStr = writeFilePath + "iapLostcache.plist";
ValueMap m_CacheMap;
if(FileUtils::getInstance()->isFileExist(m_IapCacheStr)){
m_CacheMap = FileUtils::getInstance()->getValueMapFromFile(m_IapCacheStr);
ValueMap::iterator iter;
for(iter = m_CacheMap.begin() ; iter != m_CacheMap.end() ; ++iter)
{
std::string orderCurStr = iter->first;
std::string recepitdataCurStr = m_CacheMap.at(orderCurStr.c_str()).asString();
if(!YYCompareStr(recepitdataCurStr.c_str(), "") && !YYCompareStr(orderCurStr.c_str(),"orderstr_1")){
purchaseRecepit(orderCurStr.c_str(),recepitdataCurStr.c_str());
}
}
}
else{
CCLOG("no plist data recovery!");
return;
}
}
流程结束,如有新优化内容,后续补充。