xuguohong

idfa

Showing 427 changed files with 3340 additions and 4099 deletions
No preview for this file type
......@@ -466,7 +466,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer: luo yuanyuan (82PEUDVHS9)";
CODE_SIGN_IDENTITY = "iPhone Developer: Yufeng Wang (N5VLW9NRUG)";
DEAD_CODE_STRIPPING = NO;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
......@@ -475,19 +475,20 @@
"$(PROJECT_DIR)/poolsdk_file/poolsdk",
);
INFOPLIST_FILE = poolsdk_file/poolsdk/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Demo",
"$(PROJECT_DIR)/poolsdk_file/poolsdk",
);
ONLY_ACTIVE_ARCH = YES;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.jian.wuji;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
VALID_ARCHS = "arm64 armv7";
PROVISIONING_PROFILE = "e6d180fd-5532-4218-bf56-0c1afa8ea0b4";
TARGETED_DEVICE_FAMILY = 2;
VALID_ARCHS = "arm64 armv7s";
};
name = Debug;
};
......@@ -495,7 +496,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer: luo yuanyuan (82PEUDVHS9)";
CODE_SIGN_IDENTITY = "iPhone Developer: Yufeng Wang (N5VLW9NRUG)";
DEAD_CODE_STRIPPING = NO;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
......@@ -504,19 +505,20 @@
"$(PROJECT_DIR)/poolsdk_file/poolsdk",
);
INFOPLIST_FILE = poolsdk_file/poolsdk/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Demo",
"$(PROJECT_DIR)/poolsdk_file/poolsdk",
);
ONLY_ACTIVE_ARCH = YES;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.jian.wuji;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
VALID_ARCHS = "arm64 armv7";
PROVISIONING_PROFILE = "e6d180fd-5532-4218-bf56-0c1afa8ea0b4";
TARGETED_DEVICE_FAMILY = 2;
VALID_ARCHS = "arm64 armv7s";
};
name = Release;
};
......
......@@ -37,11 +37,7 @@
[[PoolSdk shareSDK]applicationDidEnterBackground:application];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
NSLog(@"applicationWillEnterForeground1111111");
[[PoolSdk shareSDK] applicationWillEnterForeground:application];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
......@@ -58,10 +54,22 @@
return true;
}
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
[[PoolSdk shareSDK]application:app openURL:url options:options];
return YES;
}
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
[[PoolSdk shareSDK] application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
return YES;
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
[[PoolSdk shareSDK] applicationWillEnterForeground:application];
}
@end
......
......@@ -154,4 +154,36 @@
}
}
#pragma mark - 截屏
- (void)screenShot:(UIView *)view{
UIImage* image = nil;
UIGraphicsBeginImageContext(view.bounds.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsEndImageContext();
if (image != nil) {
NSLog(@"截图成功!");
UIImageWriteToSavedPhotosAlbum(image,self,@selector(image:didFinishSavingWithError:contextInfo:),NULL);
}
}
#pragma mark - 保存到相册
-(void)image:(UIImage *)image didFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo
{
if(!error){
NSLog(@"存到相册");
}else{
NSLog(@"存储失败");
}
}
@end
......
No preview for this file type
......@@ -9,7 +9,7 @@
#include "UnionInterface.h"
#import <SafariServices/SafariServices.h>
@interface Interface : NSObject <UnionInterface,SFSafariViewControllerDelegate>
@interface Interface : NSObject <UnionInterface>
@property(nonatomic, strong)UIViewController *controller;
......
......@@ -29,5 +29,7 @@
- (void)httpPostAsyncOpen:(NSString*)postUrl :(NSDictionary*)postDict;
- (NSString *)dicToString:(NSDictionary *) dict;
-(void)httpGetAsync:(NSString *)url completionHandler:(void (^ __nullable)(NSURLResponse* __nullable response, NSData* __nullable data, NSError* __nullable connectionError)) handler;
- (NSString * __nullable)dicToString:(NSDictionary * __nullable) dict;
@end
......
......@@ -30,7 +30,10 @@
@property(nonatomic, strong)NSString *openId;
#define REPORT_URL @"https://statistic.public.sdk.gzyouai.com/sdk/statistic" //@http://public.sdk.gzyouai.com:9030/sdk/statistic"//@"http://10.200.201.230:9001/sdk/statistic"//@"https://statistic.public.sdk.gzyouai.com/sdk/statistic"//
#define REPORT_URL @"https://statistic.public.sdk.gzyouai.com/sdk/statistic" //http://183.57.76.181:9030/sdk/statistic
#define REPORT_IDFA_URL @"https://statistic.public.sdk.gzyouai.com/sdk/last_channel?idfa=" //@"http://183.57.76.181:9030/sdk/last_channel?idfa="//
#define REPORT_OPEN @"open"
#define REPORT_ENTER @"enter"
#define REPORT_CREATEROLE @"createrole"
......
......@@ -36,6 +36,8 @@
-(void)viewDidAppear;
- (void)setViewController:(UIViewController *)viewController;
/**
登录SDK
*/
......@@ -185,6 +187,8 @@
- (void)applicationWillResignActive:(UIApplication *)application;
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options;
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
@end
......
......@@ -19,6 +19,9 @@
- (void)SDKinit:(UIViewController *) control;
- (void)setViewController:(UIViewController *) viewController;
/**
登录SDK
*/
......@@ -123,5 +126,7 @@
- (void)applicationWillResignActive:(UIApplication *)application;
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options;
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
@end
\ No newline at end of file
......
import shutil
import os
import plistlib
import config
import json
import packageProj
from mod_pbxproj import XcodeProject
gameProjName = config.gameProjName
channelName = "bingxue"
#copy dir xcodeproj
copyNewDirName = gameProjName + '_' + channelName + '.xcodeproj'
currentPath = os.path.abspath('.')
currentPath += '/' + copyNewDirName
if os.path.exists(currentPath):
shutil.rmtree(currentPath)
shutil.copytree(gameProjName + '.xcodeproj',currentPath)
project = XcodeProject.Load(copyNewDirName + '/project.pbxproj')
project.add_other_ldflags('-ObjC')
#frameworks = project.add_folder('poolsdk_file/poolsdk_itools')
#print(frameworks);
#add search path
channelRootPath = config.channelRootPath#'poolsdk_file'
frameworksPath = '$(PROJECT_DIR)/' + channelRootPath + '/poolsdk_' + channelName + '/SDK'
print(frameworksPath);
#add header search path
project.add_header_search_paths(frameworksPath, recursive=False)
#add framework search path
project.add_framework_search_paths(frameworksPath, recursive=False)
#add library search path
project.add_library_search_paths(frameworksPath, recursive=False)
#add poolsdk_xy dir all file into project
project.remove_group_by_name('poolsdk')
frameworkRelativePath = project.add_folder(channelRootPath + '/poolsdk_' + channelName + '/SDK')
#add sdk lib framework
#project.add_file_if_doesnt_exist('XYPlatform.framework',parent=frameworkRelativePath, weak=True)
#project.add_file_if_doesnt_exist('XYPlatformResources.bundle',parent=frameworkRelativePath, weak=True)
#remove demo file and replace sdk file
#project.remove_file_by_path('poolsdk_file/Demo')
#project.remove_group_by_name('poolsdk_file')
#project.add_file_if_doesnt_exist('PoolSdk.h',parent=frameworkRelativePath, weak=True)
#project.add_file_if_doesnt_exist('PoolSdk.m',parent=frameworkRelativePath, weak=True)
#project.add_file_if_doesnt_exist('SDKInterface.h',parent=frameworkRelativePath, weak=True)
#project.add_file_if_doesnt_exist('SDKInterface.m',parent=frameworkRelativePath, weak=True)
#ignore_unknown_type
project.add_file_if_doesnt_exist('pool_setting',parent=frameworkRelativePath, weak=True,ignore_unknown_type=True)
systemFrameworks = project.get_or_create_group('Frameworks')
#add system framework
project.add_file_if_doesnt_exist('System/Library/Frameworks/CoreTelephony.framework',parent=systemFrameworks, weak=True, tree='SDKROOT')
project.add_file_if_doesnt_exist('System/Library/Frameworks/SystemConfiguration.framework',parent=systemFrameworks, weak=True, tree='SDKROOT')
#add system dylib
systemLibs = project.get_or_create_group('Libraries')
project.add_file_if_doesnt_exist('/usr/lib/libsqlite3.dylib',parent=systemLibs, weak=True, tree='<absolute>')#absolute path
#modify info.plist reference path
project.add_single_valued_flag('INFOPLIST_FILE',channelRootPath + '/poolsdk_' + channelName + '/Info.plist')
project.add_single_valued_flag('ENABLE_BITCODE', 'NO')
readInfoPlistFilePath = channelRootPath + '/poolsdk/Info.plist'
writeInfoFilePath = channelRootPath + '/poolsdk_' + channelName + '/Info.plist'
infoContent = plistlib.readPlist(readInfoPlistFilePath)
xyInfoPath = channelRootPath + '/poolsdk_' + channelName + '/Info_' + channelName + '.plist'
xyInfoContent = plistlib.readPlist(xyInfoPath)
#read pool_setting file
settingFile = open(channelRootPath + '/poolsdk_' + channelName + '/SDK/pool_setting','rw')
try:
settingFileContent = settingFile.read( )
finally:
settingFile.close( )
#json op
jsonStr = json.loads(settingFileContent)
#modify bundle id
project.add_single_valued_flag('PRODUCT_BUNDLE_IDENTIFIER',jsonStr["appScheme"])
#update and add info.plist content
infoContent.update(xyInfoContent)
#write
plistlib.writePlist(infoContent,writeInfoFilePath)
project.save()
packageProj.buildProjName = gameProjName + '_' + channelName
packageProj.targetName = gameProjName
packageProj.buildProj()
channelRootPath = "poolsdk_file"
gameProjName = 'Demo'
\ No newline at end of file
No preview for this file type
# Copyright 2012 Calvin Rien
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# A pbxproj file is an OpenStep format plist
# {} represents dictionary of key=value pairs delimited by ;
# () represents list of values delimited by ,
# file starts with a comment specifying the character type
# // !$*UTF8*$!
# when adding a file to a project, create the PBXFileReference
# add the PBXFileReference's guid to a group
# create a PBXBuildFile with the PBXFileReference's guid
# add the PBXBuildFile to the appropriate build phase
# when adding a header search path add
# HEADER_SEARCH_PATHS = "path/**";
# to each XCBuildConfiguration object
# Xcode4 will read either a OpenStep or XML plist.
# this script uses `plutil` to validate, read and write
# the pbxproj file. Plutil is available in OS X 10.2 and higher
# Plutil can't write OpenStep plists, so I save as XML
import datetime
import json
import ntpath
import os
import plistlib
import re
import shutil
import subprocess
import uuid
from UserDict import IterableUserDict
from UserList import UserList
regex = '[a-zA-Z0-9\\._/-]*'
class PBXEncoder(json.JSONEncoder):
def default(self, obj):
"""Tests the input object, obj, to encode as JSON."""
if isinstance(obj, (PBXList, PBXDict)):
return obj.data
return json.JSONEncoder.default(self, obj)
class PBXDict(IterableUserDict):
def __init__(self, d=None):
if d:
d = dict([(PBXType.Convert(k), PBXType.Convert(v)) for k, v in d.items()])
IterableUserDict.__init__(self, d)
def __setitem__(self, key, value):
IterableUserDict.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value))
def remove(self, key):
self.data.pop(PBXType.Convert(key), None)
class PBXList(UserList):
def __init__(self, l=None):
if isinstance(l, basestring):
UserList.__init__(self)
self.add(l)
return
elif l:
l = [PBXType.Convert(v) for v in l]
UserList.__init__(self, l)
def add(self, value):
value = PBXType.Convert(value)
if value in self.data:
return False
self.data.append(value)
return True
def remove(self, value):
value = PBXType.Convert(value)
if value in self.data:
self.data.remove(value)
return True
return False
def __setitem__(self, key, value):
UserList.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value))
class PBXType(PBXDict):
def __init__(self, d=None):
PBXDict.__init__(self, d)
if 'isa' not in self:
self['isa'] = self.__class__.__name__
self.id = None
@staticmethod
def Convert(o):
if isinstance(o, list):
return PBXList(o)
elif isinstance(o, dict):
isa = o.get('isa')
if not isa:
return PBXDict(o)
cls = globals().get(isa)
if cls and issubclass(cls, PBXType):
return cls(o)
print 'warning: unknown PBX type: %s' % isa
return PBXDict(o)
else:
return o
@staticmethod
def IsGuid(o):
return re.match('^[A-F0-9]{24}$', str(o))
@classmethod
def GenerateId(cls):
return ''.join(str(uuid.uuid4()).upper().split('-')[1:])
@classmethod
def Create(cls, *args, **kwargs):
return cls(*args, **kwargs)
class PBXFileReference(PBXType):
def __init__(self, d=None):
PBXType.__init__(self, d)
self.build_phase = None
types = {
'.a': ('archive.ar', 'PBXFrameworksBuildPhase'),
'.app': ('wrapper.application', None),
'.s': ('sourcecode.asm', 'PBXSourcesBuildPhase'),
'.c': ('sourcecode.c.c', 'PBXSourcesBuildPhase'),
'.cpp': ('sourcecode.cpp.cpp', 'PBXSourcesBuildPhase'),
'.framework': ('wrapper.framework', 'PBXFrameworksBuildPhase'),
'.h': ('sourcecode.c.h', None),
'.hpp': ('sourcecode.c.h', None),
'.d': ('sourcecode.dtrace', 'PBXSourcesBuildPhase'),
'.swift': ('sourcecode.swift', 'PBXSourcesBuildPhase'),
'.icns': ('image.icns', 'PBXResourcesBuildPhase'),
'.m': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'),
'.j': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'),
'.mm': ('sourcecode.cpp.objcpp', 'PBXSourcesBuildPhase'),
'.nib': ('wrapper.nib', 'PBXResourcesBuildPhase'),
'.plist': ('text.plist.xml', 'PBXResourcesBuildPhase'),
'.json': ('text.json', 'PBXResourcesBuildPhase'),
'.png': ('image.png', 'PBXResourcesBuildPhase'),
'.rtf': ('text.rtf', 'PBXResourcesBuildPhase'),
'.tiff': ('image.tiff', 'PBXResourcesBuildPhase'),
'.txt': ('text', 'PBXResourcesBuildPhase'),
'.xcodeproj': ('wrapper.pb-project', None),
'.xib': ('file.xib', 'PBXResourcesBuildPhase'),
'.strings': ('text.plist.strings', 'PBXResourcesBuildPhase'),
'.bundle': ('wrapper.plug-in', 'PBXResourcesBuildPhase'),
'.dylib': ('compiled.mach-o.dylib', 'PBXFrameworksBuildPhase'),
'.xcdatamodeld': ('wrapper.xcdatamodel', 'PBXSourcesBuildPhase'),
'.xcassets': ('folder.assetcatalog', 'PBXResourcesBuildPhase'),
'.tbd': ('sourcecode.text-based-dylib-definition', 'PBXFrameworksBuildPhase'),
}
trees = [
'<absolute>',
'<group>',
'BUILT_PRODUCTS_DIR',
'DEVELOPER_DIR',
'SDKROOT',
'SOURCE_ROOT',
]
def guess_file_type(self, ignore_unknown_type=False):
self.remove('explicitFileType')
self.remove('lastKnownFileType')
ext = os.path.splitext(self.get('name', ''))[1]
if os.path.isdir(self.get('path')) and ext not in XcodeProject.special_folders:
f_type = 'folder'
build_phase = None
ext = ''
else:
f_type, build_phase = PBXFileReference.types.get(ext, ('?', 'PBXResourcesBuildPhase'))
self['lastKnownFileType'] = f_type
self.build_phase = build_phase
if f_type == '?' and not ignore_unknown_type:
print 'unknown file extension: %s' % ext
print 'please add extension and Xcode type to PBXFileReference.types'
return f_type
def set_file_type(self, ft):
self.remove('explicitFileType')
self.remove('lastKnownFileType')
self['explicitFileType'] = ft
@classmethod
def Create(cls, os_path, tree='SOURCE_ROOT', ignore_unknown_type=False):
if tree not in cls.trees:
print 'Not a valid sourceTree type: %s' % tree
return None
fr = cls()
fr.id = cls.GenerateId()
fr['path'] = os_path
fr['name'] = os.path.split(os_path)[1]
fr['sourceTree'] = '<absolute>' if os.path.isabs(os_path) else tree
fr.guess_file_type(ignore_unknown_type=ignore_unknown_type)
return fr
class PBXBuildFile(PBXType):
def set_weak_link(self, weak=False):
k_settings = 'settings'
k_attributes = 'ATTRIBUTES'
s = self.get(k_settings)
if not s:
if weak:
self[k_settings] = PBXDict({k_attributes: PBXList(['Weak'])})
return True
atr = s.get(k_attributes)
if not atr:
if weak:
atr = PBXList()
else:
return False
if weak:
atr.add('Weak')
else:
atr.remove('Weak')
self[k_settings][k_attributes] = atr
return True
def add_compiler_flag(self, flag):
k_settings = 'settings'
k_attributes = 'COMPILER_FLAGS'
if k_settings not in self:
self[k_settings] = PBXDict()
if k_attributes not in self[k_settings]:
self[k_settings][k_attributes] = flag
return True
flags = self[k_settings][k_attributes].split(' ')
if flag in flags:
return False
flags.append(flag)
self[k_settings][k_attributes] = ' '.join(flags)
@classmethod
def Create(cls, file_ref, weak=False):
if isinstance(file_ref, PBXFileReference):
file_ref = file_ref.id
bf = cls()
bf.id = cls.GenerateId()
bf['fileRef'] = file_ref
if weak:
bf.set_weak_link(True)
return bf
class PBXGroup(PBXType):
def add_child(self, ref):
if not isinstance(ref, PBXDict):
return None
isa = ref.get('isa')
if isa != 'PBXFileReference' and isa != 'PBXGroup':
return None
if 'children' not in self:
self['children'] = PBXList()
self['children'].add(ref.id)
return ref.id
def remove_child(self, id):
if 'children' not in self:
self['children'] = PBXList()
return
if not PBXType.IsGuid(id):
id = id.id
self['children'].remove(id)
def has_child(self, id):
if 'children' not in self:
self['children'] = PBXList()
return False
if not PBXType.IsGuid(id):
id = id.id
return id in self['children']
def get_name(self):
path_name = os.path.split(self.get('path', ''))[1]
return self.get('name', path_name)
@classmethod
def Create(cls, name, path=None, tree='SOURCE_ROOT'):
grp = cls()
grp.id = cls.GenerateId()
grp['name'] = name
grp['children'] = PBXList()
if path:
grp['path'] = path
grp['sourceTree'] = tree
else:
grp['sourceTree'] = '<group>'
return grp
class PBXNativeTarget(PBXType):
pass
class PBXProject(PBXType):
pass
class PBXContainerItemProxy(PBXType):
pass
class PBXReferenceProxy(PBXType):
pass
class PBXVariantGroup(PBXType):
pass
class PBXTargetDependency(PBXType):
pass
class PBXAggregateTarget(PBXType):
pass
class PBXHeadersBuildPhase(PBXType):
pass
class XCVersionGroup(PBXType):
pass
class PBXBuildPhase(PBXType):
def add_build_file(self, bf):
if bf.get('isa') != 'PBXBuildFile':
return False
if 'files' not in self:
self['files'] = PBXList()
self['files'].add(bf.id)
return True
def remove_build_file(self, id):
if 'files' not in self:
self['files'] = PBXList()
return
self['files'].remove(id)
def has_build_file(self, id):
if 'files' not in self:
self['files'] = PBXList()
return False
if not PBXType.IsGuid(id):
id = id.id
return id in self['files']
class PBXFrameworksBuildPhase(PBXBuildPhase):
pass
class PBXResourcesBuildPhase(PBXBuildPhase):
pass
class PBXShellScriptBuildPhase(PBXBuildPhase):
@classmethod
def Create(cls, script, shell="/bin/sh", files=[], input_paths=[], output_paths=[], show_in_log = '0'):
bf = cls()
bf.id = cls.GenerateId()
bf['files'] = files
bf['inputPaths'] = input_paths
bf['outputPaths'] = output_paths
bf['runOnlyForDeploymentPostprocessing'] = '0';
bf['shellPath'] = shell
bf['shellScript'] = script
bf['showEnvVarsInLog'] = show_in_log
return bf
class PBXSourcesBuildPhase(PBXBuildPhase):
pass
class PBXCopyFilesBuildPhase(PBXBuildPhase):
pass
class XCBuildConfiguration(PBXType):
def add_search_paths(self, paths, base, key, recursive=True, escape=True):
modified = False
if not isinstance(paths, list):
paths = [paths]
if base not in self:
self[base] = PBXDict()
for path in paths:
if recursive and not path.endswith('/**'):
path = os.path.join(path, '**')
if key not in self[base]:
self[base][key] = PBXList()
elif isinstance(self[base][key], basestring):
self[base][key] = PBXList(self[base][key])
if path == '$(inherited)':
escape = False
if escape:
if self[base][key].add('"%s"' % path): # '\\"%s\\"' % path
modified = True
else:
if self[base][key].add(path): # '\\"%s\\"' % path
modified = True
return modified
def add_header_search_paths(self, paths, recursive=True):
return self.add_search_paths(paths, 'buildSettings', 'HEADER_SEARCH_PATHS', recursive=recursive)
def add_library_search_paths(self, paths, recursive=True):
return self.add_search_paths(paths, 'buildSettings', 'LIBRARY_SEARCH_PATHS', recursive=recursive)
def add_framework_search_paths(self, paths, recursive=True):
return self.add_search_paths(paths, 'buildSettings', 'FRAMEWORK_SEARCH_PATHS', recursive=recursive)
def add_other_cflags(self, flags):
return self.add_flag('OTHER_CFLAGS', flags)
def add_other_ldflags(self, flags):
return self.add_flag('OTHER_LDFLAGS', flags)
def add_flag(self, key, flags):
modified = False
base = 'buildSettings'
if isinstance(flags, basestring):
flags = PBXList(flags)
if base not in self:
self[base] = PBXDict()
for flag in flags:
if key not in self[base]:
self[base][key] = PBXList()
elif isinstance(self[base][key], basestring):
self[base][key] = PBXList(self[base][key])
if self[base][key].add(flag):
self[base][key] = [e for e in self[base][key] if e]
modified = True
return modified
def remove_flag(self, key, flags):
modified = False
base = 'buildSettings'
if isinstance(flags, basestring):
flags = PBXList(flags)
if base in self: # there are flags, so we can "remove" something
for flag in flags:
if key not in self[base]:
return False
elif isinstance(self[base][key], basestring):
self[base][key] = PBXList(self[base][key])
if self[base][key].remove(flag):
self[base][key] = [e for e in self[base][key] if e]
modified = True
if len(self[base][key]) == 0:
self[base].pop(key, None)
return modified
def remove_other_ldflags(self, flags):
return self.remove_flag('OTHER_LD_FLAGS', flags)
# Set a single-valued flag under buildSettings
def add_single_valued_flag(self, flag, value):
modified = False
base = 'buildSettings'
key = flag
if not self.has_key(base):
self[base] = PBXDict()
if self[base].has_key(key):
if self[base][key] == value:
return False
self[base][key] = value
modified = True
return modified
# Remove a single-valued flag under buildSettings
def remove_single_valued_flag(self, flag):
modified = False
base = 'buildSettings'
key = flag
if self.has_key(base) and self[base].has_key(key):
self[base].pop(key, None)
modified = True
return modified
class XCConfigurationList(PBXType):
pass
class XcodeProject(PBXDict):
plutil_path = 'plutil'
special_folders = ['.bundle', '.framework', '.xcodeproj', '.xcassets', '.xcdatamodeld']
def __init__(self, d=None, path=None):
if not path:
path = os.path.join(os.getcwd(), 'project.pbxproj')
self.pbxproj_path = os.path.abspath(path)
self.source_root = os.path.abspath(os.path.join(os.path.split(path)[0], '..'))
IterableUserDict.__init__(self, d)
self.data = PBXDict(self.data)
self.objects = self.get('objects')
self.modified = False
root_id = self.get('rootObject')
if root_id:
self.root_object = self.objects[root_id]
root_group_id = self.root_object.get('mainGroup')
self.root_group = self.objects[root_group_id]
else:
print "error: project has no root object"
self.root_object = None
self.root_group = None
for k, v in self.objects.iteritems():
v.id = k
def add_other_cflags(self, flags):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_other_cflags(flags):
self.modified = True
def add_other_ldflags(self, flags):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_other_ldflags(flags):
self.modified = True
def remove_other_ldflags(self, flags):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.remove_other_ldflags(flags):
self.modified = True
def add_header_search_paths(self, paths, recursive=True):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_header_search_paths(paths, recursive):
self.modified = True
def add_framework_search_paths(self, paths, recursive=True):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_framework_search_paths(paths, recursive):
self.modified = True
def add_library_search_paths(self, paths, recursive=True):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_library_search_paths(paths, recursive):
self.modified = True
def add_flags(self, pairs, configuration='All'):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
# iterate over all the pairs of configurations
for b in build_configs:
if configuration != "All" and b.get('name') != configuration :
continue
for k in pairs:
if b.add_flag(k, pairs[k]):
self.modified = True
def remove_flags(self, pairs, configuration='All'):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
# iterate over all the pairs of configurations
for b in build_configs:
if configuration != "All" and b.get('name') != configuration :
continue
for k in pairs:
if b.remove_flag(k, pairs[k]):
self.modified = True
# Set a single-valued flag (whereas add_flags adds a flag to a list of flags with a given key)
def add_single_valued_flag(self, flag, value, configuration='All'):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if configuration != "All" and b.get('name') != configuration :
continue
if b.add_single_valued_flag(flag, value):
self.modified = True
# Remove a single-valued flag (whereas remove_flags deletes a flag from a list of flags with a given key)
def remove_single_valued_flag(self, flag, configuration='All'):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if configuration != "All" and b.get('name') != configuration :
continue
if b.remove_single_valued_flag(flag):
self.modified = True
def get_obj(self, id):
return self.objects.get(id)
def get_ids(self):
return self.objects.keys()
def get_files_by_os_path(self, os_path, tree='SOURCE_ROOT'):
files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference'
and f.get('path') == os_path
and f.get('sourceTree') == tree]
return files
def get_files_by_name(self, name, parent=None):
if parent:
files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference'
and f.get('name') == name
and parent.has_child(f)]
else:
files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference'
and f.get('name') == name]
return files
def get_keys_for_files_by_name(self, name):
keys = [key for key in self.objects if self.objects.data[key].get('name') == name
and self.objects.data[key].get('isa') == 'PBXFileReference']
return keys
def get_build_files(self, id):
files = [f for f in self.objects.values() if f.get('isa') == 'PBXBuildFile'
and f.get('fileRef') == id]
return files
def get_groups_by_name(self, name, parent=None):
if parent:
groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup'
and g.get_name() == name
and parent.has_child(g)]
else:
groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup'
and g.get_name() == name]
return groups
def get_or_create_group(self, name, path=None, parent=None):
if not name:
return None
if not parent:
parent = self.root_group
elif not isinstance(parent, PBXGroup):
# assume it's an id
parent = self.objects.get(parent, self.root_group)
groups = self.get_groups_by_name(name)
for grp in groups:
if parent.has_child(grp.id):
return grp
grp = PBXGroup.Create(name, path)
parent.add_child(grp)
self.objects[grp.id] = grp
self.modified = True
return grp
def get_groups_by_os_path(self, path):
path = os.path.abspath(path)
groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup'
and os.path.abspath(g.get('path', '/dev/null')) == path]
return groups
def get_build_phases(self, phase_name):
phases = [p for p in self.objects.values() if p.get('isa') == phase_name]
return phases
def get_target_by_name(self, name):
targets = self.get_build_phases('PBXNativeTarget')
target = None
for t in targets:
if t.get("name") == name:
target = t
break
return target
def get_relative_path(self, os_path):
return os.path.relpath(os_path, self.source_root)
def verify_files(self, file_list, parent=None):
# returns list of files not in the current project.
if not file_list:
return []
if parent:
exists_list = [f.get('name') for f in self.objects.values() if f.get('isa') == 'PBXFileReference' and f.get('name') in file_list and parent.has_child(f)]
else:
exists_list = [f.get('name') for f in self.objects.values() if f.get('isa') == 'PBXFileReference' and f.get('name') in file_list]
return set(file_list).difference(exists_list)
def add_run_script(self, target, script=None, insert_before_compile=False):
result = []
targets = [t for t in self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget') if t.get('name') == target]
if len(targets) != 0 :
script_phase = PBXShellScriptBuildPhase.Create(script)
for t in targets:
skip = False
for buildPhase in t['buildPhases']:
if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script:
skip = True
if not skip:
if insert_before_compile:
t['buildPhases'].insert(0, script_phase.id)
else:
t['buildPhases'].add(script_phase.id)
self.objects[script_phase.id] = script_phase
result.append(script_phase)
return result
def add_run_script_all_targets(self, script=None):
result = []
targets = self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget')
if len(targets) != 0 :
script_phase = PBXShellScriptBuildPhase.Create(script)
for t in targets:
skip = False
for buildPhase in t['buildPhases']:
if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script:
skip = True
if not skip:
t['buildPhases'].add(script_phase.id)
self.objects[script_phase.id] = script_phase
result.append(script_phase)
return result
def add_folder(self, os_path, parent=None, excludes=None, recursive=True, create_build_files=True):
if not os.path.isdir(os_path):
return []
if not excludes:
excludes = []
results = []
if not parent:
parent = self.root_group
elif not isinstance(parent, PBXGroup):
# assume it's an id
parent = self.objects.get(parent, self.root_group)
path_dict = {os.path.split(os_path)[0]: parent}
special_list = []
for (grp_path, subdirs, files) in os.walk(os_path):
parent_folder, folder_name = os.path.split(grp_path)
parent = path_dict.get(parent_folder, parent)
if [sp for sp in special_list if parent_folder.startswith(sp)]:
continue
if folder_name.startswith('.'):
special_list.append(grp_path)
continue
if os.path.splitext(grp_path)[1] in XcodeProject.special_folders:
# if this file has a special extension (bundle or framework mainly) treat it as a file
special_list.append(grp_path)
new_files = self.verify_files([folder_name], parent=parent)
# Ignore this file if it is in excludes
if new_files and not [m for m in excludes if re.match(m, grp_path)]:
results.extend(self.add_file(grp_path, parent, create_build_files=create_build_files))
continue
# create group
grp = self.get_or_create_group(folder_name, path=self.get_relative_path(grp_path), parent=parent)
path_dict[grp_path] = grp
results.append(grp)
file_dict = {}
for f in files:
if f[0] == '.' or [m for m in excludes if re.match(m, f)]:
continue
kwds = {
'create_build_files': create_build_files,
'parent': grp,
'name': f
}
f_path = os.path.join(grp_path, f)
file_dict[f_path] = kwds
new_files = self.verify_files([n.get('name') for n in file_dict.values()], parent=grp)
add_files = [(k, v) for k, v in file_dict.items() if v.get('name') in new_files]
for path, kwds in add_files:
kwds.pop('name', None)
self.add_file(path, **kwds)
if not recursive:
break
for r in results:
self.objects[r.id] = r
return results
def path_leaf(self, path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
def add_file_if_doesnt_exist(self, f_path, parent=None, tree='SOURCE_ROOT', create_build_files=True, weak=False, ignore_unknown_type=False):
for obj in self.objects.values():
if 'path' in obj:
if self.path_leaf(f_path) == self.path_leaf(obj.get('path')):
return []
return self.add_file(f_path, parent, tree, create_build_files, weak, ignore_unknown_type=ignore_unknown_type)
def add_file(self, f_path, parent=None, tree='SOURCE_ROOT', create_build_files=True, weak=False, ignore_unknown_type=False, target=None):
results = []
abs_path = ''
if os.path.isabs(f_path):
abs_path = f_path
if not os.path.exists(f_path):
return results
elif tree == 'SOURCE_ROOT':
f_path = os.path.relpath(f_path, self.source_root)
else:
tree = '<absolute>'
if not parent:
parent = self.root_group
elif not isinstance(parent, PBXGroup):
# assume it's an id
parent = self.objects.get(parent, self.root_group)
file_ref = PBXFileReference.Create(f_path, tree, ignore_unknown_type=ignore_unknown_type)
parent.add_child(file_ref)
results.append(file_ref)
# create a build file for the file ref
if file_ref.build_phase and create_build_files:
phases = self.get_build_phases(file_ref.build_phase)
if target:
target = self.get_target_by_name(target)
for phase in phases:
if (not target) or (phase.id in target.get('buildPhases')):
build_file = PBXBuildFile.Create(file_ref, weak=weak)
phase.add_build_file(build_file)
results.append(build_file)
if abs_path and tree == 'SOURCE_ROOT' \
and os.path.isfile(abs_path) \
and file_ref.build_phase == 'PBXFrameworksBuildPhase':
library_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0])
self.add_library_search_paths([library_path], recursive=False)
if abs_path and tree == 'SOURCE_ROOT' \
and not os.path.isfile(abs_path) \
and file_ref.build_phase == 'PBXFrameworksBuildPhase':
framework_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0])
self.add_framework_search_paths([framework_path, '$(inherited)'], recursive=False)
for r in results:
self.objects[r.id] = r
if results:
self.modified = True
return results
def check_and_repair_framework(self, base):
name = os.path.basename(base)
if ".framework" in name:
basename = name[:-len(".framework")]
finalHeaders = os.path.join(base, "Headers")
finalCurrent = os.path.join(base, "Versions/Current")
finalLib = os.path.join(base, basename)
srcHeaders = "Versions/A/Headers"
srcCurrent = "A"
srcLib = "Versions/A/" + basename
if not os.path.exists(finalHeaders):
os.symlink(srcHeaders, finalHeaders)
if not os.path.exists(finalCurrent):
os.symlink(srcCurrent, finalCurrent)
if not os.path.exists(finalLib):
os.symlink(srcLib, finalLib)
def get_file_id_by_path(self, f_path):
for k, v in self.objects.iteritems():
if str(v.get('path')) == f_path:
return k
return 0
def remove_file_by_path(self, f_path, recursive=True):
id = self.get_file_id_by_path(f_path)
if id != 0:
self.remove_file(id, recursive=recursive)
return
def remove_file(self, id, recursive=True):
if not PBXType.IsGuid(id):
id = id.id
if id in self.objects:
self.objects.remove(id)
# Remove from PBXResourcesBuildPhase and PBXSourcesBuildPhase if necessary
buildFiles = [f for f in self.objects.values() if f.get('isa') == 'PBXBuildFile']
for buildFile in buildFiles:
if id == buildFile.get('fileRef'):
key = buildFile.id
PBXRBP = [f for f in self.objects.values() if f.get('isa') == 'PBXResourcesBuildPhase']
PBXSBP = [f for f in self.objects.values() if f.get('isa') == 'PBXSourcesBuildPhase']
self.objects.remove(key)
if len(PBXSBP) and PBXSBP[0].has_build_file(key):
PBXSBP[0].remove_build_file(key)
if len(PBXRBP) and PBXRBP[0].has_build_file(key):
PBXRBP[0].remove_build_file(key)
if recursive:
groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup']
for group in groups:
if id in group['children']:
group.remove_child(id)
self.modified = True
def remove_group(self, id, recursive = True):
if not PBXType.IsGuid(id):
id = id.id
name = self.objects.get(id).get('path')
children = self.objects.get(id).get('children')
if name is None:
name = id
if id in self.objects:
if recursive:
for childKey in children:
childValue = self.objects.get(childKey)
if childValue.get('isa') == 'PBXGroup':
self.remove_group(childKey, True)
else:
self.remove_file(childKey, False)
self.objects.remove(id);
def remove_group_by_name(self, name, recursive = True):
groups = self.get_groups_by_name(name)
if len(groups):
for group in groups:
self.remove_group(group.id, recursive)
def move_file(self, id, dest_grp=None):
pass
def apply_patch(self, patch_path, xcode_path):
if not os.path.isfile(patch_path) or not os.path.isdir(xcode_path):
print 'ERROR: couldn\'t apply "%s" to "%s"' % (patch_path, xcode_path)
return
print 'applying "%s" to "%s"' % (patch_path, xcode_path)
return subprocess.call(['patch', '-p1', '--forward', '--directory=%s' % xcode_path, '--input=%s' % patch_path])
def apply_mods(self, mod_dict, default_path=None):
if not default_path:
default_path = os.getcwd()
keys = mod_dict.keys()
for k in keys:
v = mod_dict.pop(k)
mod_dict[k.lower()] = v
parent = mod_dict.pop('group', None)
if parent:
parent = self.get_or_create_group(parent)
excludes = mod_dict.pop('excludes', [])
if excludes:
excludes = [re.compile(e) for e in excludes]
compiler_flags = mod_dict.pop('compiler_flags', {})
for k, v in mod_dict.items():
if k == 'patches':
for p in v:
if not os.path.isabs(p):
p = os.path.join(default_path, p)
self.apply_patch(p, self.source_root)
elif k == 'folders':
# get and compile excludes list
# do each folder individually
for folder in v:
kwds = {}
# if path contains ':' remove it and set recursive to False
if ':' in folder:
args = folder.split(':')
kwds['recursive'] = False
folder = args.pop(0)
if os.path.isabs(folder) and os.path.isdir(folder):
pass
else:
folder = os.path.join(default_path, folder)
if not os.path.isdir(folder):
continue
if parent:
kwds['parent'] = parent
if excludes:
kwds['excludes'] = excludes
self.add_folder(folder, **kwds)
elif k == 'headerpaths' or k == 'librarypaths':
paths = []
for p in v:
if p.endswith('/**'):
p = os.path.split(p)[0]
if not os.path.isabs(p):
p = os.path.join(default_path, p)
if not os.path.exists(p):
continue
p = self.get_relative_path(p)
paths.append(os.path.join('$(SRCROOT)', p, "**"))
if k == 'headerpaths':
self.add_header_search_paths(paths)
else:
self.add_library_search_paths(paths)
elif k == 'other_cflags':
self.add_other_cflags(v)
elif k == 'other_ldflags':
self.add_other_ldflags(v)
elif k == 'libs' or k == 'frameworks' or k == 'files':
paths = {}
for p in v:
kwds = {}
if ':' in p:
args = p.split(':')
p = args.pop(0)
if 'weak' in args:
kwds['weak'] = True
file_path = os.path.join(default_path, p)
search_path, file_name = os.path.split(file_path)
if [m for m in excludes if re.match(m, file_name)]:
continue
try:
expr = re.compile(file_name)
except re.error:
expr = None
if expr and os.path.isdir(search_path):
file_list = os.listdir(search_path)
for f in file_list:
if [m for m in excludes if re.match(m, f)]:
continue
if re.search(expr, f):
kwds['name'] = f
paths[os.path.join(search_path, f)] = kwds
p = None
if k == 'libs':
kwds['parent'] = self.get_or_create_group('Libraries', parent=parent)
elif k == 'frameworks':
kwds['parent'] = self.get_or_create_group('Frameworks', parent=parent)
if p:
kwds['name'] = file_name
if k == 'libs':
p = os.path.join('usr', 'lib', p)
kwds['tree'] = 'SDKROOT'
elif k == 'frameworks':
p = os.path.join('System', 'Library', 'Frameworks', p)
kwds['tree'] = 'SDKROOT'
elif k == 'files' and not os.path.exists(file_path):
# don't add non-existent files to the project.
continue
paths[p] = kwds
new_files = self.verify_files([n.get('name') for n in paths.values()])
add_files = [(k, v) for k, v in paths.items() if v.get('name') in new_files]
for path, kwds in add_files:
kwds.pop('name', None)
if 'parent' not in kwds and parent:
kwds['parent'] = parent
self.add_file(path, **kwds)
if compiler_flags:
for k, v in compiler_flags.items():
filerefs = []
for f in v:
filerefs.extend([fr.id for fr in self.objects.values() if fr.get('isa') == 'PBXFileReference'
and fr.get('name') == f])
buildfiles = [bf for bf in self.objects.values() if bf.get('isa') == 'PBXBuildFile'
and bf.get('fileRef') in filerefs]
for bf in buildfiles:
if bf.add_compiler_flag(k):
self.modified = True
def backup(self, file_name=None, backup_name=None):
if not file_name:
file_name = self.pbxproj_path
if not backup_name:
backup_name = "%s.%s.backup" % (file_name, datetime.datetime.now().strftime('%d%m%y-%H%M%S'))
shutil.copy2(file_name, backup_name)
return backup_name
def save(self, file_name=None, old_format=False, sort=False):
if old_format :
self.save_format_xml(file_name)
else:
self.save_new_format(file_name, sort)
def save_format_xml(self, file_name=None):
"""Saves in old (xml) format"""
if not file_name:
file_name = self.pbxproj_path
# This code is adapted from plistlib.writePlist
with open(file_name, "w") as f:
writer = PBXWriter(f)
writer.writeln("<plist version=\"1.0\">")
writer.writeValue(self.data)
writer.writeln("</plist>")
def save_new_format(self, file_name=None, sort=False):
"""Save in Xcode 3.2 compatible (new) format"""
if not file_name:
file_name = self.pbxproj_path
# process to get the section's info and names
objs = self.data.get('objects')
sections = dict()
uuids = dict()
for key in objs:
l = list()
if objs.get(key).get('isa') in sections:
l = sections.get(objs.get(key).get('isa'))
l.append(tuple([key, objs.get(key)]))
sections[objs.get(key).get('isa')] = l
if 'name' in objs.get(key):
uuids[key] = objs.get(key).get('name')
elif 'path' in objs.get(key):
uuids[key] = objs.get(key).get('path')
else:
if objs.get(key).get('isa') == 'PBXProject':
uuids[objs.get(key).get('buildConfigurationList')] = 'Build configuration list for PBXProject "Unity-iPhone"'
elif objs.get(key).get('isa')[0:3] == 'PBX':
uuids[key] = objs.get(key).get('isa')[3:-10]
else:
uuids[key] = 'Build configuration list for PBXNativeTarget "TARGET_NAME"'
ro = self.data.get('rootObject')
uuids[ro] = 'Project object'
for key in objs:
# transitive references (used in the BuildFile section)
if 'fileRef' in objs.get(key) and objs.get(key).get('fileRef') in uuids:
uuids[key] = uuids[objs.get(key).get('fileRef')]
# transitive reference to the target name (used in the Native target section)
if objs.get(key).get('isa') == 'PBXNativeTarget':
uuids[objs.get(key).get('buildConfigurationList')] = uuids[objs.get(key).get('buildConfigurationList')].replace('TARGET_NAME', uuids[key])
self.uuids = uuids
self.sections = sections
out = open(file_name, 'w')
out.write('// !$*UTF8*$!\n')
self._printNewXCodeFormat(out, self.data, '', enters=True, sort=sort)
out.close()
@classmethod
def addslashes(cls, s):
d = {'"': '\\"', "'": "\\'", "\0": "\\\0", "\\": "\\\\", "\n":"\\n"}
return ''.join(d.get(c, c) for c in s)
def _printNewXCodeFormat(self, out, root, deep, enters=True, sort=False):
if isinstance(root, IterableUserDict):
out.write('{')
if enters:
out.write('\n')
isa = root.pop('isa', '')
if isa != '': # keep the isa in the first spot
if enters:
out.write('\t' + deep)
out.write('isa = ')
self._printNewXCodeFormat(out, isa, '\t' + deep, enters=enters)
out.write(';')
if enters:
out.write('\n')
else:
out.write(' ')
for key in sorted(root.iterkeys()): # keep the same order as Apple.
if enters:
out.write('\t' + deep)
if re.match(regex, key).group(0) == key:
out.write(key.encode("utf-8") + ' = ')
else:
out.write('"' + key.encode("utf-8") + '" = ')
if key == 'objects':
out.write('{') # open the objects section
if enters:
out.write('\n')
#root.remove('objects') # remove it to avoid problems
sections = [
('PBXBuildFile', False),
('PBXCopyFilesBuildPhase', True),
('PBXFileReference', False),
('PBXFrameworksBuildPhase', True),
('PBXGroup', True),
('PBXAggregateTarget', True),
('PBXNativeTarget', True),
('PBXProject', True),
('PBXResourcesBuildPhase', True),
('PBXShellScriptBuildPhase', True),
('PBXSourcesBuildPhase', True),
('XCBuildConfiguration', True),
('XCConfigurationList', True),
('PBXTargetDependency', True),
('PBXVariantGroup', True),
('PBXReferenceProxy', True),
('PBXContainerItemProxy', True),
('XCVersionGroup', True)]
for section in sections: # iterate over the sections
if self.sections.get(section[0]) is None:
continue
out.write('\n/* Begin %s section */' % section[0].encode("utf-8"))
self.sections.get(section[0]).sort(cmp=lambda x, y: cmp(x[0], y[0]))
if sort and section[0] == 'PBXGroup':
for entry in self.sections.get(section[0]):
entry[1]['children'] = sorted(entry[1]['children'],
key=lambda x: self.uuids[x].encode("utf-8"))
for pair in self.sections.get(section[0]):
key = pair[0]
value = pair[1]
out.write('\n')
if enters:
out.write('\t\t' + deep)
out.write(key.encode("utf-8"))
if key in self.uuids:
out.write(" /* " + self.uuids[key].encode("utf-8") + " */")
out.write(" = ")
self._printNewXCodeFormat(out, value, '\t\t' + deep, enters=section[1])
out.write(';')
out.write('\n/* End %s section */\n' % section[0].encode("utf-8"))
out.write(deep + '\t}') # close of the objects section
else:
self._printNewXCodeFormat(out, root[key], '\t' + deep, enters=enters)
out.write(';')
if enters:
out.write('\n')
else:
out.write(' ')
root['isa'] = isa # restore the isa for further calls
if enters:
out.write(deep)
out.write('}')
elif isinstance(root, UserList):
out.write('(')
if enters:
out.write('\n')
for value in root:
if enters:
out.write('\t' + deep)
self._printNewXCodeFormat(out, value, '\t' + deep, enters=enters)
out.write(',')
if enters:
out.write('\n')
if enters:
out.write(deep)
out.write(')')
else:
if len(root) > 0 and re.match(regex, root).group(0) == root:
out.write(root.encode("utf-8"))
else:
out.write('"' + XcodeProject.addslashes(root.encode("utf-8")) + '"')
if root in self.uuids:
out.write(" /* " + self.uuids[root].encode("utf-8") + " */")
@classmethod
def Load(cls, path, pure_python=False):
if pure_python:
import openstep_parser as osp
tree = osp.OpenStepDecoder.ParseFromFile(open(path, 'r'))
else:
cls.plutil_path = os.path.join(os.path.split(__file__)[0], 'plutil')
if not os.path.isfile(XcodeProject.plutil_path):
cls.plutil_path = 'plutil'
# load project by converting to xml and then convert that using plistlib
p = subprocess.Popen([XcodeProject.plutil_path, '-convert', 'xml1', '-o', '-', path], stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
# If the plist was malformed, return code will be non-zero
if p.returncode != 0:
print stdout
return None
tree = plistlib.readPlistFromString(stdout)
return XcodeProject(tree, path)
@classmethod
def LoadFromXML(cls, path):
tree = plistlib.readPlist(path)
return XcodeProject(tree, path)
# The code below was adapted from plistlib.py.
class PBXWriter(plistlib.PlistWriter):
def writeValue(self, value):
if isinstance(value, (PBXList, PBXDict)):
plistlib.PlistWriter.writeValue(self, value.data)
else:
plistlib.PlistWriter.writeValue(self, value)
def simpleElement(self, element, value=None):
"""
We have to override this method to deal with Unicode text correctly.
Non-ascii characters have to get encoded as character references.
"""
if value is not None:
value = _escapeAndEncode(value)
self.writeln("<%s>%s</%s>" % (element, value, element))
else:
self.writeln("<%s/>" % element)
# Regex to find any control chars, except for \t \n and \r
_controlCharPat = re.compile(
r"[\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f"
r"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]")
def _escapeAndEncode(text):
m = _controlCharPat.search(text)
if m is not None:
raise ValueError("strings can't contains control characters; "
"use plistlib.Data instead")
text = text.replace("\r\n", "\n") # convert DOS line endings
text = text.replace("\r", "\n") # convert Mac line endings
text = text.replace("&", "&amp;") # escape '&'
text = text.replace("<", "&lt;") # escape '<'
text = text.replace(">", "&gt;") # escape '>'
return text.encode("ascii", "xmlcharrefreplace") # encode as ascii with xml character references
No preview for this file type
import os
import commands
buildProjName = ''
targetName = ''
import shutil
import os
def buildProj():
if buildProjName == '':
print('buildProjName is not define')
else:
#build project
print('start build proj')
commands.getstatusoutput('xcodebuild -project ' + buildProjName + '.xcodeproj')
releaseDir = os.path.abspath('.') + '/Release'
if not os.path.exists(releaseDir):
os.mkdir(releaseDir)
ipaPath = releaseDir + '/' + buildProjName + '-Release.ipa'
buildPath = os.path.abspath('.') + '/build'
if os.path.exists(ipaPath):
os.remove(ipaPath)
resultStr = commands.getstatusoutput('xcrun -sdk iphoneos PackageApplication -v build/Release-iphoneos/' + targetName + '.app -o ' +ipaPath)
#print(resultStr)
if os.path.exists(buildPath):
shutil.rmtree(buildPath)
No preview for this file type
......@@ -33,6 +33,11 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.youai.sdk</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>mqq</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>mqq</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Name</string>
<key>Key</key>
<string>name_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Enabled</string>
<key>Key</key>
<string>enabled_preference</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSSliderSpecifier</string>
<key>Key</key>
<string>slider_preference</string>
<key>DefaultValue</key>
<real>0.5</real>
<key>MinimumValue</key>
<integer>0</integer>
<key>MaximumValue</key>
<integer>1</integer>
<key>MinimumValueImage</key>
<string></string>
<key>MaximumValueImage</key>
<string></string>
</dict>
</array>
</dict>
</plist>
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_350/SDK/JWSDK.bundle/en.lproj/Root.strings and /dev/null differ
......
//
// DYUserAccountModel.h
// JWSDKDemo
//
// Created by DovYoung on 16/9/26.
// Copyright © 2016年 DovYoung. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface DYExtraMessageModel : UIView
@property (nonatomic, copy) NSString *serverid; //!< 服务器ID(非常重要)
@property (nonatomic, copy) NSString *roleid; //!< 角色id
@property (nonatomic, copy) NSString *rolename; //!< 角色名字
@property (nonatomic, copy) NSString *rolelevel; //!< 角色等级
@property (nonatomic, copy) NSString *scenetype; //!< 场景类型
@property (nonatomic, copy) NSString *zonename; //!< 服务区名字
@property (nonatomic, copy) NSString *balance; //!< 游戏币金额
@property (nonatomic, copy) NSString *vip; //!< 玩家vip等级
@property (nonatomic, copy) NSString *partyname; //!< 用户所属帮派
/**
* 根据字典创建模型
*
* @param dic 字典
*
* @return 模型
*/
- (instancetype)initWithDic:(NSDictionary *)dic;
@end
//
// DYInitModel.h
// JWSDKDemo
//
// Created by DovYoung on 16/9/21.
// Copyright © 2016年 DovYoung. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface DYInitModel : NSObject
@property (nonatomic, copy) NSString *url; //!< 应用更新地址
@property (nonatomic, copy) NSString *ver; //!< 版本号
@property (nonatomic, copy) NSString *isForce; //!< 是否强制更新
@property (nonatomic, copy) NSString *msg; //!< 版本更新信息
/**
* 根据字典创建模型
*
* @param dic 字典
*
* @return 模型
*/
- (instancetype)initWithDic:(NSDictionary *)dic;
@end
//
// DYLoginModel.h
// JWSDKDemo
//
// Created by DovYoung on 16/9/21.
// Copyright © 2016年 DovYoung. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface DYLoginDataModel : NSObject
//@property (nonatomic, copy) NSString *username; //!< 用户名
@property (nonatomic, copy) NSString *uid; //!< 用户id
@property (nonatomic, copy) NSString *token; //!< 令牌
@property (nonatomic, copy) NSString *timestamp; //!< 时间戳
- (instancetype)initWithDic:(NSDictionary *)dic;
+ (instancetype)loginDataModelWithDic:(NSDictionary *)dic;
@end
//
// LoginViewController.h
// JWSDKDemo
//
// Created by DovYoung on 16/9/19.
// Copyright © 2016年 DovYoung. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "DYLoginDataModel.h"
// 登录回调协议
@protocol DYLoginViewControllerDelegate <NSObject>
@required
/**
* 成功回调
*/
- (void)loginSuccessData:(DYLoginDataModel *)dataModel;
/**
* 失败回调
*/
- (void)loginFailStatus:(NSString *)status info:(NSString *)info;
@end
@interface DYLoginViewController : UIViewController
@property(nonatomic,weak) id<DYLoginViewControllerDelegate> delegate; //!< 登录回调的代理
@property (nonatomic, strong) UIViewController *viewController;
/**
* 自动登录
*/
- (void)autoLogin;
@end
//
// DYOrderModel.h
// JWSDKDemo
//
// Created by DovYoung on 16/10/17.
// Copyright © 2016年 DovYoung. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface DYOrderModel : NSObject
//需要传
@property (nonatomic, copy) NSString *serverid; //!< 服务器id(非常重要)
@property (nonatomic, copy) NSString *pmid; //!< 支付id
@property (nonatomic, copy) NSString *gameorderid; //!< 订单id
@property (nonatomic, copy) NSString *amount; //!< 金额
@property (nonatomic, copy) NSString *gameextinfo; //!< 额外信息
@property (nonatomic, copy) NSString *proname; //!< 商品名字
@property (nonatomic, copy) NSString *roleid; //!< 角色id
@property (nonatomic, copy) NSString *rolename; //!< 角色名字
@property (nonatomic, copy) NSString *rolelevel; //!< 角色等级
@property (nonatomic, copy) NSString *proID; //!< 商品id (ituns connect上注册的)
@property (nonatomic, assign) NSInteger quantity; //!< 购买数量(扩展字段 目前为1)
@end
//
// DYStoreKitController.h
// StoreKit
//
// Created by DovYoung on 16/10/17.
// Copyright © 2016年 DovYoung. All rights reserved.
//
#import <UIKit/UIKit.h>
@class DYOrderModel,DYStoreKitController,DYSQLiteModel;
@protocol DYStoreKitControllerDelegate <NSObject>
//成功回调
- (void)paymentHandler:(NSString *)info;
//失败回调
@end
@interface DYStoreKitController : UIViewController
@property(nonatomic,weak) id<DYStoreKitControllerDelegate> delegate;
/**
单例方法
@return 单例对象
*/
+ (instancetype)sharedInstance;
/**
开始内购
@param order 内购订单信息
*/
- (void)startProductRequestWithOrder:(DYOrderModel *)order;
/**
重新验签
@param model 验签模型
*/
- (void)reveifyWithModel:(DYSQLiteModel *)model;
@end
//
// JWApi.h
// JWSDKDemo
//
// Created by DovYoung on 16/9/21.
// Copyright © 2016年 DovYoung. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "DYInitModel.h"
#import "DYExtraMessageModel.h"
#import "DYOrderModel.h"
@interface JWApi : NSObject
/**
* 闪屏
*/
+ (void)splashScreen;
/**
* 初始化
*
* @param gid 游戏id 必须
* @param appkey 游戏key 必须
* @param agent 渠道号 可传固定值 appstore
*/
+ (void)initializeWithGid:(NSString *)gid
appkey:(NSString *)appkey
agentid:(NSString *)agentid
pmver:(NSString *)pmver
handler:(void(^)(int status, NSString *info,DYInitModel *dataInit))handler;
/**
* 弹出登录
*
* @param delegate 代理
* @param serverid 游戏区服id 游戏方调起登录时,如获取不到区服,则传空即可
*/
+ (void)presentLoginViewControllerWithDelegate:(id)delegate serverid:(NSString *)serverid;
/**
* 额外信息收集
*
* @param message 信息模型
* @param handler 收集回调
*/
+ (void)collectUserExtraMessageWithExtraMessage:(DYExtraMessageModel *)message handler:(void(^)(NSString *status))handler;
/**
* 支付接口
*
* @param delegate 代理
* @param model 含有支付所需信息的模型
*/
+ (void)paymentWithDelegate:(id)delegate
model:(DYOrderModel *)order;
/**
* 退出程序
*/
+ (void)exitApplication;
@end
//
// JWSDK.h
// JWSDK
//
// Created by DovYoung on 16/9/23.
// Copyright © 2016年 DovYoung. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for JWSDK.
FOUNDATION_EXPORT double JWSDKVersionNumber;
//! Project version string for JWSDK.
FOUNDATION_EXPORT const unsigned char JWSDKVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <JWSDK/PublicHeader.h>
#import <JWSDK/JWApi.h>
//登录
#import <JWSDK/DYLoginViewController.h>
#import <JWSDK/DYLoginDataModel.h>
//初始化
#import <JWSDK/DYInitModel.h>
//额外信息
#import <JWSDK/DYExtraMessageModel.h>
//内购
#import <JWSDK/DYStoreKitController.h>
#import <JWSDK/DYOrderModel.h>
framework module JWSDK {
umbrella header "JWSDK.h"
export *
module * { export * }
}
//
// PPInterface.h
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#import <PoolSdk/PoolSdk2.h>
#import <JWSDK/JWSDK.h>
@interface SDKInterface : Interface<DYLoginViewControllerDelegate, DYStoreKitControllerDelegate>
@end
//
// UnionInterface.m
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#include "SDKInterface.h"
#import <UIKit/UIKit.h>
#import <JWSDK/JWSDK.h>
@implementation SDKInterface : Interface
/**
初始化SDK
*/
- (void)SDKinit:(UIViewController *) control
{
//必须继承
[super SDKinit:control];
[PoolConfig getInstance];
//在需要闪屏的地方调用闪屏接口
[JWApi splashScreen];
NSString* gid = [[PoolConfig getInstance]getValueByKey:@"sdkGid"];
NSString* appkey = [[PoolConfig getInstance]getValueByKey:@"sdkAppkey"];
NSString* agentid = [[PoolConfig getInstance]getValueByKey:@"sdkAgentid"];
NSString* pmver = [[PoolConfig getInstance]getValueByKey:@"sdkPmver"];
// gid = @"104";
// appkey = @"0694e5d5ab2e4864aa1f1c48d0d31cf1";
// agentid = @"appstore";
// pmver = @"101";
//请在程序加载完毕的时候调用如下接口初始化
[JWApi initializeWithGid:gid
appkey:appkey
agentid:agentid
pmver:pmver
handler:^(int status, NSString *info, DYInitModel *dataInit) {
NSLog(@"status = %d, info = %@",status, info);
}];
[[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil];
}
/**
登录SDK
*/
- (void)SDKloginSDK
{
NSLog(@"调用了LoginSDK");
//显示登录界面
[JWApi presentLoginViewControllerWithDelegate:self serverid:@""];
}
//实现如下的代理方法
/**
* 登录成功的回调
*
* @param dataModel 回到模型
*/
- (void)loginSuccessData:(DYLoginDataModel *)dataModel {
NSLog(@"sdk loginSuccessData");
NSLog(@"uid = %@",dataModel.uid);
NSLog(@"token = %@",dataModel.token);
NSLog(@"time = %@",dataModel.timestamp);
PoolLoginInfo *loginInfo = [[PoolLoginInfo alloc]init];
loginInfo.openId = dataModel.uid;//渠道userId
loginInfo.timestamp = dataModel.timestamp;
loginInfo.sign = dataModel.token;//渠道SDK的token
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[PoolChecker getInstance]startCheck:loginInfo];//登录验证请求
});
}
/**
* 登录失败的回调
*
* @param status 失败状态码
* @param info 失败的描述
*/
- (void)loginFailStatus:(NSString *)status info:(NSString *)info {
NSLog(@"sdk loginFailStatus failInfo = %@",info);
[[PoolChecker getInstance] sendNotice:PoolSDKNotificationLogin notiName:@"loginFail" statusCode:POOLSDK_ERROR_LOGIN_FAILED description:@"loginFail" extendData:info];
}
- (void)SDKreport:(PoolReportInfo *)reportInfo
{
NSLog(@"reportInfo");
if ([REPORT_CREATEROLE isEqualToString:[reportInfo reportType]]) {
DYExtraMessageModel *model = [[DYExtraMessageModel alloc] init];
model.serverid = [reportInfo serverId];
model.rolelevel = [reportInfo playerLevel];
model.rolename = [reportInfo playerName];
model.zonename = [reportInfo serverName];
model.balance = [NSString stringWithFormat:@"%@", [reportInfo diamond]];
model.vip = [reportInfo vipLevel];
model.scenetype = @"createRole";
model.partyname = [reportInfo partyName];//@"无帮派";
model.roleid = [reportInfo playerId];
//调用接口,将模型数据传入,通过status查看回调信息
[JWApi collectUserExtraMessageWithExtraMessage:model handler:^(NSString *status) {
NSLog(@"%@",status);
}];
}else if ([[reportInfo reportType] isEqualToString:REPORT_ENTER]) {
DYExtraMessageModel *model = [[DYExtraMessageModel alloc] init];
model.serverid = [reportInfo serverId];
model.rolelevel = [reportInfo playerLevel];
model.rolename = [reportInfo playerName];
model.zonename = [reportInfo serverName];
model.balance = [NSString stringWithFormat:@"%@", [reportInfo diamond]];
model.vip = [reportInfo vipLevel];
model.scenetype = @"enterServer";
model.partyname = [reportInfo partyName];//@"无帮派";
model.roleid = [reportInfo playerId];
//调用接口,将模型数据传入,通过status查看回调信息
[JWApi collectUserExtraMessageWithExtraMessage:model handler:^(NSString *status) {
NSLog(@"%@",status);
}];
}else if ([[reportInfo reportType] isEqualToString:REPORT_ROLEUPGRADE]) {
DYExtraMessageModel *model = [[DYExtraMessageModel alloc] init];
model.serverid = [reportInfo serverId];
model.rolelevel = [reportInfo playerLevel];
model.rolename = [reportInfo playerName];
model.zonename = [reportInfo serverName];
model.balance = [NSString stringWithFormat:@"%@", [reportInfo diamond]];
model.vip = [reportInfo vipLevel];
model.scenetype = @"levelUp";
model.partyname = [reportInfo partyName];//@"无帮派";
model.roleid = [reportInfo playerId];
//调用接口,将模型数据传入,通过status查看回调信息
[JWApi collectUserExtraMessageWithExtraMessage:model handler:^(NSString *status) {
NSLog(@"%@",status);
}];
}
}
/**
SDK
*/
- (void)SDKexitSDK
{
[JWApi exitApplication];
}
- (void)receivePayMessage : (NSNotification *)notification;
{
NSString *order_id = [notification object];
NSLog(@"订单ID:%@", order_id);
}
/**
@return 商品名称
*/
- (NSString*)getProductNameByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
if(appleAmount.intValue == amount.intValue){
NSString* productName = [[productList objectForKey:keyValue] objectForKey:@"name"];
return productName;
}
}
}
}
NSLog(@"get product name error amount:%@",amount);
return @"元宝";
}
/**
@return 商品ID
*/
- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSLog(@"i found %@",keyValue);
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount);
if(appleAmount.intValue == amount.intValue){
return keyValue;
}
}
}
}
return @"unknow";
}
- (void)receiveCreateOrder:(NSNotification *)notification
{
NSLog(@"创建订单成功");
PoolPayInfo *payInfo = [notification object];
NSString *openId = [payInfo playerId];
NSString *myamount = [payInfo postAmount];
NSString *queryId = [payInfo queryId];
NSString *productId = [self getProductIdByAmount:payInfo.products amount:myamount];
NSLog(@"receiveCreateOrder openid %@ amount %@ queryId %@, product@d %@", openId, myamount, queryId, productId);
DYOrderModel *order = [[DYOrderModel alloc] init];
//将proID设置为制定的ProID
order.serverid = [payInfo serverId]; //服务器id(必传)
//order.pmid; //!< 支付id
order.gameorderid = [payInfo queryId]; //游戏方订单id (必填)
order.amount = [payInfo postAmount]; //金额 (必填)
order.gameextinfo = [payInfo queryId]; //额外信息
order.proname = [payInfo productName]; //商品名称
order.roleid = [payInfo playerId]; //角色id (必填)
order.rolename = [payInfo playerName]; //角色名称
order.rolelevel = [payInfo playerLevel]; //角色等级
order.proID = productId; //商品id (必填)
//order.quantity = 1;
[JWApi paymentWithDelegate:self model:order];
}
#pragma mark - DYStoreKitControllerDelegate
//内购支付回调
-(void)paymentHandler:(NSString *)info {
NSLog(@"payment info = %@",info);
}
-(NSString*)getCurrentTimestamp{
// 时间戳转时间
NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000;
NSString* timeStr = [[NSString alloc]initWithFormat:@"%.f",interval];
return timeStr;
}
@end
{"sdkAgentid": "appstore", "sdkAppkey": "0694e5d5ab2e4864aa1f1c48d0d31cf1", "payorderurl": "http://183.57.76.181:9020/paycheck/create", "usertype": 190, "sdkSimpleName": "sanwuling_ios", "gamechannelid": "", "custom": "{}", "sdkVersionCode": "V1_8", "sdkGid": "104", "sdkPmver": "101", "loginCheckUrl": "http://183.57.76.181:9010/logincheck/check", "appScheme": "com.yuping.qyt", "c2": "", "c1": "", "paycheckurl": "http://183.57.76.181:9020/paycheck/confirm", "gameSimpleName": "fytx_test"}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>xf_game_alipay</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>xf_game_wechat</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>xf_game_union</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>alipay</string>
<string>safepay</string>
<string>weixin</string>
<string>wechat</string>
<string>uppaysdk</string>
<string>uppaywallet</string>
<string>uppayx1</string>
<string>uppayx2</string>
<string>uppayx3</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>alipay</string>
<string>safepay</string>
<string>weixin</string>
<string>wechat</string>
<string>uppaysdk</string>
<string>uppaywallet</string>
<string>uppayx1</string>
<string>uppayx2</string>
<string>uppayx3</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>xf_game_alipay</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>xf_game_wechat</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>xf_game_union</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
//
// XFPayment.h
// XFPayment
//
// Created by zhou on 2017/3/7.
// Copyright © 2017年 jett.yu. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef enum : NSUInteger {
/**
* 支付结果
*/
PayResultNumSuccess,//支付成功
PayResultNumFailed,//支付失败
PayResultNumCancel,//支付取消
PayResultNumRestart,//重新发起支付
} PayResultNum;
@protocol XFPayDelegate <NSObject>
@optional
/**
支付回调
@param result 支付结果
@param data 支付回调参数
*/
-(void)ApplePayResult:(PayResultNum)result resultData:(NSDictionary *)data;
@end
@interface XFPayment : NSObject
+(XFPayment *)sharedInstance;
@property (nonatomic, weak) id<XFPayDelegate> XFpayDelegate;
/**
支付SDK初始化
@param appid appid
@param packageid packageid
@param appkey 通用key
*/
-(void)initWithAppid:(NSString *)appid andPackageId:(NSString *)packageid andAppKey:(NSString *)appkey;
/**
发起支付方法
@param dict 支付参数
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:@"123456" forKey:@"openId"]; //游戏内唯一ID
[dict setValue:@"6" forKey:@"money"]; //支付金额
[dict setValue:@"xfpay" forKey:@"extra"]; //额外参数
[dict setValue:@"com.xfpay.test.6" forKey:@"orderid"]; //苹果支付id
[dict setValue:@"100元宝" forKey:@"pro_info"]; //商品描述
*/
-(void)payWithOrderInfo:(NSDictionary *)dict;
/**
AppDelegate.mm中实现此协议支付回调
(用于检测支付宝,银联支付状态,务必实现)
@param application application
@param url url
*/
-(void)application:(UIApplication *)application openUrl:(NSURL *)url;
@end
//
// PPInterface.h
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#import <PoolSdk/PoolSdk2.h>
#import <XFLoginSDK/XFLoginViewSDK.h>
#import <PaymentSDK/XFPayment.h>
@interface SDKInterface : Interface<XFLoginViewSDKDelegate, XFPayDelegate>
@end
//
// UnionInterface.m
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#include "SDKInterface.h"
#import <UIKit/UIKit.h>
#import <XFLoginSDK/XFLoginViewSDK.h>
#import <PaymentSDK/XFPayment.h>
#import <XFTrackIO/XFTrackIO.h>
@implementation SDKInterface : Interface
NSString *_openId;
NSString *_serverId;
NSString *_serverName;
NSString *_roleId;
NSString *_roleName;
/**
初始化SDK
*/
- (void)SDKinit:(UIViewController *) control
{
//必须继承
[super SDKinit:control];
[PoolConfig getInstance];
_openId = nil;
_serverId = nil;
_serverName = nil;
_roleId = nil;
_roleName = nil;
NSString* appId = [[PoolConfig getInstance]getValueByKey:@"sdkAppId"];
NSString* packageId = [[PoolConfig getInstance]getValueByKey:@"sdkPackageId"];
NSString* appKey = [[PoolConfig getInstance]getValueByKey:@"sdkAppKey"];
NSString* reyunKey = [[PoolConfig getInstance]getValueByKey:@"sdkReyunKey"];
[[XFPayment sharedInstance]
initWithAppid:appId //应用id(三端通用)
andPackageId:packageId //包id(三端通用)
andAppKey:appKey];//应用key(三端通用)
[[XFLoginViewSDK sharedInstance]
initWithAPPId:appId //应用id(三端通用)
andPackageId:packageId //包id(三端通用)
andAppKey:appKey];//应用key(三端通用)
[[XFTrackIO sharedInstance]
initWithAppid:appId //应用id(三端通用)
andPackageId:packageId //包id(三端通用)
andAppKey:appKey //应用key(三端通用)
andReyunKey:reyunKey];//热云key
[[XFTrackIO sharedInstance] setLogPrint:YES];//是否显示日志,默认NO
[[XFLoginViewSDK sharedInstance] setXFLoginDelegate:self];
[[XFPayment sharedInstance] setXFpayDelegate:self];
[[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil];
}
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
[[XFPayment sharedInstance] application:application openUrl:url];
return YES;
}
//#ifdef __IPHONE_9_0
//-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
// [[XFPayment sharedInstance] application:app openUrl:url];
// return YES;
//}
//#else
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
[[XFPayment sharedInstance] application:application openUrl:url];
return YES;
}
//#endif
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskAll;
}
/**
登录SDK
*/
- (void)SDKloginSDK
{
NSLog(@"调用了LoginSDK");
[[XFLoginViewSDK sharedInstance] OnLogin];
}
#pragma mark - Login Delegate//返回登录ID和登录标识
-(void)SDKLoginSuccessWithData:(NSDictionary *)dic{
NSLog(@"登录成功:%@",dic);//返回openId和token
PoolLoginInfo *loginInfo = [[PoolLoginInfo alloc]init];
loginInfo.openId = [dic objectForKey:@"openId"];//渠道userId
loginInfo.timestamp = [self getCurrentTimestamp];
loginInfo.sign = [dic objectForKey:@"token"];//渠道SDK的token
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[PoolChecker getInstance]startCheck:loginInfo];//登录验证请求
});
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:[dic objectForKey:@"openId"] forKey:@"openId"]; //帐号唯一ID
[[XFTrackIO sharedInstance]
startTrackWithType:XFTrackIOTypeAccountLogin
andTrackData:dict];
}
- (void)SDKreport:(PoolReportInfo *)reportInfo
{
NSLog(@"reportInfo");
if ([REPORT_CREATEROLE isEqualToString:[reportInfo reportType]]) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:[reportInfo openId] forKey:@"openId"];//登录ID
[dict setValue:[reportInfo serverId] forKey:@"serverId"];//服务器ID
[dict setValue:[reportInfo serverName] forKey:@"serverName"];//服务器名称
[dict setValue:[reportInfo playerId] forKey:@"roleId"];//角色ID
[dict setValue:[reportInfo playerName] forKey:@"roleName"];//角色名称
[[XFTrackIO sharedInstance]
startTrackWithType:XFTrackIOTypeEnterGame
andTrackData:dict];
}else if ([[reportInfo reportType] isEqualToString:REPORT_ENTER]) {
#if ! __has_feature(objc_arc)
if (_openId) {
[_openId release];
}
_openId = [reportInfo openId];
[_openId retain];
#else
_openId = [reportInfo openId];
#endif
#if ! __has_feature(objc_arc)
if (_serverId) {
[_serverId release];
}
_serverId = [reportInfo openId];
[_serverId retain];
#else
_serverId = [reportInfo openId];
#endif
#if ! __has_feature(objc_arc)
if (_serverName) {
[_serverName release];
}
_serverName = [reportInfo openId];
[_serverName retain];
#else
_serverName = [reportInfo openId];
#endif
#if ! __has_feature(objc_arc)
if (_roleId) {
[_roleId release];
}
_roleId = [reportInfo openId];
[_roleId retain];
#else
_roleId = [reportInfo openId];
#endif
#if ! __has_feature(objc_arc)
if (_roleName) {
[_roleName release];
}
_roleName = [reportInfo openId];
[_roleName retain];
#else
_roleName = [reportInfo openId];
#endif
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:[reportInfo openId] forKey:@"openId"];//登录ID
[dict setValue:[reportInfo serverId] forKey:@"serverId"];//服务器ID
[dict setValue:[reportInfo serverName] forKey:@"serverName"];//服务器名称
[dict setValue:[reportInfo playerId] forKey:@"roleId"];//角色ID
[dict setValue:[reportInfo playerName] forKey:@"roleName"];//角色名称
[[XFTrackIO sharedInstance]
startTrackWithType:XFTrackIOTypeEnterGame
andTrackData:dict];
}
}
/**
@return 商品名称
*/
- (NSString*)getProductNameByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
if(appleAmount.intValue == amount.intValue){
NSString* productName = [[productList objectForKey:keyValue] objectForKey:@"name"];
return productName;
}
}
}
}
NSLog(@"get product name error amount:%@",amount);
return @"元宝";
}
/**
@return 商品ID
*/
- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSLog(@"i found %@",keyValue);
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount);
if(appleAmount.intValue == amount.intValue){
return keyValue;
}
}
}
}
return @"unknow";
}
- (void)receiveCreateOrder:(NSNotification *)notification
{
NSLog(@"创建订单成功");
PoolPayInfo *payInfo = [notification object];
NSString *openId = [payInfo playerId];
NSString *myamount = [payInfo postAmount];
NSString *queryId = [payInfo queryId];
NSString *productId = [self getProductIdByAmount:payInfo.products amount:myamount];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:openId forKey:@"openId"];
[dict setValue:myamount forKey:@"money"];
[dict setValue:[payInfo productDesc] forKey:@"pro_info"];
[dict setValue:queryId forKey:@"extra"];
[dict setValue:productId forKey:@"orderid"];
[[XFPayment sharedInstance] payWithOrderInfo:dict];
}
#pragma mark - Pay Delegate //支付返回订单号和金额
-(void)ApplePayResult:(PayResultNum)result resultData:(NSDictionary *)data{
if (result == PayResultNumSuccess) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:_openId forKey:@"openId"];//登录ID
[dict setValue:_serverId forKey:@"serverId"];//服务器ID
[dict setValue:_serverName forKey:@"serverName"]; //服务器名称
[dict setValue:_roleId forKey:@"roleId"];//角色ID
[dict setValue:_roleName forKey:@"roleName"];//角色名称
[dict setValue:[data objectForKey:@"money"] forKey:@"money"];// 支付金额
[dict setValue:[data objectForKey:@"orderId"] forKey:@"orderId"]; // 支付订单ID
[[XFTrackIO sharedInstance]
startTrackWithType:XFTrackIOTypePay
andTrackData:dict];
}
}
-(NSString*)getCurrentTimestamp{
// 时间戳转时间
NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000;
NSString* timeStr = [[NSString alloc]initWithFormat:@"%.f",interval];
return timeStr;
}
@end
//
// ShowViewTest.h
// XFLoginViewSDK
//
// Created by mac-mini on 16/10/18.
// Copyright © 2016年 Jett.yu. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol XFLoginViewSDKDelegate <NSObject>
@optional
/**
代理回调方法
@param dic 回调参数
openId 登录id
token 登录token
*/
-(void)SDKLoginSuccessWithData:(NSDictionary *)dic;
@end
@interface XFLoginViewSDK : NSObject
/**
登录代理
*/
@property (nonatomic, weak) id<XFLoginViewSDKDelegate> XFLoginDelegate;
/**
实例化
@return XFLoginViewSDK 实例
*/
+(id)sharedInstance;
/**
登录初始化
@param appid 平台使用appid
@param packageid 平台使用packageid
@param appkey 通用appkey
*/
-(void)initWithAPPId:(NSString *)appid andPackageId:(NSString *)packageid andAppKey:(NSString *)appkey;
/**
开始登陆
*/
-(void)OnLogin;
@end
//
// XFTrackIO.h
// XFTrackIO
//
// Created by yu on 2017/6/9.
// Copyright © 2017年 jett. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
数据监控类型
- XFTrackIOTypeCreate: 角色创建
- XFTrackIOTypeEnterGame: 进入游戏
- XFTrackIOTypePay: 开始支付
- XFTrackIOTypeAccountRegist: 账号注册
- XFTrackIOTypeAccountLogin: 账号登录
*/
typedef NS_ENUM(NSUInteger, XFTrackIOType) {
XFTrackIOTypeActivate = 0,
XFTrackIOTypeBoot,
XFTrackIOTypeCrash,
XFTrackIOTypeCreate,
XFTrackIOTypeEnterGame,
XFTrackIOTypePay,
XFTrackIOTypeAccountRegist,
XFTrackIOTypeAccountLogin,
};
@interface XFTrackIO : NSObject
/**
实例化
@return 实例化
*/
+(id)sharedInstance;
/**
追踪初始化
@param appid 通用appid
@param packageid 通用packageid
@param appkey 通用appkey
@param reyunKey 热云key(不接入则传空)
*/
-(void)initWithAppid:(NSString *)appid andPackageId:(NSString *)packageid andAppKey:(NSString *)appkey andReyunKey:(NSString *)reyunKey;
/**
开始监控
@param type 数据监控的类型
@param data 数据监控的参数(具体传参,请参考文档)
*/
-(void)startTrackWithType:(XFTrackIOType)type andTrackData:(NSDictionary *)data;
/**
是否显示日志
@param print true or false
*/
-(void)setLogPrint:(BOOL)print;
@end
{"sdkAppKey": "11a85d38b8f63be0", "payorderurl": "http://183.57.76.181:9020/paycheck/create", "usertype": 183, "sdkReyunKey": "50ac4b354e94640078075444b5971a3c", "sdkSimpleName": "xianfeng_ios", "sdkPackageId": "1000059", "gamechannelid": "", "custom": "{}", "sdkVersionCode": "V1_0_0", "loginCheckUrl": "http://183.57.76.181:9010/logincheck/check", "sdkAppId": "10002", "appScheme": "com.twapp65gdm.qjfy1", "c2": "", "c1": "", "paycheckurl": "http://183.57.76.181:9020/paycheck/confirm", "gameSimpleName": "fytx_test"}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>i9133public</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>public.sdk.gzyouai.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
<key>sdk.shxingwan.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
<key>statistic.public.sdk.gzyouai.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>i9133public</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>public.sdk.gzyouai.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
<key>sdk.shxingwan.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
<key>statistic.public.sdk.gzyouai.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
</dict>
</dict>
</plist>
\ No newline at end of file
//
// DCSdk.h
// DCSdk
//
// Created by xqwang on 13-7-8.
// Copyright (c) 2013年 digitcube. All rights reserved.
//
#import <Foundation/Foundation.h>
//这里提供静态方法
@interface DCTrackingAgent : NSObject
/**
* @brief 初始化接口,程序启动时调用
*
* 一般在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions内调用一次即可
* !!!一定要调用,否则后面无法上报,只能调用一次
* @param appId 在我们网站上创建游戏时分配的appId,用于标识这款游戏. 注意保密!
* @param channelId 渠道id , 方便统计分析你在各渠道的推广效果
*/
+ (void)initWithAppId:(NSString *)appId andChannelId:(NSString*)channelId;
/**
* @brief 设置数据上报间隔时间,该接口需要在onStart接口之前调用,否则无效。如果不调用该接口,SDK默认以1分钟的间隔上报数据
*
**/
+(void)setUploadInterval:(unsigned int)time;
/**
* @brief 设置应用版本号,不调用该接口时SDK默认从配置文件中读取应用版本号
*
* @param version:应用版本号
*/
+(void)setVersion:(NSString*)version;
/**
* @brief 立即上报数据
**/
+(void)uploadNow;
/**
* @brief 获取设备ID
**/
+(NSString*)getUID;
@end
@interface DCTrackingPoint : NSObject
/**
@brief 广告效果追踪设置有效的效果点
@param pointId 广告效果点
@param propDictionary 触发时希望传入的属性字典
**/
+(void)setEffectPoint:(NSString*)pointId propDictionary:(NSDictionary*)dictionary;
/**
@brief 玩家登陆事件
@param accountId 玩家账户ID
**/
+(void)login:(NSString*)accountId;
/**
@brief 玩家注册事件
@param accountId 玩家账户ID
**/
+(void)createAccount:(NSString*)accountId;
/**
@brief 玩家付费事件
@param orderId 订单ID
@param currencyAmount 付费总额
@param currencyType 货币类型
@param paymentType 支付途径
**/
+(void)paymentSuccess:(NSString*)orderId currencyAmount:(double)currencyAmount currencyType:(NSString*)currencyType paymentType:(NSString*)paymentType;
@end
//
// NewTtack.h
// NewTtack
//
// Created by yun on 16/1/11.
// Copyright © 2016年 yun. All rights reserved.
//
#define TRACK_VERSION @"3.0.1"
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/*
热云移动广告效果监测 平台 api 请选择对应的api进行使用
*/
NS_ASSUME_NONNULL_BEGIN
@interface ReYunChannel : NSObject
//开启打印日志 正式上线包请关掉
+(void) setPrintLog :(BOOL)print;
// 开启数据统计
+ (void)initWithappKey:(NSString *)appKey withChannelId:(NSString *)channelId;
//注册成功后调用
+ (void)setRegisterWithAccountID:(NSString *)account;
//登陆成功后调用
+ (void)setLoginWithAccountID:(NSString *)account;
//开始付费时 调用(人民币单位是元)
+(void)setPaymentStart:(NSString *)transactionId paymentType:(NSString*)paymentType currentType:(NSString*)currencyType currencyAmount:(float)currencyAmount;
// 支付完成,付费分析,记录玩家充值的金额(人民币单位是元)
+(void)setPayment:(NSString *)transactionId paymentType:(NSString*)paymentType currentType:(NSString*)currencyType currencyAmount:(float)currencyAmount;
//自定义事件
+(void)setEvent:(NSString *)eventName;
//获取设备信息
+(NSString*)getDeviceId;
+(BOOL)RYApplication:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<NSString *,id> *)options;
@end
NS_ASSUME_NONNULL_END
\ No newline at end of file
//
// PPInterface.h
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#import <PoolSdk/PoolSdk2.h>
@interface SDKInterface : Interface
@end
//
// UnionInterface.m
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#include "SDKInterface.h"
#import <UIKit/UIKit.h>
#import "YouaiSDK/YouaiSDKMgr.h"
#import "YouaiSDK/YouaiNotifications.h"
#import "YouaiSDK/YouaiLoginInfo.h"
#import "ReYunTrack.h"
#import "DCTrackingAgent.h"
//SDK
@implementation SDKInterface : Interface
int mExchange;
/**
初始化SDK
*/
- (void)SDKinit:(UIViewController *) control
{
//必须继承
[super SDKinit:control];
[PoolConfig getInstance];
[[YouaiSDKMgr getInstance]initSDK];
[[YouaiSDKMgr getInstance]setStyleName:@"sdk"];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveLoginMessage:) name:youaiLoginNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applePayCallBack:) name:@"applePayCallBack" object:nil];
[[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil];
NSString* channelId = [[PoolConfig getInstance] getValueByKey:@"sdkSimpleName"];
[ReYunChannel initWithappKey:[[PoolConfig getInstance] getValueByKey:@"renyunAppKey"] withChannelId:channelId];
NSString* dateEyeAppId = [[PoolConfig getInstance] getValueByKey:@"dateEyeAppId"];
[DCTrackingAgent initWithAppId:dateEyeAppId andChannelId:channelId];
}
/**
登录SDK
*/
- (void)SDKloginSDK
{
NSLog(@"no parames login");
[self SDKloginSDK:self.controller];
}
- (void)SDKloginSDK:(UIViewController *)control
{
NSLog(@"调用了LoginSDK");
NSString *appId = [[PoolConfig getInstance] getValueByKey:@"APP_ID"];
NSString *appKey =[[PoolConfig getInstance] getValueByKey:@"APP_KEY"];
[[YouaiSDKMgr getInstance]openLogin:appId :appKey :control];
}
/**
loginCheck
*/
- (void)receiveLoginMessage:(NSNotification *)notification
{
NSLog(@"loginchek");
PoolLoginInfo *loginInfo = [PoolLoginInfo alloc];
loginInfo.openId = [[YouaiLoginInfo getInstance]openId];
loginInfo.sign = [[YouaiLoginInfo getInstance] token];
loginInfo.timestamp = [YouaiLoginInfo getInstance].timestamp;
[[PoolChecker getInstance] startCheck:loginInfo];
}
-(NSString*)DataTojsonString:(id)object
{
NSString *jsonString = nil;
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
jsonString = [jsonData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return jsonString;
}
/**
苹果支付结果回调
*/
- (void)applePayCallBack:(NSNotification *)notification
{
NSDictionary* payResultDic = notification.object;
NSString* receiptStr = [payResultDic objectForKey:@"payResult"];
NSString* queryId = [payResultDic objectForKey:@"query_id"];
NSDictionary* receiptDic = [NSDictionary dictionaryWithObjectsAndKeys:receiptStr,@"receipt",queryId,@"query_id", nil];
NSString* result = [[NetCenter getInstance] httpPostSyn:[PoolUtils createPayUrl] :receiptDic];
if([@"success" isEqualToString:result]){//确认订单成功
}else{//失败
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray* queryIdArray = [userDefaults objectForKey:@"queryIds"];
NSMutableArray* tempQueryIdArray = [[NSMutableArray alloc] initWithCapacity:10];
if (queryIdArray) {
}else{
queryIdArray = [[NSMutableArray alloc]initWithCapacity:10];
}
for (NSString* arrayQueryId in queryIdArray) {
[tempQueryIdArray addObject:arrayQueryId];
}
[tempQueryIdArray addObject:queryId];
[userDefaults setObject:tempQueryIdArray forKey:@"queryIds"];
[userDefaults setObject:receiptStr forKey:queryId];
[userDefaults synchronize];
}
}
/**
支付 创建订单
*/
- (void)SDKpayWithPaymentInfo:(PoolCreateOrderInfo *)payInfo
{
mExchange = [payInfo exchange].intValue;
[super SDKpayWithPaymentInfo:payInfo];
}
/**
SDK
*/
- (void)SDKgotoUserCenter
{
}
- (void)SDKreport:(PoolReportInfo *)reportInfo
{
NSLog(@"reportInfo");
NSString* reportType = [reportInfo reportType];
if (reportInfo) {
if ([reportType isEqualToString:REPORT_ENTER]) {
[ReYunChannel setLoginWithAccountID:[reportInfo playerId]];//reyun login
[DCTrackingPoint login:[reportInfo playerId]];//dateeye login
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self handlerLeakOrder];
});
}else if([reportType isEqualToString:REPORT_CREATEROLE]){
[ReYunChannel setRegisterWithAccountID:[reportInfo playerId]];//reyun reg
[DCTrackingPoint createAccount:[reportInfo playerId]];//reyun reg
}
}
}
/**
SDK
*/
- (void)SDKexitSDK
{
}
- (void)SDKlogoutSDK
{
NSLog(@"切换账号");
}
- (void)handleOpenurl:(NSURL *)url
{
}
- (void)receivePayMessage : (NSNotification *)notification;
{
NSString *order_id = [notification object];
NSLog(@"订单ID:%@", order_id);
}
//补单处理
- (void) handlerLeakOrder{
NSUserDefaults* userDefaults2 = [NSUserDefaults standardUserDefaults];
NSMutableArray* queryIdArray = [userDefaults2 objectForKey:@"queryIds"];
NSLog(@"orderDic%@",queryIdArray);
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray* failQueryIdArray = [[NSMutableArray alloc]initWithCapacity:10];//补单失败的queryid集合
if(queryIdArray){
for (NSString* queryId in queryIdArray) {
NSString* receiptStr = [userDefaults valueForKey:queryId];
NSDictionary* receiptDic = [NSDictionary dictionaryWithObjectsAndKeys:receiptStr,@"receipt",queryId,@"query_id", nil];
NSString* result = [[NetCenter getInstance] httpPostSyn:[PoolUtils createPayUrl] :receiptDic];
if([@"success" isEqualToString:result]){//成功
[userDefaults removeObjectForKey:queryId];
}else{//补单失败
[failQueryIdArray addObject:queryId];
}
}
NSLog(@"order count:%lu",(unsigned long)[failQueryIdArray count]);
if([failQueryIdArray count] > 0){//含有补单失败项
[userDefaults setObject:failQueryIdArray forKey:@"queryIds"];
}else{//全部补单成功
[userDefaults removeObjectForKey:@"queryIds"];
}
[userDefaults synchronize];
}
}
- (void)receiveCreateOrder:(NSNotification *)notification
{
NSLog(@"创建订单成功");
PoolPayInfo *payInfo = [notification object];
NSNumber *amount = @([[payInfo postAmount] integerValue] * mExchange);
NSString *serverId = [payInfo serverId];
NSString *roleName = [payInfo playerName];
NSString *queryId = [payInfo queryId];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self handlerLeakOrder];
});
//NSString *isOpenThirdPay = [payInfo isOpenThirdPay];
NSString *other = [payInfo other];
if (other && [other length] > 0) {
[[YouaiSDKMgr getInstance] openPay:serverId :roleName :amount :[payInfo queryId] :self.controller];
}else{
NSString* products = [payInfo products];
[[YouaiSDKMgr getInstance] openApplePay:self.controller products:products amount:[payInfo postAmount] queryId:queryId];
}
}
-(void)paymentSuccess:(NSString *)accountId orderId:(NSString *)orderId currencyAmount:(double)amount currencyType:(NSString *)currencyType payType:(NSString *)payType custom:(NSArray *)customArray
{
[DCTrackingPoint paymentSuccess:orderId currencyAmount:amount currencyType:currencyType paymentType:payType];
[ReYunChannel setPayment:orderId paymentType:payType currentType:currencyType currencyAmount:amount];
}
@end
\ No newline at end of file
//
// IapController.h
// mangosanguo
//
// Created by Gino on 12-11-6.
// Copyright (c) 2012年 private. All rights reserved.
//
#if applepay
#import <Foundation/Foundation.h>
#import "StoreKit/StoreKit.h"
@interface IapController : NSObject<SKProductsRequestDelegate,SKPaymentTransactionObserver>
{
bool isRequestedBuy;
SKPaymentTransaction *PayTransaction;
NSMutableArray *payArray;
SKPaymentTransaction *curTransaction;
}
+ (IapController *)sharedController;
- (id)init;
- (void)removeIt;
- (void)requestProductData;
- (void)requestBuyProduct:(NSString *)identifier;
- (void)requestProductInfoById:(NSString *)str;
- (void)comfireTransactions:(bool)isSuessPosted;
- (void)checkReceiptIsFail;
- (void)addItemToPayArray:(SKPaymentTransaction *)transaction;
- (bool)checkPayArrayIsEmpty;
- (void)checkReceiptForArray;
- (void)setAppleCallBack: (NSString*)url;
@end
#endif
\ No newline at end of file
//
// GetWifiMac.h
// mangosanguo
//
// Created by 莫 on 12-9-28.
// Copyright (c) 2012年 private. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface YouaiGetWifiMac : NSObject
+ (NSString *)macaddress;
@end
//
// YouaiLoginInfo.h
// YouaiSDK
//
// Created by 莫 东荣 on 13-4-10.
// Copyright (c) 2013年 莫 东荣. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface YouaiLoginInfo : NSObject //用户uid
{
//
NSString *openId;
//token
NSString *token;
//时间戳
NSString *timestamp;
}
@property(retain,nonatomic) NSString *openId;
@property(retain,nonatomic) NSString *token;
@property(retain,nonatomic) NSString *timestamp;
+ (YouaiLoginInfo *)getInstance;
@end
\ No newline at end of file
//
// YouaiNotifications.h
// YouaiSDK
//
// Created by 莫 东荣 on 13-4-10.
// Copyright (c) 2013年 莫 东荣. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString * const youaiExitNotification; /**< 退出 */
extern NSString * const youaiLoginNotification; /**< 登录完成的通知*/
extern NSString * const youaiPaytNotification; /**< 支付通知 */
extern NSString * const youaiShareNotification; /**< 分享通知 */
extern NSString * const youaiCenterNotification; /**< 用户中心通知 */
extern NSString * const youaiErrorNotification; /**< 出错 */
@interface YouaiNotifications : NSObject
@end
//
// YouaiSDKMgr.h
// YouaiSDK
//
// Created by 莫 东荣 on 13-4-9.
// Copyright (c) 2013年 莫 东荣. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "StoreKit/StoreKit.h"
@interface YouaiSDKMgr : NSObject
{
NSString* appId_;
NSString* appKey_;
NSString* inviterCode_;
// NSString* openId;
// NSString* loginKey;
}
@property bool isApplePaying;
+ (YouaiSDKMgr *)getInstance;
- (void)initSDK;
- (void)initSDK:(NSString *)weixinId;
- (void)openLogin:(NSString *)appId : (NSString *)appKey : (UIViewController *)controller;
- (void)openLogin:(NSString *)appId : (NSString *)appKey : (UIViewController *)controller : (NSString *) inviterCode;
- (void)openLogin:(NSString *)appId : (NSString *)appKey : (UIViewController *)controller : (NSString *) inviterCode : (NSString *)userName : (NSString *)passWord;
- (void)setStyleName:(NSString*)styleName;
- (void)openLogin:(NSString *)appId : (NSString *)appKey : (UIViewController *)controller : (NSString *)userName : (NSString *)passWord;
- (void)openCenter: (UIViewController *)controller;
- (void)openPay: (NSString *)serverId : (NSString *)nickName : (NSString *)callBack : (UIViewController *)controller;
- (void)openPay: (NSString *)serverId : (NSString *)nickName : (NSNumber *)payAmount : (NSString *)callBack : (UIViewController *)controller;
- (void)openShare: (UIViewController *)controller;
- (void)log: (NSString*)log_key : (NSInteger)log_data: (NSString*)log_remark;
- (void)openApplePay:(UIViewController*)controll products:(NSString*)products amount:(NSString*)amount queryId:(NSString*) queryId;
- (void)checkAilpay: (NSURL *)url : (UIViewController *)controller;
- (void)applePayCallBack:(NSString *)url :(SKPaymentTransaction *)transaction :(NSString *)resultStr;
@end
//
// YouaiViewController.h
// newYouaiSDK
//
// Created by Mog90 on 14-9-28.
// Copyright (c) 2014年 东荣 莫. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "YouaiLoginInfo.h"
@interface YouaiViewController : UIViewController<UIWebViewDelegate,UIAlertViewDelegate>
{
UIWebView *webView_;
UIActivityIndicatorView *activityIndicator;
}
//@property(assign) int webViewWidth;
//@property(assign) int webViewHeight;
//@property(assign) int screenwidth;
//@property(assign) int screenHeight;
@property(assign) BOOL hasCorner;
-(void)setView:(int)webViewWidth :(int) webViewHeight :(int) screenwidth :(int) screenHeight;
- (void)initWebView;
- (void)loadWebPageWithString:(NSString *)url;
- (void)loadWebPageWithJs:(NSString *)content;
- (void)postNotification:(NSString *)name : (NSString *)code;
- (void)receiveIap:(NSNotification *)notification;
@end
{"renyunAppKey": "d4f6d8e337472e5277634bcdb1ef6cf6", "dateEyeAppId": "", "payorderurl": "https://public.sdk.gzyouai.com/paycheck/create", "usertype": 139, "sdkSimpleName": "apple_xingwan", "gamechannelid": "", "APP_KEY": "f0455d5b7f2e982144b2ac8bc642e453", "custom": "{}", "sdkVersionCode": "V1_0", "loginCheckUrl": "https://public.sdk.gzyouai.com/logincheck/check", "appScheme": "com.ssmyj.ios.xw", "c2": "", "c1": "", "APP_ID": "5936756454c21d629d0c2755", "paycheckurl": "https://public.sdk.gzyouai.com/paycheck/confirm", "gameSimpleName": "qyj4"}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>xiaoaopay2016</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>xiaoaopay2016</string>
</array>
</dict>
</array>
</dict>
</plist>
//
// AppleIap.h
// Demo_youdian
//
// Created by 许 on 17/6/20.
// Copyright © 2017年 winFan. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface AppleIap : NSObject
-(void)applePay:(NSString*)products amount:(NSString*)amount queryId:(NSString*)queryId;
@end
//
// AppleIap.m
// Demo_youdian
//
// Created by 许 on 17/6/20.
// Copyright © 2017年 winFan. All rights reserved.
//
#import "AppleIap.h"
#import "IAPShare.h"
#import <PoolSdk/PoolSdk2.h>
@implementation AppleIap
/**
@return 商品ID
*/
- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
if(appleAmount.intValue == amount.intValue){
NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount);
return keyValue;
}
}
}
}
NSLog(@"amount get productId error amount:%@",amount);
return nil;
}
-(void)applePay:(NSString *)products amount:(NSString *)amount queryId:(NSString *)queryId
{
//内购ID
NSString* productId = [self getProductIdByAmount:products amount:amount];
if(productId){
[self ipaPay:productId queryId:queryId];
}else{
NSLog(@"get apple product id error");
}
}
/**
苹果支付结果回调
*/
- (void)applePayCallBack:(NSString*)receiptStr queryId:(NSString*)queryId
{
//NSDictionary* payResultDic = notification.object;
//NSString* receiptStr = [payResultDic objectForKey:@"payResult"];
//NSString* queryId = [payResultDic objectForKey:@"query_id"];
NSLog(@"applePayCallBack");
NSDictionary* receiptDic = [NSDictionary dictionaryWithObjectsAndKeys:receiptStr,@"receipt",queryId,@"query_id", nil];
NSString* result = [[NetCenter getInstance] httpPostSyn:[PoolUtils createPayUrl] :receiptDic];
if([@"success" isEqualToString:result]){//确认订单成功
}else{//失败
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray* queryIdArray = [userDefaults objectForKey:@"queryIds"];
NSMutableArray* tempQueryIdArray = [[NSMutableArray alloc] initWithCapacity:10];
if (queryIdArray) {
}else{
queryIdArray = [[NSMutableArray alloc]initWithCapacity:10];
}
for (NSString* arrayQueryId in queryIdArray) {
[tempQueryIdArray addObject:arrayQueryId];
}
[tempQueryIdArray addObject:queryId];
[userDefaults setObject:tempQueryIdArray forKey:@"queryIds"];
[userDefaults setObject:receiptStr forKey:queryId];
[userDefaults synchronize];
}
}
- (void)initIpa:(NSString*)productId{
if(![IAPShare sharedHelper].iap){
NSLog(@"iap init");
}
NSSet* dataSet = [[NSSet alloc]initWithObjects:productId, nil];
[IAPShare sharedHelper].iap = [[IAPHelper alloc] initWithProductIdentifiers:dataSet];
}
- (void)ipaPay:(NSString*) productId queryId:(NSString*)queryId{
@synchronized([PoolSdk shareSDK]) {
if([PoolSdk shareSDK].isApplePaying) {
NSLog(@"apple paying");
return;
};
[PoolSdk shareSDK].isApplePaying = true;
}
NSLog(@"productId:%@",productId);
[self initIpa:productId];
[[IAPShare sharedHelper].iap requestProductsWithCompletion:^(SKProductsRequest* request,SKProductsResponse* response)
{
NSLog(@"response");
if(response && response > 0 ) {
NSLog(@"response %lu",(unsigned long)[[IAPShare sharedHelper].iap.products count]);
if([[IAPShare sharedHelper].iap.products count] > 0){
NSLog(@"product count 1");
SKProduct* product =[[IAPShare sharedHelper].iap.products objectAtIndex:0];
NSString* queryIdStr = queryId;
[[IAPShare sharedHelper].iap buyProduct:product
onCompletion:^(SKPaymentTransaction* trans){
[PoolSdk shareSDK].isApplePaying = false;
NSLog(@"buy product callback");
if(trans.error)
{
NSLog(@"Fail %@",[trans.error localizedDescription]);
}
else if(trans.transactionState == SKPaymentTransactionStatePurchased) {
NSData* receiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
NSString* receiptStr = [receiptData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
receiptStr = [receiptStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[self applePayCallBack:receiptStr queryId:queryIdStr];
}
else if(trans.transactionState == SKPaymentTransactionStateFailed) {
NSLog(@"Fail");
}
}];
}else{
[PoolSdk shareSDK].isApplePaying = false;
}
}else{
[PoolSdk shareSDK].isApplePaying = false;
}
}];
}
@end
//
// LonginController.h
// NewLogin
//
// Created by 耿宇 on 16/3/28.
// Copyright © 2016年 JT. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface LonginController : UIViewController
@property(nonatomic,copy)void(^block)(BOOL,NSDictionary *dict);
-(instancetype)initWithGameId:(NSString *)gameId withAvatarImg:(NSString*)avatarImg withParamJson:(NSDictionary*)ParamJson;
@end
//
// PPInterface.h
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#import <PoolSdk/PoolSdk2.h>
@interface SDKInterface : Interface
@end
//
// UnionInterface.m
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#include "SDKInterface.h"
#import <UIKit/UIKit.h>
#import "LonginController.h"
#import "UpDatePerson.h"
#import "XiaoaoPay.h"
#import "AppleIap.h"
@implementation SDKInterface : Interface
/**
初始化SDK
*/
- (void)SDKinit:(UIViewController *) control
{
//必须继承
[super SDKinit:control];
[PoolConfig getInstance];
[[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil];
}
/**
登录SDK
*/
- (void)SDKloginSDK
{
NSLog(@"调用了LoginSDK");
NSString* gameId = [[PoolConfig getInstance] getValueByKey:@"gameId"];
LonginController * longin = [[LonginController alloc]initWithGameId:gameId withAvatarImg:nil withParamJson:nil];
longin.block = ^(BOOL result , NSDictionary *dic){
NSLog(@"login info %@",dic);
if (result) {
[self loginCheck:[dic objectForKey:@"usercode"] uid:[dic objectForKey:@"aokuid"]];
}else{
[[PoolChecker getInstance] sendNotice:PoolSDKNotificationLogin notiName:@"loginFail" statusCode:POOLSDK_ERROR_LOGIN_FAILED description:@"loginFail" extendData:nil];
}
};
if ([[[UIDevice currentDevice]systemVersion]floatValue]>8.0) {
longin.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
else{
self.controller.modalPresentationStyle = UIModalPresentationCurrentContext;
}
[self.controller presentViewController:longin animated:NO completion:nil];
}
/*
*登录验证请求方法模版
*/
- (void)loginCheck:(NSString *)userCode uid:(NSString*)uid
{
NSLog(@"uid:%@",uid);
PoolLoginInfo *loginInfo = [[PoolLoginInfo alloc]init];
loginInfo.openId = userCode;//渠道userId
loginInfo.timestamp = [self getCurrentTimestamp];
loginInfo.sign = uid;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[PoolChecker getInstance]startCheck:loginInfo];//登录验证请求
});
}
- (void)SDKreport:(PoolReportInfo *)reportInfo
{
NSLog(@"reportInfo");
if ([REPORT_CREATEROLE isEqualToString:[reportInfo reportType]]) {
}else if ([[reportInfo reportType] isEqualToString:REPORT_ENTER]) {
NSString *playerName = [reportInfo playerName];
NSString *playerLevel = [reportInfo playerLevel];
UpDatePerson *up = [[UpDatePerson alloc]init];
[up updatePerson:playerName withGameLevel:playerLevel withTeamId:[reportInfo partyName]];
up.block = ^(NSString * str){
NSLog(@"%@",str);//返回更新玩家信息是否成功
};
}
}
/**
SDK
*/
- (void)SDKexitSDK
{
}
- (void)SDKlogoutSDK
{
NSLog(@"切换账号");
}
- (void)receivePayMessage : (NSNotification *)notification;
{
NSString *order_id = [notification object];
NSLog(@"订单ID:%@", order_id);
}
/**
@return 商品名称
*/
- (NSString*)getProductNameByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
if(appleAmount.intValue == amount.intValue){
NSString* productName = [[productList objectForKey:keyValue] objectForKey:@"name"];
return productName;
}
}
}
}
NSLog(@"get product name error amount:%@",amount);
return @"元宝";
}
/**
@return 商品ID
*/
- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSLog(@"i found %@",keyValue);
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount);
if(appleAmount.intValue == amount.intValue){
return keyValue;
}
}
}
}
return @"unknow";
}
- (void)receiveCreateOrder:(NSNotification *)notification
{
NSLog(@"创建订单成功");
PoolPayInfo *payInfo = [notification object];
NSString *queryId = [payInfo queryId];
NSString *amount = [[NSString alloc]initWithFormat:@"%d",[payInfo postAmount].intValue * 100];
NSString *gameId = [[PoolConfig getInstance]getValueByKey:@"gameId"];
NSString *xaChannelId = [[PoolConfig getInstance]getValueByKey:@"xaChannelId"];
NSString *productName = [self getProductNameByAmount:[payInfo products] amount:amount];//公共后台获取商品名称(对应游尚的商品ID(productID))
NSString *other = [payInfo other];
if ([@"" isEqualToString:other]) {//苹果支付
[[[AppleIap alloc]init] applePay:[payInfo products] amount:[payInfo postAmount] queryId:queryId];
}else{
[[XiaoaoPay shareInstance]reuqrstPaytype:gameId andChannelid:xaChannelId andProductid:productName andUserid:[payInfo playerId] andServerid:[payInfo serverId] andExtra:queryId andProductName:[payInfo productName] andPrice:amount];
[XiaoaoPay shareInstance].block = ^(BOOL result,NSString*payName,NSString * orederId){
};
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
//添加方法:
NSLog(@"applicationWillEnterForeground");
[[NSNotificationCenter defaultCenter]postNotificationName:@"closed" object:nil];
}
-(NSString*)getCurrentTimestamp{
// 时间戳转时间
NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000;
NSString* timeStr = [[NSString alloc]initWithFormat:@"%.f",interval];
return timeStr;
}
@end
\ No newline at end of file
//
// UpDatePerson.h
// NewLogin
//
// Created by 耿宇 on 16/5/11.
// Copyright © 2016年 JT. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface UpDatePerson : NSObject
@property(nonatomic,copy)void(^block)(NSString *);
-(void)updatePerson:(NSString *)nickName withGameLevel:(NSString *)gameLevel withTeamId:(NSString*)teamId;
@end
//
// XiaoaoPay.h
// xiaoAoPay
//
// Created by jzw on 16/12/8.
// Copyright © 2016年 jzw. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface XiaoaoPay : NSObject
@property(nonatomic,copy)void(^block)(BOOL,NSString*,NSString*);
+(XiaoaoPay*)shareInstance;
-(void)reuqrstPaytype:(NSString*)gameid andChannelid:(NSString*)channelid andProductid:(NSString*)productid andUserid:(NSString*)userid andServerid:(NSString*)serverid andExtra:(NSString*)extra andProductName:(NSString *)productName andPrice:(NSString *)price;
@end
//
// IAPHelper.h
//
// Original Created by Ray Wenderlich on 2/28/11.
// Created by saturngod on 7/9/12.
// Copyright 2011 Ray Wenderlich. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "StoreKit/StoreKit.h"
typedef void (^IAPProductsResponseBlock)(SKProductsRequest* request , SKProductsResponse* response);
typedef void (^IAPbuyProductCompleteResponseBlock)(SKPaymentTransaction* transcation);
typedef void (^checkReceiptCompleteResponseBlock)(NSString* response,NSError* error);
typedef void (^resoreProductsCompleteResponseBlock) (SKPaymentQueue* payment,NSError* error);
@interface IAPHelper : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver>
@property (nonatomic,strong) NSSet *productIdentifiers;
@property (nonatomic,strong) NSArray * products;
@property (nonatomic,strong) NSMutableSet *purchasedProducts;
@property (nonatomic,strong) SKProductsRequest *request;
@property (nonatomic) BOOL production;
//init With Product Identifiers
- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers;
//get Products List
- (void)requestProductsWithCompletion:(IAPProductsResponseBlock)completion;
//Buy Product
- (void)buyProduct:(SKProduct *)productIdentifier onCompletion:(IAPbuyProductCompleteResponseBlock)completion;
//restore Products
- (void)restoreProductsWithCompletion:(resoreProductsCompleteResponseBlock)completion;
//check isPurchased or not
- (BOOL)isPurchasedProductsIdentifier:(NSString*)productID;
//check receipt but recommend to use in server side instead of using this function
- (void)checkReceipt:(NSData*)receiptData onCompletion:(checkReceiptCompleteResponseBlock)completion;
- (void)checkReceipt:(NSData*)receiptData AndSharedSecret:(NSString*)secretKey onCompletion:(checkReceiptCompleteResponseBlock)completion;
//saved purchased product
- (void)provideContentWithTransaction:(SKPaymentTransaction *)transaction;
- (void)provideContent:(NSString *)productIdentifier __deprecated_msg("use provideContentWithTransaction: instead.");
//clear the saved products
- (void)clearSavedPurchasedProducts;
- (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier;
//Get The Price with local currency
- (NSString *)getLocalePrice:(SKProduct *)product;
@end
//
// IAPHelper.m
//
// Original Created by Ray Wenderlich on 2/28/11.
// Created by saturngod on 7/9/12.
// Copyright 2011 Ray Wenderlich. All rights reserved.
//
#import "IAPHelper.h"
#import "NSString+Base64.h"
#import "SFHFKeychainUtils.h"
#if ! __has_feature(objc_arc)
#error You need to either convert your project to ARC or add the -fobjc-arc compiler flag to IAPHelper.m.
#endif
@interface IAPHelper()
@property (nonatomic,copy) IAPProductsResponseBlock requestProductsBlock;
@property (nonatomic,copy) IAPbuyProductCompleteResponseBlock buyProductCompleteBlock;
@property (nonatomic,copy) resoreProductsCompleteResponseBlock restoreCompletedBlock;
@property (nonatomic,copy) checkReceiptCompleteResponseBlock checkReceiptCompleteBlock;
@property (nonatomic,strong) NSMutableData* receiptRequestData;
@end
@implementation IAPHelper
- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers {
if ((self = [super init])) {
// Store product identifiers
_productIdentifiers = productIdentifiers;
// Check for previously purchased products
NSMutableSet * purchasedProducts = [NSMutableSet set];
for (NSString * productIdentifier in _productIdentifiers) {
BOOL productPurchased = NO;
NSString* password = [SFHFKeychainUtils getPasswordForUsername:productIdentifier andServiceName:@"IAPHelper" error:nil];
if([password isEqualToString:@"YES"])
{
productPurchased = YES;
}
if (productPurchased) {
[purchasedProducts addObject:productIdentifier];
}
}
if ([SKPaymentQueue defaultQueue]) {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
self.purchasedProducts = purchasedProducts;
}
}
return self;
}
- (void)dealloc
{
if ([SKPaymentQueue defaultQueue]) {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
}
-(BOOL)isPurchasedProductsIdentifier:(NSString*)productID
{
BOOL productPurchased = NO;
NSString* password = [SFHFKeychainUtils getPasswordForUsername:productID andServiceName:@"IAPHelper" error:nil];
if([password isEqualToString:@"YES"])
{
productPurchased = YES;
}
return productPurchased;
}
- (void)requestProductsWithCompletion:(IAPProductsResponseBlock)completion {
self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers];
_request.delegate = self;
self.requestProductsBlock = completion;
[_request start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
self.products = response.products;
self.request = nil;
if(_requestProductsBlock) {
_requestProductsBlock (request,response);
}
}
- (void)recordTransaction:(SKPaymentTransaction *)transaction {
// TODO: Record the transaction on the server side...
}
- (void)provideContentWithTransaction:(SKPaymentTransaction *)transaction {
NSString* productIdentifier = @"";
if (transaction.originalTransaction) {
productIdentifier = transaction.originalTransaction.payment.productIdentifier;
}
else {
productIdentifier = transaction.payment.productIdentifier;
}
//check productIdentifier exist or not
//it can be possible nil
if (productIdentifier) {
[SFHFKeychainUtils storeUsername:productIdentifier andPassword:@"YES" forServiceName:@"IAPHelper" updateExisting:YES error:nil];
[_purchasedProducts addObject:productIdentifier];
}
}
- (void)provideContent:(NSString *)productIdentifier {
[SFHFKeychainUtils storeUsername:productIdentifier andPassword:@"YES" forServiceName:@"IAPHelper" updateExisting:YES error:nil];
[_purchasedProducts addObject:productIdentifier];
}
- (void)clearSavedPurchasedProducts {
for (NSString * productIdentifier in _productIdentifiers) {
[self clearSavedPurchasedProductByID:productIdentifier];
}
}
- (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier {
[SFHFKeychainUtils deleteItemForUsername:productIdentifier andServiceName:@"IAPHelper" error:nil];
[_purchasedProducts removeObject:productIdentifier];
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction {
[self recordTransaction: transaction];
if ([SKPaymentQueue defaultQueue]) {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
if(_buyProductCompleteBlock)
{
_buyProductCompleteBlock(transaction);
}
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
[self recordTransaction: transaction];
[self provideContentWithTransaction:transaction];
if ([SKPaymentQueue defaultQueue]) {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
if(_buyProductCompleteBlock!=nil)
{
_buyProductCompleteBlock(transaction);
}
}
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
if (transaction.error.code != SKErrorPaymentCancelled)
{
NSLog(@"Transaction error: %@ %ld", transaction.error.localizedDescription,(long)transaction.error.code);
}
if ([SKPaymentQueue defaultQueue]) {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
if(_buyProductCompleteBlock) {
_buyProductCompleteBlock(transaction);
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default:
break;
}
}
}
- (void)buyProduct:(SKProduct *)productIdentifier onCompletion:(IAPbuyProductCompleteResponseBlock)completion {
self.buyProductCompleteBlock = completion;
self.restoreCompletedBlock = nil;
SKPayment *payment = [SKPayment paymentWithProduct:productIdentifier];
if ([SKPaymentQueue defaultQueue]) {
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
-(void)restoreProductsWithCompletion:(resoreProductsCompleteResponseBlock)completion {
//clear it
self.buyProductCompleteBlock = nil;
self.restoreCompletedBlock = completion;
if ([SKPaymentQueue defaultQueue]) {
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
else {
NSLog(@"Cannot get the default Queue");
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
NSLog(@"Transaction error: %@ %ld", error.localizedDescription,(long)error.code);
if(_restoreCompletedBlock) {
_restoreCompletedBlock(queue,error);
}
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
for (SKPaymentTransaction *transaction in queue.transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStateRestored:
{
[self recordTransaction: transaction];
[self provideContentWithTransaction:transaction];
}
default:
break;
}
}
if(_restoreCompletedBlock) {
_restoreCompletedBlock(queue,nil);
}
}
- (void)checkReceipt:(NSData*)receiptData onCompletion:(checkReceiptCompleteResponseBlock)completion
{
[self checkReceipt:receiptData AndSharedSecret:nil onCompletion:completion];
}
- (void)checkReceipt:(NSData*)receiptData AndSharedSecret:(NSString*)secretKey onCompletion:(checkReceiptCompleteResponseBlock)completion
{
self.checkReceiptCompleteBlock = completion;
NSError *jsonError = nil;
NSString *receiptBase64 = [NSString base64StringFromData:receiptData length:[receiptData length]];
NSData *jsonData = nil;
if(secretKey !=nil && ![secretKey isEqualToString:@""]) {
jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys:receiptBase64,@"receipt-data",
secretKey,@"password",
nil]
options:NSJSONWritingPrettyPrinted
error:&jsonError];
}
else {
jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys:
receiptBase64,@"receipt-data",
nil]
options:NSJSONWritingPrettyPrinted
error:&jsonError
];
}
// NSString* jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSURL *requestURL = nil;
if(_production)
{
requestURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"];
}
else {
requestURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
}
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:requestURL];
[req setHTTPMethod:@"POST"];
[req setHTTPBody:jsonData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if(conn) {
self.receiptRequestData = [[NSMutableData alloc] init];
} else {
NSError* error = nil;
NSMutableDictionary* errorDetail = [[NSMutableDictionary alloc] init];
[errorDetail setValue:@"Can't create connection" forKey:NSLocalizedDescriptionKey];
error = [NSError errorWithDomain:@"IAPHelperError" code:100 userInfo:errorDetail];
if(_checkReceiptCompleteBlock) {
_checkReceiptCompleteBlock(nil,error);
}
}
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"Cannot transmit receipt data. %@",[error localizedDescription]);
if(_checkReceiptCompleteBlock) {
_checkReceiptCompleteBlock(nil,error);
}
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.receiptRequestData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.receiptRequestData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *response = [[NSString alloc] initWithData:self.receiptRequestData encoding:NSUTF8StringEncoding];
if(_checkReceiptCompleteBlock) {
_checkReceiptCompleteBlock(response,nil);
}
}
- (NSString *)getLocalePrice:(SKProduct *)product {
if (product) {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[formatter setLocale:product.priceLocale];
return [formatter stringFromNumber:product.price];
}
return @"";
}
@end
//
// IAPShare.h
// ;
//
// Created by Htain Lin Shwe on 10/7/12.
// Copyright (c) 2012 Edenpod. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IAPHelper.h"
@interface IAPShare : NSObject
@property (nonatomic,strong) IAPHelper *iap;
+ (IAPShare *) sharedHelper;
+(id)toJSON:(NSString*)json;
@end
//
// IAPShare.m
// inappPurchasesTest
//
// Created by Htain Lin Shwe on 10/7/12.
// Copyright (c) 2012 Edenpod. All rights reserved.
//
#import "IAPShare.h"
#if ! __has_feature(objc_arc)
#error You need to either convert your project to ARC or add the -fobjc-arc compiler flag to IAPShare.m.
#endif
@implementation IAPShare
@synthesize iap= _iap;
+ (IAPShare *) sharedHelper {
static IAPShare * _sharedHelper = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedHelper = [[IAPShare alloc] init];
_sharedHelper.iap = nil;
});
return _sharedHelper;
}
+(id)toJSON:(NSString *)json
{
NSError* e = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData: [json dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: &e];
if(e==nil) {
return jsonObject;
}
else {
NSLog(@"%@",[e localizedDescription]);
return nil;
}
}
@end
//
// NSString+Base64.h
// Newsstand
//
// Created by Carlo Vigiani on 29/Oct/11.
// Copyright (c) 2011 viggiosoft. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (Base64)
+ (NSString *) base64StringFromData:(NSData *)data length:(long)length;
@end
//
// NSString+Base64.m
// Newsstand
//
// Created by Carlo Vigiani on 29/Oct/11.
// Copyright (c) 2011 viggiosoft. All rights reserved.
//
#import "NSString+Base64.h"
static char base64EncodingTable[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
@implementation NSString (Base64)
+ (NSString *) base64StringFromData:(NSData *)data length:(long)length {
unsigned long ixtext, lentext;
long ctremaining;
unsigned char input[3], output[4];
short i, charsonline = 0, ctcopy;
const unsigned char *raw;
NSMutableString *result;
lentext = [data length];
if (lentext < 1)
return @"";
result = [NSMutableString stringWithCapacity: lentext];
raw = [data bytes];
ixtext = 0;
while (true) {
ctremaining = lentext - ixtext;
if (ctremaining <= 0)
break;
for (i = 0; i < 3; i++) {
unsigned long ix = ixtext + i;
if (ix < lentext)
input[i] = raw[ix];
else
input[i] = 0;
}
output[0] = (input[0] & 0xFC) >> 2;
output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
output[3] = input[2] & 0x3F;
ctcopy = 4;
switch (ctremaining) {
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for (i = 0; i < ctcopy; i++)
[result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
for (i = ctcopy; i < 4; i++)
[result appendString: @"="];
ixtext += 3;
charsonline += 4;
if ((length > 0) && (charsonline >= length))
charsonline = 0;
}
return result;
}
@end
//
// SFHFKeychainUtils.h
//
// Created by Buzz Andersen on 10/20/08.
// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#import <UIKit/UIKit.h>
@interface SFHFKeychainUtils : NSObject {
}
+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error;
+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
@end
\ No newline at end of file
//
// SFHFKeychainUtils.m
//
// Created by Buzz Andersen on 10/20/08.
// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#import "SFHFKeychainUtils.h"
#import <Security/Security.h>
static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain";
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR
@interface SFHFKeychainUtils (PrivateMethods)
(SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
@end
#endif
@implementation SFHFKeychainUtils
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR
+(NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
if (!username || !serviceName) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
return nil;
}
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];
if (*error || !item) {
return nil;
}
// from Advanced Mac OS X Programming, ch. 16
UInt32 length;
char *password;
SecKeychainAttribute attributes[8];
SecKeychainAttributeList list;
attributes[0].tag = kSecAccountItemAttr;
attributes[1].tag = kSecDescriptionItemAttr;
attributes[2].tag = kSecLabelItemAttr;
attributes[3].tag = kSecModDateItemAttr;
list.count = 4;
list.attr = attributes;
OSStatus status = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password);
if (status != noErr) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
return nil;
}
NSString *passwordString = nil;
if (password != NULL) {
char passwordBuffer[1024];
if (length > 1023) {
length = 1023;
}
strncpy(passwordBuffer, password, length);
passwordBuffer[length] = '\0';
passwordString = [NSString stringWithCString:passwordBuffer];
}
SecKeychainItemFreeContent(&list, password);
CFRelease(item);
return passwordString;
}
+ (void) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error {
if (!username || !password || !serviceName) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
return;
}
OSStatus status = noErr;
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];
if (*error && [*error code] != noErr) {
return;
}
*error = nil;
if (item) {
status = SecKeychainItemModifyAttributesAndData(item,NULL,strlen([password UTF8String]),[password UTF8String]);
CFRelease(item);
}
else {
status = SecKeychainAddGenericPassword(NULL,strlen([serviceName UTF8String]),[serviceName UTF8String],strlen([username UTF8String]),[username UTF8String],strlen([password UTF8String]),[password UTF8String],NULL);
}
if (status != noErr) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
}
}
+ (void) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
if (!username || !serviceName) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: 2000 userInfo: nil];
return;
}
*error = nil;
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];
if (*error && [*error code] != noErr) {
return;
}
OSStatus status;
if (item) {
status = SecKeychainItemDelete(item);
CFRelease(item);
}
if (status != noErr) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
}
}
+ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
if (!username || !serviceName) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
return nil;
}
*error = nil;
SecKeychainItemRef item;
OSStatus status = SecKeychainFindGenericPassword(NULL,strlen([serviceName UTF8String]),[serviceName UTF8String],strlen([username UTF8String]),[username UTF8String], NULL,NULL,&item);
if (status != noErr) {
if (status != errSecItemNotFound) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
}
return nil;
}
return item;
}
#else
+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
if (!username || !serviceName) {
if (error != nil) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
}
return nil;
}
if (error != nil) {
*error = nil;
}
// Set up a query dictionary with the base query attributes: item type (generic), username, and service
NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil];
NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword, username, serviceName, nil];
NSMutableDictionary *query = [[NSMutableDictionary alloc] initWithObjects: objects forKeys: keys];
// First do a query for attributes, in case we already have a Keychain item with no password data set.
// One likely way such an incorrect item could have come about is due to the previous (incorrect)
// version of this code (which set the password as a generic attribute instead of password data).
NSMutableDictionary *attributeQuery = [query mutableCopy];
[attributeQuery setObject: (id) kCFBooleanTrue forKey:(__bridge_transfer id) kSecReturnAttributes];
CFTypeRef attrResult = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) attributeQuery, &attrResult);
//NSDictionary *attributeResult = (__bridge_transfer NSDictionary *)attrResult;
if (status != noErr) {
// No existing item found--simply return nil for the password
if (error != nil && status != errSecItemNotFound) {
//Only return an error if a real exception happened--not simply for "not found."
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
}
return nil;
}
// We have an existing item, now query for the password data associated with it.
NSMutableDictionary *passwordQuery = [query mutableCopy];
[passwordQuery setObject: (id) kCFBooleanTrue forKey: (__bridge_transfer id) kSecReturnData];
CFTypeRef resData = NULL;
status = SecItemCopyMatching((__bridge CFDictionaryRef) passwordQuery, (CFTypeRef *) &resData);
NSData *resultData = (__bridge_transfer NSData *)resData;
if (status != noErr) {
if (status == errSecItemNotFound) {
// We found attributes for the item previously, but no password now, so return a special error.
// Users of this API will probably want to detect this error and prompt the user to
// re-enter their credentials. When you attempt to store the re-entered credentials
// using storeUsername:andPassword:forServiceName:updateExisting:error
// the old, incorrect entry will be deleted and a new one with a properly encrypted
// password will be added.
if (error != nil) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil];
}
}
else {
// Something else went wrong. Simply return the normal Keychain API error code.
if (error != nil) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
}
}
return nil;
}
NSString *password = nil;
if (resultData) {
password = [[NSString alloc] initWithData: resultData encoding: NSUTF8StringEncoding];
}
else {
// There is an existing item, but we weren't able to get password data for it for some reason,
// Possibly as a result of an item being incorrectly entered by the previous code.
// Set the -1999 error so the code above us can prompt the user again.
if (error != nil) {
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil];
}
}
return password;
}
+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error
{
if (!username || !password || !serviceName)
{
if (error != nil)
{
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
}
return NO;
}
// See if we already have a password entered for these credentials.
NSError *getError = nil;
NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername: username andServiceName: serviceName error:&getError];
if ([getError code] == -1999)
{
// There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code.
// Delete the existing item before moving on entering a correct one.
getError = nil;
[self deleteItemForUsername: username andServiceName: serviceName error: &getError];
if ([getError code] != noErr)
{
if (error != nil)
{
*error = getError;
}
return NO;
}
}
else if ([getError code] != noErr)
{
if (error != nil)
{
*error = getError;
}
return NO;
}
if (error != nil)
{
*error = nil;
}
OSStatus status = noErr;
if (existingPassword)
{
// We have an existing, properly entered item with a password.
// Update the existing item.
if (![existingPassword isEqualToString:password] && updateExisting)
{
//Only update if we're allowed to update existing. If not, simply do nothing.
NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass,kSecAttrService,kSecAttrLabel,kSecAttrAccount,nil];
NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword,serviceName,serviceName,username,nil];
NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys];
status = SecItemUpdate((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) [NSDictionary dictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (__bridge_transfer NSString *) kSecValueData]);
}
}
else
{
// No existing entry (or an existing, improperly entered, and therefore now
// deleted, entry). Create a new entry.
NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass,kSecAttrService,kSecAttrLabel,kSecAttrAccount,kSecValueData,nil];
NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword,serviceName,serviceName,username,[password dataUsingEncoding: NSUTF8StringEncoding],nil];
NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys];
status = SecItemAdd((__bridge CFDictionaryRef) query, NULL);
}
if (error != nil && status != noErr)
{
// Something went wrong with adding the new item. Return the Keychain error code.
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
return NO;
}
return YES;
}
+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error
{
if (!username || !serviceName)
{
if (error != nil)
{
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
}
return NO;
}
if (error != nil)
{
*error = nil;
}
NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil];
NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword, username, serviceName, kCFBooleanTrue, nil];
NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys];
OSStatus status = SecItemDelete((__bridge CFDictionaryRef) query);
if (error != nil && status != noErr)
{
*error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
return NO;
}
return YES;
}
#endif
@end
\ No newline at end of file
{"gtAppId": "3271E2986B984E5D83C94471C63292A9", "gameId": "1113", "payorderurl": "https://public.sdk.gzyouai.com/paycheck/create", "usertype": 189, "sdkSimpleName": "youshang_ios", "gamechannelid": "9628", "xaChannelId": "9628", "custom": "{}", "sdkVersionCode": "V1_0_0", "loginCheckUrl": "https://public.sdk.gzyouai.com/logincheck/check", "appScheme": "com.xiaoao.xsqy", "c2": "", "c1": "", "adAppId": "1313CF7DE9604F1AA262B78D5D0F45C0", "paycheckurl": "https://public.sdk.gzyouai.com/paycheck/confirm", "gameSimpleName": "fytx_test"}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ProjectID</key>
<string>1</string>
<key>devEnv</key>
<string>65094646</string>
</dict>
</plist>
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/en.lproj/InfoPlist.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/en.lproj/Localizable.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/ko.lproj/InfoPlist.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/ko.lproj/Localizable.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/ru.lproj/InfoPlist.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/ru.lproj/Localizable.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/zh-Hans.lproj/InfoPlist.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/zh-Hans.lproj/Localizable.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/zh-Hant.lproj/InfoPlist.strings and /dev/null differ
......
Binary files a/PoolSdk_Demo/poolsdk_file/poolsdk_zhongshouyou/SDK/LuckBundle.bundle/zh-Hant.lproj/Localizable.strings and /dev/null differ
......
//
// LuckIAPManage.h
// luck
//
// Created by CaiShengWei on 15/7/30.
// Copyright (c) 2015年 William. All rights reserved.
//
#import <Foundation/Foundation.h>
//支付成功通知
extern NSString * const kLuckIAPPayResultSuccessNotification;
//支付失败通知
extern NSString * const kLuckIAPPayResultFailNotification;
//恢复成功通知
extern NSString * const kLuckIAPRestoreSuccessNotification;
@interface LuckIAPManage : NSObject
/**
* IAP支付单例
*/
+ (LuckIAPManage *) defaultManage;
/**
* IAP支付
*
* @param roleName 游戏角色
* @param roleId 角色ID
* @param server 游戏区服
* @param serverId 服务器ID
* @param feePointId 计费点ID(纯数字)
* @param goodName 商品名称
* @param goodDesc 商品描述
* @param callBackInfo 厂商自定义参数
*
*/
- (void)startPayWithRoleName:(NSString *)roleName
roleId:(NSString *)roleId
server:(NSString *)server
serverId:(NSString *)serverId
feePointId:(NSString *)feePointId
goodName:(NSString *)goodName
goodDesc:(NSString *)goodDesc
callBackInfo:(NSString *)callBackInfo;
/**
* 恢复购买(非消耗品和自动续订恢复)
*
* @param roleName 游戏角色
* @param roleId 角色ID
* @param server 游戏区服
* @param serverId 服务器ID
* @param callBackInfo 厂商自定义参数
*/
- (void)restoreTransactionsRoleName:(NSString *)roleName
roleId:(NSString *)roleId
server:(NSString *)server
serverId:(NSString *)serverId
callBackInfo:(NSString *)callBackInfo;
@end
//
// LuckLoginManage.h
// LuckNewDemo
//
// Created by CaiShengWei on 15/7/22.
// Copyright (c) 2015年 luck. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface LuckLoginManage : NSObject
//使用单例类,方便在全局控制
+ (LuckLoginManage *)defaultManage;
//隐藏显示提示框登录界面
- (void)showLoginAlertView;
- (void)hideLoginAlertView;
//显示隐藏控制器登录界面
- (void)showLoginViewController;
- (void)hideLoginViewController;
//显示隐藏浮动图标(单机游戏不要显示浮标)
- (void)showFloatMenuView;
- (void)hideFloatMenuView;
//显示游戏客服
- (void)showGameServiceView;
//显示评价页面(该接口实现由苹果控制,每年展示3次,iOS10.3以上才能使用)
- (void)showEvaluateView;
/**显示绑定手机视图*/
- (void)showBindingPhoneView;
/**绑定手机成功的通知 会传递手机号码*/
extern NSString * const kLuckBlindingPhoneSuccessNotification;
/**
* 提交用户角色信息
* 参数配置
* @param role 游戏角色(必填)
* @param roleId 角色Id
* @param server 游戏区服(必填)
* @param serverId 游戏服务器ID
* @param callBackInfo 厂商自定义参数
*/
- (void)commitUserRoleWithRole:(NSString *)role
roleId:(NSString *)roleId
server:(NSString *)server
serverId:(NSString *)serverId
callBackInfo:(NSString *)callBackInfo;
#pragma mark - 单机登录方法
/**
* 单机游戏切换账号
*/
- (void)changeAccountOnSingleGame;
#pragma mark - 显示论坛
/**
* 显示论坛
*/
- (void)showForumViewController;
@end
//
// LuckProject.h
// luck
//
// Created by CaiShengWei on 15/7/30.
// Copyright (c) 2015年 William. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
* 枚举类型:屏幕方向
*/
typedef NS_ENUM(NSInteger, LuckInterfaceOrientationMask) {
LuckViewPortrait = 0, //竖屏(不可旋转)
LuckViewLandscape, //横屏(可旋转)
LuckViewLandscapeLeft, //横屏(home键在左边,不可旋转)
LuckViewLandscapeRight,//横屏(home键在右边,不可旋转)
};
@interface LuckProject : NSObject
/**
* 单例模式
*/
+ (LuckProject *) shareData;
/**
* 项目参数配置
* @param gameName 游戏名称
* @param gameVerName 游戏版本号
* @param customerEmail 客服邮箱/QQ
* @param customerPhone 客户电话
* @param viewOrientations 屏幕方向
* @param isCopyRighted YES有版权,NO无版权(是否有logo)
* @param isSingleGame 是否是单机游戏
*/
- (void)projectWithGameName:(NSString *)gameName
gameVerName:(NSString *)gameVerName
customerEmail:(NSString *)customerEmail
customerPhone:(NSString *)customerPhone
viewOrientations:(LuckInterfaceOrientationMask)viewOrientations
isCopyRighted:(BOOL)isCopyRighted
isSingleGame:(BOOL)isSingleGame;
/**
* 第三方登录回调
* @param application
* @param url
* @param sourceApplication
* @param annotation
*/
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation;
/**
* 第三方登录回调
* @param application
* @param url
*/
- (BOOL)application:(UIApplication *)application
handleOpenURL:(NSURL *)url;
@end
//
// PPInterface.h
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#import <PoolSdk/PoolSdk2.h>
@interface SDKInterface : Interface
@end
//
// UnionInterface.m
// PoolSdk
//
// Created by winFan on 11/23/15.
// Copyright (c) 2015 winFan. All rights reserved.
//
#include "SDKInterface.h"
#import <UIKit/UIKit.h>
#import <LuckSDK/LuckProject.h>
#import <LuckSDK/LuckLoginManage.h>
#import <LuckSDK/LuckIAPManage.h>
@implementation SDKInterface : Interface
/**
初始化SDK
*/
- (void)SDKinit:(UIViewController *) control
{
//必须继承
[super SDKinit:control];
[PoolConfig getInstance];
NSString * sdkGameName = [[PoolConfig getInstance]getValueByKey:@"sdkGameName"];
NSString * sdkEmail = [[PoolConfig getInstance]getValueByKey:@"sdkEmail"];
NSString * sdkPhone = [[PoolConfig getInstance]getValueByKey:@"sdkPhone"];
//配置项目参数
[[LuckProject shareData] projectWithGameName:sdkGameName
gameVerName:[[[NSBundle mainBundle]infoDictionary] objectForKey:@"CFBundleVersion"]
customerEmail:sdkEmail
customerPhone:sdkPhone
viewOrientations:LuckViewLandscape
isCopyRighted:NO
isSingleGame:NO]; //viewOrientations (屏幕方向): CmgeViewPortrait 竖屏(不可旋转),\
CmgeViewLandscape 横屏(可旋转),\ CmgeViewLandscapeLeft 横屏(home 键在左边,不可旋转),\ CmgeViewLandscapeRight 横屏 (home 键在右边,不可旋转)
//isCopyRighted (是否有版权): YES有版权,NO无版权 //isSingleGame(是否是单机游戏): YES 单机游戏,NO 网游
[[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil];
//登录成功,获取登录信息(单机登录失败时也会发此通知,用户信息字典为nil)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loginInfo:)
name:@"luckLoginInfo"
object:nil];
//注册成功的通知,可在此进行新用户注册的计数
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(regSuccess)
name:@"luckRegisterSuccess"
object:nil];
//退出登录界面
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(quitLoginView)
name:@"kLuckQuitLogin"
object:nil];
}
- (NSString *)encodeParameter:(NSString *)originalPara {
CFStringRef encodeParaCf = CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef)originalPara, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8);
NSString *encodePara = (__bridge NSString *)(encodeParaCf);
CFRelease(encodeParaCf);
return encodePara;
}
// ************************** 实现所有监听方法 ************************** //
//登录成功后服务器返回的字典参数(单机登录失败时也会收到此通知,用户信息字典为nil)
-(void)loginInfo:(NSNotification *)value
{
NSDictionary *dic = [value object];
NSLog(@"dic = %@",dic);
//用户帐号
//NSString * luckUserAccount =[NSString stringWithFormat:@"%@",[dic objectForKey:@"a"]];
//用户ID
NSString * luckUserId =[NSString stringWithFormat:@"%@", [dic objectForKey:@"b"]];
//服务器当前时间戳
NSString * luckTimestamp = [NSString stringWithFormat:@"%@",[dic objectForKey:@"d"]];
//MD5(userId&timestamp&appkey)
NSString * luckSign = [NSString stringWithFormat:@"%@", [self encodeParameter:[dic objectForKey:@"e"]]];
PoolLoginInfo *loginInfo = [[PoolLoginInfo alloc]init];
loginInfo.openId = luckUserId;//渠道userId
loginInfo.timestamp = luckTimestamp;
loginInfo.sign = luckSign;//渠道SDK的token
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[PoolChecker getInstance]startCheck:loginInfo];//登录验证请求
});
/*******网游 登录成功后,显示浮标*******/
[[LuckLoginManage defaultManage] showFloatMenuView];
}
//退出登录界面
-(void)quitLoginView
{
NSLog(@"sdk 退出登录界面");
}
//注册成功后的操作
-(void)regSuccess
{
NSLog(@"sdk 注册成功");
}
#pragma mark - 第三方支付回调
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [[LuckProject shareData]application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [[LuckProject shareData] application:application handleOpenURL:url];
}
#pragma mark - sdk操作
/**
登录SDK
*/
- (void)SDKloginSDK
{
NSLog(@"调用了LoginSDK");
//全屏模式登录界面
//[[LuckLoginManage defaultManage] showLoginViewController];
//半透明登录
[[LuckLoginManage defaultManage] showLoginAlertView];
}
- (void)SDKreport:(PoolReportInfo *)reportInfo
{
NSLog(@"reportInfo");
if ([REPORT_CREATEROLE isEqualToString:[reportInfo reportType]]) {
}else if ([[reportInfo reportType] isEqualToString:REPORT_ENTER]) {
//提交用户角色信息
[[LuckLoginManage defaultManage] commitUserRoleWithRole:[reportInfo playerName]
roleId:[reportInfo playerId]
server:[reportInfo serverName]
serverId:[reportInfo serverId]
callBackInfo:@""];
}
}
/**
@return 商品名称
*/
- (NSString*)getProductNameByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
if(appleAmount.intValue == amount.intValue){
NSString* productName = [[productList objectForKey:keyValue] objectForKey:@"name"];
return productName;
}
}
}
}
NSLog(@"get product name error amount:%@",amount);
return @"元宝";
}
/**
@return 商品ID
*/
- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount
{
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil];
if(jsonData){
NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
if(productList){
NSEnumerator* keysList = [productList keyEnumerator];
id keyValue;
while (keyValue = [keysList nextObject])
{
NSLog(@"i found %@",keyValue);
NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"];
NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount);
if(appleAmount.intValue == amount.intValue){
return keyValue;
}
}
}
}
return @"unknow";
}
- (void)receiveCreateOrder:(NSNotification *)notification
{
NSLog(@"创建订单成功");
PoolPayInfo *payInfo = [notification object];
NSString *myamount = [payInfo postAmount];
NSString *productId = [self getProductIdByAmount:payInfo.products amount:myamount];
NSLog(@"commit productId:%@",productId);
//IAP支付
[[LuckIAPManage defaultManage] startPayWithRoleName:[payInfo playerName]
roleId:[payInfo playerId]
server:[payInfo serverName]
serverId:[payInfo serverId]
feePointId:productId
goodName:[payInfo productName]
goodDesc:[payInfo productDesc]
callBackInfo:[payInfo queryId]];
}
-(NSString*)getCurrentTimestamp{
// 时间戳转时间
NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000;
NSString* timeStr = [[NSString alloc]initWithFormat:@"%.f",interval];
return timeStr;
}
@end
{"payorderurl": "http://183.57.76.181:9020/paycheck/create", "usertype": 187, "sdkSimpleName": "zhongshouyou", "gamechannelid": "", "custom": "{}", "sdkVersionCode": "V2_2_9", "loginCheckUrl": "http://183.57.76.181:9010/logincheck/check", "appScheme": "appScheme", "c2": "", "c1": "", "paycheckurl": "http://183.57.76.181:9020/paycheck/confirm", "gameSimpleName": "fytx_test"}
\ No newline at end of file
channelRootPath = "poolsdk_file"
gameProjName = 'Demo'
\ No newline at end of file
# Copyright 2012 Calvin Rien
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# A pbxproj file is an OpenStep format plist
# {} represents dictionary of key=value pairs delimited by ;
# () represents list of values delimited by ,
# file starts with a comment specifying the character type
# // !$*UTF8*$!
# when adding a file to a project, create the PBXFileReference
# add the PBXFileReference's guid to a group
# create a PBXBuildFile with the PBXFileReference's guid
# add the PBXBuildFile to the appropriate build phase
# when adding a header search path add
# HEADER_SEARCH_PATHS = "path/**";
# to each XCBuildConfiguration object
# Xcode4 will read either a OpenStep or XML plist.
# this script uses `plutil` to validate, read and write
# the pbxproj file. Plutil is available in OS X 10.2 and higher
# Plutil can't write OpenStep plists, so I save as XML
import datetime
import json
import ntpath
import os
import plistlib
import re
import shutil
import subprocess
import uuid
from UserDict import IterableUserDict
from UserList import UserList
regex = '[a-zA-Z0-9\\._/-]*'
class PBXEncoder(json.JSONEncoder):
def default(self, obj):
"""Tests the input object, obj, to encode as JSON."""
if isinstance(obj, (PBXList, PBXDict)):
return obj.data
return json.JSONEncoder.default(self, obj)
class PBXDict(IterableUserDict):
def __init__(self, d=None):
if d:
d = dict([(PBXType.Convert(k), PBXType.Convert(v)) for k, v in d.items()])
IterableUserDict.__init__(self, d)
def __setitem__(self, key, value):
IterableUserDict.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value))
def remove(self, key):
self.data.pop(PBXType.Convert(key), None)
class PBXList(UserList):
def __init__(self, l=None):
if isinstance(l, basestring):
UserList.__init__(self)
self.add(l)
return
elif l:
l = [PBXType.Convert(v) for v in l]
UserList.__init__(self, l)
def add(self, value):
value = PBXType.Convert(value)
if value in self.data:
return False
self.data.append(value)
return True
def remove(self, value):
value = PBXType.Convert(value)
if value in self.data:
self.data.remove(value)
return True
return False
def __setitem__(self, key, value):
UserList.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value))
class PBXType(PBXDict):
def __init__(self, d=None):
PBXDict.__init__(self, d)
if 'isa' not in self:
self['isa'] = self.__class__.__name__
self.id = None
@staticmethod
def Convert(o):
if isinstance(o, list):
return PBXList(o)
elif isinstance(o, dict):
isa = o.get('isa')
if not isa:
return PBXDict(o)
cls = globals().get(isa)
if cls and issubclass(cls, PBXType):
return cls(o)
print 'warning: unknown PBX type: %s' % isa
return PBXDict(o)
else:
return o
@staticmethod
def IsGuid(o):
return re.match('^[A-F0-9]{24}$', str(o))
@classmethod
def GenerateId(cls):
return ''.join(str(uuid.uuid4()).upper().split('-')[1:])
@classmethod
def Create(cls, *args, **kwargs):
return cls(*args, **kwargs)
class PBXFileReference(PBXType):
def __init__(self, d=None):
PBXType.__init__(self, d)
self.build_phase = None
types = {
'.a': ('archive.ar', 'PBXFrameworksBuildPhase'),
'.app': ('wrapper.application', None),
'.s': ('sourcecode.asm', 'PBXSourcesBuildPhase'),
'.c': ('sourcecode.c.c', 'PBXSourcesBuildPhase'),
'.cpp': ('sourcecode.cpp.cpp', 'PBXSourcesBuildPhase'),
'.framework': ('wrapper.framework', 'PBXFrameworksBuildPhase'),
'.h': ('sourcecode.c.h', None),
'.hpp': ('sourcecode.c.h', None),
'.d': ('sourcecode.dtrace', 'PBXSourcesBuildPhase'),
'.swift': ('sourcecode.swift', 'PBXSourcesBuildPhase'),
'.icns': ('image.icns', 'PBXResourcesBuildPhase'),
'.m': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'),
'.j': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'),
'.mm': ('sourcecode.cpp.objcpp', 'PBXSourcesBuildPhase'),
'.nib': ('wrapper.nib', 'PBXResourcesBuildPhase'),
'.plist': ('text.plist.xml', 'PBXResourcesBuildPhase'),
'.json': ('text.json', 'PBXResourcesBuildPhase'),
'.png': ('image.png', 'PBXResourcesBuildPhase'),
'.rtf': ('text.rtf', 'PBXResourcesBuildPhase'),
'.tiff': ('image.tiff', 'PBXResourcesBuildPhase'),
'.txt': ('text', 'PBXResourcesBuildPhase'),
'.xcodeproj': ('wrapper.pb-project', None),
'.xib': ('file.xib', 'PBXResourcesBuildPhase'),
'.strings': ('text.plist.strings', 'PBXResourcesBuildPhase'),
'.bundle': ('wrapper.plug-in', 'PBXResourcesBuildPhase'),
'.dylib': ('compiled.mach-o.dylib', 'PBXFrameworksBuildPhase'),
'.xcdatamodeld': ('wrapper.xcdatamodel', 'PBXSourcesBuildPhase'),
'.xcassets': ('folder.assetcatalog', 'PBXResourcesBuildPhase'),
'.tbd': ('sourcecode.text-based-dylib-definition', 'PBXFrameworksBuildPhase'),
}
trees = [
'<absolute>',
'<group>',
'BUILT_PRODUCTS_DIR',
'DEVELOPER_DIR',
'SDKROOT',
'SOURCE_ROOT',
]
def guess_file_type(self, ignore_unknown_type=False):
self.remove('explicitFileType')
self.remove('lastKnownFileType')
ext = os.path.splitext(self.get('name', ''))[1]
if os.path.isdir(self.get('path')) and ext not in XcodeProject.special_folders:
f_type = 'folder'
build_phase = None
ext = ''
else:
f_type, build_phase = PBXFileReference.types.get(ext, ('?', 'PBXResourcesBuildPhase'))
self['lastKnownFileType'] = f_type
self.build_phase = build_phase
if f_type == '?' and not ignore_unknown_type:
print 'unknown file extension: %s' % ext
print 'please add extension and Xcode type to PBXFileReference.types'
return f_type
def set_file_type(self, ft):
self.remove('explicitFileType')
self.remove('lastKnownFileType')
self['explicitFileType'] = ft
@classmethod
def Create(cls, os_path, tree='SOURCE_ROOT', ignore_unknown_type=False):
if tree not in cls.trees:
print 'Not a valid sourceTree type: %s' % tree
return None
fr = cls()
fr.id = cls.GenerateId()
fr['path'] = os_path
fr['name'] = os.path.split(os_path)[1]
fr['sourceTree'] = '<absolute>' if os.path.isabs(os_path) else tree
fr.guess_file_type(ignore_unknown_type=ignore_unknown_type)
return fr
class PBXBuildFile(PBXType):
def set_weak_link(self, weak=False):
k_settings = 'settings'
k_attributes = 'ATTRIBUTES'
s = self.get(k_settings)
if not s:
if weak:
self[k_settings] = PBXDict({k_attributes: PBXList(['Weak'])})
return True
atr = s.get(k_attributes)
if not atr:
if weak:
atr = PBXList()
else:
return False
if weak:
atr.add('Weak')
else:
atr.remove('Weak')
self[k_settings][k_attributes] = atr
return True
def add_compiler_flag(self, flag):
k_settings = 'settings'
k_attributes = 'COMPILER_FLAGS'
if k_settings not in self:
self[k_settings] = PBXDict()
if k_attributes not in self[k_settings]:
self[k_settings][k_attributes] = flag
return True
flags = self[k_settings][k_attributes].split(' ')
if flag in flags:
return False
flags.append(flag)
self[k_settings][k_attributes] = ' '.join(flags)
@classmethod
def Create(cls, file_ref, weak=False):
if isinstance(file_ref, PBXFileReference):
file_ref = file_ref.id
bf = cls()
bf.id = cls.GenerateId()
bf['fileRef'] = file_ref
if weak:
bf.set_weak_link(True)
return bf
class PBXGroup(PBXType):
def add_child(self, ref):
if not isinstance(ref, PBXDict):
return None
isa = ref.get('isa')
if isa != 'PBXFileReference' and isa != 'PBXGroup':
return None
if 'children' not in self:
self['children'] = PBXList()
self['children'].add(ref.id)
return ref.id
def remove_child(self, id):
if 'children' not in self:
self['children'] = PBXList()
return
if not PBXType.IsGuid(id):
id = id.id
self['children'].remove(id)
def has_child(self, id):
if 'children' not in self:
self['children'] = PBXList()
return False
if not PBXType.IsGuid(id):
id = id.id
return id in self['children']
def get_name(self):
path_name = os.path.split(self.get('path', ''))[1]
return self.get('name', path_name)
@classmethod
def Create(cls, name, path=None, tree='SOURCE_ROOT'):
grp = cls()
grp.id = cls.GenerateId()
grp['name'] = name
grp['children'] = PBXList()
if path:
grp['path'] = path
grp['sourceTree'] = tree
else:
grp['sourceTree'] = '<group>'
return grp
class PBXNativeTarget(PBXType):
pass
class PBXProject(PBXType):
pass
class PBXContainerItemProxy(PBXType):
pass
class PBXReferenceProxy(PBXType):
pass
class PBXVariantGroup(PBXType):
pass
class PBXTargetDependency(PBXType):
pass
class PBXAggregateTarget(PBXType):
pass
class PBXHeadersBuildPhase(PBXType):
pass
class XCVersionGroup(PBXType):
pass
class PBXBuildPhase(PBXType):
def add_build_file(self, bf):
if bf.get('isa') != 'PBXBuildFile':
return False
if 'files' not in self:
self['files'] = PBXList()
self['files'].add(bf.id)
return True
def remove_build_file(self, id):
if 'files' not in self:
self['files'] = PBXList()
return
self['files'].remove(id)
def has_build_file(self, id):
if 'files' not in self:
self['files'] = PBXList()
return False
if not PBXType.IsGuid(id):
id = id.id
return id in self['files']
class PBXFrameworksBuildPhase(PBXBuildPhase):
pass
class PBXResourcesBuildPhase(PBXBuildPhase):
pass
class PBXShellScriptBuildPhase(PBXBuildPhase):
@classmethod
def Create(cls, script, shell="/bin/sh", files=[], input_paths=[], output_paths=[], show_in_log = '0'):
bf = cls()
bf.id = cls.GenerateId()
bf['files'] = files
bf['inputPaths'] = input_paths
bf['outputPaths'] = output_paths
bf['runOnlyForDeploymentPostprocessing'] = '0';
bf['shellPath'] = shell
bf['shellScript'] = script
bf['showEnvVarsInLog'] = show_in_log
return bf
class PBXSourcesBuildPhase(PBXBuildPhase):
pass
class PBXCopyFilesBuildPhase(PBXBuildPhase):
pass
class XCBuildConfiguration(PBXType):
def add_search_paths(self, paths, base, key, recursive=True, escape=True):
modified = False
if not isinstance(paths, list):
paths = [paths]
if base not in self:
self[base] = PBXDict()
for path in paths:
if recursive and not path.endswith('/**'):
path = os.path.join(path, '**')
if key not in self[base]:
self[base][key] = PBXList()
elif isinstance(self[base][key], basestring):
self[base][key] = PBXList(self[base][key])
if path == '$(inherited)':
escape = False
if escape:
if self[base][key].add('"%s"' % path): # '\\"%s\\"' % path
modified = True
else:
if self[base][key].add(path): # '\\"%s\\"' % path
modified = True
return modified
def add_header_search_paths(self, paths, recursive=True):
return self.add_search_paths(paths, 'buildSettings', 'HEADER_SEARCH_PATHS', recursive=recursive)
def add_library_search_paths(self, paths, recursive=True):
return self.add_search_paths(paths, 'buildSettings', 'LIBRARY_SEARCH_PATHS', recursive=recursive)
def add_framework_search_paths(self, paths, recursive=True):
return self.add_search_paths(paths, 'buildSettings', 'FRAMEWORK_SEARCH_PATHS', recursive=recursive)
def add_other_cflags(self, flags):
return self.add_flag('OTHER_CFLAGS', flags)
def add_other_ldflags(self, flags):
return self.add_flag('OTHER_LDFLAGS', flags)
def add_flag(self, key, flags):
modified = False
base = 'buildSettings'
if isinstance(flags, basestring):
flags = PBXList(flags)
if base not in self:
self[base] = PBXDict()
for flag in flags:
if key not in self[base]:
self[base][key] = PBXList()
elif isinstance(self[base][key], basestring):
self[base][key] = PBXList(self[base][key])
if self[base][key].add(flag):
self[base][key] = [e for e in self[base][key] if e]
modified = True
return modified
def remove_flag(self, key, flags):
modified = False
base = 'buildSettings'
if isinstance(flags, basestring):
flags = PBXList(flags)
if base in self: # there are flags, so we can "remove" something
for flag in flags:
if key not in self[base]:
return False
elif isinstance(self[base][key], basestring):
self[base][key] = PBXList(self[base][key])
if self[base][key].remove(flag):
self[base][key] = [e for e in self[base][key] if e]
modified = True
if len(self[base][key]) == 0:
self[base].pop(key, None)
return modified
def remove_other_ldflags(self, flags):
return self.remove_flag('OTHER_LD_FLAGS', flags)
# Set a single-valued flag under buildSettings
def add_single_valued_flag(self, flag, value):
modified = False
base = 'buildSettings'
key = flag
if not self.has_key(base):
self[base] = PBXDict()
if self[base].has_key(key):
if self[base][key] == value:
return False
self[base][key] = value
modified = True
return modified
# Remove a single-valued flag under buildSettings
def remove_single_valued_flag(self, flag):
modified = False
base = 'buildSettings'
key = flag
if self.has_key(base) and self[base].has_key(key):
self[base].pop(key, None)
modified = True
return modified
class XCConfigurationList(PBXType):
pass
class XcodeProject(PBXDict):
plutil_path = 'plutil'
special_folders = ['.bundle', '.framework', '.xcodeproj', '.xcassets', '.xcdatamodeld']
def __init__(self, d=None, path=None):
if not path:
path = os.path.join(os.getcwd(), 'project.pbxproj')
self.pbxproj_path = os.path.abspath(path)
self.source_root = os.path.abspath(os.path.join(os.path.split(path)[0], '..'))
IterableUserDict.__init__(self, d)
self.data = PBXDict(self.data)
self.objects = self.get('objects')
self.modified = False
root_id = self.get('rootObject')
if root_id:
self.root_object = self.objects[root_id]
root_group_id = self.root_object.get('mainGroup')
self.root_group = self.objects[root_group_id]
else:
print "error: project has no root object"
self.root_object = None
self.root_group = None
for k, v in self.objects.iteritems():
v.id = k
def add_other_cflags(self, flags):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_other_cflags(flags):
self.modified = True
def add_other_ldflags(self, flags):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_other_ldflags(flags):
self.modified = True
def remove_other_ldflags(self, flags):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.remove_other_ldflags(flags):
self.modified = True
def add_header_search_paths(self, paths, recursive=True):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_header_search_paths(paths, recursive):
self.modified = True
def add_framework_search_paths(self, paths, recursive=True):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_framework_search_paths(paths, recursive):
self.modified = True
def add_library_search_paths(self, paths, recursive=True):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if b.add_library_search_paths(paths, recursive):
self.modified = True
def add_flags(self, pairs, configuration='All'):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
# iterate over all the pairs of configurations
for b in build_configs:
if configuration != "All" and b.get('name') != configuration :
continue
for k in pairs:
if b.add_flag(k, pairs[k]):
self.modified = True
def remove_flags(self, pairs, configuration='All'):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
# iterate over all the pairs of configurations
for b in build_configs:
if configuration != "All" and b.get('name') != configuration :
continue
for k in pairs:
if b.remove_flag(k, pairs[k]):
self.modified = True
# Set a single-valued flag (whereas add_flags adds a flag to a list of flags with a given key)
def add_single_valued_flag(self, flag, value, configuration='All'):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if configuration != "All" and b.get('name') != configuration :
continue
if b.add_single_valued_flag(flag, value):
self.modified = True
# Remove a single-valued flag (whereas remove_flags deletes a flag from a list of flags with a given key)
def remove_single_valued_flag(self, flag, configuration='All'):
build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration']
for b in build_configs:
if configuration != "All" and b.get('name') != configuration :
continue
if b.remove_single_valued_flag(flag):
self.modified = True
def get_obj(self, id):
return self.objects.get(id)
def get_ids(self):
return self.objects.keys()
def get_files_by_os_path(self, os_path, tree='SOURCE_ROOT'):
files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference'
and f.get('path') == os_path
and f.get('sourceTree') == tree]
return files
def get_files_by_name(self, name, parent=None):
if parent:
files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference'
and f.get('name') == name
and parent.has_child(f)]
else:
files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference'
and f.get('name') == name]
return files
def get_keys_for_files_by_name(self, name):
keys = [key for key in self.objects if self.objects.data[key].get('name') == name
and self.objects.data[key].get('isa') == 'PBXFileReference']
return keys
def get_build_files(self, id):
files = [f for f in self.objects.values() if f.get('isa') == 'PBXBuildFile'
and f.get('fileRef') == id]
return files
def get_groups_by_name(self, name, parent=None):
if parent:
groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup'
and g.get_name() == name
and parent.has_child(g)]
else:
groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup'
and g.get_name() == name]
return groups
def get_or_create_group(self, name, path=None, parent=None):
if not name:
return None
if not parent:
parent = self.root_group
elif not isinstance(parent, PBXGroup):
# assume it's an id
parent = self.objects.get(parent, self.root_group)
groups = self.get_groups_by_name(name)
for grp in groups:
if parent.has_child(grp.id):
return grp
grp = PBXGroup.Create(name, path)
parent.add_child(grp)
self.objects[grp.id] = grp
self.modified = True
return grp
def get_groups_by_os_path(self, path):
path = os.path.abspath(path)
groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup'
and os.path.abspath(g.get('path', '/dev/null')) == path]
return groups
def get_build_phases(self, phase_name):
phases = [p for p in self.objects.values() if p.get('isa') == phase_name]
return phases
def get_target_by_name(self, name):
targets = self.get_build_phases('PBXNativeTarget')
target = None
for t in targets:
if t.get("name") == name:
target = t
break
return target
def get_relative_path(self, os_path):
return os.path.relpath(os_path, self.source_root)
def verify_files(self, file_list, parent=None):
# returns list of files not in the current project.
if not file_list:
return []
if parent:
exists_list = [f.get('name') for f in self.objects.values() if f.get('isa') == 'PBXFileReference' and f.get('name') in file_list and parent.has_child(f)]
else:
exists_list = [f.get('name') for f in self.objects.values() if f.get('isa') == 'PBXFileReference' and f.get('name') in file_list]
return set(file_list).difference(exists_list)
def add_run_script(self, target, script=None, insert_before_compile=False):
result = []
targets = [t for t in self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget') if t.get('name') == target]
if len(targets) != 0 :
script_phase = PBXShellScriptBuildPhase.Create(script)
for t in targets:
skip = False
for buildPhase in t['buildPhases']:
if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script:
skip = True
if not skip:
if insert_before_compile:
t['buildPhases'].insert(0, script_phase.id)
else:
t['buildPhases'].add(script_phase.id)
self.objects[script_phase.id] = script_phase
result.append(script_phase)
return result
def add_run_script_all_targets(self, script=None):
result = []
targets = self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget')
if len(targets) != 0 :
script_phase = PBXShellScriptBuildPhase.Create(script)
for t in targets:
skip = False
for buildPhase in t['buildPhases']:
if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script:
skip = True
if not skip:
t['buildPhases'].add(script_phase.id)
self.objects[script_phase.id] = script_phase
result.append(script_phase)
return result
def add_folder(self, os_path, parent=None, excludes=None, recursive=True, create_build_files=True):
if not os.path.isdir(os_path):
return []
if not excludes:
excludes = []
results = []
if not parent:
parent = self.root_group
elif not isinstance(parent, PBXGroup):
# assume it's an id
parent = self.objects.get(parent, self.root_group)
path_dict = {os.path.split(os_path)[0]: parent}
special_list = []
for (grp_path, subdirs, files) in os.walk(os_path):
parent_folder, folder_name = os.path.split(grp_path)
parent = path_dict.get(parent_folder, parent)
if [sp for sp in special_list if parent_folder.startswith(sp)]:
continue
if folder_name.startswith('.'):
special_list.append(grp_path)
continue
if os.path.splitext(grp_path)[1] in XcodeProject.special_folders:
# if this file has a special extension (bundle or framework mainly) treat it as a file
special_list.append(grp_path)
new_files = self.verify_files([folder_name], parent=parent)
# Ignore this file if it is in excludes
if new_files and not [m for m in excludes if re.match(m, grp_path)]:
results.extend(self.add_file(grp_path, parent, create_build_files=create_build_files))
continue
# create group
grp = self.get_or_create_group(folder_name, path=self.get_relative_path(grp_path), parent=parent)
path_dict[grp_path] = grp
results.append(grp)
file_dict = {}
for f in files:
if f[0] == '.' or [m for m in excludes if re.match(m, f)]:
continue
kwds = {
'create_build_files': create_build_files,
'parent': grp,
'name': f
}
f_path = os.path.join(grp_path, f)
file_dict[f_path] = kwds
new_files = self.verify_files([n.get('name') for n in file_dict.values()], parent=grp)
add_files = [(k, v) for k, v in file_dict.items() if v.get('name') in new_files]
for path, kwds in add_files:
kwds.pop('name', None)
self.add_file(path, **kwds)
if not recursive:
break
for r in results:
self.objects[r.id] = r
return results
def path_leaf(self, path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
def add_file_if_doesnt_exist(self, f_path, parent=None, tree='SOURCE_ROOT', create_build_files=True, weak=False, ignore_unknown_type=False):
for obj in self.objects.values():
if 'path' in obj:
if self.path_leaf(f_path) == self.path_leaf(obj.get('path')):
return []
return self.add_file(f_path, parent, tree, create_build_files, weak, ignore_unknown_type=ignore_unknown_type)
def add_file(self, f_path, parent=None, tree='SOURCE_ROOT', create_build_files=True, weak=False, ignore_unknown_type=False, target=None):
results = []
abs_path = ''
if os.path.isabs(f_path):
abs_path = f_path
if not os.path.exists(f_path):
return results
elif tree == 'SOURCE_ROOT':
f_path = os.path.relpath(f_path, self.source_root)
else:
tree = '<absolute>'
if not parent:
parent = self.root_group
elif not isinstance(parent, PBXGroup):
# assume it's an id
parent = self.objects.get(parent, self.root_group)
file_ref = PBXFileReference.Create(f_path, tree, ignore_unknown_type=ignore_unknown_type)
parent.add_child(file_ref)
results.append(file_ref)
# create a build file for the file ref
if file_ref.build_phase and create_build_files:
phases = self.get_build_phases(file_ref.build_phase)
if target:
target = self.get_target_by_name(target)
for phase in phases:
if (not target) or (phase.id in target.get('buildPhases')):
build_file = PBXBuildFile.Create(file_ref, weak=weak)
phase.add_build_file(build_file)
results.append(build_file)
if abs_path and tree == 'SOURCE_ROOT' \
and os.path.isfile(abs_path) \
and file_ref.build_phase == 'PBXFrameworksBuildPhase':
library_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0])
self.add_library_search_paths([library_path], recursive=False)
if abs_path and tree == 'SOURCE_ROOT' \
and not os.path.isfile(abs_path) \
and file_ref.build_phase == 'PBXFrameworksBuildPhase':
framework_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0])
self.add_framework_search_paths([framework_path, '$(inherited)'], recursive=False)
for r in results:
self.objects[r.id] = r
if results:
self.modified = True
return results
def check_and_repair_framework(self, base):
name = os.path.basename(base)
if ".framework" in name:
basename = name[:-len(".framework")]
finalHeaders = os.path.join(base, "Headers")
finalCurrent = os.path.join(base, "Versions/Current")
finalLib = os.path.join(base, basename)
srcHeaders = "Versions/A/Headers"
srcCurrent = "A"
srcLib = "Versions/A/" + basename
if not os.path.exists(finalHeaders):
os.symlink(srcHeaders, finalHeaders)
if not os.path.exists(finalCurrent):
os.symlink(srcCurrent, finalCurrent)
if not os.path.exists(finalLib):
os.symlink(srcLib, finalLib)
def get_file_id_by_path(self, f_path):
for k, v in self.objects.iteritems():
if str(v.get('path')) == f_path:
return k
return 0
def remove_file_by_path(self, f_path, recursive=True):
id = self.get_file_id_by_path(f_path)
if id != 0:
self.remove_file(id, recursive=recursive)
return
def remove_file(self, id, recursive=True):
if not PBXType.IsGuid(id):
id = id.id
if id in self.objects:
self.objects.remove(id)
# Remove from PBXResourcesBuildPhase and PBXSourcesBuildPhase if necessary
buildFiles = [f for f in self.objects.values() if f.get('isa') == 'PBXBuildFile']
for buildFile in buildFiles:
if id == buildFile.get('fileRef'):
key = buildFile.id
PBXRBP = [f for f in self.objects.values() if f.get('isa') == 'PBXResourcesBuildPhase']
PBXSBP = [f for f in self.objects.values() if f.get('isa') == 'PBXSourcesBuildPhase']
self.objects.remove(key)
if len(PBXSBP) and PBXSBP[0].has_build_file(key):
PBXSBP[0].remove_build_file(key)
if len(PBXRBP) and PBXRBP[0].has_build_file(key):
PBXRBP[0].remove_build_file(key)
if recursive:
groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup']
for group in groups:
if id in group['children']:
group.remove_child(id)
self.modified = True
def remove_group(self, id, recursive = True):
if not PBXType.IsGuid(id):
id = id.id
name = self.objects.get(id).get('path')
children = self.objects.get(id).get('children')
if name is None:
name = id
if id in self.objects:
if recursive:
for childKey in children:
childValue = self.objects.get(childKey)
if childValue.get('isa') == 'PBXGroup':
self.remove_group(childKey, True)
else:
self.remove_file(childKey, False)
self.objects.remove(id);
def remove_group_by_name(self, name, recursive = True):
groups = self.get_groups_by_name(name)
if len(groups):
for group in groups:
self.remove_group(group.id, recursive)
def move_file(self, id, dest_grp=None):
pass
def apply_patch(self, patch_path, xcode_path):
if not os.path.isfile(patch_path) or not os.path.isdir(xcode_path):
print 'ERROR: couldn\'t apply "%s" to "%s"' % (patch_path, xcode_path)
return
print 'applying "%s" to "%s"' % (patch_path, xcode_path)
return subprocess.call(['patch', '-p1', '--forward', '--directory=%s' % xcode_path, '--input=%s' % patch_path])
def apply_mods(self, mod_dict, default_path=None):
if not default_path:
default_path = os.getcwd()
keys = mod_dict.keys()
for k in keys:
v = mod_dict.pop(k)
mod_dict[k.lower()] = v
parent = mod_dict.pop('group', None)
if parent:
parent = self.get_or_create_group(parent)
excludes = mod_dict.pop('excludes', [])
if excludes:
excludes = [re.compile(e) for e in excludes]
compiler_flags = mod_dict.pop('compiler_flags', {})
for k, v in mod_dict.items():
if k == 'patches':
for p in v:
if not os.path.isabs(p):
p = os.path.join(default_path, p)
self.apply_patch(p, self.source_root)
elif k == 'folders':
# get and compile excludes list
# do each folder individually
for folder in v:
kwds = {}
# if path contains ':' remove it and set recursive to False
if ':' in folder:
args = folder.split(':')
kwds['recursive'] = False
folder = args.pop(0)
if os.path.isabs(folder) and os.path.isdir(folder):
pass
else:
folder = os.path.join(default_path, folder)
if not os.path.isdir(folder):
continue
if parent:
kwds['parent'] = parent
if excludes:
kwds['excludes'] = excludes
self.add_folder(folder, **kwds)
elif k == 'headerpaths' or k == 'librarypaths':
paths = []
for p in v:
if p.endswith('/**'):
p = os.path.split(p)[0]
if not os.path.isabs(p):
p = os.path.join(default_path, p)
if not os.path.exists(p):
continue
p = self.get_relative_path(p)
paths.append(os.path.join('$(SRCROOT)', p, "**"))
if k == 'headerpaths':
self.add_header_search_paths(paths)
else:
self.add_library_search_paths(paths)
elif k == 'other_cflags':
self.add_other_cflags(v)
elif k == 'other_ldflags':
self.add_other_ldflags(v)
elif k == 'libs' or k == 'frameworks' or k == 'files':
paths = {}
for p in v:
kwds = {}
if ':' in p:
args = p.split(':')
p = args.pop(0)
if 'weak' in args:
kwds['weak'] = True
file_path = os.path.join(default_path, p)
search_path, file_name = os.path.split(file_path)
if [m for m in excludes if re.match(m, file_name)]:
continue
try:
expr = re.compile(file_name)
except re.error:
expr = None
if expr and os.path.isdir(search_path):
file_list = os.listdir(search_path)
for f in file_list:
if [m for m in excludes if re.match(m, f)]:
continue
if re.search(expr, f):
kwds['name'] = f
paths[os.path.join(search_path, f)] = kwds
p = None
if k == 'libs':
kwds['parent'] = self.get_or_create_group('Libraries', parent=parent)
elif k == 'frameworks':
kwds['parent'] = self.get_or_create_group('Frameworks', parent=parent)
if p:
kwds['name'] = file_name
if k == 'libs':
p = os.path.join('usr', 'lib', p)
kwds['tree'] = 'SDKROOT'
elif k == 'frameworks':
p = os.path.join('System', 'Library', 'Frameworks', p)
kwds['tree'] = 'SDKROOT'
elif k == 'files' and not os.path.exists(file_path):
# don't add non-existent files to the project.
continue
paths[p] = kwds
new_files = self.verify_files([n.get('name') for n in paths.values()])
add_files = [(k, v) for k, v in paths.items() if v.get('name') in new_files]
for path, kwds in add_files:
kwds.pop('name', None)
if 'parent' not in kwds and parent:
kwds['parent'] = parent
self.add_file(path, **kwds)
if compiler_flags:
for k, v in compiler_flags.items():
filerefs = []
for f in v:
filerefs.extend([fr.id for fr in self.objects.values() if fr.get('isa') == 'PBXFileReference'
and fr.get('name') == f])
buildfiles = [bf for bf in self.objects.values() if bf.get('isa') == 'PBXBuildFile'
and bf.get('fileRef') in filerefs]
for bf in buildfiles:
if bf.add_compiler_flag(k):
self.modified = True
def backup(self, file_name=None, backup_name=None):
if not file_name:
file_name = self.pbxproj_path
if not backup_name:
backup_name = "%s.%s.backup" % (file_name, datetime.datetime.now().strftime('%d%m%y-%H%M%S'))
shutil.copy2(file_name, backup_name)
return backup_name
def save(self, file_name=None, old_format=False, sort=False):
if old_format :
self.save_format_xml(file_name)
else:
self.save_new_format(file_name, sort)
def save_format_xml(self, file_name=None):
"""Saves in old (xml) format"""
if not file_name:
file_name = self.pbxproj_path
# This code is adapted from plistlib.writePlist
with open(file_name, "w") as f:
writer = PBXWriter(f)
writer.writeln("<plist version=\"1.0\">")
writer.writeValue(self.data)
writer.writeln("</plist>")
def save_new_format(self, file_name=None, sort=False):
"""Save in Xcode 3.2 compatible (new) format"""
if not file_name:
file_name = self.pbxproj_path
# process to get the section's info and names
objs = self.data.get('objects')
sections = dict()
uuids = dict()
for key in objs:
l = list()
if objs.get(key).get('isa') in sections:
l = sections.get(objs.get(key).get('isa'))
l.append(tuple([key, objs.get(key)]))
sections[objs.get(key).get('isa')] = l
if 'name' in objs.get(key):
uuids[key] = objs.get(key).get('name')
elif 'path' in objs.get(key):
uuids[key] = objs.get(key).get('path')
else:
if objs.get(key).get('isa') == 'PBXProject':
uuids[objs.get(key).get('buildConfigurationList')] = 'Build configuration list for PBXProject "Unity-iPhone"'
elif objs.get(key).get('isa')[0:3] == 'PBX':
uuids[key] = objs.get(key).get('isa')[3:-10]
else:
uuids[key] = 'Build configuration list for PBXNativeTarget "TARGET_NAME"'
ro = self.data.get('rootObject')
uuids[ro] = 'Project object'
for key in objs:
# transitive references (used in the BuildFile section)
if 'fileRef' in objs.get(key) and objs.get(key).get('fileRef') in uuids:
uuids[key] = uuids[objs.get(key).get('fileRef')]
# transitive reference to the target name (used in the Native target section)
if objs.get(key).get('isa') == 'PBXNativeTarget':
uuids[objs.get(key).get('buildConfigurationList')] = uuids[objs.get(key).get('buildConfigurationList')].replace('TARGET_NAME', uuids[key])
self.uuids = uuids
self.sections = sections
out = open(file_name, 'w')
out.write('// !$*UTF8*$!\n')
self._printNewXCodeFormat(out, self.data, '', enters=True, sort=sort)
out.close()
@classmethod
def addslashes(cls, s):
d = {'"': '\\"', "'": "\\'", "\0": "\\\0", "\\": "\\\\", "\n":"\\n"}
return ''.join(d.get(c, c) for c in s)
def _printNewXCodeFormat(self, out, root, deep, enters=True, sort=False):
if isinstance(root, IterableUserDict):
out.write('{')
if enters:
out.write('\n')
isa = root.pop('isa', '')
if isa != '': # keep the isa in the first spot
if enters:
out.write('\t' + deep)
out.write('isa = ')
self._printNewXCodeFormat(out, isa, '\t' + deep, enters=enters)
out.write(';')
if enters:
out.write('\n')
else:
out.write(' ')
for key in sorted(root.iterkeys()): # keep the same order as Apple.
if enters:
out.write('\t' + deep)
if re.match(regex, key).group(0) == key:
out.write(key.encode("utf-8") + ' = ')
else:
out.write('"' + key.encode("utf-8") + '" = ')
if key == 'objects':
out.write('{') # open the objects section
if enters:
out.write('\n')
#root.remove('objects') # remove it to avoid problems
sections = [
('PBXBuildFile', False),
('PBXCopyFilesBuildPhase', True),
('PBXFileReference', False),
('PBXFrameworksBuildPhase', True),
('PBXGroup', True),
('PBXAggregateTarget', True),
('PBXNativeTarget', True),
('PBXProject', True),
('PBXResourcesBuildPhase', True),
('PBXShellScriptBuildPhase', True),
('PBXSourcesBuildPhase', True),
('XCBuildConfiguration', True),
('XCConfigurationList', True),
('PBXTargetDependency', True),
('PBXVariantGroup', True),
('PBXReferenceProxy', True),
('PBXContainerItemProxy', True),
('XCVersionGroup', True)]
for section in sections: # iterate over the sections
if self.sections.get(section[0]) is None:
continue
out.write('\n/* Begin %s section */' % section[0].encode("utf-8"))
self.sections.get(section[0]).sort(cmp=lambda x, y: cmp(x[0], y[0]))
if sort and section[0] == 'PBXGroup':
for entry in self.sections.get(section[0]):
entry[1]['children'] = sorted(entry[1]['children'],
key=lambda x: self.uuids[x].encode("utf-8"))
for pair in self.sections.get(section[0]):
key = pair[0]
value = pair[1]
out.write('\n')
if enters:
out.write('\t\t' + deep)
out.write(key.encode("utf-8"))
if key in self.uuids:
out.write(" /* " + self.uuids[key].encode("utf-8") + " */")
out.write(" = ")
self._printNewXCodeFormat(out, value, '\t\t' + deep, enters=section[1])
out.write(';')
out.write('\n/* End %s section */\n' % section[0].encode("utf-8"))
out.write(deep + '\t}') # close of the objects section
else:
self._printNewXCodeFormat(out, root[key], '\t' + deep, enters=enters)
out.write(';')
if enters:
out.write('\n')
else:
out.write(' ')
root['isa'] = isa # restore the isa for further calls
if enters:
out.write(deep)
out.write('}')
elif isinstance(root, UserList):
out.write('(')
if enters:
out.write('\n')
for value in root:
if enters:
out.write('\t' + deep)
self._printNewXCodeFormat(out, value, '\t' + deep, enters=enters)
out.write(',')
if enters:
out.write('\n')
if enters:
out.write(deep)
out.write(')')
else:
if len(root) > 0 and re.match(regex, root).group(0) == root:
out.write(root.encode("utf-8"))
else:
out.write('"' + XcodeProject.addslashes(root.encode("utf-8")) + '"')
if root in self.uuids:
out.write(" /* " + self.uuids[root].encode("utf-8") + " */")
@classmethod
def Load(cls, path, pure_python=False):
if pure_python:
import openstep_parser as osp
tree = osp.OpenStepDecoder.ParseFromFile(open(path, 'r'))
else:
cls.plutil_path = os.path.join(os.path.split(__file__)[0], 'plutil')
if not os.path.isfile(XcodeProject.plutil_path):
cls.plutil_path = 'plutil'
# load project by converting to xml and then convert that using plistlib
p = subprocess.Popen([XcodeProject.plutil_path, '-convert', 'xml1', '-o', '-', path], stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
# If the plist was malformed, return code will be non-zero
if p.returncode != 0:
print stdout
return None
tree = plistlib.readPlistFromString(stdout)
return XcodeProject(tree, path)
@classmethod
def LoadFromXML(cls, path):
tree = plistlib.readPlist(path)
return XcodeProject(tree, path)
# The code below was adapted from plistlib.py.
class PBXWriter(plistlib.PlistWriter):
def writeValue(self, value):
if isinstance(value, (PBXList, PBXDict)):
plistlib.PlistWriter.writeValue(self, value.data)
else:
plistlib.PlistWriter.writeValue(self, value)
def simpleElement(self, element, value=None):
"""
We have to override this method to deal with Unicode text correctly.
Non-ascii characters have to get encoded as character references.
"""
if value is not None:
value = _escapeAndEncode(value)
self.writeln("<%s>%s</%s>" % (element, value, element))
else:
self.writeln("<%s/>" % element)
# Regex to find any control chars, except for \t \n and \r
_controlCharPat = re.compile(
r"[\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f"
r"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]")
def _escapeAndEncode(text):
m = _controlCharPat.search(text)
if m is not None:
raise ValueError("strings can't contains control characters; "
"use plistlib.Data instead")
text = text.replace("\r\n", "\n") # convert DOS line endings
text = text.replace("\r", "\n") # convert Mac line endings
text = text.replace("&", "&amp;") # escape '&'
text = text.replace("<", "&lt;") # escape '<'
text = text.replace(">", "&gt;") # escape '>'
return text.encode("ascii", "xmlcharrefreplace") # encode as ascii with xml character references
import os
import commands
buildProjName = ''
targetName = ''
import shutil
import os
def buildProj():
if buildProjName == '':
print('buildProjName is not define')
else:
#build project
print('start build proj')
commands.getstatusoutput('xcodebuild -project ' + buildProjName + '.xcodeproj')
releaseDir = os.path.abspath('.') + '/Release'
if not os.path.exists(releaseDir):
os.mkdir(releaseDir)
ipaPath = releaseDir + '/' + buildProjName + '-Release.ipa'
buildPath = os.path.abspath('.') + '/build'
if os.path.exists(ipaPath):
os.remove(ipaPath)
resultStr = commands.getstatusoutput('xcrun -sdk iphoneos PackageApplication -v build/Release-iphoneos/' + targetName + '.app -o ' +ipaPath)
#print(resultStr)
if os.path.exists(buildPath):
shutil.rmtree(buildPath)
......@@ -9,7 +9,7 @@
#include "UnionInterface.h"
#import <SafariServices/SafariServices.h>
@interface Interface : NSObject <UnionInterface,SFSafariViewControllerDelegate>
@interface Interface : NSObject <UnionInterface>
@property(nonatomic, strong)UIViewController *controller;
......
......@@ -29,5 +29,7 @@
- (void)httpPostAsyncOpen:(NSString*)postUrl :(NSDictionary*)postDict;
- (NSString *)dicToString:(NSDictionary *) dict;
-(void)httpGetAsync:(NSString *)url completionHandler:(void (^ __nullable)(NSURLResponse* __nullable response, NSData* __nullable data, NSError* __nullable connectionError)) handler;
- (NSString * __nullable)dicToString:(NSDictionary * __nullable) dict;
@end
......
......@@ -30,7 +30,10 @@
@property(nonatomic, strong)NSString *openId;
#define REPORT_URL @"https://statistic.public.sdk.gzyouai.com/sdk/statistic" //@http://public.sdk.gzyouai.com:9030/sdk/statistic"//@"http://10.200.201.230:9001/sdk/statistic"//@"https://statistic.public.sdk.gzyouai.com/sdk/statistic"//
#define REPORT_URL @"https://statistic.public.sdk.gzyouai.com/sdk/statistic" //http://183.57.76.181:9030/sdk/statistic
#define REPORT_IDFA_URL @"https://statistic.public.sdk.gzyouai.com/sdk/last_channel?idfa=" //@"http://183.57.76.181:9030/sdk/last_channel?idfa="//
#define REPORT_OPEN @"open"
#define REPORT_ENTER @"enter"
#define REPORT_CREATEROLE @"createrole"
......
......@@ -187,6 +187,8 @@
- (void)applicationWillResignActive:(UIApplication *)application;
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options;
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
@end
......
......@@ -126,5 +126,7 @@
- (void)applicationWillResignActive:(UIApplication *)application;
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options;
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
@end
\ No newline at end of file
......