1

我遇到了编码问题...控制台中没有错误,但输出编码不正确。我必须在字符串上使用Digest::SHA1.hexdigest,然后必须 pack使用结果。

下面的例子应该输出 '{´p)ODýGΗ£Iô8ü:iÀ' 但它输出 '{?p)OD?GΗ?I?8?:i?' 在控制台和日志文件中的“{�p)OD�G^BΗ�I�8^D�:i�”。

所以,我的变量称为pack等于'{?p)OD?GΗ?I?8?:i?' 而不是'{´p)ODýGΗ£Iô8ü:iÀ'。这是一个大问题......我在 Rails 任务中做这件事。有什么想法吗?

谢谢

# encoding: utf-8
require 'digest/sha1'

namespace :my_app do
    namespace :check do
        desc "Description"

        task :weather => :environment do

            hexdigest = Digest::SHA1.hexdigest('29d185d98c984a359e6e6f26a0474269partner=100043982026&code=34154&profile=large&filter=movie&striptags=synopsis%2Csynopsisshort&format=json&sed=20130527')
            pack = [hexdigest].pack("H*")

            puts pack # => {?p)OD?GΗ?I?8?:i?
            puts '{´p)ODýGΗ£Iô8ü:iÀ' # => {´p)ODýGΗ£Iô8ü:iÀ

        end
    end
end
4

3 回答 3

0

这就是我所做的(我从 PHP 到 Ruby 的转换)

# encoding: utf-8
require 'open-uri'
require 'base64'
require 'digest/sha1'

class Allocine

    $_api_url = 'http://api.allocine.fr/rest/v3'
    $_partner_key
    $_secret_key
    $_user_agent = 'Dalvik/1.6.0 (Linux; U; Android 4.2.2; Nexus 4 Build/JDQ39E)'

    def initialize (partner_key, secret_key)
        $_partner_key = partner_key
        $_secret_key = secret_key
    end

    def get(id)
        # build the params
        params = {  'partner' => $_partner_key,
                    'code' => id,
                    'profile' => 'large',
                    'filter' => 'movie',
                    'striptags' => 'synopsis,synopsisshort',
                    'format' => 'json' }

        # do the request
        response = _do_request('movie', params)

        return response
    end

    private
    def _do_request(method, params)

        # build the URL
        query_url = $_api_url + '/' + method

        # new algo to build the query
        http_build_query = Rack::Utils.build_query(params)
        sed = DateTime.now.strftime('%Y%m%d')
        sig = URI::encode(Base64.encode64(Digest::SHA1.digest($_secret_key + http_build_query + '&sed=' + sed)))

        return sig
    end
end

然后打电话

allocine = Allocine.new(ALLOCINE_PARTNER_KEY, ALLOCINE_SECRET_KEY)
puts allocine.get('any ID')

获取方法在 PHP 中返回“e7RwKU9E%2FUcCzpejSfQ4BPw6acA%3D”,在 Ruby 中返回“cPf6I4ZP0qHQTSVgdKTbSspivzg=%0A”...

再次感谢

于 2013-05-27T17:07:19.720 回答
0

谢谢你们的帮助。问题解决了。使用以下代码,我获得了与 PHP 完全相同的字符串:

http_build_query = Rack::Utils.build_query(params)
sed = DateTime.now.strftime('%Y%m%d')
sig = CGI::escape(Base64.strict_encode64(Digest::SHA1.digest($_secret_key + http_build_query + '&sed=' + sed)))

现在我有另一个问题,我在这里打开了一个新问题

非常感谢你。

于 2013-05-28T10:05:24.683 回答
0

我认为由于调试了从 PHP 到 Ruby 的转换的其他部分,所以出现了这个“编码”问题。将使用参数摘要的目标 API 看起来将接受在 Ruby 中构造的签名变量,如下所示(编辑:这是猜测,Ruby 和 PHP 在 URI 编码和 base64 默认值方面也可能存在相关差异):

require 'digest/sha1'
require 'base64'
require 'uri'

sig_data = 'edhefhekjfhejk8edfefefefwjw69partne...'
sig = URI.encode( Base64.encode64( Digest::SHA1.digest( sig_data ) ) )
 => "+ZabHg22Wyf7keVGNWTc4sK1ez4=%0A"

sig_data正在签名的参数的精确构造也很重要。这是由 PHP 方法生成的http_build_query,我不知道将应用于输入参数的顺序或转义。如果您的 Ruby 版本以不同的顺序获取它们,或者以不同的方式转义到 PHP,则签名将是错误的(编辑:实际上我们可能正在这里寻找发送 API 的确切查询字符串的签名 - 我不知道)。可能是这类问题导致您陷入签名如何构建的兔子洞?

于 2013-05-27T17:02:17.017 回答