Немає DEVELOPER_PAYLOAD при використанні In App Billing в Android

травня
28
2012

Проблема наступна: при тестуванні оплати з використанням in-app billing в Android не приходить властивість DEVELOPER_PAYLOAD від Google-маркету, хоч вона і встановлена в REQUEST_PURCHASE запиті.

Властивість DEVELOPER_PAYLOAD необхідна для того щоб "зв'язати" данні відправляємого запиту з відповіддю від маркету так як спілкування між програмою і маркетом відбувається асинхронно. Для цього в запиті REQUEST_PURCHASE програміст повинен встановити властивість DEVELOPER_PAYLOAD, яка повернеться разом із запитом GET_PURCHASE_INFORMATION.

Це відбувається при використанні наступних ідентифікаторів для тестування:

При використанні в реальних умовах без емуляції таких проблем не виникає. Тому або штучно встановіть цю властивість, або тестуйте програму з живими банківськими картами. Якщо Ви володієте аккаунтом продавця Google Play, то транзакції можна скасовувати.

Розглянемо приклад Dungeons від Google, в якому описана робота з In-app billing. У першу чергу, зверніть увагу на наступні рядки коду в класі Dungeons, саме так присвоюються згадані вище ідентифікатори:


new CatalogEntry("android.test.purchased", R.string.android_test_purchased,
		Managed.UNMANAGED),
new CatalogEntry("android.test.canceled", R.string.android_test_canceled,
		Managed.UNMANAGED),
new CatalogEntry("android.test.refunded", R.string.android_test_refunded,
		Managed.UNMANAGED),
new CatalogEntry("android.test.item_unavailable", R.string.android_test_item_unavailable,
		Managed.UNMANAGED),

Також в прикладі є підклас RequestPurchase в класі BillingService, за допомогою якого відбувається відсилання властивості DEVELOPER_PAYLOAD:


class RequestPurchase extends BillingRequest {
	public final String mProductId;
	public final String mDeveloperPayload;

	public RequestPurchase(String itemId) {
		this(itemId, null);
	}

	public RequestPurchase(String itemId, String developerPayload) {
		// This object is never created as a side effect of starting this
		// service so we pass -1 as the startId to indicate that we should
		// not stop this service after executing this request.
		super(-1);
		mProductId = itemId;
		mDeveloperPayload = developerPayload;
	}

	@Override
	protected long run() throws RemoteException {
		Bundle request = makeRequestBundle("REQUEST_PURCHASE");
		request.putString(Consts.BILLING_REQUEST_ITEM_ID, mProductId);
		// Note that the developer payload is optional.
		if (mDeveloperPayload != null) {
			request.putString(Consts.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload);
		}
		Bundle response = mService.sendBillingRequest(request);
		PendingIntent pendingIntent
				= response.getParcelable(Consts.BILLING_RESPONSE_PURCHASE_INTENT);
		if (pendingIntent == null) {
			Log.e(TAG, "Error with requestPurchase");
			return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID;
		}

		Intent intent = new Intent();
		ResponseHandler.buyPageIntentResponse(pendingIntent, intent);
		return response.getLong(Consts.BILLING_RESPONSE_REQUEST_ID,
				Consts.BILLING_RESPONSE_INVALID_REQUEST_ID);
	}

	@Override
	protected void responseCodeReceived(ResponseCode responseCode) {
		ResponseHandler.responseCodeReceived(BillingService.this, this, responseCode);
	}
}

Зверніть увагу на наступні рядки коду:


if (mDeveloperPayload != null) {
	request.putString(Consts.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload);
}

Переконайтеся, що в змінну request додається властивість DEVELOPER_PAYLOAD, тобто, викликається конструктор з двома строковими параметрами і властивість mDeveloperPayload ніде не переписується.

Завершальний етап - отримання DEVELOPER_PAYLOAD у відповіді від сервера. Вся обробка знаходиться в методі onPurchaseStateChange() класу Dungeons:


@Override
public void onPurchaseStateChange(PurchaseState purchaseState, String itemId,
		int quantity, long purchaseTime, String developerPayload) {
	if (Consts.DEBUG) {
		Log.i(TAG, "onPurchaseStateChange() itemId: " + itemId + " " + purchaseState);
	}

	if (developerPayload == null) {
		logProductActivity(itemId, purchaseState.toString());
	} else {
		logProductActivity(itemId, purchaseState + "\n\t" + developerPayload);
	}

	if (purchaseState == PurchaseState.PURCHASED) {
		mOwnedItems.add(itemId);
	}
	mCatalogAdapter.setOwnedItems(mOwnedItems);
	mOwnedItemsCursor.requery();
}

На цьому все, спасибі за увагу! :)

Напишіть перше повідомлення!

Ви повинні увійти під своїм аккаунтом щоб залишати коментарі