میشه کمی درباره کلید عمومی برنامه ( base64EncodedPublicKey ) توضیح بدبد.
باید کلید عمومی برنامه را از کجا دریافت کنیم؟
با تشکر.
میشه کمی درباره کلید عمومی برنامه ( base64EncodedPublicKey ) توضیح بدبد.
باید کلید عمومی برنامه را از کجا دریافت کنیم؟
با تشکر.
اصولا کاربران برنامه مارکت را روی گوشی خودشون نگه میدارند و زیاد نباید فکر همچین مساله هایی باشیم
ولی در مورد اول میشه از سرویس گزارش خطا (اگه اسمشو درست گفته باشم) که قبلا تو همین تالار معرفی شده بود استفاده کرد که به جای پیغام معمولی force close پیغام شما نمایش داده شود و برنامه بسته شود. (( اگر تونستی این کار را رو پرداخت درون برنامه ای پیاده سازی کنی اینجا هم آموزش بزار تا بقیه هم استفاده کنند ))
درباره مورد دوم فکر نمیدونم برنامه بازار نصب نباشه برنامه carsh میشه یا نه ، اما اگر همین طوره که میگی ناشی از اینه که با اینکه اطلاعات کاربر ذخیره شده بعد از هر بار ورود دوباره به سیستم وصل میشه که با استفاده از فراخوانی متد onDestroy در شرط sharedprefences که ارتباط با بازار را قطع میکنه فکر نمیکنم دیگر برنامه crash بشه.
در مطلب قبلی گفتم اگر برنامه کافه بازار بر روی گوشی نصب نباشه برنامه ما که پرداخت درون برنامه ای داره خطا میده و میپره بیرون.
من یک ترای کش گذاشتم مشکل حل شد
Log.d(TAG, "Starting setup.");
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up In-app Billing: " + result);
}
// Hooray, IAB is fully set up!
try {
mHelper.queryInventoryAsync(mGotInventoryListener) ;
} catch (Exception e){
Toast.makeText(getApplicationContext(), getString(R.string.nobazar), Toast.LENGTH_LONG).show();
dialog.hide();
}
}
آیا این روش بهترین روش هست یا نه؟
آره جواب داد. تازه خودم چندین بار چک کردم
سلام به همگی
در مطلب قبلی یک کد دادم که اگر برنامه کافه بازار بر روی گوشی نصب نباشه دیگه خطا نده اما متوجه شدم یک ایراد دیگه هم داره
ایرادش اینکه اگر برنامه کافه بازار را نصب کنید باز هم برنامه شما مشکل داره و اجرا نمیشه
کد را به این شکل تغییر دهید همه چیز درست میشه:
try {
Log.d(TAG, "Starting setup.");
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up In-app Billing: " + result);
}
// Hooray, IAB is fully set up!
mHelper.queryInventoryAsync(mGotInventoryListener) ;
}
});
} catch (Exception e){
Toast.makeText(getApplicationContext(), "برنامه کافه بازار بر روی تلفن همرای شما نصب نیست", Toast.LENGTH_LONG).show();
dialog.hide();
}
دوستان ممنون از توضیحاتی که دادین ولی من قرار نیست برنامه ام را در کافه بازار بفروشم آیا راهی وجود دارد که خودم مستقیم به بانک متصل بشم ؟
چون برای استفاده از کد های کافه بازار لازمه که حتما برنامه در کافه بازار قرار داده بشه
لطفا راهنمایی کنید کارم خیلی گیره این مساله هست
ممنونم
قبلا در یکی از تاپیک ها درباره این موضوع بحث شده خواهشا این سوالات را در این تاپیک قرار ندهید تا تاپیک از موضوع اصلی منحرف نشود ممنون
چرا ارور میده ؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟ ؟؟؟؟
قضیش چیه؟؟؟
اونجاهایی که قرمز کردم!!!!!
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = MainActivity.this;
if (context.getPackageManager().hasSystemFeature(Pack ageManager.FEATURE_CAMERA_FLASH)){
mTorch = (ToggleButton) findViewById(R.id.toggleButton1);
mTorch.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.d(TAG, "onCheckedChanged");
try{
if (cam == null){
cam = Camera.open();
}
camParams = cam.getParameters();
List<String> flashModes = camParams.getSupportedFlashModes();
if (isChecked){
if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) {
camParams.setFlashMode(Parameters.FLASH_MODE_TORCH );
}else{
showDialog(MainActivity.this, FLASH_TORCH_NOT_SUPPORTED);
}
} else {
camParams.setFlashMode(Parameters.FLASH_MODE_OFF);
}
cam.setParameters(camParams);
cam.startPreview();
}catch (Exception e) {
Log.d(TAG, "Caught " + e);
Toast.makeText(MainActivity.this,
"Camera/Torch failure: " + e, Toast.LENGTH_SHORT).show();
e.printStackTrace();
if (cam != null) {
cam.stopPreview();
cam.release();
}
}
}
});
surfaceView = (SurfaceView) this.findViewById(R.id.hiddenSurfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_P USH_BUFFERS);
surfaceHolder.addCallback(this);
} else {
showDialog(MainActivity.this, FLASH_NOT_SUPPORTED);
}
}
سلام دوستان خسته نباشید
با کد هایی که بازار و دوستان برای پرداخت گذاشتن به مشکل خوردم .... با کلی جستجو یه سری کد دیگه پیدا کردم .... خیلی خوب کار میکنه فقط یه مشکلی داره... مشکلش اینه پس از پرداخت تغییراتی که خواستیمو اعمال میکنه ولی برنامه رو یبار بازو بسته میکنم دوباره میره رو حالت قبل از پرداخت... دوستان یه نگاه کنید ببینید میتونید مشکلشو حل کنید ؟
کد ها :
package com.pay.pay;
import com.pay.pay.util.IabHelper;
import com.pay.pay.util.IabResult;
import com.pay.pay.util.Inventory;
import com.pay.pay.util.Purchase;
import com.pay.pay.util.Security;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import com.pay.pay.BuildConfig;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
public class MainActivity extends Activity {
private Button clickButton;
private Button buyButton;
private static final String TAG = "com.pay.pay";
IabHelper mHelper;
static final String ITEM_SKU = "1151";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buyButton = (Button)findViewById(R.id.buyButton);
clickButton = (Button)findViewById(R.id.clickButton);
clickButton.setEnabled(false);
String base64EncodedPublicKey =
"MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBrwC18T7oHr2Pb ZjqN1Sg8F8DzuLg3He5uf6uJ7fJcpAdttCpVFD11nEaarWJa3Y xn/1JB3EIBYyMFfWSvUnM8ffJ7DhPOLIccE7lYyrpZjKeB9QguPGW x7VUSKPkSkww99F4GuAM2rl4Q2LCxu6uXPDf98pg4h+doTN+nk rfqYqh6Tb13X9SMfnOVurpF/83pHWLd5C6x5g4n8RL8Bps8I2SUgEO/M95B74oVLm0CAwEAAQ==";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new
IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess()) {
Log.d(TAG, "In-app Billing setup failed: " +
result);
} else {
Log.d(TAG, "In-app Billing is set up OK");
mHelper.enableDebugLogging(true, TAG);
}
}
});
}
public void buyClick(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener, "mypurchasetoken");
}
public void buttonClicked (View view)
{
//clickButton.setEnabled(false);
buyButton.setEnabled(true);
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,
Purchase purchase)
{
if (result.isFailure()) {
// Handle error
return;
}
else if (purchase.getSku().equals(ITEM_SKU)) {
consumeItem();
buyButton.setEnabled(false);
}
}
};
public void consumeItem() {
mHelper.queryInventoryAsync(mReceivedInventoryList ener);
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// Handle failure
} else {
mHelper.consumeAsync(inventory.getPurchase(ITEM_SK U),
mConsumeFinishedListener);
}
}
};
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =
new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase,
IabResult result) {
if (result.isSuccess()) {
clickButton.setEnabled(true);
} else {
// handle error
}
}
};
@Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null)
mHelper.dispose();
mHelper = null;
}
public static boolean verifyPurchase(String base64PublicKey,
String signedData, String signature) {
if (TextUtils.isEmpty(signedData) ||
TextUtils.isEmpty(base64PublicKey) ||
TextUtils.isEmpty(signature)) {
Log.e(TAG, "Purchase verification failed: missing data.");
if (BuildConfig.DEBUG) {
return true;
}
return false;
}
PublicKey key = Security.generatePublicKey(base64PublicKey);
return Security.verify(key, signedData, signature);
}
}
شما می خواهید بعد از پرداخت متد زیر که false قرار دادید انجام بشه درسته؟
clickButton.setEnabled(true);
دقیقا توضیح بده چیکار میخوای بکنی؟؟
بله دقیقا
ولی میخوام این حالت سیو بمونه که کاربر اگه برنامه رو پاک کرد دوباره نصب کرد ، یا حداقلش بازو بسته کرد برنامه رو به مشکل نخوره دوباره پرداخت کنه .
این کد انگار یه چیزایی کم داره!!!!
وقتی دوباره وارد برنامه میشی (باید به اینترنت وصل باشی) کد بالا که گفتم اجرا میشه؟؟؟؟
تو خط 117 شما بعد از اینکه پرداخت تایید شد مقدار را false قرار دادی که!!!!
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,
Purchase purchase)
{
if (result.isFailure()) {
// Handle error
return;
}
else if (purchase.getSku().equals(ITEM_SKU)) {
consumeItem();
buyButton.setEnabled(false);
}
تقریبا مشکلی نداره ، فقط Button های که False بودن پس از پرداخت true میشن . اما برنامه یبار باز و بسته میشه میره با حالت اول false میشه طرف دوباره باید پرداخت کنه
مقدار دیفالت ClickButton ام false هست میخوام پس از پرداخت که مقدارش true میشه سیو شه بمونه این حالت برای کاربر ، حدافلش برنامه finish شد یا ReInstall کرد clickButton براش true باشه همچنان
با این کدی که گذاشتی اصلا حال نکردم
متد ها را منظم نوشته
اینجا آموزش کامل همراه با پروژه قرار دادم که میتونی استفاده کنی
هم به صورت ذخیره داده ها بعد از پزداخت هم به صورت چک کردن اینترنتی پرداخت از بازار:
https://github.com/hamedjj/BazaarInAppBilling
از این کدها استفاده کنی مشکلی نداری
خط 117 دکمه ای که برای خرید گذاشته بودمو false کردم فقط
با کد های شما مشکل داشتم Eclipse ام نمیدونم با win 8.1 نمیسازه یا مشکل کجاست عینا کدای شما رو کپی کردم ولی اروور داشتم
راستی برنامتونو تست کردم پرداختشم انجام دادم ولی پس از Reinstall همچی پرید و پرداختو دوباره باید انجام میدادم
بنظرم این مشکل پریدن پرداخت باید حل شه به صورت زیر :
وقتی کاربر پرداختو انجام داد یه فایل با یه مقدار خاصی تو حافظه گوشیش ذخیره کنیم
بعد بریم شرط بزاریم که ببین اون فایل هست یا نه ؟
اگه بود برنامه permium باشه
اگه نبود not permium باشه و بره پرداختو انجام بده ...
خوب کاری که sharedPreferences میکنه همینه
تو پروژه آموزشی اول mIsPremium را برابر false قرار گرفت و گفتیم اگه true شد کاربر ویژه هست :
boolean mIsPremium = false;
mIsPremium = preferences.getBoolean(KEY, false);
if (mIsPremium == true) {
updateUi();
return;
}
بعد از پرداخت متد updateui که اجرا میشه مقدار false را به true تغییر میده و ذخیره میکنه که با دیگه برای ورود به برنامه هم به اینترنت نیازی نیست.
// change the mIsPremium to true
SharedPreferences.Editor newtask = preferences.edit();
newtask.putBoolean(KEY, true);
newtask.commit();
سلام من تو پیاده سازی پرداخت مشکلی ندارم
فقط در قسمت آپدیت عناصر صفحه من پرداخت تو یه اکتیوتی جدا انجام میشه ولی میخام عناصر یک صفحه دیگه آپدیت بشه مثلا تو صفحه اولم 5 تا دکمه دارم که یکیش بازه و چهارتاش رو اگه کاربر کلیک کنه یک دیالوگ بشه نمایش داده میشه که میخای پرداخت کنی یا نه اگه بگه آره وارد اکتیوتی پرداخت میشه حالا بعد از پرداخت من چه جوری عناصر صفحه ام رو آپدیت کنم ؟
مشکل من فعلا حل شد پروسه پرداخت رو آوردم تو صفحه اصلی و دکمه پرداخت رو اضافه کردم و گفتم بعد از پرداخت سیوش کن و دفعه های بعد که وارد نرم افزار میشه به جای آپدیت صفحه ای که دارم مستقیما به یک صفحه طراحی شده مخصوص اعضای ویژه بره خوبیش اینه که تو کاربر ساده میتونی هر جای رو که بخای آزاد بزاری یا دسترسی ندی مثلا تو کاربر ساده تمام دکمه های صفحه اول بازه و کاربر میتونه تمام امکانات برنامه رو مشاهده کنه اینجوری بیشتر تحریک میشه که نرم افزار رو بخره
تشکر از راهنمایی خوبتون ...
یک سوال داشتم
در تابع onSavedUpgradeAppButtonClicked
یک خطی هست
String payload = "gdhassdflsldaslfkahsjahsjakaasa";
payload این چیه؟؟؟
از کجا باید به دستش بیاریم؟؟؟
رشتهٔ developerPayload برای مشخص کردن هرگونه آرگومان اضافی که از بازار میخواهید همراه اطلاعات خرید برای شما فرستاده شود، استفاده میشود.
توضیحات بازار:
برای درخواست خرید حتما از developer payload استفاده کنید
در API نسخه ۳ پرداخت درون برنامهای شما میتوانید همراه هر درخواست خرید یک developer payload هم به بازار ارسال کنید. این رشته میتواند به عنوان یک شناسهٔ منحصر به فرد از سمت شما برای این خرید در نظر گرفته شود. بازار بعد از اتمام مراحل خرید این رشته را همراه با جزئیات پرداخت به برنامهٔ شما بازمیگرداند.
شما باید این رشته را برای احراز هویت کاربری که درخواست خرید را داده است به بازار ارسال کنید. برای محصولات مصرف شدنی این رشته میتواند کاملا تصادفی ساخته شود، در حالیکه برای محصولاتی که مصرف شدنی نیستند، برای اطمینان از صحت خریده شدن محصول باید از یک رشتهٔ منحصر به فرد استفاده کنید.
وقتی که پاسخ را از بازار دریافت کردید، مطمئن شوید developer payload که بازار همراه با جزئیات خرید به شما بازگردانده است، همانی است که شما برای شروع عملیات پرداخت به بازار ارسال کرده بودید. برای اطمینان از امنیت پیشنهاد میشود این عملیات را بر روی سرور خود انجام دهید.
الان خوب این رو چگونه تولید کنیم؟؟؟ محدودیتی دارد؟؟؟
انگشتتو بزار رو کیبور تند تند تایپ کن
محدودیتی هم نداره
اصلا اگه خواستی هم نذار
سلام
آقا امروز داشتم به یک مسئله فکر میکردم، اینکه اگر یکی برنامه رو بخره و یوزر و پسووردش رو بده به بقیه، بقیه هم میتونن از برنامه استفاده کنن
اگر بخوایم همچین اتفاقی نیفته چکار باید بکنیم ؟؟؟
البته راهی که به ذهن من میرسه اینه که آیدی گوشی و حساب کاربری توی سرور ذخیره بشه و بعد چک بشه
اما آیا راهی غیر از عملیات سمت سرور هست ؟؟؟
تنها راهی که من میشناسم همونه که هربار ورود از طریق بازار چک بشه که تو پروژه آموزشی هست
بازار هم همین راه را تاکید کرده و راه دیگه ای تو مستنداتش وجود نداره
این راهی که گفتی خوبه ولی یه مشکلی داره اینه که پرداخت درون برنامه ای یه مزیتی که داره تو دستگاه دیگه اگه برنامه را نصب کنی نیاز به خرید مجدد نیست .... (شاید کاربر گوشی جدید خرید)
همون راه اولی که بازار گفته به نظر من بهترینه
نه اون راه نیاز داره که هر بار کاربر آنلاین وارد برنامه بشه، این به شدت باعث نارضایتی کاربر میشه
مخصوصا توی ایران با این وضع اینترنت
بعدشم فرقی نداره که، طرف وقتی یوزر و پسوورد داشته باشه ، خب هر سری با همون میاد دیگه
--------------------------------
ولی حالا که یکم بیشتر فک میکنم، به این نتیجه میرسم کسی اوسکول نیست که یوزر و پسووردش رو همگانی بده به بقیه
نهایتش میده به 2-3 نفر از دوستاش، دیگه توی سایت که نمیذاره
اگر گذاشت، ما میریم با پسووردش وارد میشیم، پسووردش رو عوض میکنیم
قسمت بعدی پروژه آموزشی پرداخت درون برنامه ای
در این قسمت صفحه پرداخت در یک کلاس جدا درست شده که شما میتوانید با استفاده از آن یک یا چند قسمت از برنامه را به صورت درون خرید قرار دهید.
برنامه همراه با توضیحات در صفحه github پروژه قرار گرفت:
دانلود و آموزش برنامه در Github
آموزش بعدی درباره محصولات مصرفی خواهد بود.
دوستان کسی میدونی عکس background Button هارو پس از پرداخت چجوری میشه عوض کرد ؟ فقط ثابت باشه که نپره با شروع مجدد برنامه پس از پرداخت
حامد جان کد فعال سازی رو علاوه بر onCreate توی onRestart هم بنویس تا لازم نباشه حتما کاربر برنامه رو دوباره اجرا کنه
چطور باید متد onRestart را بنویسم
تا حالا باهاش کار نکردم
اینم کد custompremium
public class CustomPremium extends Activity {
Button btn5;
Button btn4;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.custompremium);
updatebtn();
btn4 = (Button) findViewById(R.id.custombtn);
btn5 = (Button) findViewById(R.id.Activebtn);
btn4.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(CustomPremium.this, PurchaseApp.class));
}
});
}
public void updatebtn() {
btn5 = (Button) findViewById(R.id.Activebtn);
if (PurchaseApp.mIsPremium) {
btn5.setEnabled(true);
btn5.setBackgroundResource(R.drawable.button_norma l);
btn5.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(), R.string.active, Toast.LENGTH_SHORT).show();
}
});
findViewById(R.id.custombtn).setEnabled(false);
}else {
return;
}
}
}
حامد جان onRestart هیچ فرقی نداره با onCreate کد نوشتنش
توی اکتیویتی از منوی source گزینه override/implement methodes رو بزن، بعد onRestart رو ادد کن
onRestart بعد از اینکه کاربر از یک اکتیویتی دیگه برگشت، یا مثلا برنامه متوقف شد و دوباره برگشت به اون اکتیویتی اجرا میشه
حالا شما این متد رو که اضافه کردی، کافیه توش همون تابع updateBtn رو فراخوانی کنی
با تشکر از poorman جان عزیز
متد onRestart در اکتیویتی CustomPremium افزوده شد که دیگر نیازی برای خروج از برنامه بعد از تایید پرداخت نیست