提取 GWT 服务的结果

发布于 2024-11-09 00:37:30 字数 2092 浏览 4 评论 0原文

凌乱、复杂的问题,但就这样吧。我正在开发一个与 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 网上论坛消息的各种引用都在谈论有线格式的描述,但找不到底层消息或任何可以让我逆转这一点的连贯参考:有人掌握方便的参考吗?如果我至少能理解编码是什么,我也许可以摆脱上面问题 1 中的类文件。
  3. 我开始在 http://code.google.com/ 上浏览 Android Market api 库p/android-market-api/,认为他们必须完成一些 Android Market 通信集成,而且他们似乎是使用 protobuf 完成的。 GWT/protobufs 通信位有什么不错的参考吗?

这种疯狂的根本原因是我需要能够从 Google Checkout 获取常规汇率值,这样当我导入外币销售交易时,我可以按照交易时的现行汇率进行转换。当前的 Checkout 报告格式不提供此功能,因此大多数人最终会使用与 Google 使用的不匹配的替代汇率来源。这显然是 Google Checkout 集成界面的一个缺点,但如果我们开始研究 Google Checkout 界面的缺点,我们就会在这里待上一周。我的目的是轮询结帐界面以查找新履行的订单,然后请求适当的汇率表,以便我可以近乎实时地了解收到的付款是多少。我已经掌握了民意调查部分,但无法完全通过汇率部分。

Messy, complicated question, but here goes. I'm working on an integration project with Google Checkout, and there is a Google Checkout GWT service that returns the currency conversion rates used by the Checkout web interface to convert USD into local currencies. This endpoint is hosted at https://market.android.com/publish/gwt/, and staring at Firebug I see this going to the server:

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|

and this being returned

//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]

Forgive the odd formatting: can't quite get the code block to format right.

Wandering the web for hours on end I was able to determine that the RegularImmutableList class is in the Guava libraries (at http://code.google.com/p/guava-libraries/). What I'm looking for is:

  1. I can't find the com.google.common.money.SimpleMoney or com.google.common.money.CurrencyCode classes anywhere: anyone seen them?
  2. The GWT wire format appears to be an odd JSON string. I see various references to Google Groups messages talking about descriptions of the wire format, but can't find the underlying messages or any coherent reference that would let me reverse this: anyone have a handle on a handy reference? If I can at least understand WHAT the encoding is I might be able to get away without the class files from question 1 above.
  3. I started wandering through the Android Market api library at http://code.google.com/p/android-market-api/, figuring they have to have done SOME of the Android Market communication integration, and they appear to have done so using protobufs. Is there any decent reference for the GWT/protobufs communication bits?

The underlying reason for this craziness is that I need to be able to take regular exchange rate values from Google Checkout so when I'm importing sales transactions in foreign currencies I can do the conversion at the prevailing rate at the time of the transaction. The current Checkout reporting formats do NOT provide this, so most folks end up using alternative sources of exchange rates that don't match what Google uses. It is clearly a shortcoming on the part of Google Checkout's integration interface, but if we got started on shortcomings of Google Checkout's interface we'd be here all week. My intention is to poll the Checkout interface for newly fulfilled orders and then request the appropriate exchange rate table so I can figure out in near real-time what the incoming payments are. I've got the polling bit down pat but can't quite get past the exchange rate bit.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月下伊人醉 2024-11-16 00:37:30

在尝试创建一个脚本来为我的应用程序批量上传应用内产品时(CSV 上传不断失败,并出现模糊的错误消息),我成功地理解了 GWT AJAX 协议。

它实际上非常简单,只是它要求您了解所有使用的类的结构。或者你猜猜,就像 Google 使用的内部类的情况一样。 :)

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


请求格式

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 - 标志。 1FLAG_ELIDE_TYPE_NAMES2FLAG_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/415975576​​0
  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/415975576​​0
    6. 序列化参数。每个对象由其类名和序列化字段列表或对先前遇到的对象的负整数反向引用表示。在我们的例子中,我们有两个对象:
      1. 5 - com.google.common.money.CurrencyCode/112449834,只有一个整数字段:235
      2. 6 - java.util.ArrayList/415975576​​0,其中有一个整数长度字段13,后跟 13 个序列化列表项。请注意,其中 12 个是与上面的序列化相同的 CurrencyCode 对象,最后一个是对我们在 while (de -)序列化此请求,即 CurrencyCode(235)

响应格式

//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. 然后是 1 类型的序列化对象 - com.google.common.collect.RegularImmutableList/440499227 具有一个整数长度字段 13,后跟 13 个类 2 的序列化对象 - com.google.common.money.SimpleMoney/627983206。每个 SimpleMoney 对象都有两个字段,例如:
    1. 'Dlfg' - 编码为 Base64 数字的长整型字段。这个特定的数字是940000
    2. 3, 18 - 具有整数字段 18
    3. CurrencyCode 对象

