Tuesday, May 31, 2016

MacOSX 엘케피탄 트랙패드 세손가락으로 드래그하기

엘케피탄은 한영키도 그렇지만 기본적으로 트랙패드 세손가락으로 드래그하기가 설정이 안되어 있다.

그래서 다음과 같이 설정한다. 손쉬운 사용 > 트랙패드 옵션...에 들어가서 '드래그 활성화'를 한다음에 '세 손가락으로 드래그'하기를 선택한다.

MacOSX 엘케피탄 한영전환 설정하기 Command+Space

MacOSX 엘케피탄으로 오면서 예전버전에서 사용하던 Command+Space로 한영전환이 되지 않고 Control+Space로 한영전환이 되어서 정말 불편하게 되었다.

설정 > 키보드 > 단축키 > 입력소스에서 다시 Command+Space로 설정한다.
그런데 그냥 이렇게 설정하게 되면 Spotlight와 키가 겹치게 되므로 Spotlight도 키를 다음과 같이 바꾸어 주어야 한다.

언리얼엔진4 설치

언리얼엔진4가 요즘 최신 유행이라서 개발 맥북프로에 설치를 해보았다.
아직 샘플프로그램은 하나도 돌려보지 않은 상태이다.
그래도 정말 멋진 게임 엔진이 될것 같다는 생각이 든다.

삼성전자 연봉 및 근속

직급 기간 승진율 연봉(기본급/세전)
=======================================================================
사원 입사후 2년 대졸초임 약 3800만원정도
주임 3년차 ~ 5년차 95%(거의 자동빵) 평균 4천대 중반
대리 6년차 ~ 9년차. 75%정도 평균 5천대 중반
과장 10년차 ~ 14년차 50~60%정도 평균 6천대 중후반
차장 15년차 ~ 20년차 40%정도 평균 7천대 중후반
부장 20년 이상 30%정도 평균 8천대 중후반

대개 이런식으로 되어 있습니다. 승급연한은 기본적으론 저 정도 되고 개인의 능력에 따라 속도의 차이가 있습니다. 승진율이라고 쓴건 진급대상자중 진급되는 사람의 비율입니다.

연봉은 기본급을 적은거구 저기에 PI와 PS가 추가 되는데 PI는 생산성장려금인데 개인 인센티브라고 보시면 되는데 대개 고과에 따라 차등 지급 되고 연봉의 평균 15%수준이라고 보면 됩니다.
제가 다닐때는 일년에 두번 나눠서 줬습니다.

그리고 중요한게 PS인데 이건 초과수익에 대한 인센티브인데 사업부마다 차등 지급됩니다.
최고가 연봉의 50%로 2월에 일시 불로 지급하는데 이게 짭잘합니다만 무선사업부(스마트폰)이런데는 50%를 다 받지만 백색가전사업부 이런데는 한푼도 못 받습니다.
여기 가끔 보면 삼전 신입사원이 연봉 6000이다 이런글을 보는데 무선사업부 신입사원이라면 이것저석 다 합치면 세전으로 그정도 될 듯 합니다만 4000만원대 받는 사람이 더 많습니다.

잘 모르시는 분들은 삼전에 입사할려면 대단한 스펙이 필요할 거라고 생각하시는데 사실 상대적으로 다른 대기업보다 학벌을 가장 안 따집니다. 숫자로 봐도 그렇고 비율을 봐도 그렇고 지방대 비율이 가장 높은 곳이 삼전입니다. 아 물론 주로 공대에 해당하는 얘기입니다. 상대도 있긴 있는데 그 비율이 낮습니다.

삼전이 지방대를 많이 뽑는 이유중에 하나가 지방사업장이 많아서 그렇습니다. 경북대 출신들은 주로 구미로 많이가고 전남대출신들은 주로 광주로 많이 보냅니다. 구미 광주 말고도 지방사업장이 많은데 서울 출신을 보내면 퇴사로 이어지는 경우가 많아 그지역 출신을 주로 보내게 됩니다.

흔히 대기업은 경쟁이 빡세서 오래다니기 힘들다고 하는데 사실은 그렇지 않습니다.

밑에 댓글을 보니 삼성전자 평균근속이 6년이라고 하시는데 그건 통계상의 오류가 있는 겁니다.

