Перейти к содержанию
Fire Monkey от А до Я
  • 0

Пример с TInAppPurchase


Major

Вопрос

Ребят, покажите пошагово плиз, как работать с компонентом TInAppPurchase. В Сети ничего не нашел, кроме примера CapitalIAP.

ИМХО, это один из важнейших компонентов, где ошибка может дорого стоить.

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Вот мой юнит для работы с покупками в приложении:

unit UnitInAppPurchase;

interface

uses
//  UnitGetDeviceInfo,
  FMX.InAppPurchase,
  System.Classes,
  System.SysUtils,
  System.Hash;

//const
//  HashMixer = 'p345mcq34mq';
type
  TBillingEventPurchased = procedure(ASecretKey : String) of object;
  TBillingEventNotPurchased = procedure of object;
  TBillingLog = procedure(AMessage : String) of object;

  TBilling = class
  private
    InAppPurchase: TInAppPurchase;
    FBillingEventPurchased : TBillingEventPurchased;
    FBillingEventNotPurchased : TBillingEventNotPurchased;
    FBillingLog : TBillingLog;
    FNoAdsID : String;
    FSecretKey : String;
    FApplicationLicenseKey : String;
    procedure InAppPurchaseSetupComplete(Sender: TObject);
    procedure InAppPurchaseProductsRequestResponse(Sender: TObject; const Products: TIAPProductList; const InvalidProductIDs: TStrings);
    procedure InAppPurchaseError(Sender: TObject; FailureKind: TFailureKind; const ErrorMessage: string);
    procedure InAppPurchasePurchaseCompleted(Sender: TObject; const ProductID: string; NewTransaction: Boolean);
    procedure ConsumeComplete(Sender: TObject; const ProductID: string);
    procedure ConsumeFailed(Sender: TObject; const ProductID, ErrorMessage: string);
    function GetSecretKey : String;
    function CheckSecretKey : Boolean;
    procedure LogMy(AMessage : String);
  public
//    Constructor Create(AApplicationLicenseKey, ANoAdsID, ASecretKey : String);
    constructor Create(AApplicationLicenseKey, ANoAdsID : String);
    destructor Destroy;
    procedure CheckPurchase;
    procedure Purchase;
//  published
    property OnPurchased : TBillingEventPurchased read FBillingEventPurchased write FBillingEventPurchased;
    property OnNotPurchased : TBillingEventNotPurchased read FBillingEventNotPurchased write FBillingEventNotPurchased;
    property OnPurchasedError : TBillingEventNotPurchased read FBillingEventNotPurchased write FBillingEventNotPurchased;
    property OnLog : TBillingLog read FBillingLog write FBillingLog;
  end;

implementation

//Constructor TBilling.Create(AApplicationLicenseKey, ANoAdsID, ASecretKey : String);
Constructor TBilling.Create(AApplicationLicenseKey, ANoAdsID : String);
begin
  FNoAdsID:=ANoAdsID;
  FApplicationLicenseKey:=AApplicationLicenseKey;
//  FSecretKey:=ASecretKey;
  InAppPurchase:=TInAppPurchase.Create(Nil);
  InAppPurchase.ApplicationLicenseKey:=FApplicationLicenseKey;
  InAppPurchase.ProductIDs.Add(FNoAdsID);
  InAppPurchase.OnSetupComplete := InAppPurchaseSetupComplete;
  InAppPurchase.OnProductsRequestResponse := InAppPurchaseProductsRequestResponse;
  InAppPurchase.OnError := InAppPurchaseError;
  InAppPurchase.OnPurchaseCompleted := InAppPurchasePurchaseCompleted;
  InAppPurchase.OnConsumeCompleted := ConsumeComplete;
  InAppPurchase.OnConsumeFailed := ConsumeFailed;
end;

Destructor TBilling.Destroy;
begin
  if Assigned(InAppPurchase) then
    FreeAndNil(InAppPurchase);
  inherited;
end;

procedure TBilling.Purchase;
begin
  try
    InAppPurchase.PurchaseProduct(FNoAdsID);
  except
    LogMy('PurchaseProduct except');
  end;
end;

procedure TBilling.CheckPurchase;
begin
  if CheckSecretKey Then
  begin
    LogMy('CheckSecretKey True - Disable Ads');
    FSecretKey:=GetSecretKey;
    if Assigned(OnPurchased) then
      OnPurchased(FSecretKey);
    Exit;
  end;
  LogMy('CheckSecretKey False - Check InAppPurchase status');
  InAppPurchase.SetupInAppPurchase;
