Solana signature verification fail between dApp and rust server

I am developing a dApp with its own SPL token. I am using Flutter/Dart for the client and Rust for the server. I want the service to be usable by users with no SOLs in their wallets, so I would like to pay for all user transactions.
I am experiencing an issue implementing the process in which a user spends the SPL token. The process requires two signatures: one signed by the user’s wallet and another signed by the server handling the transaction fee. The process is as below.

  1. User/client creates a message, signs it, and sends them to the server.
  2. Server verifies the user’s signature.
  3. The server signs the message and sends the transaction to the Solana network, taking care of the transaction fees.

However, the verification in #2 above fails every time.
I suspect it might be due to some issues in encoding the message using Flutter and decoding it using Rust, but I am not really sure. I am using the cryptoplease-dart flutter package and the Solana-sdk rust crate.
My code is as below. I have been stuck with this issue for a while now. Can anybody please help?

 // My server code.
  // rpc_client : solana client.
  // payer : my server wallet. payer every transaction.
  // param : http body data send my dApp.
  // param.address : user’s wallet address.
  // param.signature : sign about spend user token message on dApp(flutter-dart).
  // param.recentBlockhash : recent block hash using user’s signature.

  // find ATA
  let str_address = params.get(“address”).unwrap();
  let address = Pubkey::from_str(str_address).unwrap();
  let mut rpc_result = rpc_client.get_token_accounts_by_owner(&address, TokenAccountsFilter::Mint(alum_token)).unwrap();
  let str_account = rpc_result.pop().unwrap();
  let user_account = Pubkey::from_str(&str_account.pubkey).unwrap();
  rpc_result = rpc_client.get_token_accounts_by_owner(&payer.pubkey(), TokenAccountsFilter::Mint(alum_token)).unwrap();
  let str_account = rpc_result.pop().unwrap();
  let payer_account = Pubkey::from_str(&str_account.pubkey).unwrap();

  // user’s signature
  let str_signature = params.get(“signature”).unwrap();
  let user_signature = Signature::from_str(str_signature).unwrap();

  // block hash
  let str_block_hash = params.get(“recentBlockhash”).unwrap();
  let vec_block_hash = bs58::decode(str_block_hash).into_vec().unwrap();
  let block_hash = solana_program::해시::hash(&vec_block_hash);

  let it = transfer(
    &spl_token::id(),
    &user_account,
    &payer_account,
    &address,
    &[&address, &payer.pubkey()],
    1 * ALUM_DEC,
  ).unwrap();

  let message = Message::new(&[it.clone()], Some(&payer.pubkey()));
  let result = user_signature.verify(&address.to_bytes(), &message.serialize());
  if result {
    println!(“user verify success”);
  } else {
    println!(“user verify fail”);
  }
  // My dApp code.
  // wallet : modle of user solana info.
  // blockHash : using sign and send to server
  Future<String> signToSpendToken(
      WalletModel wallet, RecentBlockhash blockHash) async {
    int alum = 1 * pow(10, alumDecimals).toInt();
    Ed25519HDPublicKey userAccount =
        Ed25519HDPublicKey.fromBase58(wallet.account);

    var it = TokenInstruction.transfer(
        amount: alum,
        source: userAccount,
        destination: payerAccount,
        owner: wallet.keyPair.publicKey,
        signers: <Ed25519HDPublicKey>[wallet.keyPair.publicKey, payerAddress]);

    Message message = Message(instructions: [it]);

    var signedTx = await wallet.keyPair
        .signMessage(message: message, recentBlockhash: blockHash.blockhash);

    return signedTx.signatures.first.toBase58();
  }