ruby on rails 關於微信企業號回調模式初步驗證通過後再次簽名驗證失敗的解決

這塊我在8月17號的時候碰到過,再回調模式初步驗證通過以後,微信服務器後續的信息會由原來的msg_signature. timestamp. nonce. echostr改爲3個參數msg_signature. timestamp. nonce以及一串 xml信息,少了第四個參數,而簽名驗證的生成又必須要用到第4個參數echostr,否則單一的用timestamp. nonce. token生成的signature會跟接收的msg_signature不一致,導致驗證是否爲微信服務器發送的消息失敗。

因此我們必須自己通過解讀xml裏的參數Encrypt拿到echostr來加入簽名字符串的加密生成,同時也可以拿到其他解密後的xml信息生成一個hashmap進行後續的開發應用:

#@msg_encrypt就是我們要的Encrypt

  # 加密
  def encrypt(aes_key, text, corpid)
    text    = text.force_encoding("ASCII-8BIT")
    random  = SecureRandom.hex(8)
    msg_len = [text.length].pack("N")
    text    = "#{random}#{msg_len}#{text}#{corpid}"
    text    = encode(text)
    text    = handle_cipher(:encrypt, aes_key, text)
    Base64.encode64(text)
  end

  # 對密文進行解密.
  # text 需要解密的密文
  def decrypt(aes_key, text, corpid)
    status = 200
    text        = Base64.decode64(text)
    text        = handle_cipher(:decrypt, aes_key, text)
    result      = decode(text)
    content     = result[16...result.length]
    len_list    = content[0...4].unpack("N")
    xml_len     = len_list[0] 
    xml_content = content[4...4 + xml_len]
    from_corpid = content[xml_len+4...content.size]
    # TODO: refactor
    if corpid != from_corpid
      Rails.logger.debug("#{__FILE__}:#{__LINE__} Failure because #{corpid} != #{from_corpid}")
      status = 401
    end
    [xml_content, status]
  end


  # 對需要加密的明文進行填充補位
  # 返回補齊明文字符串
  def encode(text)
    # 計算需要填充的位數
    amount_to_pad = @BLOCK_SIZE - (text.length % @BLOCK_SIZE)
    amount_to_pad = @BLOCK_SIZE if amount_to_pad == 0
    # 獲得補位所用的字符
    pad_chr = amount_to_pad.chr
    "#{text}#{pad_chr * amount_to_pad}"
  end


   def setup_wechat_message
      wx = Wx.new
      # Rails.logger.debug("encoding_aes_key: #{encoding_aes_key}, qy_token: #{qy_token}, corp_id: #{corp_id}")
      param_xml        = request.body.read
      hash             = MultiXml.parse(param_xml)['xml']
      @msg_encrypt  = hash["Encrypt"]
      @body_xml       = OpenStruct.new(hash)
      @content           = decrypt(aes_key, @body_xml.Encrypt, corp_id)[0]
      @hash               = MultiXml.parse(@content)["xml"]
   end



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章