پیاده سازی پرداخت درون برنامه ای کافه بازار

در پست قبلی گفتم برای پرداخت درون برنامه ای کافه بازار دو سه هفته ای درگیر بودم. الان که نگاه می کنم خیلی آسانتر از آن چیزی بوده که وقت من را گرفته بود. این پست را برای کسانی می نویسم که می خواهند برای اولین بار پرداخت درون برنامه ای کافه بازار را پیاده سازی کنند. ابتدا سعی می کنم کلیت کار را شرح دهم و بعد وارد مباحث فنی پیاده سازی شوم.


کلیت پرداخت درون برنامه ای به این شکل هست که ابتدا شما باید کوئری بزنید که آیا این اپلیکیشن قبلا خریداری شده است یا نه؟ اگر خریداری نشده است کاربر را به صفحه پرداخت درون برنامه ای کافه بازار هدایت کنید و در صورت موفق بودن پرداخت نسخه پرمیوم اپلیکیشن خودتان را در اختیار کاربر قرار دهید (در برنامه نویسی به این نتیجه رسیدم دید کلی به موضوعات داشته باشم تا بتوانم آنها را درک کنم، شما هم سعی کنید کلی نگاه کنید و جزیی پیاده سازی کنید).


حالا توصیه می کنم این قسمت از مستندات کافه بازار را حتما بخوانید (فقط به صورت روزنامه وار بخوانید تا کلیت ماجرا را درک کنید،درگیر مطالب فنی و جزیی نشوید). این قسمت مطلب خاصی ندارد و فقط یک سری توضیحات درباره پرداخت درون برنامه ای و اشتراک اپلیکیشن ارائه شده است. توصیه اکید دارم اگر بار اول هست می خواهید پرداخت درون برنامه ای را پیاده سازی کنید سراغ اشتراک ماهیانه و محصولات مصرفی نروید چون واقعا گیج خواهید شد. یک اپلیکیشن نمونه بسازید که فقط پرداخت درون برنامه ای ساده را بتوانید پیاده سازی کنید. اپلیکیشن خود را در پنل کافه بازار آپلود کنید و محصولی برای پرداخت درون برنامه ای ایجاد کنید. تمام توضیحات برای این قسمت را در ادامه می آورم (توضیحات از کافه بازار کپی شده است و اگر نیاز باشد توضیح بیشتری می دهم) اما اگر تمایل دارید می توانید از این لینک که مستندات کافه بازار است استفاده کنید. بعید می دانم برای این قسمت مشکل خاصی داشته باشید اما اگر مشکلی پیش آمد در کامنت ها بپرسید تا کمکتان کنم.


ایجاد لیست محصولات

پنل بازار به شما این امکان را می‌دهد که به ازای هر یک از برنامه‌های‌تان یک لیست جدا از محصولات داشته باشید. شما تنها وقتی می‌توانید یک محصول را در برنامه‌تان به فروش برسانید که آن را در پنل ثبت کرده باشید. توجه داشته باشید که هر برنامه لیست محصولات مربوط به خود را دارد و امکان فروش محصولات دیگر برنامه‌ها در برنامهٔ شما وجود ندارد.

لیست محصولات مربوط به برنامهٔ خود را می‌توانید با ورود به پنل توسعه‌دهندگی‌تان و سپس انتخاب برنامه‌ٔ مورد نظر، در سربرگ «پرداخت درون‌برنامه‌ای» مشاهده فرمائید.

در لیست محصولات برای هر محصول اطلاعاتی از قبیل شناسه کالا، عنوان، قیمت، توضیحات محصول، نوع (فروشی یا اشتراکی) و وضعیت (فعال یا غیرفعال) وجود دارد. این لیست فقط شامل اطلاعات کلی دربارهٔ محصول شماست و به هیچ وجه محتوای محصول شما را شامل نمی‌شود. یعنی اینکه شما خودتان باید محصولی (محتوا) را که در برنامه‌تان می‌فروشید، به دست کاربر برسانید.


