提取GWT服务的结果

时间:2011-05-19 18:11:05

标签: java gwt-rpc google-checkout protocol-buffers

凌乱,复杂的问题,但这里有。我正在与Google Checkout合作开发一个集成项目,并且有一个Google Checkout GWT服务可以返回Checkout网络界面用于将美元转换为本地货币的货币转换率。这个端点托管在https://market.android.com/publish/gwt/,并且盯着Firebug我看到它进入服务器:

7|0|6|https://market.android.com/publish/gwt/|FCCA4108CB89BFC2FEC78BA7363D4AF6|com.google.wireless.android.vending.developer.

shared.MerchantService|getCurrencyExchangeRates|com.google.common.money.CurrencyCode/112449834|java.util.ArrayList/4159755760

|1|2|3|4|2|5|6|5|235|6|13|5|18|5|81|5|53|5|72|5|102|5|121|5|177|5|175|5|205|5|204|5|55|5|86|-1|

并且返回

//OK[235,3,'D0JA',2,86,3,'CXXg',2,55,3,'DW2A',2,204,3,'X9NA',2,205,3,'EuvA',2,175,3,'VIig',2,177,3,'E2Dw',2,121,3,'E4ziA',2,1

02,3,'do$Q',2,72,3,'T82w',2,53,3,'Ds0Q',2,81,3,'Cq5g',2,18,3,'Dlfg',2,13,1,["com.google.common.collect.RegularImmutableList/4

40499227","com.google.common.money.SimpleMoney/627983206","com.google.common.money.CurrencyCode/112449834"],0,7]

原谅奇怪的格式:无法让代码块正确格式化。

漫游网络数小时我能够确定RegularImmutableList类在Guava库中(http://code.google.com/p/guava-libraries/)。我正在寻找的是:

  1. 我无法在任何地方找到com.google.common.money.SimpleMoneycom.google.common.money.CurrencyCode课程:有人见过他们吗?
  2. GWT有线格式似乎是一个奇怪的JSON字符串。我看到Google Groups消息的各种引用都在谈论有线格式的描述,但找不到底层消息或任何连贯的引用,这些都可以让我反驳这一点:任何人都有一个方便的引用句柄?如果我至少可以理解编码是什么,我可以在没有上述问题1的类文件的情况下逃脱。
  3. 我开始在http://code.google.com/p/android-market-api/浏览Android Market api库,认为他们必须完成一些Android Market通信集成,他们似乎已经使用protobufs这样做了。 GWT / protobufs通信位是否有任何不错的参考?
  4. 这种疯狂的根本原因是我需要能够从Google Checkout获取常规汇率值,所以当我以外币进口销售交易时,我可以按照当时的现行汇率进行转换。交易。目前的Checkout报告格式不提供此功能,因此大多数人最终会使用与Google使用的不同的替代汇率来源。这显然是Google Checkout集成界面的一个缺点,但如果我们开始了解Google Checkout界面的缺点,我们整个星期都会在这里。我的目的是在Checkout界面上查询新履行的订单,然后请求相应的汇率表,以便我可以近乎实时地了解收到的付款是什么。我已经把轮询比特调低了,但不能完全超过汇率位。

3 个答案:

答案 0 :(得分:1)

在尝试创建脚本以批量上传我的应用程序的应用程序内产品时(CSV上传经常失败并显示错误的错误消息),我已成功理解了GWT AJAX协议。

它实际上很简单,除了它要求你知道所有使用的类的结构。或者猜测,就像谷歌使用的内部类一样。 :)

我将使用问题中的示例来详细解释协议。


请求格式

7|0|6|https://market.android.com/publish/gwt/|FCCA4108CB89BFC2FEC78BA7363D4AF6|com.google.wireless.android.vending.developer.shared.MerchantService|getCurrencyExchangeRates|com.google.common.money.CurrencyCode/112449834|java.util.ArrayList/4159755760|1|2|3|4|2|5|6|5|235|6|13|5|18|5|81|5|53|5|72|5|102|5|121|5|177|5|175|5|205|5|204|5|55|5|86|-1|

请求是以竖线分隔的标记列表,具有以下含义:

  1. 7 - 协议版
  2. 0 - 标志。 1 FLAG_ELIDE_TYPE_NAMES 2 FLAG_RPC_TOKEN_INCLUDED
  3. 6 - 字符串令牌计数
  4. 6个字符串代币:
    1. https://market.android.com/publish/gwt/
    2. FCCA4108CB89BFC2FEC78BA7363D4AF6
    3. com.google.wireless.android.vending.developer.shared.MerchantService
    4. getCurrencyExchangeRates
    5. com.google.common.money.CurrencyCode/112449834
    6. java.util.ArrayList/4159755760
  5. 实际编码请求,它使用基于1的索引从上面的列表中引用字符串:
    1. 1 - https://market.android.com/publish/gwt/ - 基本网址
    2. 2 - FCCA4108CB89BFC2FEC78BA7363D4AF6 - 一些哈希值,在GWT来源中引用为serializationPolicyStrongName
    3. 3 - com.google.wireless.android.vending.developer.shared.MerchantService - 服务名称
    4. 4 - getCurrencyExchangeRates - 方法名称
    5. 2 - 参数计数。参数类型如下:
      1. 5 - com.google.common.money.CurrencyCode/112449834
      2. 6 - java.util.ArrayList/4159755760
    6. 序列化参数。每个对象由其类名和序列化字段列表表示,或者由对前面遇到的对象的负整数反向引用表示。在我们的例子中,我们有两个对象:
      1. 5 - com.google.common.money.CurrencyCode/112449834,只有一个整数字段: 235
      2. 6 - java.util.ArrayList/4159755760,其中有一个整数字段 13 ,后跟13个序列化列表项。请注意,其中12个是CurrencyCode对象序列化的,就像上面的那个一样,最后一个是对我们遇到的第一个对象(反序列化)的反向引用( -1 )此请求,即CurrencyCode(235)

  6. 响应格式

    //OK[235,3,'D0JA',2,86,3,'CXXg',2,55,3,'DW2A',2,204,3,'X9NA',2,205,3,'EuvA',2,175,3,'VIig',2,177,3,'E2Dw',2,121,3,'E4ziA',2,102,3,'do$Q',2,72,3,'T82w',2,53,3,'Ds0Q',2,81,3,'Cq5g',2,18,3,'Dlfg',2,13,1,["com.google.common.collect.RegularImmutableList/440499227","com.google.common.money.SimpleMoney/627983206","com.google.common.money.CurrencyCode/112449834"],0,7]
    

    响应在格式上与请求非常相似,除了它是JS格式的数组(虽然不是JSON,因为它使用无效的单引号),而且的顺序相反。 字段含义如下:

    1. 7 - 协议版
    2. 0 - 标记,与请求相同
    3. 字符串标记数组:
      1. com.google.common.collect.RegularImmutableList/440499227
      2. com.google.common.money.SimpleMoney/627983206
      3. com.google.common.money.CurrencyCode/112449834
    4. 然后使用一个整数长度字段 13 1 - com.google.common.collect.RegularImmutableList/440499227类型的序列化对象,接着是13个 2类的序列化对象 - com.google.common.money.SimpleMoney/627983206。每个SimpleMoney对象都有两个字段,例如:
      1. 'Dlfg' - 编码为base64编号的长整数字段。这个特别的 940000
      2. 3,18 - CurrencyCode具有整数字段的对象 18

答案 1 :(得分:0)

您正在研究的是GWT-RPC序列化格式。不幸的是,它没有公开记录。 Fortunatelly GWT是开源的,因此您可以查看源代码以了解它是如何生成的。

注意:此格式可能会在GWT版本之间发生变化(我在2.2中已知过)。这最有可能也是谷歌没有记录的原因 - 如果他们这样做,他们需要保持向后兼容。

  1. 您看到的类名是Google Checkout内部使用的Java类。当GWT编译为JS时,名称会被破坏,因此您不再看到它们。
  2. 如上所述,这是GWT-RPC。
  3. 您要做的是对Google内部API进行逆向工程。我不会那样做因为,a。它可能会更改,恕不另行通知,打破您的应用程序,b。我确定Goog不喜欢它,它可能违反了服务协议(你读过它吗?)。

答案 2 :(得分:0)

我有一些用VB编写的代码,可能对你有用,可以实现如何解析GWT Serialized字符串。 “Datos”包含您收到的字符串。

aAux = Split(Datos, ",[")
aAux(1) = Replace(aAux(1), "],0,7]", "")
aAux(0) = Replace(aAux(0), "//OK[", "")
aAux(0) = Replace(aAux(0), "'", "")

aDescripcion = Split(aAux(1), """,""")
aValor = Split(aAux(0), ",")
InvertirArray aValor

For X = 0 To UBound(aValor)
    If Not IsNumeric(aValor(X)) Then
        Exit For
    End If
    If adescripcion(Int(aValor(X))-1) = "gov.senasa.embalajemadera.shared.domain.Pais/3238585366" Then  
        For Y = X + 1 To UBound(aValor)
            If Int(aValor(Y)) = "" Then '- Do what you want 
            end if
            If adescripcion(Int(aValor(Y))) = "java.lang.Integer/3438268394" Then 
        '- Do what you want
        Next Y
    End If
Next X

当然,你必须根据自己的需要调整它,你必须对数组进行一些调整......

InvertirArray:

Public Sub InvertirArray(ByRef Arr() As String)
'- el array va tiene que empezar en 0
Dim X As Long
Dim Hasta As Long
Dim Tmp As String

If UBound(Arr) Mod 2 = 0 Then
   '- Es impar
    Hasta = UBound(Arr) + 1
Else
    Hasta = UBound(Arr)
End If

For X = LBound(Arr) To UBound(Arr) \ 2
    Tmp = Arr(X)
    Arr(X) = Arr(UBound(Arr) - X)
    Arr(UBound(Arr) - X) = Tmp
Next X
end sub

当然,您需要解码和编码长数字和日期。所以:

Public Function EncodeDateGwt(Numero As Double, Optional isDate As Boolean = False) As String

 Dim s As String
Dim a As Double
Dim i As Integer
Dim u As Integer
Dim Base As String
Numero = IIf(isDate, Numero * 1000, Numero)
Base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$"
Do While Val(Numero) <> 0
    a = Numero
    i = 0
    Do While a >= 64
        i = i + 1
        a = a / 64
    Loop
    If i <> u - 1 And u <> 0 Then EncodeDateGwt = EncodeDateGwt & String(u - i - 1, Left(Base, 1))
    a = Int(a)
    EncodeDateGwt = EncodeDateGwt + Mid(Base, a + 1, 1)
    Numero = Numero - a * (64 ^ i)
    u = i
Loop
EncodeDateGwt = EncodeDateGwt & String(i, Left(Base, 1))
End Function

Public Function DecodeDateGwt(Texto As String, Optional isDate As Boolean = False) As Long

Dim Base As String
Dim a As Integer
Base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$"
For a = 1 To Len(Texto)
    DecodeDateGwt = DecodeDateGwt + (InStr(Base, Mid(Texto, a, 1)) - 1) *     (Len(Base) ^ ((Len(Texto) - (a))))
Next
DecodeDateGwt = IIf(isDate, DecodeDateGwt / 1000, DecodeDateGwt)
'devuelve timestamp
End Function

如果您需要编码/解码是一个日期,那么您需要在此之前执行此操作:

    Call encodegwtdate(date2unix("20/02/2016"),true)



Public Function Date2Unix(ByVal vDate As Date) As Long
Date2Unix = DateDiff("s", Unix1970, vDate)
End Function

Public Function Unix2Date(vUnixDate As Long) As Date
Unix2Date = DateAdd("s", vUnixDate, Unix1970)
End Function

希望你解决它。顺便说一下,有谁知道负数是什么意思?????