구글 인앱결제 v3 예제입니다.
- http://westwoodforever.blogspot.kr/2013/10/unity3d-integration-google-in-app.html
http://theeye.pe.kr/archives/2130
위 링크에서 퍼왔습니다(감사합니다!)
- 아이템등록법 취소방법등을 추가하였습니다.
1. 구글 인앱 빌링 라이브러리 설치 및 임포트는 아래링크를 참고하십시오.
http://westwoodforever.blogspot.kr/2013/10/unity3d-integration-google-in-app.html
2. Buy 버튼을 누르면 인앱 결제창이 뜨고 결제가 되는 예제입니다.
매니페스트에 추가해주세요!
<uses-permission android:name="com.android.vending.BILLING" />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | <p>import java.util.List; import org.json.JSONException; import org.json.JSONObject; import com.android.vending.billing.IInAppBillingService; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; public class InAppTestActivity extends Activity { IInAppBillingService mService; IabHelper mHelper; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main1); bindService( new Intent( "com.android.vending.billing.InAppBillingService.BIND" ), mServiceConn, Context.BIND_AUTO_CREATE); String base64EncodiedPushedkey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuCphx6V1V9XXqe" + "XGgPMHgEtq64/199fDj0n46H2Gw7Qje+WXJKboCTvydomWUhpCxSknklv/7XhBC4/UI0VbWCVnWSz" + "+D2WYS+phunjtluImwAoT33/oV7Z4hempYKdPDaR24txT6GJgzT7ATJKffO6Wi4TgVILNcIQ1/LpXBALFvEFy" + "WiLEz5FB0hO4eemZtgnWTvUlsT7mdCo704l2PpfNtlpVwUixUVk21bHKiklVcR7AzI3yxFPa8SFSfNe4D7j5prBxSl" + "35wP5s5bRB0lsJ2DeaY8T9bdfZLqb8/ZObf68j8r7mVau9CIqDR/gpPjFUHam1RRPpiZPDxxxxxxx" ; // developer console -> 서비스및 API -> 어플리케이션용 라이센스 키를 복사해서 넣으시면 됩니다. InAppInit_U(base64EncodiedPushedkey, true ); Button innapp1 = (Button) findViewById(R.id.innapp1); innapp1.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { InAppBuyItem_U( "item01" ); // 제품id를 써줍니다. 앱배포시에 인앱상품등록시 등록할 id입니다. } }); } public void InAppInit_U(String strPublicKey, boolean bDebug) { Log.d( "myLog" , "Creating IAB helper." + bDebug); mHelper = new IabHelper( this , strPublicKey); if (bDebug == true ) { mHelper.enableDebugLogging( true , "IAB" ); } mHelper.startSetup( new IabHelper.OnIabSetupFinishedListener() { @Override public void onIabSetupFinished(IabResult result) { // TODO Auto-generated method stub boolean bInit = result.isSuccess(); Log.d( "myLog" , "IAB Init " + bInit + result.getMessage()); if (bInit == true ) { Log.d( "myLog" , "Querying inventory." ); mHelper.queryInventoryAsync(mGotInventoryListener); } Toast.makeText(InAppTestActivity. this , "InAppInit_U" , Toast.LENGTH_SHORT).show(); } }); } IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { public void onQueryInventoryFinished(IabResult result, Inventory inventory) { if (result.isFailure()) { Log.d( "myLog" , "Failed to query inventory: " + result); SendConsumeResult( null , result); return ; } /* * Check for items we own. Notice that for each purchase, we check * the developer payload to see if it's correct! See * verifyDeveloperPayload(). */ List</p><p></p><string> inappList = inventory .getAllOwnedSkus(IabHelper.ITEM_TYPE_INAPP); // inappList.add("item01"); for (String inappSku : inappList) { Purchase purchase = inventory.getPurchase(inappSku); Log.d( "myLog" , "Consumeing ... " + inappSku); mHelper.consumeAsync(purchase, mConsumeFinishedListener); } Log.d( "myLog" , "Query inventory was successful." ); } }; public void InAppBuyItem_U(final String strItemId) { runOnUiThread( new Runnable() { @Override public void run() { // TODO Auto-generated method stub /* * TODO: for security, generate your payload here for * verification. See the comments on verifyDeveloperPayload() * for more info. Since this is a SAMPLE, we just use an empty * string, but on a production app you should carefully generate * this. */ String payload = "user_id" ; mHelper.launchPurchaseFlow(InAppTestActivity. this , strItemId, 1001, mPurchaseFinishedListener, payload); Log.d( "myLog" , "InAppBuyItem_U " + strItemId); } }); } IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { public void onIabPurchaseFinished(IabResult result, Purchase purchase) { Log.d( "myLog" , "Purchase finished: " + result + ", purchase: " + purchase); //결제 완료 되었을때 각종 결제 정보들을 볼 수 있습니다. 이정보들을 서버에 저장해 놓아야 결제 취소시 변경된 정보를 관리 할 수 있을것 같습니다~ if (purchase != null ) { if (!verifyDeveloperPayload(purchase)) { Log.d( "myLog" , "Error purchasing. Authenticity verification failed." ); } mHelper.consumeAsync(purchase, mConsumeFinishedListener); } else { Toast.makeText(InAppTestActivity. this , String.valueOf(result.getResponse()), Toast.LENGTH_SHORT).show(); } } }; boolean verifyDeveloperPayload(Purchase p) { String payload = p.getDeveloperPayload(); /* * TODO: verify that the developer payload of the purchase is correct. * It will be the same one that you sent when initiating the purchase. * * WARNING: Locally generating a random string when starting a purchase * and verifying it here might seem like a good approach, but this will * fail in the case where the user purchases an item on one device and * then uses your app on a different device, because on the other device * you will not have access to the random string you originally * generated. * * So a good developer payload has these characteristics: * * 1. If two different users purchase an item, the payload is different * between them, so that one user's purchase can't be replayed to * another user. * * 2. The payload must be such that you can verify it even when the app * wasn't the one who initiated the purchase flow (so that items * purchased by the user on one device work on other devices owned by * the user). * * Using your own server to store and verify developer payloads across * app installations is recommended. */ return true ; } // Called when consumption is complete IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { public void onConsumeFinished(Purchase purchase, IabResult result) { Log.d( "myLog" , "Consumption finished. Purchase: " + purchase + ", result: " + result); SendConsumeResult(purchase, result); } }; protected void SendConsumeResult(Purchase purchase, IabResult result) { JSONObject jsonObj = new JSONObject(); try { jsonObj.put( "Result" , result.getResponse()); if (purchase != null ) { jsonObj.put( "OrderId" , purchase.getOrderId()); jsonObj.put( "Sku" , purchase.getSku()); jsonObj.put( "purchaseData" , purchase.getOriginalJson()); jsonObj.put( "signature" , purchase.getSignature()); Log.d( "myLog" , "OrderId" + purchase.getOrderId()); Log.d( "myLog" , "Sku" + purchase.getSku()); Log.d( "myLog" , "purchaseData" + purchase.getOriginalJson()); Log.d( "myLog" , "signature" + purchase.getSignature()); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d( "myLog" , "onActivityResult(" + requestCode + "," + resultCode + "," + data); if (requestCode == 1001) { // Pass on the activity result to the helper for handling if (!mHelper.handleActivityResult(requestCode, resultCode, data)) { // not handled, so handle it ourselves (here's where you'd // perform any handling of activity results not related to // in-app // billing... super .onActivityResult(requestCode, resultCode, data); } else { Log.d( "myLog" , "onActivityResult handled by IABUtil." ); } } } @Override protected void onDestroy() { super .onDestroy(); if (mServiceConn != null ) { unbindService(mServiceConn); } } ServiceConnection mServiceConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = IInAppBillingService.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mService = null ; } }; } </string> |
3. 위에 예제를 돌려보면 결제하기를 하면 제품이 없다고 나옵니다. 당연히 제품을 등록안했으니 안나오겠죠^^;
SSISO Community