اضافه کردن محصولات

برای اضافه کردن محصولات از طریق سربرگ «پرداخت درون‌برنامه‌ای» باید مراحل زیر را طی کنید:

۱. به حساب کاربری خود وارد شوید.

۲. وارد پنل توسعه‌دهندگی خود شوید.

۳. برنامه مدنظرتان را انتخاب کنید و وارد سربرگ «پرداخت درون‌برنامه‌ای» شوید.

۴. روی دکمه <<محصول جدید>> کلیک کنید و اطلاعات مورد نیاز برای هر محصول را وارد کنید.



برای هر محصول موارد زیر را باید وارد کنید:

  • شناسهٔ کالا
    شناسهٔ کالای هر محصول در هر برنامه باید منحصر به فرد باشد. این شناسه باید با حروف کوچک لاتین یا یک عدد شروع شود و همگی کاراکترهای استفاده شده در آن باید فقط از حروف کوچک لاتین، اعداد لاتین، _ و نقطه باشند.
    شما به هیچ عنوان مجاز به ویرایش شناسهٔ یک محصول بعد از ایجاد آن نیستید و امکان استفادهٔ مجدد از این شناسه‌ها نیز وجود ندارد.
  • عنوان
    یک توضیح بسیار کوچک از محصول است که به ازای هر برنامهٔ شما باید منحصر به فرد باشد. ارائهٔ عنوان برای هر محصول ضروری است و پیشنهاد می‌شود برای نمایش بهتر طول عنوان بیش از ۲۵ کاراکتر نباشد.
  • توضیحات
    یک توضیح مفصل برای محصولی که می‌خواهید بفروشید باید ارائه کنید. این توضیح در صفحهٔ پرداخت بازار به کاربر نشان داده می‌شود. البته امکان استفاده از این توضیح در برنامهٔ خودتان نیز وجود دارد.
  • قیمت
    برای هر محصول باید یک قیمت به ریال وارد کنید. حداقل و حداکثر این قیمت در قرارداد شما با بازار مشخص شده است. قیمت محصول نمی‌تواند از مقداری که در قرارداد شما مشخص شده است، کمتر یا بیشتر باشد.

حالا می رسیم به قسمت نسبتا سخت ماجرا. ابتدا حداقل یک بار این صفحه از مستندات را به طور کامل بخوانید تا درک کلی از آنچه انجام خواهید داد داشته باشید. برای شروع پیاده سازی توصیه می کنم از این قسمت مستندات شروع کنید.

این مرحله تا برقراری ارتباط با بازار کاملا واضح و شفاف توضیح داده شده است. تا ابتدای این مرحله را به آسانی می توانید انجام دهید. چند فایل باید در پروژه خود کپی کنید. مجوز پرداخت در فایل مانیفست بدهید و پروژه را بیلد کنید. در قسمت نهایی کار شما باید کدنویسی را شروع کنید و با بازار ارتباط برقرار کنید تا بتوانید محصول خود را بفروشید. من راهی که خودم انجام داده ام را در اینجا می نویسم. یک اکتیویتی جدید با نام BuyActivity ایجاد می کنیم. سپس این کدها را در آن کپی می کنیم. کدها را از لینک دانلود کنید و در اکتیویتی مربوطه کپی کنید(خدا را شکر که متوجه شدم ویرگول هم از کداسنیپت پشتیبانی می کند اما باز هم لینک دانلود کدها را برای شما در اینجا قرار داده ام لینک دانلود).

‍‍

public class BuyActivity extends AppCompatActivity {

