1. 前端部分(可以直接copy 网易易盾的官方文档) 修改一下 接口指向 nodejs

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>验证码示例-智能无感知bind模式</title>
  </head>
  <body>
    <form action="/login" method="post">
      <input type="text" name="username" placeholder="用户名" />
      <input type="password" name="password" placeholder="密码" />
      <input type="hidden" name="captchaId" value="从易盾申请的captchaId" />
      <div id="captcha"></div>
      <!-- 验证码容器元素 -->
      <button type="submit" id="submit-btn">登录</button>
    </form>

    <script
      charset="UTF-8"
      type="text/javascript"
      src="http://cstaticdun.126.net/load.min.js"
    ></script>
    <script>
      var captchaIns
      initNECaptcha(
        {
          element: '#captcha',
          captchaId: '49fa346201934f81bf866dca2b7f42c8',
          mode: 'bind', // 仅智能无感知验证码时,mode 才能设置为 bind
          width: '320px',
          //enableClose: true, // 由业务方控制验证码弹框关闭
          onVerify: function(err, ret) {
            // 用户验证码验证成功后,进行实际的提交行为
            // todo
            if (err) console.log(err)
            if (!err) {
              request(ret.validate)
              console.log(ret.validate)
            }
          }
        },
        function(instance) {
          // 初始化成功后得到验证实例instance,可以调用实例的方法
          captchaIns = instance
        },
        function(err) {
          // 初始化失败后触发该函数,err对象描述当前错误信息
        }
      )
      // 监听需要绑定的 button 的点击事件,手动调用实例的verify方法来验证
      document
        .getElementById('submit-btn')
        .addEventListener('click', function(e) {
          e.preventDefault()
          captchaIns && captchaIns.verify()
        })
      const request = NECaptchaValidate => {
        var xhr = new XMLHttpRequest()
        xhr.onreadystatechange = function() {
          console.log(this)
          if (this.readyState == 4) {
            if (this.status >= 200 && this.status < 300) {
              console.log('xhr.responseText', xhr.responseText)
            }
          }
        }
        xhr.open('post', 'http://192.168.1.227:20001/test163')
        xhr.setRequestHeader(
          'Content-Type',
          'application/x-www-form-urlencoded'
        )
        xhr.send(JSON.stringify({ NECaptchaValidate }))
      }
    </script>
  </body>
</html>

2. 后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const request = require("request");
const queryString = require("querystring");
const uuid = require("uuid");
const md5 = require("md5");
const app = new Koa();
// 写入自己申请的key id 
const secretKey = "XXXXXXXXXXXXXXXXXXXXX";
const captchaId = "XXXXXXXXXXXXXXXXXXXXX";
const secretId = "XXXXXXXXXXXXXXXXXXXXX";
const genSignature = (secretKey, paramsJson) => {
  const sorter = paramsJson => {
    const sortedJson = {};
    const sortedKeys = Object.keys(paramsJson).sort();
    for (let i = 0; i < sortedKeys.length; i++) {
      sortedJson[sortedKeys[i]] = paramsJson[sortedKeys[i]];
    }
    return sortedJson;
  };
  const sortedParam = sorter(paramsJson);
  let needSignatureStr = "";
  for (let key in sortedParam) {
    var value = sortedParam[key];
    needSignatureStr = needSignatureStr + key + value;
  }
  needSignatureStr += secretKey;
  return md5(needSignatureStr);
};
app.use(cors());
app.use(async ctx => {
  if (ctx.request.path === "/test163") {
    let str = "";
    const s = new Promise((resolve, reject) => {
      ctx.req.on("data", data => {
        str += data;
      });
      ctx.req.on("end", () => {
        resolve(str);
      });
    });
    const data = JSON.parse(await s);
    const requestData = {
      captchaId,
      nonce: uuid().substr(4), // 32位
      secretId,
      timestamp: new Date().getTime(),
      version: "v2",
      user: "",
      validate: data.NECaptchaValidate
    };
    const signature = genSignature(secretKey, requestData);
    Object.assign(requestData, {
      signature
    });
    const responseData = new Promise((resolve, reject) => {
      request(
        {
          headers: {
            "Content-Type": "application/x-www-form-urlencoded"
          },
          url: "http://c.dun.163yun.com/api/v2/verify",
          body: queryString.stringify(requestData),
          method: "POST"
        },
        (error, response, data) => {
          try {
            console.log('verify result: \n', data)
            resolve(data);
          } catch (e) {
            console.log("logout err", e);
          }
        }
      );
    });
    ctx.body = await responseData;
  } else {
    ctx.response.body = {
      code: 666
    };
  }
});

app.listen(20001, () => {
  console.log("listen on: http://127.0.0.1:20001");
});