첫째, 생산직 여자근로자의 경우 결혼하면 퇴사하는 경우가 엄청나게 많습니다. 교대근무를 해야하는데 살림이나 육아를 병행하기가 쉽지가 않습니다. 생산직의 경우 여자의 비율이 훨씬 높습니다.

둘째, 자발적 퇴사자의 경우 대개 조기 퇴사자가 많습니다.

이 두가지경우가 포함되다 보니 근속이 짧게 나오는 거지 맘만 먹으면 정년까지 다닐 수 있습니다.

대졸사원의 경우 100명이 입사동기가 있다면 대개 아래와 같다고 보시면 됩니다.

입사 1년차에 퇴사 : 대개 맘에 안드는 사업부로 발령나거나 지방사업장으로 발령 나는 경우에 해당합니다.
또는 억지로 취직을 하긴 했으나 원래의 꿈을 찾아 공부를 게속 하거나 자격증 시험을 위해 퇴사하는 경우도 있습니다. 여기에 해당하는 경우가 적게는 20% 많게는 30%가 넘는 경우도 봤습니다.

입사 3년차에 퇴사 : 아경우 조직생활에 적응을 못하는 경우에 해당됩니다. 참으면서 2~3년 직장생활을 했는데 결국 적응하지 못하고 조금 널럴한 직장으로 이직하게 됩니다. 이런 경우가 10% 넘습니다.

이미 입사 3년차쯤 되면 동기들의 1/3이상이 다른 곳으로 떠난 상태입니다.

입 사 7년차 전후 : 이시기가 각종 스카웃제의가 가장 많을 때입니다. 직급으로는 대리말년이난 과장초임인데 어느 정도만 되도 다른 기업이나 헤드헌터들에게 스카웃 제의가 많이 들어옵니다. 이때쯤 되면 대충 감이 옵니다. 내가 삼성에서 승승장구할 정도는 아니라고 판단되는 사람들이 다른 직장으로 옮기게 됩니다.

그래서 과장쯤 되면 절반이상의 동기들이 옆에 없습니다.

입 사 15년차 : 이시기에 접어들면 처지는 사람이 나옵니다. 승진에 누락되고 한직으로 돌기만 하고 이때에는 회사의 명퇴프로그램이 있으면 유혹을 받게 됩니다. 명퇴금 챙기고 대개는 한급 아래인 중견기업이나 삼전과 거래관계인 1차 납품업체로 주로 옮깁니다. 그래도 이때까진 옮길만 합니다.

입사 20년차 : 동기들은 다들 부장이고 빠른 친구들은 임원 단 사람도 나옵니다.
근 데 여기서 밀린 사람들은 엄청난 눈치와 스트레스를 받아야 합니다. 이걸 무시하고 다니면 다니는 건데 간단한 문제가 아닙니다. 그래서 그 스트레스 때문에 퇴사를 하게 됩니다. 대개 취직은 어려우니 개인사업을 하게 됩니다. 물론 끝까지 버티고 남는 사람도 제법 있긴 합니다.

이때쯤 되면 동기들의 10%정도만 회사에 남아 있습니다.

http://i.orbi.kr/bbs/board.php?bo_table=united&wr_id=3579828

이공계 대기업 과장 연봉

삼성전자의 경우 박사든 사원부터 시작했든 책임 1년차이면 차이가 나는건 박사 수당과 연봉 고과 딜해서 좋은 고과를 1-2년 정도 보장 받아서 차이가 나는 연봉 밖에 없습니다. 어차피 사원으로 시작한 사람도 올라가면서 고과를 잘 받았다면 박사 받고 들어오는 사람보다 연봉이 높을 수 있고요. 연봉 테이블이 정해져 있기 때문에 특수 인재라고 연봉을 더 높게 받는게 아니라 직급을 조정하거나 보너스를 더 많이 받고 오거나 고과를 좀 더 오랫동안 좋은 고과를 보장해 줍니다.


