c# 执行node.js的程序

抖音小程序的获取手机号码的代码是用node.js写的,但我们的后端是C#,能否在C#里执行node.js 获取到手机号码呢?

// Node.js
const crypto = require("crypto");

function decrypt(encryptedData, sessionKey, iv) {
  const decipher = crypto.createDecipheriv(
    "aes-128-cbc",
    Buffer.from(sessionKey, "base64"),
    Buffer.from(iv, "base64")
  );
  let ret = decipher.update(encryptedData, "base64");
  ret += decipher.final();
  return ret;
}




小程序取得手机号码:
https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/guide/open-capabilities/sensitive-data-process

https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/guide/open-capabilities/acquire-phone-number-acquire

下面是用python取手机号码的例子,如果能用C#调用能实现都可以。

# python
import base64

# https://www.pycryptodome.org/
# pip install pycryptodome
from Crypto.Cipher import AES


def decrypt(encrypted_data, session_key, iv):
    data = base64.b64decode(encrypted_data)
    _key = base64.b64decode(session_key)
    _iv = base64.b64decode(iv)

    cipher = AES.new(_key, AES.MODE_CBC, _iv)
    return cipher.decrypt(data)

基于new bing的实现:
在C#中执行Node.js的代码是可行的,可以使用第三方的Node.js运行环境,如edge-js或node-chakra等库。

具体操作流程如下:

安装edge-js或者node-chakra。
在C#代码中引入Node.js模块并调用该模块的方法。
示例代码如下:

using System;
using System.Threading.Tasks;
using EdgeJs;

public class Program
{
    public async static Task Main(string[] args)
    {
        var decrypt = Edge.Func(@"
            const crypto = require('crypto');
            return function (encryptedData, sessionKey, iv, callback) {
                const decipher = crypto.createDecipheriv(
                    'aes-128-cbc',
                    Buffer.from(sessionKey, 'base64'),
                    Buffer.from(iv, 'base64')
                );
                let ret = decipher.update(encryptedData, 'base64', 'utf8');
                ret += decipher.final('utf8');
                callback(null, ret);
            }
        ");

        var result = await decrypt("encrypted data", "session key", "iv");
        Console.WriteLine(result); // 输出解密后的数据
    }
}


需要注意的是,在使用Edge.js或node-chakra时需要先安装Node.js环境。

可以在C#中执行node.js代码
在C#应用程序中运行JavaScript文件,并在其中执行获取手机号码的JavaScript代码。
参考代码:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
using Microsoft.Extensions.PlatformAbstractions;  
using Microsoft.Extensions.FileProviders;  
using Microsoft.CodeAnalysis;  
using Microsoft.CodeAnalysis.CSharp;  
using Microsoft.CodeAnalysis.CSharp.Syntax;  
using Microsoft.CodeAnalysis.Scripting;  
using Microsoft.CodeAnalysis.Scripting.Hosting;  
using Microsoft.CodeAnalysis.CSharp.Scripting.Hosting;  
using System.IO;  
  
namespace YourNamespace  
{  
    class Program  
    {  
        static async Task Main(string[] args)  
        {  
            var provider = await Script Providers.DefaultSignatureProvider.GetDefaultSignatureAsync();  
            var options = new Script Options { Language = CSharpLanguage.Instance };  
            var script = CSharpScript.FromFiles(new string[] { "your_javascript_file.js" }, options);  
            var result = await script.RunAsync();  
            Console.WriteLine(result); // output: your_phone_number  
        }  
    }  
}


// pages/onePages/userInfo/userInfo.js
const app = getApp();
var WXBizDataCrypt = require('../../../utils/WXBizDataCrypt');
Page({
  //页面的初始数据
  data: {
    encryptedData: "", //手机号的加密数据
    iv: "",
    sessionKey: "", //wx.login,获取session_key
    phone: "",
    nick: "",
  },
 
  //生命周期函数--监听页面显示
  onShow: function () {     
    this.wxLogin();
  },
 
  //通过绑定手机号登录
  getPhoneNumber: function (e) {
    var that = this;
    console.log("点击按钮获取手机号",e); //获取encryptedData、iv,encryptedData就是加密的数据
    if(e.detail.errMsg == 'getPhoneNumber:fail no permission'){
      app.utils.showToast("小程序未认证", "none", 1000);
      return false;
    } else if(e.detail.iv == undefined || !e.detail.iv){
      app.utils.showToast("授权失败", "none", 1000);
      return false;
    } else if(e.detail.errMsg == 'getPhoneNumber:user deny'){
      //用户拒绝授权,停留在当前页
    } else {  
      that.setData({ "encryptedData": e.detail.encryptedData, "iv": e.detail.iv });
      //检查session_key 是否失效,失效会导致手机号获取两次的问题   
      wx.checkSession({
        success: (res) => { 
          console.log("未失效", res)
          var pc = new WXBizDataCrypt(app.appId, that.data.sessionKey);
          var data = pc.decryptData(that.data.encryptedData, that.data.iv);
          console.log("解密后Data",data);
          wx.setStorageSync('phone', data.phoneNumber);
          wx.redirectTo({ url: '/pages/onePages/home/home' });
        },
        fail: (err)=>{ 
          console.log("失效 重新wx.login")
          that.wxLogin(function(){
            var pc = new WXBizDataCrypt(app.appId, that.data.session_key);
            var data = pc.decryptData(that.data.encryptedData, that.data.iv);
            wx.setStorageSync('phone', data.phoneNumber); //将手机号存storage
            wx.redirectTo({ url: '/pages/onePages/home/home' });
          }) 
        }
      })
    }
  }, //获取手机号
 
  //手机号解码:wx.login获取 code, 再通过wx.request获取 session_key
  wxLogin(callback){
    var that = this;
    wx.login({
      success (res) {
        // console.log("wx.login",res)  //wx.login获取 code
        wx.request({
          url: 'https://api.weixin.qq.com/sns/jscode2session?appid='+app.appId+'&secret='+app.appSecret+'&js_code=' + res.code + '&grant_type=authorization_code',
          method: 'POST',
          header: { 'content-type': 'application/json' },
          success: function (obj) {
            // console.log("解密",obj); //获取openid, session_key
            that.setData({"sessionKey": obj.data.session_key});
            if(callback) callback();
          }
        })
      }
    }); //wx.login 结束
  }
   
}) 

您可以使用C#调用Node.js并获取其输出结果。这可以通过使用Process类来实现。下面是一个示例代码,其中我们假设您已经安装了Node.js和相关依赖项:


using System;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        string nodePath = "path/to/node.exe"; // Node.js执行文件路径
        string scriptPath = "path/to/your/script.js"; // Node.js脚本文件路径

        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = nodePath,
            Arguments = scriptPath,
            UseShellExecute = false,
            RedirectStandardOutput = true
        };

        using (Process process = Process.Start(startInfo))
        {
            if (process != null)
            {
                string output = process.StandardOutput.ReadToEnd();
                Console.WriteLine(output);
            }
        }
    }
}

