Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Paypal JS SDK API
#1
Hi at all,
i have integrated paypal javascript api in intraweb and this is the code on OnApprove Payment

onApprove: function(data, actions) {    ' + sLineBreak +
                '  $.busyLoadSetup({ fontawesome: "fa fa-spinner fa-spin fa-5x fa-fw" }); $.busyLoadFull("show"); ' + sLineBreak +
                '  return actions.order.capture().then(function(orderData) {  ' + sLineBreak +
                '  // dettaglio di risposta ' + sLineBreak +
                '    addHiddenInput("JSONRESPONSE",JSON.stringify(orderData, null, 2));    ' + sLineBreak +
                '    ajaxCall("JsonPayPalResponse","&TipoAbbonamento='+ TipoAbbonamento.ToString +'",false); //abbonamento personale ' + sLineBreak +
                '    });                  ' + sLineBreak +
                '  },  ' + sLineBreak +


(AggiungiLog add log a table to get state of payment)
I use an hidden input to capture json and then i pass it to callback.
I use 2 callback 1 is

procedure TBSNuovoPagamentoPaypalForm.JsonPayPalResponse(EventParams: TStringList);
var
  js      : string;
  TipoAbb : string;
  dm      : TMod1;
  jsCall  : string;
begin
  TipoAbb := EventParams.Values['TipoAbbonamento'];
  //salvo il log della response
 
  js := Format('addHiddenInput("%s",%s);', ['JSONTOELAB', 'document.getElementsByName("JSONRESPONSE")[0].value']);
  jsCall := ' ajaxCall("ElaboraPagamentiDaJson","&TipoAbbonamento='+TipoAbb+'",false);';
  js := js + jsCall;
  //cambiato su un'unica chiamata
  WebApplication.CallBackResponse.AddJavaScriptToExecuteAsCDATA(js);
end;


and the other is to get the hidden input value

procedure TBSNuovoPagamentoPaypalForm.ElaboraPagamentiDaJson(EventParams: TStringList);
var
  JSonProcess              : string;
  TipoPagamento            : string;
  JSonObject              : TJSONObject;
  JSonValueCompleted      : TJSonValue;
  JSonValueId              : TJSonValue;
  Abbonamento              : string;
  dm                      : TMod1;
begin
  JSonProcess := EventParams.Values['JSONTOELAB'];
  TipoPagamento := EventParams.Values['TipoAbbonamento'];
  JSonObject := nil;
  dm := LockDataModule();
  try
    dm.AggiungiLog('Risposta json server paypal',Copy(JSonProcess,1,3000));
    JSonObject := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(JSonProcess), 0) as TJSONObject;

    if JSonObject = nil then
    begin
      WebApplication.ShowMessage('Errore nella decodifica di risposta del server Paypal.com');
      dm.AggiungiLog('Errore decodifica json paypal','ElaboraPagamentiDaJson JSonObject nil');
      Exit;
    end;

    JSonValueCompleted := JSonObject.GetValue('status');
    JSonValueId := JSonObject.GetValue('id');
    if (UpperCase(JSonValueCompleted.Value) = 'COMPLETED') and (JSonValueId.Value <> '')  then
    begin
      //pagamento completato e posso procedere con generazione fattura e abilitazione utente
      IWTimer1.ExtraTagParams.AddPair('TipoAbbonamento',TipoPagamento);
      IWTimer1.ExtraTagParams.AddPair('IDPAGAMENTO',JSonValueId.Value);
      if TipoPagamento = CODABBINPS.ToString then //per abbonamento comunicazioni inps.
        IWTimer1.ExtraTagParams.AddPair('Datore',CodDatore.ToString);
      BSDialogoAttesa.ModalVisible := True;
      IWTimer1.Enabled := True;
    end;

  finally
    if Assigned(JSonObject) then
      JSonObject.Free;
    UnlockDataModule(dm);
    WebApplication.CallBackResponse.AddJavaScriptToExecute('$.busyLoadFull("hide");');
  end;
end;

with JavaScript do // creo hidden input per il ritorno del valore funzione javascript
begin
    Add('function addHiddenInput(aName,aValue) {');
    Add('  var frm = $(getSubmitForm());');
    Add('  if (!frm.length) return false;');
    Add('  var hid = frm.find("input[name=\"" + aName + "\"]");');
    Add('  if (!hid.length) {');
    Add('    hid = $("<input type=\"hidden\" name =\"" + aName + "\">");');
    Add('    frm.append(hid);');
    Add('  }');
    Add('  hid.val(aValue);');
    Add('  AddChangedControl(aName);');
    Add('}');
    Add('');
 end;

