You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

460 lines
15 KiB
PHTML

5 years ago
<?php
namespace Base\Service;
use Base\Model\PromoteModel;
use Base\Model\ApplyModel;
use Base\Tool\Base62;
use Base\Tool\PlistDemo;
5 years ago
use GuzzleHttp\Client;
5 years ago
class GameSourceService {
const IS_FIXED_IOS13 = true;
const DEBUG = true;
5 years ago
public function __construct()
{
}
/**
* 获取IPA中的.app后缀目录
*/
5 years ago
public function getIpaAppPath($zip)
{
$appPath = '';
5 years ago
for ($i = 0; $i < $zip->numFiles; $i++) {
$name = $zip->getNameIndex($i);
if (preg_match("/^Payload.*?\.app/", $name, $matches)) {
$appPath = $matches[0];
break;
}
}
return $appPath;
}
5 years ago
public function deleteOldChannelConfigFolder($zip, $txChannelFolder)
{
for ($i = 0; $i < $zip->numFiles; $i++) {
$name = $zip->getNameIndex($i);
if (strpos($name, $txChannelFolder) === 0) {
$zip->deleteName($name);
}
}
}
5 years ago
public function getChannelConfigFile($zip, $sdkVersion)
5 years ago
{
5 years ago
$configUrl = '';
5 years ago
if ($sdkVersion == 1) {
5 years ago
$configUrl = "META-INF/mch.properties";
} else {
5 years ago
$appPath = $this->getIpaAppPath($zip);
$configUrl = $appPath . '/_CodeSignature/TXChannel';
5 years ago
}
return $configUrl;
}
5 years ago
public function getChannelConfigFolder($zip, array $packData)
{
5 years ago
$appPath = $this->getIpaAppPath($zip);
5 years ago
return $appPath . '/TXChannel/' . Base62::encode(json_encode($packData, JSON_UNESCAPED_UNICODE));
}
5 years ago
public function getGameSourceUrl($gameSource)
{
if (empty($gameSource)) {
return '';
}
5 years ago
$path = '';
5 years ago
if($gameSource['file_type'] == 1) {
5 years ago
$path = './Uploads/SourcePack/';
}else{
$path = './Uploads/Ios/original/';
}
$fileUrl = $path . $gameSource['file_name'];
return ROOTTT . ltrim($fileUrl, './');
}
public function packChannel($localPath, $game, $gameSource, $apply = null)
{
$packData = [
'game_id' => $game['id'],
'game_name' => $game['game_name'],
'game_appid' => $game['game_appid'],
5 years ago
'promote_id' => $apply ? $apply['promote_id'] : '0',
'promote_account' => $apply ? $apply['promote_account'] : '自然渠道',
'source_version' => $gameSource['source_version'],
];
5 years ago
5 years ago
$zip = new \ZipArchive();
if (!$zip->open($localPath, \ZipArchive::CREATE)) {
return false;
}
if (self::IS_FIXED_IOS13 && $game['sdk_version'] == 2) {
5 years ago
$channelFolder = $this->getChannelConfigFolder($zip, $packData);
return $this->packChannelFolder($zip, $channelFolder);
} else {
5 years ago
$channelFile = $this->getChannelConfigFile($zip, $game['sdk_version']);
5 years ago
return $this->packChannelFile($zip, $channelFile, $packData);
}
5 years ago
$zip->close();
return false;
}
/**
* 打入渠道信息文件
5 years ago
* @param string $zip 包文件
* @param string $distFile 打入文件名
* @param array $packData 打入信息
* @return boolean 是否成功
*/
5 years ago
public function packChannelFile($zip, $distFile, array $packData)
5 years ago
{
5 years ago
$zip->addFromString($distFile, json_encode($packData));
return true;
5 years ago
}
/**
* 打入渠道信息目录用于IOS主要为了解决IOS13问题
5 years ago
* @param string $zip 包文件
* @param string $distFolder 打入文件夹
* @return boolean 是否成功
*/
5 years ago
public function packChannelFolder($zip, $distFolder)
{
5 years ago
$rows = explode('/' , $distFolder);
5 years ago
unset($rows[count($rows) -1]);
5 years ago
$txChannelFolder = implode('/', $rows) . '/';
$this->deleteOldChannelConfigFolder($zip, $txChannelFolder);
$zip->addEmptyDir($distFolder);
return true;
}
5 years ago
/**
* 原包打包
*/
public function sourcePack($gameSource, $game)
{
$relativeUrl = $gameSource['file_url'];
$localPath = ROOTTT . ltrim($relativeUrl, './');
$originalUrl = '';
if ($game['sdk_version'] == 2) {
$oldLocalPath = $localPath;
$localPath = str_replace('Uploads/SourcePack', 'Uploads/Ios/original', $oldLocalPath);
$originalUrl = $relativeUrl;
5 years ago
$relativeUrl = str_replace('Uploads/SourcePack', 'Uploads/Ios/original', $relativeUrl);
5 years ago
copy($oldLocalPath, $localPath);
}
$status = $this->packChannel($localPath, $game, $gameSource);
5 years ago
if (!$status) {
return [
'status' => false,
'message' => '打包失败,原包加入信息失败!',
];
}
$distFilePath = 'SourcePack/' . $gameSource['file_name'];
$result = $this->uploadPackage($localPath, $distFilePath);
$fileUrl = '';
if ($result['status']) {
$fileUrl = $result['data']['url'];
$fileUrl = $fileUrl == '@' ? $relativeUrl : $fileUrl;
} else {
return [
'status' => false,
5 years ago
'message' => '打包失败上传OSS失败' . $result['message'],
5 years ago
];
}
$plistUrl = '';
$orgPlistUrl = '';
if ($game['sdk_version'] == 2) {
$params = [
'packageName' => $gameSource['bao_name'],
'gameId' => $game['id'],
5 years ago
'gameName' => $game['game_name'],
5 years ago
'promoteId' => 0,
'packageUrl' => $fileUrl,
5 years ago
'gameIcon' => get_cover($game['icon'], 'path'),
5 years ago
'type' => 'pack'
];
5 years ago
5 years ago
$result = $this->createPlist($params);
if ($result['status']) {
$plistUrl = $result['data']['path'];
} else {
return [
'status' => false,
5 years ago
'message' => '打包失败生成plist文件失败' . $result['message'],
5 years ago
];
}
$params['type'] = 'org';
$result = $this->createPlist($params);
if ($result['status']) {
$orgPlistUrl = $result['data']['path'];
} else {
return [
'status' => false,
5 years ago
'message' => '打包失败生成原包plist文件失败' . $result['message'],
5 years ago
];
}
}
return [
'status' => true,
'message' => '打包成功!',
'data' => [
'plistUrl' => $plistUrl,
'orgPlistUrl' => $orgPlistUrl,
'fileUrl' => $fileUrl,
'originalUrl' => $originalUrl,
]
];
}
/**
* 渠道打包
*/
public function channelPack($gameSource, $game, $apply, $launchCount = 0)
{
$debugTime1 = microtime(true);
5 years ago
$gameSourceUrl = $this->getGameSourceUrl($gameSource);
if ($gameSource == null || !file_exists($gameSourceUrl)) {
M('apply', 'tab_')->where(['id' => $apply['id']])->setField('enable_status', -1);
}
/* 检测是否存在投放申请,存在则更改投放申请信息,否则进行渠道打包 */
if ($launchCount > 0) {
M('apply', 'tab_')->where(['id' => $apply['id']])->setField('enable_status', 3);
$launchData = ['launch_packge' => 2, 'launch_down_url'=>'' , 'launch_plist_url'=>''];
M('apply_launch', 'tab_')->where(['apply_id' => $apply['id'], 'launch_packge'=>['in', [0, 2, 3]]])->save($launchData);
}
$savePath = '';
$fileName = 'game_package' . $apply['game_id'] . '-' . $apply['promote_id'];
if ($apply['sdk_version'] == 1) {
5 years ago
$fileName .= '.apk';
$savePath = 'Uploads/GamePack/' . $fileName;
5 years ago
} else {
5 years ago
$fileName .= '.ipa';
$savePath = 'Uploads/IosGamePack/' . $fileName;
5 years ago
}
$relativePath = './' . $savePath;
$localPath = ROOTTT . $savePath;
$debugTime2 = microtime(true);
5 years ago
copy($gameSourceUrl, $localPath);
$debugTime3 = microtime(true);
$status = $this->packChannel($localPath, $game, $gameSource, $apply);
5 years ago
if (!$status) {
return [
'status' => false,
'message' => '打包失败,加入渠道信息失败!',
];
}
$debugTime4 = microtime(true);
5 years ago
$distFilePath = 'GamePack/' . $fileName;
5 years ago
$result = $this->uploadPackage($localPath, $distFilePath, true);
5 years ago
if ($result['status']) {
$packageUrl = $result['data']['url'];
$packageUrl = $packageUrl == '@' ? $relativePath : $packageUrl;
} else {
return [
'status' => false,
5 years ago
'message' => '打包失败上传OSS失败' . $result['message'],
5 years ago
];
}
$debugTime5 = microtime(true);
5 years ago
$plistInfo = ['game_id' => $apply['game_id'], 'promote_id' => $apply['promote_id']];
$plistUrl = '';
if ($apply['sdk_version'] == 2) {
$params = [
'packageName' => $gameSource['bao_name'],
'gameId' => $game['id'],
5 years ago
'gameName' => $game['game_name'],
5 years ago
'promoteId' => $apply['promote_id'],
'packageUrl' => $packageUrl,
5 years ago
'gameIcon' => get_cover($game['icon'], 'path'),
5 years ago
'type' => 'pack'
];
$result = $this->createPlist($params);
if ($result['status']) {
$plistUrl = $result['data']['path'];
} else {
return [
'status' => false,
5 years ago
'message' => '打包失败生成plist文件失败' . $result['message'],
5 years ago
];
}
}
5 years ago
$applyService = new ApplyService();
5 years ago
$applyService->updateAfterPack($apply, $packageUrl, $plistUrl);
$debugTime6 = microtime(true);
$debugInfo = '';
if (self::DEBUG) {
$debugInfo .= '[' .
'总计:' . ($debugTime6 - $debugTime1) .
' 复制:' . ($debugTime3 - $debugTime2) .
' 打包:' . ($debugTime4 - $debugTime3) .
' 上传:' . ($debugTime5 - $debugTime4) .
']';
}
5 years ago
return [
'status' => true,
'message' => '打包成功!' . $debugInfo,
5 years ago
'data' => [
'plistUrl' => $plistUrl,
]
];
}
5 years ago
public function uploadPackage($localFilePath, $distFilePath, $isDeleteLocal = false)
5 years ago
{
5 years ago
$isChunk = C('PACKAGE_CHUNK_ENABLED') ? true : false;
5 years ago
if (get_tool_status('oss_storage') == 1) {
if ($isChunk) {
return $this->uploadPackageChunk($localFilePath, $distFilePath, $isDeleteLocal);
} else {
return $this->uploadPackageOnce($localFilePath, $distFilePath, $isDeleteLocal);
5 years ago
}
} else {
// 不上传OSS等第三方服务器
return [
'status' => true,
'message' => '上传成功',
'data' => [
'url' => '@'
],
];
}
}
public function uploadPackageChunk($localFilePath, $distFilePath, $isDeleteLocal = false)
{
$client = new Client([
5 years ago
'base_uri' => C('PACKAGE_CHUNK_URL'),
'timeout' => 10.0,
]);
$response = $client->post('/upload', [
'verify' => false,
'form_params' => [
5 years ago
'file' => $localFilePath,
5 years ago
'dest' => $distFilePath,
5 years ago
'is_delete_local' => ($isDeleteLocal ? 1 : 0),
]
]);
$result = (string)$response->getBody();
$result = json_decode($result, true);
if (!$result) {
return [
'status' => false,
'message' => '请求打包失败',
];
}
return $result;
}
public function uploadPackageOnce($localFilePath, $distFilePath, $isDeleteLocal = false)
{
$ossService = new OssService();
$result = $ossService->upload($localFilePath, $distFilePath);
if ($isDeleteLocal && file_exists($localFilePath)) {
@unlink($localFilePath);
}
return $result;
}
5 years ago
//生成游戏渠道plist文件
public function createPlist($params)
{
$packageName = $params['packageName'] ?? '';
5 years ago
$gameName = $params['gameName'] ?? '';
5 years ago
$gameId = $params['gameId'] ?? 0;
$promoteId = $params['promoteId'] ?? 0;
$packageUrl = $params['packageUrl'] ?? '';
$platformId = $params['platformId'] ?? 0;
$position = $params['position'] ?? 0;
$gameIcon = $params['gameIcon'] ?? '';
$type = $params['type'] ?? '';
if ($gameId == 0) {
return [
'status' => false,
'message' => '游戏ID错误',
];
}
if ($type == '' || !in_array($type, ['org', 'pack'])) {
return [
'status' => false,
'message' => '类型错误',
];
}
$xml = new \DOMDocument();
$xml->loadXML(PlistDemo::$content);
5 years ago
$online = $xml->getElementsByTagName('dict'); //查找节点
$elements = $online->item(1)->getElementsByTagName('string'); //第二个节点下所有string
foreach ($elements as $element) {
switch ($element->textContent) {
case 'ipa_url':
if (preg_match("/http/", $packageUrl)) {
$element->nodeValue = $packageUrl;
} else {
5 years ago
$element->nodeValue = C('DOMAIN_DOWNLOAD') . ltrim($packageUrl, '.');
5 years ago
}
break;
case 'icon':
if (preg_match("/http/", $gameIcon)) {
$element->nodeValue = $gameIcon;
} else {
5 years ago
$element->nodeValue = C('DOMAIN_OFFICIAL_PC') . ltrim($gameIcon, '.');
5 years ago
}
break;
case 'com.dell':
$element->nodeValue = $packageName;
break;
case '1.0.0':
$element->nodeValue = false;
break;
case 'mchdemo':
5 years ago
$element->nodeValue = $gameName;
5 years ago
break;
}
}
$fileName = '';
if ($type == 'pack') {
if ($promoteId == 0) {
$fileName = 'Uploads/SourcePlist/'. $gameId . '.Plist';
} elseif ($platformId > 0) {
$fileName = 'Uploads/GamePlist/'. $gameId . '-' . $promoteId . '-' . $platformId . '-' .$position . '.Plist';
} else {
$fileName = 'Uploads/GamePlist/'. $gameId . '-' . $promoteId . '.Plist';
}
} elseif ($type == 'org') {
$fileName = 'Uploads/OrgSourcePlist/'. $gameId . '.Plist';
}
$xml->save('./' . $fileName);
return [
'status' => true,
'message' => '生成成功',
'data' => [
'path' => './' . $fileName
]
];
}
5 years ago
}