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

Bob32

Пользователи
  • Постов

    109
  • Зарегистрирован

  • Посещение

  • Победитель дней

    1

Сообщения, опубликованные Bob32

  1. Добрый день!

    Настраиваю сейчас встроенные покупки по Apple, потом буду под Google.

    Создал встроенную покупку на сайте AppleStore Connect. Она создалась.

    Это моя первая встраенная покупка - при попытке ее отправить на ревью - сайт пишет, что ее на ревью можно отправить только с приложением. Оно пока сыровато  - и я планировал его заливать чуть позже.

    В приложении пытаюсь считать этот ProductID (этой встроенной покупки) - но получаю его в списке Invalid Products. Наверное, это правильно - ведь я покупку пока не запостил дальше, ее не проапрувили итп….

     

    Как это все тестировать и что, получается надо заливать на AppStore сырую программу (в которой я даже не оттестировал этот функционал) , чтобы эта покупка "заработала", потом это все тестировать и потом снова выкладывать новый релиз?

    я правильно мысль Эпла уловил, или что-то не догоняю?

    …..

    и еще, у меня ProductID начинается с цифры - нормально ли это? сайт такое название проглотил.

    и еще! ) у меня будет пополнение счёта пользователя в Игре. что выбирать расходуемую покупку - знаю.

    консоль AppleStore Connect предлагает фиксированный выбор стоимости - те 75, 149, 229, 299, 379, 459, 529, 599, 699,749, 849,899,9991090,1150,1190,1290,1390, 1450,1490, 1590 …………….. 

    вероятно, эти цифры "танцуются" от курса рубля - 1 доллар, 2, 3...… хотя встречаются и странные цифры, которые при делении на 75 не дают близкий к целому числу результат.

    вопрос вот в чем - мне нужно будет завести , допустим 10 встренных покупок - на какую сумму пользователь хочет пополнить счёт. дальше ему их где-нить в комбо-боксе показывать, он выбирает и я совершаю покупку. я правильно мысль уловил?

    на произвольную сумму он счет увеличить не сможет. Верно? а что будет когда курс доллара поплывёт? мне вручную все это править придется?

     

    СПАСИБО ЗА ВАШИ ДЕЛЬНЫЕ СОВЕТЫ!

  2. есть теория, а есть - практика! )

    и есть вот такая жизненная ситуация! ) переписывать это не буду - оно работает!

    но шобы совсем моднявым парнем стать - готов обернуть! от меня не убудет! )))))))))

    ну серьезно - вот как в этой ситуации это лучше сделать? ) 

  3. ну если весь вот этот ужас )   (а это треть этой процедуры)  я в один TThread.Synchronize  оберну - мне это зачтётся?  )

     

    или надо идти внутрь каждой вот например из этих процедур и там это делать? все они меняют данные на формах.

        TCommand.GetMyQuests : fmQuestsEditor.LoadMyQuestsInListView(ARequest);
        TCommand.GetAllQuests : ListViewUpdate(ARequest);
        TCommand.GetQuest : fmQuestsEditor.LoadQuestData(ARequest);
        TCommand.DeleteQuest,
        TCommand.CopyQuest : if ARequest.Error then fmQuestsEditor.lbError.Text:='Connection problems... #32'{+ARequest.ErrorMsg} else fmQuestsEditor.LoadMyQuests;
        TCommand.GetQuestsPOI : GetQuestsPOI(ARequest);
        TCommand.GetPOI : GetPOI(ARequest);
        TCommand.LoadQuestLocally : LoadQuestLocally(ARequest);
        TCommand.ProcessGameData : ;                                ////////////////////////////////////
        TCommand.GetAuthorGames : fmFinance.LoadFinanceListView(ARequest);
        TCommand.GetUserMoneyRequests : fmMoneyRequest.LoadMoneyRequestListView(ARequest);
        TCommand.ProcessPaymentRequest: fmMoneyRequest.ProcessPaymentRequest(ARequest);
        TCommand.GetOpenRequests : fmOpenRequests.LoadMoneyRequestListView(ARequest);
        TCommand.ProcessOpenPaymentRequest: fmOpenRequests.ProcessOpenPaymentRequests(ARequest);
        TCommand.GetUserDetails : GetUserDetails(ARequest);

    мне конечно проще - один раз все это обернуть.

     

    procedure TfmMain.OnReceiveData(const ARequest : TRequest);
    begin
      if ARequest.Error then
        begin
          lbError.Text:='Connection problems... #32';//+ARequest.ErrorMsg;
        //    exit;
        end;

      case ARequest.Command of
        TCommand.Log :
          begin
         // Log(ARequest.Content);
          end;

        TCommand.GetMessagesFromDataBase : ;

        TCommand.GetMessages : GetMessages(ARequest);

        TCommand.AddQuestTask:
          if ARequest.Error then fmQuestsEditor.Label25.Text:='Connection problems... #32'//+ARequest.ErrorMsg
          else
            begin
              fmQuestsEditor.Label25.Text:='Задание успешно добавлено!';
              fmQuestsEditor.edTasksQty.Text:=IntToStr(StrToInt(Trim(fmQuestsEditor.edTasksQty.Text))+1);
              fmQuestsEditor.edCurrentTask.Text:=IntToStr(StrToInt(Trim(fmQuestsEditor.edCurrentTask.Text))+1);
              fmQuestsEditor.edTasksQtyChange(Self);
              fmQuestsEditor.CheckBox1.IsChecked:=False;
              fmQuestsEditor.CheckBox2.IsChecked:=False;
              fmQuestsEditor.CheckBox3.IsChecked:=False;
              fmQuestsEditor.CheckBox4.IsChecked:=False;
              fmQuestsEditor.Memo1.Text:='';
              fmQuestsEditor.Edit2.Text:='';
            end;
        TCommand.DeleteQuestTask:
          begin
            fmQuestsEditor.SpeedButton11.Enabled:=True;
            if ARequest.Error then fmQuestsEditor.Label25.Text:='Connection problems... #32'//+ARequest.ErrorMsg
            else
              begin
                fmQuestsEditor.edTasksQty.Text:=IntToStr(StrToInt(Trim(fmQuestsEditor.edTasksQty.Text))-1);
                fmQuestsEditor.edTasksQtyChange(Self);
                fmQuestsEditor.CheckBox1.IsChecked:=False;
                fmQuestsEditor.CheckBox2.IsChecked:=False;
                fmQuestsEditor.CheckBox3.IsChecked:=False;
                fmQuestsEditor.CheckBox4.IsChecked:=False;
                fmQuestsEditor.Memo1.Text:='';
                fmQuestsEditor.Edit2.Text:='';
                fmQuestsEditor.edCurrentTaskChange(Self);
                fmQuestsEditor.Label25.Text:='Задание удалено!';
              end;
          end;
        TCommand.MoveTaskToLeft:
          begin
            fmQuestsEditor.SpeedButton14.Enabled:=True;
            if ARequest.Error then fmQuestsEditor.Label25.Text:='Connection problems... #32'//+ARequest.ErrorMsg
            else
               begin
                 fmQuestsEditor.edCurrentTask.Value:=fmQuestsEditor.edCurrentTask.Value-1;
                 fmQuestsEditor.Label25.Text:='Задание перемещено!';
               end;
          end;
        TCommand.MoveTaskToRight:
          begin
            fmQuestsEditor.SpeedButton16.Enabled:=True;
            if ARequest.Error then fmQuestsEditor.Label25.Text:='Connection problems... #32'//+ARequest.ErrorMsg
            else
              begin
                fmQuestsEditor.edCurrentTask.Value:=fmQuestsEditor.edCurrentTask.Value+1;
                fmQuestsEditor.Label25.Text:='Задание перемещено!';
              end;
          end;
        TCommand.UpdateQuestTask: if ARequest.Error then fmQuestsEditor.Label25.Text:='Connection problems... #32'{+ARequest.ErrorMsg} else fmQuestsEditor.Label25.Text:='Задание сохранено!';

       // TCommand.GetQuestTask: GetQuestTask(ARequest);
        TCommand.GetQuestTask4Edit: fmQuestsEditor.LoadTaskData(ARequest);

        TCommand.GetImage :
          begin
           // Memo1.Lines.Add({GetFileNameFromRequest(}ARequest.Query{)}+'-');  ////////////////
            if Trim(GetFileNameFromRequest(ARequest.Query))='' then
              begin
                lbError.Text:='Ошибка!Некорректное имя файла #172';
                exit;
              end;

            imBuffer.Bitmap.Assign(ARequest.BitmapSurface);

            imBuffer.Bitmap.SaveToFile(TPath.Combine(TPath.GetDocumentsPath, GetFileNameFromRequest(ARequest.Query)));
            if Assigned(ARequest.BitmapSurface) then ARequest.BitmapSurface.Free;
            

            { этот код был в онлайн версии 
            imMediaFile.Bitmap.Assign(ARequest.BitmapSurface);
            imMediaFile.Visible:=True;
            if Assigned(ARequest.BitmapSurface) then ARequest.BitmapSurface.Free;}
          end;
        TCommand.GetImageWithCheck :
          begin
            fmQuestsEditor.Image1.Bitmap.Assign(ARequest.BitmapSurface);
            fmQuestsEditor.Memo1.Visible:=False;
            fmQuestsEditor.SpeedButton27.Visible:=False;
            fmQuestsEditor.Image1.Visible:=True;
            fmQuestsEditor.SpeedButton18.Visible:=True;
            if Assigned(ARequest.BitmapSurface) then ARequest.BitmapSurface.Free;
          end;
        TCommand.UpdateUser :  UpdateUser(ARequest);
        TCommand.GetTopPlayers : GetTopPlayers(ARequest);
        TCommand.AddQuest :
          begin
            fmQuestsEditor.GetQuestId(ARequest);
            fmQuestsEditor.NewQuest:=False;
            fmQuestsEditor.SpeedButton6.Enabled:=True;
          end;
     

     

     

    ….

  4. сорри, у еще один вопрос по этой теме ) 

    у меня в программе общение с сервером происходит в отдельном потоке, когда надо что-то получить - я из основного в тот (в очередь) команду с параметрами ставлю - в том потоке это обрабатывается, когда приходит ответ - вызывается событие onReceiveData, на которое я вешаю обработчик (это процедура из основной формы), в ней CASE на 100+ команд, и по каждой я вызываю какую то процедуру на какой-то из форм и она что-то там отрисовывает.

     

    мне нужно в каждой из этих процедур делать свой TThread.Synchronize - там, где я визуальные компоненты меняю, или один раз это сделать в onReceiveData, - фактически - этот CASE of ….. и вызовы 100 процедур в него поместить?

    как правильно?

  5. 2 часа назад, krapotkin сказал:

    синхронная концепция вызова и синхронизация потоков не имеют ничего общего

    то, что программа не пойдет дальше, пока не закончится POST, никак не отменяет того, что вызовы экранных компонентов должны происходить только в главном потоке

    поэтому TThread.Synchronize

    я понимаю, что учить меня Вам наверное не очень интересно, но простите меня пожалуйста и за еще один вопрос:

    а физически какая разница существует между вот таким присвоением TMemo (или любого другого визуального компонента) через TThread.Synchronize -  и простым присваиванием без него?

    что вообще на самом деле этот TThread.Synchronize делает?

     

    …..

    кстати, события этого кода происходят просто по кнопке в одной из форм приложения. это же основной поток?

  6. 7 минут назад, slav_z сказал:

    if Assigned(FHTTPClient) then FHTTPClient.Free;    замените на просто  FHTTPClient.Free

    Хорошо. ) просто я перестал писать программы на Дельфи ещё при Ельцине ) сейчас пришлось вернуться обратно. Ельцина нет, а привычки остались ) 

  7. можете кидаться в меня тухлыми помидорами, но я этот турецкий модуль на 3400 строк с амбициозными названиями SuperObject использовать не стал! )

     

    вот так код выглядит на нашем рабоче-крестьянском уровне! и он работает! )

     

      Str:=Memo1.Lines.Text;
      Str:=Str.Replace('%Amount%',IntToStr(StrToInt(Edit4.Text)*100),[rfReplaceAll]);
      Str:=Str.Replace('%OrderId%',IntToStr(OrderId));
      Str:=Str.Replace('%Email%',fmSettings.Edit5.Text,[rfReplaceAll]);
      Str:=Str.Replace('%Phone%',fmSettings.Edit4.Text,[rfReplaceAll]);


      stSrc := TStringStream.Create('', TEncoding.UTF8);
      stRes := TStringStream.Create('', TEncoding.UTF8);
      stSrc.WriteString(Str);
      stSrc.Position := 0;

      FHTTPClient:=THTTPClient.Create;

      FHTTPClient.ConnectionTimeout:=ConstHTTPClientConnectionTimeout;
      FHTTPClient.ResponseTimeout:=ConstHTTPClientResponseTimeout;
      FHTTPClient.Accept:='application/json';
      FHTTPClient.ContentType:='application/json';
      FHTTPClient.AcceptCharSet := 'UTF-8';
      FHTTPClient.HandleRedirects := false;

        try
        try
          HTTPResponse:=FHTTPClient.Post({'https://umka.space/api/index.php'}'https://securepay.tinkoff.ru/v2/Init',stSrc, stRes);
          if (HTTPResponse.StatusCode = 200) then
            begin
              Str:=stRes.DataString;
              Memo2.Lines.Text := Str;
            end
          else
            begin

            end;

        except
          Memo2.Lines.Clear;
        end;
      finally
        if Assigned(FHTTPClient) then FHTTPClient.Free;
        BytesStream.Free;
        stSrc.Free;
        stRes.Free;
      end;

      JSON:=TJSONObject(TJSONObject.ParseJSONValue(Str));

  8. Спасибо за пояснение!

    но разве из хелпа не следует, что в случае поялвения второго стрима в парамтерах POST - основной поток не будет ждать и пойдет дальше? (см текст выше. я это понял так.)

  9. 4 часа назад, krapotkin сказал:

    код приложен, запускайте и играйтесь до просветления

    можно вопрос для понимания?

    r := h.Post(URL, stSrc, stRes);
        if r.StatusCode=200 then
        begin
          x := so(stRes.DataString);
          tthread.Synchronize(nil,
            procedure
            begin
              m1.Lines.Text := x.AsJSON(True);
            end);
        end
        else
        begin
          tthread.Synchronize(nil,
            procedure
            begin
              m1.Lines.Add(r.StatusText);
            end);

     

    вот в этом коде у  POST - второй параметр. это значит, что 

    If you want to receive the response data as your HTTP client downloads it from the target server, instead of waiting for your HTTP client to download the whole data, use the AResponseContent parameter to specify a stream to receive the downloaded data. Alternatively, you can wait for your HTTP client to download the whole response data, and obtain the response data as a stream from the ContentStream property of the response object that Get returns.

    Regardless of whether you receive the data as it comes or wait for the whole data to be available, you can handle the OnReceiveData event to track the progress of the download of the response data.

     

    ….надо по окончанию загрузки  - ловить момент обработчиком на OnReceiveData. разве нет?

    как эта схема с tthread.Synchronize в данном случае работает? ВОТ ЭТОГО НЕ ПОНИМАЮ! )

     

    ……..

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

  10. 2 часа назад, krapotkin сказал:

    он не в фоне докачивается, а синхронно

    но он точно рабочий)

    а вот сам запрос сделан именно в фоне. собсно как и должно быть всегда

    просто для моего понимания. вот смотрите - человек в программе нажал на кнопку - оплатить. больше сейчас делать ему нечего.он все равно будет ждать. так ли много смысла это запускать в фоне? длится для пользователя это будет все равно одни и те же доли секунды.

  11. 48 минут назад, krapotkin сказал:

    код приложен, запускайте и играйтесь до просветления

    Спасибо Вам огромное за время и помощь!

    я сделаю, как в вашем коде.

    справедливости ради , этот Post  (с двумя стримами, из которых второй докачиватся в фоне) - это другая функция этого класса. в той есть баг. это моё мнение )

    r := h.Post(URL, stSrc, stRes);

  12. 4 минуты назад, krapotkin сказал:

    1975142031_QIPShot-Screen247.png.c9f0cd1b1d93479e6a52f4f67cd0c8e7.png httpDemo.7z 32 \u043a\u0411 · 0 загрузок

    вот демо 

    работает одинаково на Windows и Android

    на Берлине? у меня Рио.  в этом тоже может быть дело. и на Рио под ИОС-ом тоже работает. под АНдроидом - нет. может как-то изголиться и по другому из реквестконтента сгружать данные до парсера?

  13. вот эту структуру можно залить в Memo1 - тогда и менять в ней ничего не надо

    вот это не нужно:

    Str:=Str.Replace('%Amount%',IntToStr(StrToInt(Edit4.Text)*100),[rfReplaceAll]);
      Str:=Str.Replace('%OrderId%',IntToStr(OrderId));
      Str:=Str.Replace('%Email%',fmSettings.Edit5.Text,[rfReplaceAll]);
      Str:=Str.Replace('%Phone%',fmSettings.Edit4.Text,[rfReplaceAll]);


    {
        "TerminalKey": "1595881652554DEMO",
        "Amount": "140000",
        "OrderId": "2105094",
        "Description": "Подарочная карта на 1400.00 рублей",
        "DATA": {
            "Phone": "+71234567890",
            "Email": "a@test.com"
        },
        "Receipt": {
            "Email": "a@test.ru",
            "Phone": "+79031234567",
            "EmailCompany": "b@test.ru",
            "Taxation": "osn",
            "Items": [
                {
                    "Name": "Наименование товара 1",
                    "Price": 10000,
                    "Quantity": 1.00,
                    "Amount": 10000,
                    "PaymentMethod": "full_prepayment",
                    "PaymentObject": "commodity",
                    "Tax": "vat10",
                    "Ean13": "0123456789"
                },
                {
                    "Name": "Наименование товара 2",
                    "Price": 20000,
                    "Quantity": 2.00,
                    "Amount": 40000,
                    "PaymentMethod": "prepayment",
                    "PaymentObject": "service",
                    "Tax": "vat20"
                },
                {
                    "Name": "Наименование товара 3",
                    "Price": 30000,
                    "Quantity": 3.00,
                    "Amount": 90000,
                    "Tax": "vat10"
                }
            ]
        }
    }
     

  14. 4 минуты назад, krapotkin сказал:

    не работает же конкретный кусок

    его можно вынести в отдельный проект или просто кинуть кусок кода, там же один код, компоненты не требуются. нужен только URL и все собсно

      Str:=Memo1.Lines.Text;
      Str:=Str.Replace('%Amount%',IntToStr(StrToInt(Edit4.Text)*100),[rfReplaceAll]);
      Str:=Str.Replace('%OrderId%',IntToStr(OrderId));
      Str:=Str.Replace('%Email%',fmSettings.Edit5.Text,[rfReplaceAll]);
      Str:=Str.Replace('%Phone%',fmSettings.Edit4.Text,[rfReplaceAll]);


      BytesStream:=TBytesStream.Create(TEncoding.UTF8.GetBytes(Str));

      FHTTPClient:=THTTPClient.Create;
      FHTTPClient.ConnectionTimeout:=ConstHTTPClientConnectionTimeout;
      FHTTPClient.ResponseTimeout:=ConstHTTPClientResponseTimeout;
      FHTTPClient.UserAgent:='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';
      FHTTPClient.Accept:='application/json';
      FHTTPClient.AcceptEncoding:='gzip, deflate';
      FHTTPClient.AcceptLanguage:='ru,en-US;q=0.8,en;q=0.6';
      FHTTPClient.ContentType:='application/json';
      FHTTPClient.AcceptCharSet := 'UTF-8';

        try
        try
          HTTPResponse:=FHTTPClient.Post({'https://umka.space/api/index.php'}'https://securepay.tinkoff.ru/v2/Init', BytesStream);
          if Assigned(HTTPResponse) and (HTTPResponse.StatusCode = 200) then
            begin
              if Assigned(HTTPResponse.ContentStream) then Memo2.Lines.LoadFromStream(HTTPResponse.ContentStream)
              else Memo2.Lines.Clear;
            end
          else
            begin
              lbError.Text:='Connection problems... #380 '+IntToStr(HTTPResponse.StatusCode);
              AniIndicator1.Visible:=False;
              AniIndicator1.Enabled:=False;
              exit;
            end;

        except
          Memo2.Lines.Clear;
        end;
      finally
        if Assigned(FHTTPClient) then FHTTPClient.Free;
        BytesStream.Free;
      end;

      //Memo2.Lines.LoadFromStream(HTTPResponse.ContentStream);

      JSON:=TJSONObject(TJSONObject.ParseJSONValue(Memo2.Lines.Text));

      if not JSON.TryGetValue('Success', Success) then
        begin
          lbError.Text:='Connection problems... #382';
          AniIndicator1.Visible:=False;
          AniIndicator1.Enabled:=False;
          exit;
        end;

  15. 1 минуту назад, krapotkin сказал:

    приложите мин пример, или если приватные данные, в личку,  могу запустить на Android

    а что имеется ввиду - форма с кодом?

    весь проект очень большой. или просто кусок кода?

  16. 10 минут назад, krapotkin сказал:

    упс, опечатался, AcceptCharset конечно

    но тут есть нюансы

    поэтому я спрашиваю именно что реально приходит на сервер а не что настроено при отправке

    иногда это не одно и то же. я тоже долго разбирался с этой проблемой и там много всяких нюансов бывает.

    В последний раз убил два дня, чтобы понять, что реальный сервер делает redirect а по стандарту Delphi делает POST редирект как GET. И это все портило.

    Пришлось подкрутить немного...

        [Host] => umka.space
        [Port] => 443
        [X-Forwarded-For] => 31.173.84.116
        [X-Real-IP] => 31.173.84.116
        [X-Forwarded-Port] => 443
        [X-MH-Host] => umka.space
        [Content-Length] => 760
        [Accept-Language] => ru,en-US;q=0.8,en;q=0.6
        [Accept-Encoding] => gzip, deflate
        [Accept] => application/json
        [Content-Type] => application/json
        [User-Agent] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586
        [Accept-Charset] => UTF-8
    FHTTPClient.Accept:='application/json' оставил только это - выше заголовки уже то, что получается после после этого изменения)

  17. 1 минуту назад, krapotkin сказал:

    кстати, требуется же ответ сервера JSON ? тогда

    FHTTPClient.Accept:='application/json'

    а если он там среди прочих перечислен  - могут быть проблемы?

    (сейчас заголовки подкручу)

     

    Спасибо Вам за помощь!

  18. 2 минуты назад, krapotkin сказал:

    А покажите заголовки, которые приходят вместе с вашим запросом на сервер ?

    Судя по ошибке, сервер отвечает вам не в кодировке UTF8.

    За это отвечает AcceptEncoding

    httpclient я настраиваю так:  

    FHTTPClient:=THTTPClient.Create;
      FHTTPClient.ConnectionTimeout:=ConstHTTPClientConnectionTimeout;
      FHTTPClient.ResponseTimeout:=ConstHTTPClientResponseTimeout;
      FHTTPClient.UserAgent:='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';
      FHTTPClient.Accept:='text/html,application/json,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
      FHTTPClient.AcceptEncoding:='gzip, deflate';
      FHTTPClient.AcceptLanguage:='ru,en-US;q=0.8,en;q=0.6';
      FHTTPClient.ContentType:='application/json';
      FHTTPClient.AcceptCharSet := 'UTF-8';

    а как смотреть на сервере эти заголовки? я в php тоже не силён. (

  19. ...или как это можно из HTTPResponse.ContentStream скгружать ParseJSONValue для парсинга минуя ТМемо?

    там вот такие типы допускаются:

    class function ParseJSONValue(const Data: PByte; const Offset: Integer; const ALength: Integer; Options: TJSONParseOptions): TJSONValue; overload; static;
    class function ParseJSONValue(const Data: TArray<Byte>; const Offset: Integer; IsUTF8: Boolean = True): TJSONValue; overload; inline; static;
    class function ParseJSONValue(const Data: TArray<Byte>; const Offset: Integer; Options: TJSONParseOptions): TJSONValue; overload; inline; static;
    class function ParseJSONValue(const Data: TArray<Byte>; const Offset: Integer; const ALength: Integer; IsUTF8: Boolean = True): TJSONValue; overload; inline; static;
    class function ParseJSONValue(const Data: TArray<Byte>; const Offset: Integer; const ALength: Integer; Options: TJSONParseOptions): TJSONValue; overload; inline; static;
    class function ParseJSONValue(const Data: string; UseBool: Boolean = False; RaiseExc: Boolean = False): TJSONValue; overload; static;
    class function ParseJSONValue(const Data: UTF8String; UseBool: Boolean = False; RaiseExc: Boolean = False): TJSONValue; overload; static

     

    возможно имеет смысл как-то байтами это передать, по аналогии, как туда запрос формировали. я не очень силен в этих новомодных штучках, - как это можно сделать альтернативным образом?

  20. 11 часов назад, krapotkin сказал:

    да что это за таинственные структуры, что так сложны? какой размер полученного JSON ?

    если бы все было так печально, то форумы бы ломились от одинаковых тем, но ведь не видно такого

    хотя родные либы json мне не нравится, я пользуюсь XSuperObject, но они 100% рабочие

    проблема 100% в коде

    Добрый день! читаю периодически Ваши сообщения, знаю Вас, как человека  очень грамотного, поэтому слова эти меня зацепили.... )))

    и сделал я вот что:

    встал в 5 утра ж))), залез на свой сервер, на php написал небольшую заглушку ловить такие POST-ы.

    Запустил Дельфи. Теперь в сухом остатке:

     

    (в Мемо1.Lines - json структура)

     

    Код:

    HTTPResponse:=FHTTPClient.Post('https://umka.space/api/index.php'{'https://securepay.tinkoff.ru/v2/Init'}, Memo1.Lines);

    НЕ РАБОТАЕТ ни на Иосе, ни на Андроиде - на сервер вообще никто по посту не стучится...

    хотя вот как выглядит в хелпе описание этой функции - передавать TStrings - можно!

    function Post(const AURL: string; const ASourceFile: string; const AResponseContent: TStream = nil; const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    function Post(const AURL: string; const ASource: TStrings; const AResponseContent: TStream = nil;  const AEncoding: TEncoding = nil; const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    function Post(const AURL: string; const ASource: TStream; const AResponseContent: TStream = nil;  const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    function Post(const AURL: string; const ASource: TMultipartFormData; const AResponseContent: TStream = nil;  const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;
    

     

     

    Код:

    BytesStream:=TBytesStream.Create(TEncoding.UTF8.GetBytes(Memo1.Lines.Text));

    HTTPResponse:=FHTTPClient.Post('https://umka.space/api/index.php'{'https://securepay.tinkoff.ru/v2/Init'}, BytesStream);

    работает и на иосе и на андроиде - в логе сервера в обоих случаях появяется моя структура - в том виде в котором надо.

    вывод функция Post, которая получает TStrings - хреновая.

     

    но это пол беды - эта проблема как раз решена! теперь вторая часть - то что не решено -

    когда POST сгружает ответный json, котрый прислали в ответ на мой запрос в HTTPResponse.ContentStream

    (это продолжение этого же кода)

    if Assigned(HTTPResponse) and (HTTPResponse.StatusCode = 200) then
            begin
               Memo2.Lines.LoadFromStream(HTTPResponse.ContentStream)

               JSON:=TJSONObject(TJSONObject.ParseJSONValue(Memo2.Lines.Text))
            end

     

     

    то на иосе в Мемо2 сгружается хороший json и он замечательно потом распарсивается в следующей строчке.

    а вот под андроидом в ContentStream образуется какой-то мусор с периодически встречающимися словами "TMemoryStream". попыка его даже загрузить в Мемо часто приводит к эксепшену "No mapping for the Unicode character exists in target multi-bytecode page".

    под иосом и андроидом это происходит на одном и том же коде - при одинаковых вводных параметрах. верьте мне! )

     

    ВЫВОД - или функция битая, или json ломается при заливании в TMemo.

    Дайте пожалуйста совет - как это можно быстро исправить. полтора дня потерял. (

    другие компоненты? есть что-то бесплатное на примете? в инди вроде есть свой аналогичный httpclient….. но я им никогда не пользовался. 

    все это происходит под 10.3.3 Rio Community Edition.

     

    СПАСИБО! )

  21. Наткнулся сегодня на продолжение этой истории - код, который предложили вчера - работает под иосом, но не работает под андроидом. Даже нетронутый ран-тайм Мемо - при такой конвертации в Bytes и ещё до отправки На сервер в json не распаковывается. Сервер соответственно его тоже не понимает. Ручками такую структуру городить как объект Джейсона рантайм геморроидально  - структура большая. Поэтому я ее сейчас в виде болванки гружу в мемо текстом, и в ходе работы replace-ом меняю в теле параметры - вместо %идентификатор% в болванку подставляю значение. Может подскажите идею - как это можно сделать ещё, чтобы на эти грабли не налетать? Те - тут и до отправки на внешний сервер понятно, что что-то ломается, тк

    son:=TJSONObject.ParseJSONValue(Bytes, 0);
    ... под андроидом даже из девственной болванки нормально считать json не может. 
    под иосом этот же код работает.

×
×
  • Создать...