end;

function TBilling.GetSecretKey : String;
Var ADeviceIMEI : String;
begin
// Это был костыль для хранения флага о покупке локально, не оправдал себя и изъят из обращения
//  ADeviceIMEI:=GetDeviceIMEI;
//  Result:=System.Hash.THashSHA1.GetHashString(HashMixer+ADeviceIMEI+FNoAdsID);
end;

function TBilling.CheckSecretKey : Boolean;
begin
    Result:=False;
//  Result:=FSecretKey.Equals(GetSecretKey);
end;


procedure TBilling.InAppPurchaseSetupComplete(Sender: TObject);
begin
  LogMy('InAppPurchaseSetupComplete');
  try
    LogMy('InAppPurchase.QueryProducts');
    InAppPurchase.QueryProducts;
  except
    on E:Exception do
      LogMy('QueryProducts Exception: '+e.Message);
  end;
end;

procedure TBilling.InAppPurchaseProductsRequestResponse(Sender: TObject;
  const Products: TIAPProductList; const InvalidProductIDs: TStrings);
var Product: TProduct;
begin
  LogMy('TMainForm.InAppPurchaseProductsRequestResponse');
  LogMy('Start search '+FNoAdsId);
  LogMy('Products.Count='+Products.Count.ToString);
  for Product in Products do
  begin
    LogMy('Start search '+FNoAdsId);
    if Product.ProductID = FNoAdsId then
    begin
      LogMy('Founded '+FNoAdsId);
      if InAppPurchase.IsProductPurchased(FNoAdsId) then
      begin
        // КУПЛЕНО!!!!
        LogMy(FNoAdsID+' Yes ProductPurchased');
        FSecretKey:=GetSecretKey;
        if Assigned(OnPurchased) then
          OnPurchased(FSecretKey);
      end
      Else
      begin
        LogMy(FNoAdsID+' Not ProductPurchased');
        if Assigned(OnNotPurchased) then
          OnNotPurchased;
      end;
      Exit;
    end;
  end;
  LogMy('Product not found - OnNotPurchased');
  if Assigned(OnNotPurchased) then
    OnNotPurchased;
  LogMy('TMainForm.InAppPurchaseProductsRequestResponse END');
end;

procedure TBilling.InAppPurchaseError(Sender: TObject;
  FailureKind: TFailureKind; const ErrorMessage: string);
Var S: String;
begin
  if FailureKind = TFailureKind.ProductsRequest Then
    S:='ProductsRequest';
  if FailureKind = TFailureKind.Purchase Then
    S:='Purchase';
  if Assigned(OnPurchasedError) then
    OnPurchasedError;

  LogMy('Purchasing error ('+S+'):'+ErrorMessage);
end;

procedure TBilling.InAppPurchasePurchaseCompleted(Sender: TObject;
  const ProductID: string; NewTransaction: Boolean);
begin
  LogMy('TMainForm.InAppPurchasePurchaseCompleted');
  if ProductID = FNoAdsID then
  begin
    LogMy('HideAndDestroyAds');
    FSecretKey:=GetSecretKey;
    if Assigned(OnPurchased) then
      OnPurchased(FSecretKey);
  end;
end;

procedure TBilling.ConsumeComplete(Sender: TObject; const ProductID: string);
begin
  LogMy('Consume Complete: ' + ProductID);
end;

procedure TBilling.ConsumeFailed(Sender: TObject; const ProductID, ErrorMessage: string);
begin
  LogMy('Consume Failed: ' + ProductID);
end;

procedure TBilling.LogMy(AMessage : String);
begin
  if Assigned(OnLog) then
    OnLog(AMessage);
end;

end.

Использовать вот так:

const   NoAdsID = 'mysuperapp_remove_ad'; //название товара, тоже что и консоли разработчика
...
private 
    Billing : TBilling;
    procedure BillingEventPurchased(ASecretKey : String);
    procedure BillingEventNotPurchased;
    procedure BillingEventPurchasedError;
    procedure BillingLog(AMessage : String);
    procedure DisablePurchaseUI;
    procedure EnablePurchaseUI;