While trying to create a script to bulk upload in-app products for my application (CSV upload constantly failed with obscure error messages), I have managed to understand the GWT AJAX protocol.

It's actually pretty simple, except it requires you to know structure of all used classes. Or guess it, as is the case with internal classes used by Google. :)

I'll use examples from the question to explain the protocol in detail.


Request format

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|

The request is pipe-delimited list of tokens with the following meaning:

  1. 7 - protocol version
  2. 0 - flags. 1 is FLAG_ELIDE_TYPE_NAMES, 2 is FLAG_RPC_TOKEN_INCLUDED
  3. 6 - string token count
  4. 6 string tokens:
    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. The actual encoded request, which references strings from the list above using 1-based indices:
    1. 1 - https://market.android.com/publish/gwt/ - base URL
    2. 2 - FCCA4108CB89BFC2FEC78BA7363D4AF6 - some hash, which is references as serializationPolicyStrongName in GWT sources.
    3. 3 - com.google.wireless.android.vending.developer.shared.MerchantService - service name
    4. 4 - getCurrencyExchangeRates - method name
    5. 2 - parameter count. Parameter types follow:
      1. 5 - com.google.common.money.CurrencyCode/112449834
      2. 6 - java.util.ArrayList/4159755760
    6. Serialized parameters. Each object is represented either by its classname and list of serialized fields or by negative integer back-reference to previously encountered object. In our case we have two objects:
      1. 5 - com.google.common.money.CurrencyCode/112449834, which only has one integer field: 235
      2. 6 - java.util.ArrayList/4159755760, which has one integer length field 13, followed by 13 serialized list items. Note that 12 of them are CurrencyCode objects serialized just as the above one, and the last one is a backreference (-1) to the very first object we encountered while (de-)serializing this request, i.e. CurrencyCode(235)

Response format

//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]

The response is very similar in format to the request except it's JS-formatted array (though not JSON, as it uses invalid single quotes), and it's in reverse order.
The field meaning is as follows:

  1. 7 - protocol version
  2. 0 - flags, same as for request
  3. Array of string tokens:
    1. com.google.common.collect.RegularImmutableList/440499227
    2. com.google.common.money.SimpleMoney/627983206
    3. com.google.common.money.CurrencyCode/112449834
  4. And then goes one serialized object of type 1 - com.google.common.collect.RegularImmutableList/440499227 with one integer length field 13, followed by 13 serialized objects of class 2 - com.google.common.money.SimpleMoney/627983206. Each SimpleMoney object has two fields, for example:
    1. 'Dlfg' - long integer field encoded as base64 number. This particular one is 940000
    2. 3, 18 - CurrencyCode object with integer field 18
静待花开 2024-11-16 00:37:30

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

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

  1. 您看到的类名称是 Google Checkout 内部使用的 Java 类。当 GWT 编译为 JS 时,名称会被破坏,因此您将不再看到它们。
  2. 如前所述,这是 GWT-RPC。
  3. 您正在尝试做的是对 Google 内部 API 进行逆向工程。我不会那样做,因为,a.它可能会在没有通知的情况下发生变化,从而破坏您的应用程序,并且,b。我确信 Goog 不会喜欢它,而且它可能违反了服务协议(你读过吗?)。

What you are looking at is GWT-RPC serialization format. Unfortunatelly it is not publicly documented. Fortunatelly GWT is open-source so you could look at the source to see how it is produced.

Note: This format might change between GWT versions (I known it did in 2.2). This is most likelly also a reason why Google does not document it - if they did they'd need to keep it backward compatible.

  1. Class names that you see are Java classes that Google Checkout uses internally. When GWT is compiled to JS the names get mangled so you don't see them any more.
  2. As noted this is GWT-RPC.
  3. What you are trying to do is reverse-engineer Google internal APIs. I wouldn't do that because, a. It might change without notice, breaking your app and, b. I'm sure Goog wouldn't like it and it probably violates the service agreement (have you read it?).
你不是我要的菜∠ 2024-11-16 00:37:30

我有一些用 VB 编写的代码,可能对您了解如何解析 GWT 序列化字符串有用。 “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

希望你能解决它。顺便问一下,有人知道负数是什么意思吗????

I have some code made in VB that may be useful for you to realize how to parse GWT Serialized strings. "Datos" contains the string you received.

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

Of course you have to adapt it to your needs and you will have to play a little bit with the arrays...

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

And of course you need to decode and encode Long Numbers and dates. So:

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

If what you need to encode/decode is a date, then you need to do this before:

    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

Hope you solve it. By the way, does anyone knows what negative numbers means?????

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文