您需要将 nodePath 和 scriptPath 替换为实际的路径,然后在运行时调用 Main() 方法即可。请注意,此示例仅是基础代码框架,具体实现方式可能因特定情况而异。

这...用C#实现不就好了。
看起来跟微信的解密方式差不多。

可以使用C#中的Process类来运行Node.js脚本,然后通过标准输入、标准输出或命令行参数来进行数据传递。所以,你可以编写一个Node.js脚本来实现获取手机号码的功能,然后在C#程序中调用该脚本以获取手机号码。

以下是一个演示程序,通过调用Node.js脚本来获取手机号码。

Node.js脚本(getPhoneNumber.js)

const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.question('请输入手机号码:', (answer) => {
    console.log('你输入的手机号码是:', answer);
    rl.close();
});

C#程序:

using System;
using System.Diagnostics;

namespace NodeJsDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            string node = "C:\\Program Files\\nodejs\\node.exe"; // Node.js路径
            string script = "C:\\getPhoneNumber.js"; // Node.js脚本路径

            var process = new Process();
            process.StartInfo.FileName = node;
            process.StartInfo.Arguments = script;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.UseShellExecute = false;

            bool isOk = false;
            process.OutputDataReceived += (sender, e) =>
            {
                if (e.Data != null && e.Data.Contains("请输入手机号码:"))
                {
                    process.StandardInput.WriteLine("13888888888"); // 输入手机号码
                    isOk = true;
                }
                else if (e.Data != null && isOk)
                {
                    Console.WriteLine("获取到的手机号码是:{0}", e.Data);
                    process.Kill();
                }
            };

            process.Start();
            process.BeginOutputReadLine();

            Console.ReadLine();
            process.Kill();
        }
    }
}

运行C#程序,将会弹出一个命令行窗口,要求用户输入手机号码。在这个例子中,我们直接在C#中为用户输入手机号码,而你可以在实际应用中以任何方式获得需要查询的手机号码。

Node.js脚本收到手机号码后,通过标准输出将其打印出来,再通过C#程序捕获输出结果并进行处理。

可以通过使用 C# 的 Process 类与 Node.js 安装包中的 node.exe 执行文件结合,实现C# 中执行 Node.js 代码

是的,你可以通过在 C# 中使用适当的库来执行 Node.js 代码并获取手机号码。在 C# 中执行 Node.js 代码的一种常见方法是使用 Edge.js 库。Edge.js 提供了一种将 C# 和 JavaScript (包括 Node.js) 代码集成到同一个应用程序中的方式。

以下是一个示例,展示了如何在 C# 中使用 Edge.js 来执行给定的 Node.js 代码并获取手机号码:

using System;
using System.Threading.Tasks;
using System.Dynamic;
using EdgeJs;

class Program
{
    static async Task Main()
    {
        var nodeCode = @"
            const crypto = require('crypto');
            
            function decrypt(encryptedData, sessionKey, iv) {
                const decipher = crypto.createDecipheriv(
                    'aes-128-cbc',
                    Buffer.from(sessionKey, 'base64'),
                    Buffer.from(iv, 'base64')
                );
                let ret = decipher.update(encryptedData, 'base64');
                ret += decipher.final();
                return ret;
            }

            module.exports = decrypt;
        ";

        // 创建动态对象以传递参数给 Node.js 代码
        dynamic parameters = new ExpandoObject();
        parameters.encryptedData = "encrypted_data_here";
        parameters.sessionKey = "session_key_here";
        parameters.iv = "iv_here";

        // 使用 Edge.js 执行 Node.js 代码
        Func<object, Task<object>> nodeFunc = Edge.Func(nodeCode);
        var result = await nodeFunc(parameters);

        // 处理从 Node.js 代码返回的结果
        string phoneNumber = result.ToString();
        Console.WriteLine("Decrypted Phone Number: " + phoneNumber);
    }
}


请替换示例代码中的 "encrypted_data_here"、"session_key_here" 和 "iv_here" 为实际的加密数据、会话密钥和初始化向量。