원글님이 물은 대강의 연봉에 대해 제가 아는 바를 한국 나이로 말씀드리면, 남자 병역필: 27세 시작 - 대리(31세) - 과장(35세) - 차장(39세) - 부장(43세) - 상무(51세) 여자 (혹은 면제): 24세 시작 ... 똑같음 삼성: 대리=선임, 과장=책임 (senior engineer), 부장=수석 (principal engineer), 차장 없음. LG: 과장=선임, 차장=책임, 부장=수석. 회사마다 과장 달기 까지 7년이 걸리는 곳도 있고 7년이었다가 8년이 된 곳도 있고 그렇습니다.


일반적인 남자의 경우 35세에 과장을 처음 달게 됩니다. 그리고 43세에 부장이 되죠. 다만 여기서 예외가 되는게 여자와 면제자 그리고 석사 후에 병특으로 입사한 경우입니다. 이 경우 3살을 빼서 32살에 과장, 40세 부장이 평균이 되죠. 박사의 경우는 석사와 박사를 따로 했다면 비교적 짧게 걸리는 전공의 경우 도합 6-7년 정도 걸리고, CS 처럼 오래 걸리는 경우 7-9년이 걸립니다. 그리고 경력 없이 박사만 했다면 과장 1년차를 받습니다.


따라서 군대를 갔다온 경우 학부 후 바로 박사를 시작했다면 위에서 1년정도 빼면 됩니다. 여자분이 학부 졸후 바로 박사를 시작해서 6년만에 받았다면, 30살에 과장으로 시작하게 되어 일반 사원으로 시작하거나 석박사 합쳐 8년 걸린 사람보다 5년이 진급이 빠르게 됩니다. 여기에 보통 잘나가는 사업부의 경우 좋은 고과가 많이 나오므로 보통 진급을 1-2년 빨리 하죠. 그러면 40대 초반에 임원을 달게 됩니다. 중소 기업이나 기업의 규모가 작을 수록 승진에 걸리는 기한이 짧게 됩니다. 따라서 젊은 나이에 임원을 달고 있는 건 흔한 일이지만 연봉은 대기업 과장보다 낮은 경우가 수두룩 합니다. 여기서 하나 짚고 넘어갈 것은, 대기업에 40대 초반에 임원으로 승진한 분이 많다고 해서 그때에 임원으로 승진해야 한다고 생각하는 겁니다.


삼성전자 같은 경우도 15년 전에는 이렇게 큰 기업이 아니었습니다. 따라서 승진이 더 빨랐고요. 원래 승진 가속도는 회사가 커지는 속도에 비례하게 되어 있습니다. 예전에 우리나라 기업들이 계속 고성장할 때에는 30대에 임원 달고 사장 다는 일이 많았던 것도 이와 비례합니다. 이런 점에서 보면 반드시 정점에 올라 있는 대기업 만이 최고가 아니라 계속해서 성장해 나가는 회사에 있는 것의 장점도 기업 선택시에 생각해 봐야죠.


연봉은 과장 1년차이면 삼전은 윗분들 얘기하신대로 모든 보너스가 최대치로 나올 경우 1억 근처가 됩니다. 연구소는 이보다 5백-1천 정도 낮다고 보면 되고, 잘 안되는 사업부는 7-8천정도라 봐야죠. 현대차는 7천 정도, LG 전자는 5천 초반, KT는 5천, 포스코는 5천, 일반 중소기업 3천-5천, 은행 등 금융권과 SK 텔레콤은은 7천-1억, 탑 3 컨설팅은 1억2천-3천 정도, 가 과장 1년차에 해당하는 일반적인 군대 갔다온 남자 35살, 여자 32살의 연봉이라고 보면 됩니다.


중소 기업 중에도 귀한 엔지니어들은 6-7천 받기도 하고요. 공무원과 군인, 학교 선생님은 3-5천. 남자는 레지던트를 막 마칠 나인 다음(여자는 3년 더+) 이므로 큰 병원에 월급장이로 취업하면 연봉 5-7천 정도. 지방으로 갈 경우 연봉 7천-1억 2천. 교수가 될 나이이기도 하므로 교수는 6천-9천. 파일럿 1억. 변리사 8천. 회계사 6천-1억 정도라고 봐야 겠네요. 물론 주로 열거된 직업군들은 고연봉에 고학벌 등이 많으므로 사실상 평균은 이와 관련이 없다고 봐야 겠네요. 괜찮은 대학 나온 평범한 회사원이라면 남자 35살에 연봉 4-6천이라고 봐야 할 듯 합니다.

