인앱 결제 구현

인앱 셋팅 => 바로가기

출처 : http://it77.tistory.com/74 

인앱 결제 연동 중 나오는 에러들 : http://westwoodforever.blogspot.kr/2012/11/google-play-in-app-billing_14.html


 

1. 안드로이드 스튜디오 기준 Tools > Android > SDK Manager에서 extras > google play billing libray 설치

2. C:\sdk\extras\google\play_billing\samples\TrivialDrive\src\com 폴더를 내 프로젝트로 복사

   ※ android.vending.billing 패키지명 수정하지 마세요!

 

 

3. build.gradle 에 아래 추가

 


android{}안에...
    sourceSets {
        main {
            aidl.srcDirs = ['src/main/java']
        }
    }

 

 

4. 메뉴 Build > rebuild project

5. AndroidManifest.xml에 아래 추가


<USES-PERMISSION android:name="com.android.vending.BILLING" />

 

6. MainActivity.java


public class MainActivity extends ActionBarActivity {
    IInAppBillingService mService;
    IabHelper mHelper;

    ServiceConnection mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IInAppBillingService.Stub.asInterface(service);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND"), mServiceConn, Context.BIND_AUTO_CREATE);

        // 구글에서 발급받은 바이너리키를 입력해줍니다
        String base64EncodedPublicKey = "API key 입력";

        mHelper = new IabHelper(this, base64EncodedPublicKey);
        mHelper.enableDebugLogging(true);

        mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
            public void onIabSetupFinished(IabResult result) {
                if (!result.isSuccess()) {
                    // 구매오류처리 ( 토스트하나 띄우고 결제팝업 종료시키면 되겠습니다 )
                }

               // 구매목록을 초기화하는 메서드입니다.
               // v3으로 넘어오면서 구매기록이 모두 남게 되는데 재구매 가능한 상품( 게임에서는 코인같은아이템은 ) 구매후 삭제해주어야 합니다.
               // 이 메서드는 상품 구매전 혹은 후에 반드시 호출해야합니다. ( 재구매가 불가능한 1회성 아이템의경우 호출하면 안됩니다 )
                AlreadyPurchaseItems();
            }
        });

    }

    public void AlreadyPurchaseItems() {
        try {
            Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
            int response = ownedItems.getInt("RESPONSE_CODE");
            if (response == 0) {

                ArrayList purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
                String[] tokens = new String[purchaseDataList.size()];
                for (int i = 0; i < purchaseDataList.size(); ++i) {
                    String purchaseData = (String) purchaseDataList.get(i);
                    JSONObject jo = new JSONObject(purchaseData);
                    tokens[i] = jo.getString("purchaseToken");
                    // 여기서 tokens를 모두 컨슘 해주기
                    mService.consumePurchase(3, getPackageName(), tokens[i]);
                }
            }
        // 토큰을 모두 컨슘했으니 구매 메서드 처리
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 구매
    public void Buy(String id_item) {
        try {
            Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),	id_item, "inapp", "test");
            PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");

            if (pendingIntent != null) {
                mHelper.launchPurchaseFlow(this, getPackageName(), 1001,  mPurchaseFinishedListener, "test");

            } else {
                // 결제가 막혔다면
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener  = new IabHelper.OnIabPurchaseFinishedListener() {
        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
            // 여기서 아이템 추가 해주시면 됩니다.
            // 만약 서버로 영수증 체크후에 아이템 추가한다면, 서버로 purchase.getOriginalJson() , purchase.getSignature() 2개 보내시면 됩니다.
        }
    };

    @Override
    public void onDestroy(){
        super.onDestroy();
        if(mServiceConn != null){
            unbindService(mServiceConn);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(mHelper ==null) return; //iabHelper가 null값인경우 리턴

        if(!mHelper.handleActivityResult(requestCode, resultCode, data)){ //iabHelper가 데이터를 핸들링하도록 데이터 전달
            super.onActivityResult(requestCode, resultCode, data);
        }
    }
}

 

7. 서버에서 영수증 인증하기


$purchaseJson = $_POST['purchaseJson']; // 앱에서 넘어온 영수증 purchase.getOriginalJson() 
$signature = $_POST['signature']; // 앱에서 넘어온 signature purchase.getSignature() 
$public_key_base64 = "구글 애플리케이션용 라이선스 키";

$result = verifySignatureTransaction($purchaseJson, $signature, $public_key_base64);

// 영수증 검증 성공
if($result === true) {
    $arr = json_decode($purchaseJson);
    $order_id = $arr->orderId; // 주문번호
    // 영수증 중복체크 (DB에 orderId를 저장하여 중복체크를 합니다.
    $sql = "select count(*) from test where order_id=:order_id";
}else{
// 에러
}

function verifySignatureTransaction($purchaseJson, $signature, $public_key_base64) {
    $key = "-----BEGIN PUBLIC KEY-----\n".chunk_split($public_key_base64, 64, "\n").'-----END PUBLIC KEY-----';        
    $key =  openssl_pkey_get_public($key);
				
    if ($key === false) {
        return false;
    }
		
    $result = openssl_verify($purchaseJson, base64_decode($signature), $key, OPENSSL_ALGO_SHA1);
		
				
    switch($result){
        case 1:
            return true;
            break;
        default:
            return false;
            break;
    }
}
Trackback 0 Comment 0