PagSeguro integration - brazilian market means of payment

Hello,

I’m having a hard time trying to develop a payment tool for PagSeguro, one of the leading payment platforms in Brazil.

Their documentation says the app should POST to a specific endpoint with some parameters. That can be done with HTTPSecureSocket. Problem is the response I get is:

[code]HTTP Status 406 - No match for accept header

type Status report

message No match for accept header

description The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request “accept” headers (No match for accept header).[/code]

I believe the Header settings of the request seems to be ok.

Is there something I’m missing in my code below?

Public Sub Get_Sale_ID()

Dim mylink As String = "https://ws.sandbox.pagseguro.uol.com.br/v2/sessions"
Dim dadosform As New Dictionary

dadosform.Value("appID") = "zepipayer"
dadosform.Value("appKey") = "5863542E0A0A90B77499EF9E6F80CACD" 

Dim buscador As New HTTPSecureSocket

buscador.requestHeaders.DeleteAllHeaders

buscador.requestHeaders.AppendHeader("Content-Type", "application/json;charset=ISO-8859-1")
buscador.requestHeaders.AppendHeader("Accept", "application/vnd.pagseguro.com.br.v3+json;charset=ISO-8859-1")
buscador.requestHeaders.AppendHeader("Accept-Language", "utf-8, iso-8859-1;q=0.5, *;q=0.1")
buscador.requestHeaders.AppendHeader("Accept-Charset", "iso-8859-1")
  
buscador.SetFormData(dadosform)

buscador.Secure = True
buscador.ConnectionType = HTTPSecureSocket.TLSv1

AddHandler buscador.PageReceived, WeakAddressOf Recebido_Secure

buscador.Post(mylink)

End Sub

This is their documentation page:

https://devs.pagseguro.uol.com.br/docs/pagamento-recorrente-endpoints-da-api

This is what I have for receiving data from the webpage:

Public Sub Recebido_Secure(sender As HTTPSecureSocket, s1 As String, i1 As Integer, ih As InternetHeaders, s2 As String)
  dim dt As New Date
  
  TextArea1.Text = ""
  
  TextArea1.AppendText "RECEIVED " + dt.SQLDateTime + " " + EndOfLine
  
  TextArea1.AppendText Str(sender.ErrorCode) + EndOfLine
  TextArea1.AppendText s1 + EndOfLine
  TextArea1.AppendText str(i1) + EndOfLine
  
  HTMLViewer1.LoadPage(s2)
  
End Sub

Thanks in advance! Any help is welcome…

HTTP 406 Not Acceptable - The server isn’t able to produce a response that you can accept.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406

This is happening because you are defining the language and charset that you can accept as something other than what the server is willing or able to send.

Good to understand.

Figuring out how to solve that. Already filed a complaint to the supplier. I’m following exactly the ‘Accept’ parameter explained in the documentation, but keep getting error 406. So frustrating…

Accept: application/vnd.pagseguro.com.br.v3+json;charset=ISO-8859-1

or

Accept: application/vnd.pagseguro.com.br.v3+xml;charset=ISO-8859-1

Are those lines requested to be there?

buscador.requestHeaders.AppendHeader(“Accept-Language”, “utf-8, iso-8859-1;q=0.5, *;q=0.1”)
buscador.requestHeaders.AppendHeader(“Accept-Charset”, “iso-8859-1”)

Is the communication guaranteed to be coded as iso-8859-1 instead of usual Xojo utf-8 ?

Not sure. This is what the supplier tells about the server side.

I’m pretty sure this line is malformed:

buscador.requestHeaders.AppendHeader(“Accept-Language”, “utf-8, iso-8859-1;q=0.5, *;q=0.1”)

utf and iso are charsets, not languages.

I got past the first issue… PagSeguro will return a valid ID at each request!

I had to change the way the “Sale ID” is fetched. Adapted some PHP code from here: https://github.com/atailton/pagseguro

Instead of using appID and appKey, I’m using the simpler approach of using email and token to retrieve the ID from PagSeguro.

Another change is in the Contet-Type, which now is application/x-www-form-urlencoded; charset=ISO-8859-1.

The method to retrieve an ID from PagSeguro became like this (I cleaned up the code a little bit for clarity):

Public Sub Get_Sale_ID()

Dim dadosform As New Dictionary

dadosform.Value("email") = "myregisteredemail@pagseguro.com.br"
dadosform.Value("token") = "my32characterlengthttokenatpagseguro"

Dim buscador As New HTTPSecureSocket

buscador.requestHeaders.DeleteAllHeaders
buscador.requestHeaders.AppendHeader("Content-Type", "application/x-www-form-urlencoded; charset=ISO-8859-1")
buscador.Secure = True
buscador.ConnectionType = HTTPSecureSocket.TLSv1