학사출신 삼성전자 무선,반도체 기준 연봉

학사출신 삼성전자 무선,반도체 기준

초봉 6000
대리 7000
과장 9000
차장 1억
부장 1.2억
상무 2~3억
전무 4~6억

성과급 포함, 세전기준
부사장 이상급은 연봉협상 천차만별
박사 마치고 입사할시에는 과장급으로 입사

Parallels 최신버전 무료 어플라이언스

오랫만에 맥북프로를 포맷하고 새로 깔면서 Parallels도 새로 설치했다.
윈도우를 새로 설치하려고 보니 아래와 같은 무료 어플라이언스가 있었다.
이제는 ISO이미지가 없어도 OS를 자동으로 설치를 할수가 있다.
대단한 발전이다. 클라우드 서비스를 따라가는 것 같다.
 

Sunday, May 29, 2016

Android 디바이스 화면 크기 구하기

DisplayMetrics dm = getApplicationContext().getResources().getDisplayMetrics();
int width = dm.widthPixels;
int height = dm.heightPixels;

Thursday, May 26, 2016

iOS 리젝 사유 17.1 Apps cannot transmit data...

변경된 사항이 거의 없는데도 불구하고 아래의 사유로 iOS 앱이 리젝 되었다.
이 문제의 원인은 사용자 정보를 서버로 전송하는데 유저의 동의를 구하지 않았고, 개인정보 취급방침을 지정하지 않았다는 것이다.
예전에 스토어 심사를 할때는 유저의 동의를 구하는 절차는 구현하였는데, 개인정보 취급방침이 없었던게 문제이다.
이번에 웹브라우저로 링크를 걸어서 개인정보 취급방침을 띄우는 것을 구현하고 재심사를 신청했다.

17.1 - Apps cannot transmit data about a user without obtaining the user's prior permission and providing the user with access to information about how and where the data will be used

17.1 Details

We noticed that your app does not obtain the user’s consent prior to uploading users’ scores to a global leaderboard.

To collect personal data with your app, you must make it clear to the user that their personal data will be uploaded to your server.

Next Steps

Please revise your app to include a privacy policy URL in the App Information page on iTunesConnect and ensure that the URL you provide directs users to your privacy policy.

Android Studio gradle export jar

안드로이드 스튜디오에서 라이브러리 프로젝트를 jar 파일로 만드는 방법을 알아보자.

//기존의 jar파일을 지우는 task
task deleteOldJar(type: Delete) {
    delete 'release/daumapi.jar'
}

//라이브러리 프로젝트의 output인 classes.jar를 daumapi.jar로 이름 변경
task exportJar(type: Copy) {
// classes.jar 패스는 여기에 떨어짐
    from('build/intermediates/bundles/release/')
    into('release/')
    include('classes.jar')
    rename('classes.jar', 'daumapi.jar')
}

exportJar.dependsOn(deleteOldJar, build)

Wednesday, May 25, 2016

Node.js console exit

process.exit(0); // 0은 리턴 값

또는

.exit


PHP getallheaders() 구현 소스

if (!function_exists('getallheaders')) {
    /**
     * Get all HTTP header key/values as an associative array for the current request.
     *
     * @return string[string] The HTTP header key/value pairs.
     */
    function getallheaders()
    {
        $headers = array();
        $copy_server = array(
            'CONTENT_TYPE'   => 'Content-Type',
            'CONTENT_LENGTH' => 'Content-Length',
            'CONTENT_MD5'    => 'Content-Md5',
        );
        foreach ($_SERVER as $key => $value) {
            if (substr($key, 0, 5) === 'HTTP_') {
                $key = substr($key, 5);
                if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) {
                    $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));
                    $headers[$key] = $value;
                }
            } elseif (isset($copy_server[$key])) {
                $headers[$copy_server[$key]] = $value;
            }
        }
        if (!isset($headers['Authorization'])) {
            if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
                $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
            } elseif (isset($_SERVER['PHP_AUTH_USER'])) {
                $basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
                $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pa
ss);
            } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
                $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
            }
        }
        return $headers;
    }
}

Tuesday, May 24, 2016

Github를 만들었습니다