...
FormCreate start
Var AppLicenseKey : String;
...
  AppLicenseKey:='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxim8ZGAIhK/FPhpXT0r6MXHYxYi1qcMfIiKOkiBDHcRYgRLK7';
  AppLicenseKey:=AppLicenseKey+'********************************************************************************';
  AppLicenseKey:=AppLicenseKey+'******************************************************************************';
  AppLicenseKey:=AppLicenseKey+'*******************************************************************************';
  AppLicenseKey:=AppLicenseKey+'Mgv7JP8A+qcDV3lm4M9OKBgxBRLaejxHd1iH3tsMR8PLkKUUf3yrMW8QIDAQAB';

  Billing:=TBilling.Create(AppLicenseKey, NoAdsID);
  Billing.OnPurchased:=BillingEventPurchased;
  Billing.OnNotPurchased:=BillingEventNotPurchased;
  Billing.OnPurchasedError:=BillingEventPurchasedError;
  Billing.OnLog:=BillingLog;
  Billing.CheckPurchase;
FormCreate stop
...

procedure TFormMain.BillingEventPurchased(ASecretKey : String);
begin
//  LogMy('CheckSecretKey True - Disable Ads');
  Setting.Flags.AdsShowFlag:=False;
  DisablePurchaseUI; // удаляет кнопки и прочую фигню предлагающую купить товар (товар в данном случае - Удаление рекламы)
  HideAndDestroyAds; // удаление рекламы из приложения, так как товар куплен
//  Setting.SecretKey:=ASecretKey;
//  SaveFormState;
end;

procedure TFormMain.BillingEventNotPurchased;
begin
  Setting.Flags.AdsShowFlag:=True;
  EnablePurchaseUI;
  ShowAds;
end;

procedure TFormMain.BillingEventPurchasedError;
begin
  Setting.Flags.AdsShowFlag:=True;
//  EnablePurchaseUI;
  ShowAds;
end;

procedure TFormMain.BillingLog(AMessage : String);
begin
//  Memo.Lines.Insert(0,AMessage);
end;

procedure TFormMain.DisablePurchaseUI;
begin
  ButtonRemoveAds.Visible:=False;
  LayoutRemoveAds.Visible:=False;
end;

procedure TFormMain.EnablePurchaseUI;
begin
  LayoutRemoveAds.Visible:=True;
  ButtonRemoveAds.Visible:=True;
end;

 

Ссылка на комментарий
  • 0
18 часов назад, Major сказал:

спасибо большое!

а с AdMob-ом работали?

Да, работал. И кстати соответствующий раздел этого форума содержит всю необходимую вам информацию.

Ссылка на комментарий
  • 0

Спасибо за код.

А зачем в вашем коде:

Var AppLicenseKey : String;
...
  AppLicenseKey:='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxim8ZGAIhK/FPhpXT0r6MXHYxYi1qcMfIiKOkiBDHcRYgRLK7';
  AppLicenseKey:=AppLicenseKey+'********************************************************************************';
  AppLicenseKey:=AppLicenseKey+'******************************************************************************';
  AppLicenseKey:=AppLicenseKey+'*******************************************************************************';
  AppLicenseKey:=AppLicenseKey+'Mgv7JP8A+qcDV3lm4M9OKBgxBRLaejxHd1iH3tsMR8PLkKUUf3yrMW8QIDAQAB';

Чтобы запутать взломщика?

Ссылка на комментарий
  • 0
6 минут назад, Major сказал:

Спасибо за код.

А зачем в вашем коде:


Var AppLicenseKey : String;
...
  AppLicenseKey:='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxim8ZGAIhK/FPhpXT0r6MXHYxYi1qcMfIiKOkiBDHcRYgRLK7';
  AppLicenseKey:=AppLicenseKey+'********************************************************************************';
  AppLicenseKey:=AppLicenseKey+'******************************************************************************';
  AppLicenseKey:=AppLicenseKey+'*******************************************************************************';
  AppLicenseKey:=AppLicenseKey+'Mgv7JP8A+qcDV3lm4M9OKBgxBRLaejxHd1iH3tsMR8PLkKUUf3yrMW8QIDAQAB';

Чтобы запутать взломщика?

Хм. Можно и так это рассматривать. Но лучше сначала изучить теоретическую часть покупок в приложении и понять что именно и для чего вы делаете. Копипастить код не поможет. Подробности тут https://www.google.ru/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=покупки+в+приложениях+андроид&*

Ссылка на комментарий
  • 0
19 минут назад, Major сказал:

По вашей ссылке в основном открываются программы для взлома.

кстати, если не секрет, вашу программу взламывали?

Ссылка это поиск в гугле интересующей вас информации. Думать о жутких хакерах и взломе вашего приложения можно начинать при количестве скачиваний вашего приложения от миллиона и выше. Или при стоимости приложения в несколько тысяч рублей. В противном случае гипотетических хакеров можно не принимать во внимание. 

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...