AddHandler buscador.PageReceived, WeakAddressOf Recebido_Secure

buscador.Post("https://ws.sandbox.pagseguro.uol.com.br/v2/sessions")
End Sub

I’m facing another issue now…

In order for the payment tool to work, it is needed to use some javascript. I chosed to use a webcontrolwrapper to do that.

I followed the Web Control SDK manual. I have already successfully developed one of these webcontrols by myself previously.

Unfortunately when I try to run the thing for PagSeguro, I get this javascript error message:

Could not execute returned javascript: SetSession is not defined Source: SetSession('9cc1c88f0e41452b8e3b8ac842ea7762', 'cNrZPj5K'); Xojo.comm.ajax.begin();

First parameter is the “Sale ID” I fought for in the first post. Second is the ControlID in the webpage.

Why it says ‘SetSession’ is not defined?

I believe I did it correctly, declaring it on the ‘HTMLHeader’ Shared Method of the wrapper:

[code]Public Shared Function HTMLHeader(CurrentSession as WebSession) as String
If Not IsLibraryRegistered(CurrentSession, JavascriptNamespace, “PagSeguro”) Then
RegisterLibrary(CurrentSession, JavascriptNamespace, “PagSeguro”)
Dim sa() As String

sa.Append "<script src=""https://stc.pagseguro.uol.com.br/pagseguro/api/v2/checkout/pagseguro.directpayment.js""></script>"
sa.Append "<script>"
sa.Append a_SetSession
sa.Append a_GeraIDUsuario
sa.Append a_BuscaBandeira
sa.Append a_Parcelamento
sa.Append a_CriaToken
sa.Append a_ListaMeiosDisponiveis
sa.Append "</script>"

Dim kp As String
kp = Join(sa, EndOfLine.UNIX)

Return join(sa,EndOfLine.UNIX)

End If
End Function
[/code]

a_SetSession, a_GeraIDUsuario, a_BuscaBandeira, a_Parcelamento, a_CriaToken and a_ListaMeiosDisponiveis are constants containing the function definitions. Variable ‘kp’, used for debugging, aggregates them all and reads like this:

[code]

[/code]

The Event Definitions required by ‘Xojo.triggerServerEvent’ are properly defined.

What am I missing? I can’t make sure the javascript is perfect. Is that it? Anything else?

I’m really interested (and committed to) in finishing this for my own purposes and also to post it as a working solution here or even at github. Maybe I can save someone the hard time (and some fun) I’m having with this…

I’m making progress…

Apparently the issue was here:

[code]Public Shared Function HTMLHeader(CurrentSession as WebSession) as String
If Not IsLibraryRegistered(CurrentSession, JavascriptNamespace, “PagSeguroDirectPayment”) Then
RegisterLibrary(CurrentSession, JavascriptNamespace, “PagSeguroDirectPayment”)
Dim sa() As String

sa.Append "<script src=""https://stc.pagseguro.uol.com.br/pagseguro/api/v2/checkout/pagseguro.directpayment.js""></script>"
sa.Append "<script>"
sa.Append a_SetSession
sa.Append a_GeraIDUsuario
sa.Append a_BuscaBandeira
sa.Append a_Parcelamento
sa.Append a_CriaToken
sa.Append a_ListaMeiosDisponiveis
sa.Append "</script>"
  
Return join(sa,EndOfLine.UNIX)

End If
End Function
[/code]

The javascript library name is “PagSeguroDirectPayment” instead of “PagSeguro” as initially posted.

I’ll keep going. As soon as I have a working solution I’ll post back.

Hello,

Here is a first attempt at making this PagSeguro payment to work.

https://github.com/LeonidasBrasileiro/XojoPagSeguro.git

I have used a webcontrolwrapper for the javascript part and embedded it on a ContainerControl, which also encapsulates everything needed for the payments (credit card data, buyer’s data, …). In order to show the project, I made a shopping cart so people can add products to it and simulate a purchase.

In order for it to work, it is needed a PagSeguro account. I suggest a ‘sandbox’ account, which was what I used, with all configurations made at their portal (email, token, etc.).

The sample app works but has some flaws I’m working on. Any suggestions/improvements are welcome.

In order to work, you need to adapt some ‘PagSeguro_’ constants at the Session object and place an instance of the ‘Pagador’ control on a page. I think the sample app is good enough to show how it works.

Next Steps:

For a real world application, I will remove all the ‘Pag_Seguro_’ Constants and set them on a separate text file on the server, so they can be loaded as properties whenever a new session starts. I can even (maybe) use a SQLite database to store these values for improved security.

Another improvement to be made is using a database for handling values stored in the Session.saleitem dictionary.

I couldn’t figure how to solve an annoying issue of the app: It will not allow a new purchase after completing one and going back to the shopping cart page.

Code and Interface mixes english and portuguese expressions. Sorry for that.