프로그램 소스를 Google 드라이브에만 올리다가 드디어 github를 만들었습니다.

원래는 소스공개를 하지 않는 개인 프로젝트는 github보다는 bitbucket에 올려두었는데 공개용 소스는 앞으로 아래의 링크에 올리겠습니다.

감사합니다.
두덕리온라인

https://github.com/duongame

Friday, May 20, 2016

Android PHP 인앱 구매 영수증 서버 검증

이전에 iOS와 PHP로도 인앱 구매 영수증 서버 검증을 진행했는데 이번에는 Android에도 적용해 보자.

일단 플레이스토어에 가면 다음과 같이 [서비스 및 API] > [라이센스 및 인앱 결제] 항목에 Base64 인코딩된 RSA 공개키가 있다.


이것을 .pem형식으로 다음과 같이 저장한다.
물론 PHP의 chunk_split함수를 이용해도 된다.
단, 설명문에 RSA 공개키라고 하더라도 반드시 그냥 PUBLIC KEY라고 입력해야 한다. 

-----BEGIN PUBLIC KEY-----
한 줄에 64바이트씩 잘라서 입력
-----END PUBLIC KEY-----

다음은 안드로이드에서 구매후 $signature와 $data를 보내줘야 한다.
주의할 사항은 $data는 original json을 그대로 보내면 된다.
        params.put("signature", info.getSignature());
        params.put("data", info.getOriginalJson());

검증 PHP는 다음과 같이 구성한다.
openssl_verify가 1을 리턴하면 검증이 성공한 것이다.

function verify_android($signature) {
    // key 파일을 읽음
    $public_key_path="./play.pem";
    $public_key = file_get_contents($public_key_path);
    $public_key_id = openssl_get_publickey ($public_key);
    $decoded_signature = base64_decode($signature);
    $data="";
    if(isset($_POST['data'])) {
        $data = $_POST['data'];       
    }
    $result = (int)openssl_verify($data, $decoded_signature, $public_key_id);
    if($result == 1) {
        return true;
    }
    else {
        return false;
    }   
}

PHP Visual Studio Code에서 패스설정하기

새로나온 에디터인 Visual Studio Code에서 다음과 같이 PHP파일을 편집하다 보면 에러 메세지가 나올 때가 있다. 

Cannot validate the php file. The php program was not found. Use the 'php.validate.executablePath' setting to configure the location of 'php'

그럴 때는 파일 > 기본설정 > 사용자 설정 에서 다음과 같이 PHP 실행파일 패스를 입력한다.



PHP json_encode 후에 앞에 이상한 문자가 추가되는 현상(strange character)

PHP로 json_encode하여서 클라이언트에서 응답을 받았는데, android studio 화면상에 보이는 문자와 실제의 문자열의 길이가 달랐다. 그리고 JSONObject의 parse가 자꾸 실패를 하게 되었다.

이렇게 되는 원인을 찾았는데 PHP 소스파일의 인코딩이 UTF-8 with BOM으로 되어 있었다. 이것을 UTF-8로 변경해주면 문제 없이 동작한다.

최근에 atom, vscode등 여러가지 에디터를 변경하면서 생긴 문제이다. 항상 기존의 코드와인코딩이 맞는지를 항상 확인하자.

Wednesday, May 18, 2016

Node.js 최신버전 업데이트

sudo npm cache clean -f
sudo npm install -g n
sudo n stable

sudo npm update npm -g

Monday, May 16, 2016

iOS PHP 인앱 구매 영수증 서버 검증

//iOS -(void)serverVerfication:(SKPaymentTransaction*)transaction andRestore:(BOOL)isRestore
{
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    NSString *user_id = [userDefault objectForKey:@"uid"];
    NSString *item_id = transaction.payment.productIdentifier;
   
    // 추가된 order_id(구글과 맞추기 위해서 용어를 변경하였다.)
    NSString *order_id;
    int restore = 0;
    if(isRestore == YES) {
        order_id = transaction.originalTransaction.transactionIdentifier;
        restore = 1;
    }
    else {
        order_id = transaction.transactionIdentifier;
    }

    // Load the receipt from the app bundle.
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
   
    // Create the JSON object that describes the request
    NSError *error;
    NSDictionary *requestContents = @{
                                      @"receipt-data": [receipt base64EncodedStringWithOptions:0],
                                      @"platform": @"ios",
                                      @"item_id": item_id,
                                      @"order_id": order_id,
                                      @"user_id": user_id,
                                      @"restore": [NSNumber numberWithInt:restore],
                                      @"sandbox": [NSNumber numberWithInt:0]
                                      };
    NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                          options:0
                                                            error:&error];
   
    // Create a POST request with the receipt data.