Then the timer excute code to activate the service to user with a busy modal dialog 

Sometimes callback JsonPayPalResponse does not fire. In paypal i have the payment in status complete and response ok but in the OnApprove can't fire the callback to activate the service for the user.
In sandbox and test case i can't reproduce the issue but some user can't activate. I open a ticket on paypal and the order is correctly captured with json response ok.
The calls to paypal are javascript based on documentation that you can find here https://developer.paypal.com/sdk/js/configuration/

Is the right way to process jSon that come from paypal onApprove callback?

Thank you

Andrea
Reply
#2
Sorry for the late reply, somehow I missed this.

It's hard to know what's going on because it is kind of complicate to figure out from the code only...

Why are you using the hidden input to pass the data to the callback? Can't you pass the string directly to it?

What caught my eye is this piece of Javascript code:

' addHiddenInput("JSONRESPONSE",JSON.stringify(orderData, null, 2)); ' + sLineBreak +
' ajaxCall("JsonPayPalResponse","&TipoAbbonamento='+ TipoAbbonamento.ToString +'",false); //abbonamento personale ' + sLineBreak +
' }); ' + sLineBreak +

addHiddenInput changes the DOM and ajaxCall() fires directly. As you mentioned above, seems that the ajaxCall needs the hidden input, is that so?

From my experience when adding nodes to the DOM sometimes code that runs immediately after that may or may not perceive the new node.

Is like the browser effectively updates the DOM tree only after calling the ajaxCall() line (it's like they were executed out of order).

I would start trying to call the ajaxCall() from inside a setTimeout call, something like:

setTimeout(function(){ajaxCall(bla bla bla)}, 10);

and see how it goes.
Reply
#3
(05-27-2022, 03:00 AM)Alexandre Machado Wrote: Sorry for the late reply, somehow I missed this.

It's hard to know what's going on because it is kind of complicate to figure out from the code only...

Why are you using the hidden input to pass the data to the callback? Can't you pass the string directly to it?

What caught my eye is this piece of Javascript code:

                '    addHiddenInput("JSONRESPONSE",JSON.stringify(orderData, null, 2));    ' + sLineBreak +
                '    ajaxCall("JsonPayPalResponse","&TipoAbbonamento='+ TipoAbbonamento.ToString +'",false); //abbonamento personale ' + sLineBreak +
                '    });                  ' + sLineBreak +

addHiddenInput changes the DOM and ajaxCall() fires directly. As you mentioned above, seems that the ajaxCall needs the hidden input, is that so?

From my experience when adding nodes to the DOM sometimes code that runs immediately after that may or may not perceive the new node.

Is like the browser effectively updates the DOM tree only after calling the ajaxCall() line (it's like they were executed out of order).

I would start trying to call the ajaxCall() from inside a setTimeout call, something like:

setTimeout(function(){ajaxCall(bla bla bla)}, 10);

and see how it goes.
Hi Alexandre thank you for response. I think hidden input is more clean. If i pass from server a long string in isapi i coulb be generate an error on lenght of string that for security reason it could be short. Ok i can pass the call in a settimeout function. The problem is that happens something in particolar condition.
Very hard to find
Andrea
Reply
#4
(05-27-2022, 03:00 AM)Alexandre Machado Wrote: Sorry for the late reply, somehow I missed this.

It's hard to know what's going on because it is kind of complicate to figure out from the code only...

Why are you using the hidden input to pass the data to the callback? Can't you pass the string directly to it?

What caught my eye is this piece of Javascript code:

                '    addHiddenInput("JSONRESPONSE",JSON.stringify(orderData, null, 2));    ' + sLineBreak +
                '    ajaxCall("JsonPayPalResponse","&TipoAbbonamento='+ TipoAbbonamento.ToString +'",false); //abbonamento personale ' + sLineBreak +
                '    });                  ' + sLineBreak +

addHiddenInput changes the DOM and ajaxCall() fires directly. As you mentioned above, seems that the ajaxCall needs the hidden input, is that so?

From my experience when adding nodes to the DOM sometimes code that runs immediately after that may or may not perceive the new node.

Is like the browser effectively updates the DOM tree only after calling the ajaxCall() line (it's like they were executed out of order).

I would start trying to call the ajaxCall() from inside a setTimeout call, something like:

setTimeout(function(){ajaxCall(bla bla bla)}, 10);

and see how it goes.
Hi Alexandre,
i set the timeout like you suggest, but i have the same problem. Sometimes the callback does not fire. Can i share the code with you to have any suggestion?

Thank you
Andrea
Reply
#5
Yes, sure, feel free to send it via email if you find appropriate.
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)