Почему API биллинга Google, установленный в их документации, постоянно возвращает код 5?
Я начинающий разработчик Android, который никогда не использовал биллинг внутри приложения. Поэтому я выполнил шаги, описанные в собственной документации Google по адресу http://developer.android.com/google/play/billing/billing_integrate.html.
Я добавил файл IInAppBillingService.aidl в main/aidl/com.android.vending.billing, и моя структура соответствует бесчисленным скриншотам, которые я видел в Интернете.
Я добавил код, очень похожий на пример кода, в часть моего приложения, которая взаимодействует с моим онлайн-магазином. Упрощенная версия этого кода с удалением посторонних вещей:
imports...
import android.content.ServiceConnection;
import com.android.vending.billing.IInAppBillingService;
public class intMarket extends Activity {
IInAppBillingService mService;
public static final String SHARED_PREFS_NAME="myAppSettings";
public static String purchaseToken = "";
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
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intbrowser);
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
String tUrl = getString(R.string.urlMarket);
SharedPreferences settings = getSharedPreferences(SHARED_PREFS_NAME, 0);
myWebView.loadUrl(tUrl);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mService != null) {
unbindService(mServiceConn);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
purchaseToken = jo.getString("purchaseToken");
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
}
public class WebAppInterface {
Context mContext;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
/** Show a toast from the web page */
@JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
@JavascriptInterface
public void purchaseItem(Integer itemID, String itemName, BigDecimal itemPrice) {
// Credit Purchase
ArrayList<String> skuList = new ArrayList<String> ();
Bundle querySkus = new Bundle();
querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
String purchaseCreditsResponse = "Success";
try {
Bundle skuDetails = mService.(3, getPackageName(), "inapp", querySkus);
Log.d("WPS", skuDetails.toString());
int response = skuDetails.getInt("RESPONSE_CODE");
Log.d("WPS", Integer.toString(response));
if (response == 0) {
ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
String thisItemID = "0";
for (String thisResponse : responseList) {
JSONObject object = new JSONObject(thisResponse);
String itemPrice = object.getString("price");
if (itemPrice.equals(itemPrice.toString()))
thisItemID = object.getString("productId");
}
if (Integer.parseInt(thisItemID) > 0) {
Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), thisItemID, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
if (buyIntentBundle.getInt("RESPONSE_CODE") == 0) {
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
//startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
// purchaseToken
purchaseCreditsResponse = "Failure";
Toast.makeText(mContext, "Buying: " + itemName, Toast.LENGTH_LONG).show();
}
} else {
purchaseCreditsResponse = "Failure";
Toast.makeText(mContext, "Sorry, but there was a problem with your purchase. Please try again. If the problem persists, contact support. Error Code: 001.", Toast.LENGTH_LONG).show();
}
} else {
purchaseCreditsResponse = "Failure";
Toast.makeText(mContext, "Sorry, but there was a problem with your purchase. Please try again. If the problem persists, contact support. Error Code: 002.", Toast.LENGTH_LONG).show();
}
} catch (RemoteException e) {
purchaseCreditsResponse = "Failure";
Toast.makeText(mContext, "Sorry, but there was a problem with your purchase. Please try again. If the problem persists, contact support. Error Code: 003.", Toast.LENGTH_LONG).show();
} catch (JSONException e) {
purchaseCreditsResponse = "Failure";
Toast.makeText(mContext, "Sorry, but there was a problem with your purchase. Please try again. If the problem persists, contact support. Error Code: 004.", Toast.LENGTH_LONG).show();
}// catch (IntentSender.SendIntentException e) {
// purchaseCreditsResponse = "Failure";
// Toast.makeText(mContext, "Sorry, but there was a problem with your purchase. Please try again. If the problem persists, contact support. Error Code: 005.", Toast.LENGTH_LONG).show();
//}
// Purchase Report
// Report purchase and get response into purchaseResponse
// Todo
// Credit Consumption
// Todo
}
}
}
Затем я скомпилировал эту версию, загрузил APK в Google Play в качестве альфа-теста и опубликовал его. Я делаю обновления и использую ADB для установки новых скомпилированных APK на свой телефон, но я постоянно получаю следующее из этого кода в LogCat:
03-23 15:07:55.325 2958-3009/? D/WPS﹕ Bundle[mParcelledData.dataSize=48]
03-23 15:07:55.325 2958-3009/? D/WPS﹕ 5
Что, конечно, указывает: BILLING_RESPONSE_RESULT_DEVELOPER_ERROR
Я прочитал в другом посте SO, что вы не можете проверить выставление счетов на устройстве, основная учетная запись которого совпадает с учетной записью разработчика. Поэтому вчера я потратил несколько часов на то, чтобы найти другой телефон и настроить его с помощью совершенно отдельной учетной записи (и единственной учетной записи на устройстве). Я загрузил новую сборку в Google Play в качестве альфа-теста и опубликовал ее. Я подождал, пока другой телефон получит новую версию, и снова попытался протестировать биллинг. Телефон сообщил об этом сообщении об ошибке, которое я встроил:
Sorry, but there was a problem with your purchase. Please try again. If the problem persists, contact support. Error Code: 002.
Что указывает на ту же ошибку, с которой я столкнулся раньше. Это подразумевает, что есть проблема с моим кодом, которая не удивит меня.
Я ничего не сделал с большим гигантским лицензионным кодом, который появляется на панели разработчиков Google Play, потому что в вышеупомянутой документации ничего не сказано о том, что он требуется. Но так ли это? Если нет, то как насчет моего кода вызывает эту проблему?
2 ответа
Люди комментируют, что это ошибка в биллинговом API Google (может быть, Google считает это функцией?). Похоже, вы должны потреблять токен покупки, так же, как парень здесь:
String purchaseToken = o.optString("token", o.optString("purchaseToken"));
// Consume purchaseToken, handling any errors
mService.consumePurchase(3, getPackageName(), purchaseToken);
Подтвердите это com.android.vending.BILLING
добавлен в ваши разрешения манифеста.
Также убедитесь, что ваше приложение подписано вашим рабочим ключом, и версия в Google Play должна совпадать с версией, с которой вы тестируете.
Также взгляните на эту легкую, простую библиотеку, которую вы можете использовать на Github
ниже: https://github.com/anjlab/android-inapp-billing-v3