//    NSURL *storeURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];


    //검증하려고 하는 자체 서버
    NSURL *storeURL = [NSURL URLWithString:[URLManager getPaymentLog]];
    NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
    [storeRequest setHTTPMethod:@"POST"];
    [storeRequest setHTTPBody:requestData];
   
    // Make a connection to the iTunes Store on a background queue.
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                               if (connectionError) {
                                   /* ... Handle error ... */
                               } else {
                                   NSError *error;
                                   NSString *jsonData = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

                                   NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:[jsonData dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
                                   if (!jsonResponse) { /* ... Handle error ...*/
                                   }
                                   /* ... Send a response back to the device ... */
                                   NSNumber *result = [jsonResponse objectForKey:@"result"];
                                   if(result == nil) {
                                       NSLog(@"구매 인증 실패");
                                       handleSendBuyEvent(-1, 0);// M_E_ERROR = -1
                                   }
                                   else {
                                       if([result longValue] == 0) {
                                           NSLog(@"구매 인증 성공");
                                           [self provideContent: transaction.payment.productIdentifier];
                                       }
                                       else {
                                           NSLog(@"구매 인증 실패 %d", [result longValue]);
                                           handleSendBuyEvent(-1, 0);// M_E_ERROR = -1
                                       }
                                   }
                               }
                           }];
   
}

 
//PHP
//JSON데이터를 $_POST에 넣어준다
$postdata = file_get_contents("php://input");
$_POST = json_decode($postdata, true);

function verify($sandbox, $receipt) {
    // Environment sandbox인지 체크
    // 영수증을 애플 서버에 보내자
    $endpoint = "";
   
    // 샌드박스일 경우
    if($sandbox == 1) {
         $endpoint = 'https://sandbox.itunes.apple.com/verifyReceipt';     
    }
    else {// 실결제일 경우
        $endpoint = 'https://buy.itunes.apple.com/verifyReceipt';
    }
    error_log("endpoint=$endpoint");

    $postData = json_encode(array('receipt-data' => $receipt)); 
   
    // curl로 요청하자
    $ch = curl_init($endpoint); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION , true); 
    curl_setopt($ch, CURLOPT_POST, true); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
   
    $response = curl_exec($ch); 
    $errno    = curl_errno($ch); 
    $errmsg   = curl_error($ch); 
    curl_close($ch);  

    error_log("response=$response");
    if($errno)
        error_log("errno=$errno");
    if($errmsg)
        error_log("errmsg=$errmsg");
    error_log("response ok");
   
    $data = json_decode($response);
    error_log("data=".print_r($data, true));
   
    if(!is_object($data)) {
        return false;
    }
   
    if(!isset($data->status) || $data->status != 0) {
        return false;
    }
    return true;
}

    // 2. 애플 영수증 검증
    // 실결제를 먼저하고, 샌드박스 결제를 검증해야 한다.
    // 왜냐하면 애플 심사과정에서는 샌드박스로 테스트를 하기 때문이다.
    if(strlen($receipt) > 0) {
        if(!verify(0, $receipt)) {// 실결제 테스트
            if(!verify(1, $receipt)) {// 샌드박스 테스트
                // 실결제, 샌드박스 둘다 실패하면 에러다
                $ret = array("result" => 5, "error" => "receipt error");
                echo json_encode($ret);
                exit;
            }
        }
    }
    // 문제없이 exit가 안되었다면 검증이 성공한 것이다.

Thursday, May 5, 2016

Java 하위 폴더 모든 소스 컴파일 빌드

다음과 같이 build.sh를 만들면 src폴더 하위에 있는 모든 java파일을 컴파일 할수 있다.
java파일과 같은 폴더내에 class파일이 만들어진다.

cd src
javac -cp . -d . $(find . -name *.java)