package com.totu.unity; import android.app.Activity; import android.content.Intent; import android.util.Log; import com.android.vending.billing.IabHelper; import com.android.vending.billing.IabResult; import com.android.vending.billing.Inventory; import com.android.vending.billing.Purchase; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.RequestParams; import com.unity3d.player.UnityPlayer; import org.apache.http.Header; import org.apache.http.util.EncodingUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.LinkedList; import static com.totu.unity.ProductType.managed; import static com.totu.unity.ProductType.subscription; import static com.totu.unity.ProductType.unmanaged; enum ProductType {managed, unmanaged, subscription, none }; public class GoogleIAB { static final String TAG = "AndroidBilling"; static String GoogleIAB_OBJECT = "GoogleIAB"; // 자료를 주고받을 서버주소 static final String urlPrefix = "http://192.168.0.254/"; private static Activity saveActivity; static IabHelper mHelper; static String saveLicenseKey; static int saveUserKeyNo=0; static boolean selfDebugMode = true; // 제품ID 저장. static LinkedList<String> managedProducts; static LinkedList<String> unmanagedProducts; static LinkedList<String> subscriptionProducts; public static boolean isInit = false; // 실행중인 유니티 Activity 반환 static Activity getUnityActivity() { return UnityPlayer.currentActivity; } // 초기화 public static void Init(String licenseKey, String targetGameObjectName, int userKeyNo, String productIDjsonStr) { if( mHelper != null) { Log.d(TAG, "이미 IAB helper를 할당했습니다."); return; } // 필요한 매개 변수 저장 saveLicenseKey = licenseKey; GoogleIAB_OBJECT = targetGameObjectName; saveUserKeyNo = userKeyNo; saveActivity = getUnityActivity(); //IabHelper 생성 mHelper = new IabHelper(saveActivity, saveLicenseKey); mHelper.enableDebugLogging(selfDebugMode); isInit = true; // 제품ID를 변환하여 등록. try { JSONObject jObject = new JSONObject(productIDjsonStr); SetupSkus(jObject); } catch (JSONException e) { e.printStackTrace(); } mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { @Override public void onIabSetupFinished(IabResult result) { Log.d(TAG, "IabHelper 초기화 완료"); // 초기화를 실패했는지 체크 if(!result.isSuccess()) { // 유니티로 초기화실패 상황전달 UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "Error", "" + result.getResponse()); return; } Log.d(TAG, "초기화성공 후 소모하지않은 인앱 상품 체크"); mHelper.queryInventoryAsync(mGotInventoryListener); } }); } // 구매 요청 public static void PurchaseInappItem(final String sku) { if(!isInit) { Log.d(TAG, "GoogleIAB가 초기화되지않았습니다"); return; } saveActivity.runOnUiThread(new Runnable() { public void run() { AsyncHttpClient client = new AsyncHttpClient(); String url = urlPrefix+"farmdefence/getPayloadGoogleIAB.php"; //서버에 전달할 데이터 RequestParams sendParams = new RequestParams(); sendParams.put("userKeyNo", saveUserKeyNo); sendParams.put("sku", sku); client.get(url, sendParams, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { String developerPayload = EncodingUtils.getString( responseBody, 0, responseBody.length, "UTF-8") ; Log.d(TAG, "서버에서 전달받은 developer payload : " + developerPayload); mHelper.launchPurchaseFlow( saveActivity, sku, 4885, mPurchaseFinishedListener, developerPayload); } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Log.d(TAG, "payload error"); } }); } }); } // 상품정보를 등록 static void SetupSkus(JSONObject jObject) { managedProducts = new LinkedList<String>(); unmanagedProducts = new LinkedList<String>(); subscriptionProducts = new LinkedList<String>(); try { JSONArray tempJArray = jObject.getJSONArray("managedProducts"); for (int i = 0; i < tempJArray.length(); ++i) { try { managedProducts.addLast(tempJArray.getString(i)); } catch (JSONException e1) { e1.printStackTrace(); } } tempJArray = jObject.getJSONArray("unmanagedProducts"); for(int i=0;i<tempJArray.length();++i) { try { unmanagedProducts.addLast(tempJArray.getString(i)); } catch (JSONException e1) { e1.printStackTrace(); } } tempJArray = jObject.getJSONArray("subscription"); for(int i=0;i<tempJArray.length();++i) { try { subscriptionProducts.addLast(tempJArray.getString(i)); } catch (JSONException e1) { e1.printStackTrace(); } } } catch (JSONException e) { e.printStackTrace(); } } // 결제된 상품이 어떤형식의 제품인지 체크. static ProductType CheckPurchaseItem(String purchasedSku) { // 관리되는상품 if( managedProducts != null ) { for(String nowProduct : managedProducts) { if(nowProduct.equals(purchasedSku)) { return managed; } } } //관리되지않는상품 if( unmanagedProducts != null ) { for(String nowProduct : unmanagedProducts) { if(nowProduct.equals(purchasedSku)) { return unmanaged; } } } //구독상품 if( subscriptionProducts != null ) { for(String nowProduct : subscriptionProducts) { if(nowProduct.equals(purchasedSku)) { return subscription; } } } return ProductType.none; } // 결제결과를 전송받는다 public static void onActivityResult( Activity activity, int requestCode, int resultCode, Intent data) { if( selfDebugMode ) { Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data); } if (!mHelper.handleActivityResult(requestCode, resultCode, data)) { } else { Log.d(TAG, "onActivityResult handled by IABUtil."); } } // 결제가 완료되면 호출된다 static IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { public void onIabPurchaseFinished(IabResult result, Purchase purchase) { if( selfDebugMode ) { Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase); } if (result.isFailure()) { Log.d(TAG, "결제 에러"); UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "Error", "" + result.getResponse()); return; } CheckVerifyDeveloperPayload(purchase); } }; // 결제를 통해서가지고 있는 제품(관리되는 상품, 구독 상품)과 관리지되않는 상품 중아직소모되지않은 상품을 정리한다. static IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { public void onQueryInventoryFinished(IabResult result, Inventory inventory) { Log.d(TAG, "인벤토리 상품 체크 완료"); if (result.isFailure()) { UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "Error", "" + result.getResponse()); return; } Log.d(TAG, "인벤토리 상품 체크 성공"); //관리되는 상품 체크. if(managedProducts != null) { for(String productID : managedProducts) { if(inventory.hasPurchase(productID)) { Purchase managedProduct = inventory.getPurchase(productID); // 상품 검증 CheckVerifyDeveloperPayload(managedProduct); } } } //구독 상품 체크 if(subscriptionProducts != null) { for(String productID : subscriptionProducts) { if(inventory.hasPurchase(productID)) { Purchase subscriptionProduct = inventory.getPurchase(productID); // 상품 검증 CheckVerifyDeveloperPayload(subscriptionProduct); } } } //관리되지않는 상품 체크. if(unmanagedProducts != null) { for(String productID : unmanagedProducts) { Purchase unmanagedProduct = inventory.getPurchase(productID); // 상품 소모 if (unmanagedProduct != null) { mHelper.consumeAsync( unmanagedProduct, mConsumeFinishedListener); } } } Log.d(TAG, "인벤토리 상품 처리 종료"); } }; // 소모가 완료되면 호출된다 static IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { public void onConsumeFinished(final Purchase purchase, IabResult result) { if( selfDebugMode ) { Log.d(TAG, "소모완료. Purchase: " + purchase + ", result: " + result); } if (result.isSuccess()) { AsyncHttpClient client = new AsyncHttpClient(); //서버에 전달할 데이터 RequestParams sendParams = new RequestParams(); sendParams.put("userKeyNo", saveUserKeyNo); sendParams.put("sku", purchase.getSku()); sendParams.put("payload", purchase.getDeveloperPayload()); String url = urlPrefix+"farmdefence/getPurchaseResultGoogleIAB.php"; client.get(url, sendParams, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { String result = EncodingUtils.getString( responseBody, 0, responseBody.length, "UTF-8") ; Log.d(TAG, "purchase result : "+result); if(result.equals("noResult")) { // 결제한 정보가존재하지않는경우. Log.d(TAG, "DB에 결제한 정보가 없습니다"); UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "Error", "-4886"); } else if(result.equals("noSkuInfo")) { //sku가 database 에 등록되지않은경우. Log.d(TAG, " DB에 sku가 등록되않았습니다"); UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "Error", "-4887"); } else if(result.equals("noPriceInfo")) { // 가격 정보가등록되지 않은 경우. Log.d(TAG, "가격정보가 DB에 등록되지 않았습니다"); UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "Error", "-4888"); } else { // 정상적으로 처리된 경우. UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "PurchaseCompletedUnmanaged", result); Log.d(TAG, "소모 성공"); } } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Log.d(TAG, "consume error"); } }); } else { //소모 실패한 경우 UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "Error", "" + result.getResponse()); } Log.d(TAG, "소모 과정 완료"); } }; // 서버에 올바른 결제인지 검증요청 후 결과 기준으로 이후 과정처러 static void CheckVerifyDeveloperPayload(final Purchase p) { AsyncHttpClient client = new AsyncHttpClient(); String url = urlPrefix+"farmdefence/verificationGoogleIAB.php"; //서버에 전달할 데이터 RequestParams sendParams = new RequestParams(); sendParams.put("userKeyNo", saveUserKeyNo); sendParams.put("orderId", p.getOrderId()); sendParams.put("packageName", p.getPackageName()); sendParams.put("productId", p.getSku()); sendParams.put("purchaseTime", p.getPurchaseTime()); sendParams.put("purchaseState", p.getPurchaseState()); sendParams.put("developerPayload", p.getDeveloperPayload()); sendParams.put("purchaseToken", p.getToken()); client.post(url, sendParams, new AsyncHttpResponseHandler() { @Override public void onSuccess( int statusCode, Header[] headers, byte[] responseBody) { String result = EncodingUtils.getString( responseBody, 0, responseBody.length, "UTF-8") ; Log.d(TAG, "verify return : " + result); //결제가 실패한 경우. if(result.equals("0")) { UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "Error", "-4885"); return; } // 결제된 상품타입 판단. String productID = p.getSku(); ProductType nowPurchaseItemType = CheckPurchaseItem(productID); // 상품타입별 처리. switch(nowPurchaseItemType) { case managed: UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "PurchaseCompletedManaged", productID); //전달하는 정보는 자신의 프로젝트에 알맞게 처리합니다. break; case subscription: UnityPlayer.UnitySendMessage( GoogleIAB_OBJECT, "PurchaseCompletedSubscription", productID); //전달하는 정보는 자신의 프로젝트에 알맞게 처리합니다. break; case unmanaged: mHelper.consumeAsync(p, mConsumeFinishedListener); break; } } @Override public void onFailure( int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Log.d(TAG, "verification error"); } }); } }