    //SweetAlertDialogCustom mProgressDialog;
    private boolean mBazaarInstalled;
    // SKUs for our products: the premium upgrade (non-consumable)
    static final String SKU_PREMIUM = &quotpremium&quot
    // Does the user have the premium upgrade?
    boolean mIsPremium = false;
    // (arbitrary) request code for the purchase flow
    static final int RC_REQUEST = 1;
    private static final String TAG = BuyActivity.class.getSimpleName() + &quotTAG&quot
    // The helper object
    IabHelper mHelper;
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_buy);
        ButterKnife.bind(this);
        
        //neshan dadan progress bar
        //mProgressDialog = SweetAlertHelper.loadingSweetAlert(this, &quotدر حال اتصال به بازار&quot);
        mHelper = new IabHelper(this, base64EncodedPublicKey);
        Log.d(TAG, &quotStarting setup.&quot);
        Log.d(TAG, &quotStarting setup.&quot);
        
          try {
              mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
              public void onIabSetupFinished(IabResult result) {
                  //mProgressDialog.dismiss();
                  mBazaarInstalled = true;
                  Log.d(TAG, &quotSetup finished.&quot);
                  
                      if (!result.isSuccess()) {
                          // moshkeli dar ertebat ba bazaar pish amad
                          Log.e(&quotTAG&quot, &quotfailed to access bazaar &quot + result);
                          mProgressDialog.dismiss();
                          //neshan dad dialog khata be karbar(dar inja sweet alert)
                          new SweetAlertDialogCustom(BuyActivity.this,
                          SweetAlertDialogCustom.CUSTOM_IMAGE_TYPE)
                              .setTitleText(&quotکاربر گرامی&quot)
                              .setContentText(&quotخطایی در ارتباط با بازار رخ داد! از وصل بودن اینترنت خود مطمئن شوید.&quot)
                              .setConfirmClickListener(new
                              SweetAlertDialogCustom.OnSweetClickListener() {
                                  @Override
                                  public void (SweetAlertDialogCustom sDialog) {
                                      finish();
                                  }
                              }).show();
                              Log.e(TAG, &quotProblem setting up In-app Billing: &quot + result);
                        }
                        // Hooray, IAB is fully set up!
                        mHelper.queryInventoryAsync(mGotInventoryListener);
                        }
                   });
               } catch (Exception ex) {
                   //bazaar ruye gooshie karbar nasb nist, bayad handle shavad
                   mBazaarInstalled = false;
                   mProgressDialog.dismiss();
                   //neshan dad dialog khata be karbar(dar inja sweet alert)
                   new SweetAlertDialogCustom(BuyActivity.this,
                       SweetAlertDialogCustom.CUSTOM_IMAGE_TYPE)
                       .setTitleText(&quotکاربر گرامی&quot)
                       .setContentText(&quotبرای خرید این اپلیکیشن باید برنامه کافه بازار را نصب کنید!&quot)
                       .setConfirmClickListener(new SweetAlertDialogCustom.OnSweetClickListener(
                           {
                           @Override
                           public void (SweetAlertDialogCustom sDialog) {
                               finish();
                           }
                      }).show();
                  }
            }
            
            IabHelper.QueryInventoryFinishedListener mGotInventoryListener = 
                new IabHelper.QueryInventoryFinishedListener() {
                    public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
                        Log.d(TAG, &quotQuery inventory finished.&quot);
                        mProgressDialog.dismiss();
                        if (result.isFailure()) {
                            // moshkeli dar ertebat ba bazaar pish amad
                            Log.e(&quotTAG&quot, &quotfailed to access bazaar &quot + result);
                            //neshan dad dialog khata be karbar(dar inja sweet alert)
                            new SweetAlertDialogCustom(BuyActivity.this,
                                SweetAlertDialogCustom.CUSTOM_IMAGE_TYPE)
                                .setTitleText(&quotکاربر گرامی&quot)
                                .setContentText(&quotخطایی در ارتباط با بازار رخ داد! از وصل بودن اینترنت خود                                 مطمئن شوید.&quot)
                                .setConfirmClickListener(new
                                    SweetAlertDialogCustom.OnSweetClickListener() {
                                        @Override
                                        public void (SweetAlertDialogCustom sDialog) {
                                            finish();
                                        }
                                  }).show();
                              return;
                              } else {
                              Log.d(TAG, &quotQuery inventory was successful.&quot);
                              // does the user have the premium upgrade?
                              //aya karbar noskhe premium ra ghablan kharide ast? 
                              mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
                              // update UI accordingly
                              //agar kharide ast bayad mohtava barayash baz shavad
                              if (mIsPremium) {
                              //barname be activity digari ke hedayat mishavad va mohtava baraye
                              //karbar baz mishavad
                              Intent intent = new Intent(BuyActivity.this, MainActivity.class);
                              startActivity(intent);
                              } else {
                                  try {
                                      mHelper.launchPurchaseFlow(BuyActivity.this, SKU_PREMIUM,
                                      RC_REQUEST, mPurchaseFinishedListener, &quotpayload-string&quot);
                                      } catch (Exception ex) {
                                 }
                            }
                            Log.d(TAG, &quotUser is &quot + (mIsPremium ? &quotPREMIUM&quot : &quotNOT PREMIUM&quot));
                       }
                       Log.d(TAG, &quotInitial inventory query finished; enabling main UI.&quot);
                  }
             };
             IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = 
                     new IabHelper.OnIabPurchaseFinishedListener() {
                         public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
                             if (result.isFailure()) {
                                 // moshkeli dar ertebat ba bazaar pish amad
                                 Log.e(&quotTAG&quot, &quotfailed to access bazaar &quot + result);
                                 //neshan dad dialogE khata be karbar(dar inja sweet alert)
                                 new SweetAlertDialogCustom(BuyActivity.this,
                                         SweetAlertDialogCustom.CUSTOM_IMAGE_TYPE)
                                             .setTitleText(&quotکاربر گرامی&quot)
                                             .setContentText(&quotخطایی در ارتباط با بازار رخ داد! از وصل بودن اینترنت خود مطمئن شوید.&quot)
                                             .setConfirmClickListener(
                                                 new SweetAlertDialogCustom.OnSweetClickListener() {
                                                     @Override
                                                     public void (SweetAlertDialogCustom sDialog) {
                                                         finish();
                                                     }
                                                }).show();
                                           return;
                                       } else if (purchase.getSku().equals(SKU_PREMIUM)) {
                                           // give user access to premium content and update the UI
                                           // be karbar dastrasi be mohtavaye premium(puli) ra bedahid.
                                           //karbar kharid ra kamel anjam dad
                                           Intent intent = new Intent(BuyActivity.this, MainActivity.class);
                                           startActivity(intent);
                                           }
                                      }
                                  };
                                  
                                  @Override
                                  protected void onActivityResult(int requestCode, 
                                          int resultCode, Intent data) {
                                   super.onActivityResult(requestCode, resultCode, data);
                                   // Pass on the activity result to the helper for handling
                                   if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
                                       super.onActivityResult(requestCode, resultCode, data);
                                   } else {
                                       Log.d(TAG, &quotonActivityResult handled by IABUtil.&quot);
                                  }
                             }
                             
                             @Override
                             public void onDestroy() {
                                 super.onDestroy();
                                 if (mHelper != null && mBazaarInstalled) mHelper.dispose();
                                     mHelper = null;
                                 }
                            }




توجه کنید که هشدارها را با SweetAlert پیاده سازی کرده بودم و در این فایل کامنت کرده ام. بیشتر کامنت ها را به فینگلیش نوشته ام تا به راحتی متوجه کارکرد کدها شوید. حتما یک بار همه کدها و کامنتها را بخوانید. در صورتی که این پست مفید بود لایک را فراموش نکنید و هر سوال یا ابهامی برایتان وجود داشت در کامنتها عنوان کنید تا بیشتر توضیح دهم.



از ویرگول عزیز خواهشمندم قسمت کداسنیپت را یک ویرایش اساسی برایش در نظر بگیرند. حدود یک ساعت فقط درگیر گذاشتن همین کداسنیپت در پست بودم. متاسفانه بعد از کپی کردن کدها هر خط کد را یک کد اسنیپت در نظر می گیرد.