wangguoyu 6 ماه پیش
والد
کامیت
17131829e8

+ 179 - 0
components/captcha4/index.vue

@@ -0,0 +1,179 @@
+<template>
+  <view class="geetest_component"> </view>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      wv: null,
+      lastTime: "",
+      defaultConfig: {
+        clientVersion: "uniapp-v1.0",
+        clientType: uni.getSystemInfoSync().platform,
+        protocol: "http://",
+        mi: {
+          geeid: {
+            bd: "",
+            d: "",
+            e: "",
+            fp: "",
+            ts: "",
+            ver: "",
+            client_type: "",
+          },
+          packageName: "",
+          displayName: "",
+          appVer: "",
+          build: "",
+          clientVersion: "",
+          process_id: "",
+          process_id_test: "",
+          zid: "",
+        },
+      },
+    };
+  },
+  props: {
+    config: {
+      type: Object,
+      default: function () {
+        return {};
+      },
+    },
+  },
+  mounted() {},
+  methods: {
+    showCaptcha() {
+      var that = this;
+      // #ifdef APP-PLUS
+
+      // 合并参数
+      _assign(this.defaultConfig, this.config, {
+        challenge: this.getUuid(),
+      }); //每次更新challenge
+
+      // 创建webview
+      this.wv = plus.webview.create(
+        `hybrid/html/captcha4/index.html?data=${encodeURIComponent(
+          JSON.stringify(this.defaultConfig)
+        )}`,
+        "gt_webview",
+        {
+          background: "transparent",
+          width: "100%", //String类型,窗口的宽度.支持百分比、像素值,默认为100%.未设置width属性值时,可同时设置left和right属性值改变窗口的默认宽度.
+          height: "100%",
+        }
+      );
+
+      // 获取webview
+      var currentWebview = this.$root.$scope.$getAppWebview(); //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
+      currentWebview.append(this.wv);
+
+      plus.globalEvent.addEventListener("plusMessage", (msg) => {
+        //有重复推送问题
+        const result = msg.data.args.data;
+        if (result.name == "postMessage") {
+          if (result.arg.time === that.lastTime) {
+            // 处理uni连续推送bug
+            return;
+          }
+          that.lastTime = result.arg.time;
+          switch (result.arg.type) {
+            case "ready":
+              that.captchaReady();
+              break;
+            case "error":
+              that.captchaError(result.arg.data);
+              break;
+            case "fail":
+              that.captchaFail();
+              break;
+            case "close":
+              that.captchaClose();
+              break;
+            case "result":
+              that.captchaSuccess(result.arg.data);
+              break;
+            default:
+              break;
+          }
+        }
+      });
+
+      this.wv.overrideUrlLoading(
+        {
+          mode: "reject",
+        },
+        (e) => {
+          plus.runtime.openURL(e.url);
+        }
+      );
+      // #endif
+    },
+    captchaReady() {
+      this.$emit("captchaReady");
+      this.wv.evalJS("jsBridge.callback('showBox')");
+    },
+    captchaSuccess(data) {
+      this.$emit("captchaSuccess", data);
+      this.wv.hide();
+    },
+    captchaClose() {
+      this.$emit("captchaClose");
+      this.wv.hide();
+    },
+    captchaError: function (e) {
+      uni.showToast({
+        title: JSON.stringify(e),
+        icon: "none",
+        duration: 2000,
+      });
+      this.$emit("captchaError", e);
+      this.wv.hide();
+    },
+    captchaFail() {
+      this.$emit("captchaFail");
+    },
+    getAppWebview(that) {
+      if (that.$scope) {
+        return that.$scope.$getAppWebview();
+      } else {
+        this.getAppWebview(that.$parent);
+      }
+    },
+    getUuid() {
+      return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
+        /[xy]/g,
+        function (c) {
+          const r = (Math.random() * 16) | 0;
+          const v = c === "x" ? r : (r & 0x3) | 0x8;
+          return v.toString(16);
+        }
+      );
+    },
+  },
+};
+
+function _assign(target) {
+  if (typeof Object.assign === "function") {
+    return Object.assign.apply(Object, arguments);
+  }
+  if (target == null) {
+    throw new Error("Cannot convert undefined or null to object");
+  }
+
+  const newTarget = Object(target);
+  for (let index = 1; index < arguments.length; index++) {
+    const source = arguments[index];
+    if (source !== null) {
+      for (const key in source) {
+        if (Object.prototype.hasOwnProperty.call(source, key)) {
+          newTarget[key] = source[key];
+        }
+      }
+    }
+  }
+  return newTarget;
+}
+</script>
+<style lang="scss"></style>

+ 488 - 0
hybrid/html/captcha4/ct4.js

@@ -0,0 +1,488 @@
+"v1.0.0 Captcha4 Inc.";
+
+(function (window) {
+    "use strict";
+    if (typeof window === 'undefined') {
+        throw new Error('Captcha4 requires browser environment');
+    }
+
+var document = window.document;
+var Math = window.Math;
+var head = document.getElementsByTagName("head")[0];
+var TIMEOUT = 10000;
+
+function _Object(obj) {
+    this._obj = obj;
+}
+
+_Object.prototype = {
+    _each: function (process) {
+        var _obj = this._obj;
+        for (var k in _obj) {
+            if (_obj.hasOwnProperty(k)) {
+                process(k, _obj[k]);
+            }
+        }
+        return this;
+    },
+    _extend: function (obj){
+        var self = this;
+        new _Object(obj)._each(function (key, value){
+            self._obj[key] = value;
+        })
+    }
+};
+
+var uuid = function () {
+        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+            var r = Math.random() * 16 | 0;
+            var v = c === 'x' ? r : (r & 0x3 | 0x8);
+            return v.toString(16);
+        });
+    };
+
+function Config(config) {
+    var self = this;
+    new _Object(config)._each(function (key, value) {
+        self[key] = value;
+    });
+}
+
+Config.prototype = {
+    apiServers: ['captcha.alicaptcha.com','captchabak.alicaptcha.com'],
+    staticServers: ["static.alicaptcha.com"],
+    protocol: 'http://',
+    typePath: '/load',
+    fallback_config: {
+        bypass: {
+            staticServers: ["static.alicaptcha.com"],
+            type: 'bypass',
+            bypass: '/v4/alibypass.js'
+        }
+    },
+    _get_fallback_config: function () {
+        var self = this;
+        if (isString(self.type)) {
+            return self.fallback_config[self.type];
+        } else {
+            return self.fallback_config.bypass;
+        }
+    },
+    _extend: function (obj) {
+        var self = this;
+        new _Object(obj)._each(function (key, value) {
+            self[key] = value;
+        })
+    }
+};
+var isNumber = function (value) {
+    return (typeof value === 'number');
+};
+var isString = function (value) {
+    return (typeof value === 'string');
+};
+var isBoolean = function (value) {
+    return (typeof value === 'boolean');
+};
+var isObject = function (value) {
+    return (typeof value === 'object' && value !== null);
+};
+var isFunction = function (value) {
+    return (typeof value === 'function');
+};
+var MOBILE = /Mobi/i.test(navigator.userAgent);
+
+var callbacks = {};
+var status = {};
+
+var random = function () {
+    return parseInt(Math.random() * 10000) + (new Date()).valueOf();
+};
+
+// bind 函数polify, 不带new功能的bind
+
+var bind = function(target,context){
+    if(typeof target !== 'function'){
+        return;
+    }
+    var args = Array.prototype.slice.call(arguments,2);
+
+    if(Function.prototype.bind){
+        return target.bind(context, args);
+    }else {
+        return function(){
+            var _args = Array.prototype.slice.call(arguments);
+            return target.apply(context,args.concat(_args));
+        }
+    }
+}
+
+
+
+var toString = Object.prototype.toString;
+
+var _isFunction = function(obj) {
+  return typeof(obj) === 'function';
+};
+var _isObject = function(obj) {
+  return obj === Object(obj);
+};
+var _isArray = function(obj) {
+  return toString.call(obj) == '[object Array]';
+};
+var _isDate = function(obj) {
+  return toString.call(obj) == '[object Date]';
+};
+var _isRegExp = function(obj) {
+  return toString.call(obj) == '[object RegExp]';
+};
+var _isBoolean = function(obj) {
+  return toString.call(obj) == '[object Boolean]';
+};
+
+
+function resolveKey(input){
+  return  input.replace(/(\S)(_([a-zA-Z]))/g, function(match, $1, $2, $3){
+          return $1 + $3.toUpperCase() || "";
+  })
+}
+
+function camelizeKeys(input, convert){
+  if(!_isObject(input) || _isDate(input) || _isRegExp(input) || _isBoolean(input) || _isFunction(input)){
+      return convert ? resolveKey(input) : input;
+  }
+
+  if(_isArray(input)){
+      var temp = [];
+      for(var i = 0; i < input.length; i++){
+          temp.push(camelizeKeys(input[i]));
+      }
+
+  }else {
+      var temp = {};
+      for(var prop in input){
+          if(input.hasOwnProperty(prop)){
+              temp[camelizeKeys(prop, true)] = camelizeKeys(input[prop]);
+          }
+      }
+  }
+  return temp;
+}
+
+var loadScript = function (url, cb, timeout) {
+    var script = document.createElement("script");
+    script.charset = "UTF-8";
+    script.async = true;
+
+    // 对geetest的静态资源添加 crossOrigin
+    if ( /static\.geetest\.com/g.test(url)) {
+        script.crossOrigin = "anonymous";
+    }
+
+    script.onerror = function () {
+        cb(true);
+        // 错误触发了,超时逻辑就不用了
+        loaded = true;
+    };
+    var loaded = false;
+    script.onload = script.onreadystatechange = function () {
+        if (!loaded &&
+            (!script.readyState ||
+            "loaded" === script.readyState ||
+            "complete" === script.readyState)) {
+
+            loaded = true;
+            setTimeout(function () {
+                cb(false);
+            }, 0);
+        }
+    };
+    script.src = url;
+    head.appendChild(script);
+
+    setTimeout(function () {
+        if (!loaded) {
+            script.onerror = script.onload = null;
+            script.remove && script.remove();
+            cb(true);
+        }
+    }, timeout || TIMEOUT);
+};
+
+var normalizeDomain = function (domain) {
+    // special domain: uems.sysu.edu.cn/jwxt/geetest/
+    // return domain.replace(/^https?:\/\/|\/.*$/g, ''); uems.sysu.edu.cn
+    return domain.replace(/^https?:\/\/|\/$/g, ''); // uems.sysu.edu.cn/jwxt/geetest
+};
+var normalizePath = function (path) {
+    path = path && path.replace(/\/+/g, '/');
+    if (path.indexOf('/') !== 0) {
+        path = '/' + path;
+    }
+    return path;
+};
+var normalizeQuery = function (query) {
+    if (!query) {
+        return '';
+    }
+    var q = '?';
+    new _Object(query)._each(function (key, value) {
+        if (isString(value) || isNumber(value) || isBoolean(value)) {
+            q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
+        }
+    });
+    if (q === '?') {
+        q = '';
+    }
+    return q.replace(/&$/, '');
+};
+var makeURL = function (protocol, domain, path, query) {
+    domain = normalizeDomain(domain);
+
+    var url = normalizePath(path) + normalizeQuery(query);
+    if (domain) {
+        url = protocol + domain + url;
+    }
+
+    return url;
+};
+
+var load = function (config, protocol, domains, path, query, cb, handleCb) {
+    var tryRequest = function (at) {
+        // 处理jsonp回调,这里为了保证每个不同jsonp都有唯一的回调函数
+        if(handleCb){
+            var cbName = "captcha4_" + random();
+            // 需要与预先定义好cbname参数,删除对象
+            window[cbName] = bind(handleCb, null, cbName);
+            query.callback = cbName;
+        }
+        var url = makeURL(protocol, domains[at], path, query);
+        loadScript(url, function (err) {
+            if (err) {
+                // 超时或者出错的时候 移除回调
+                if(cbName){
+                  try {
+                     window[cbName] = function(){
+                       window[cbName] = null;
+                      }
+                    } catch (e) {}
+                }
+
+                if (at >= domains.length - 1) {
+                    cb(true);
+                    // report gettype error
+                } else {
+                    tryRequest(at + 1);
+                }
+            } else {
+                cb(false);
+            }
+        }, config.timeout);
+    };
+    tryRequest(0);
+};
+
+
+var jsonp = function (domains, path, config, callback) {
+
+    var handleCb = function (cbName, data) {
+
+        // 保证只执行一次,全部超时的情况下不会再触发;
+
+        if (data.status == 'success') {
+            callback(data.data);
+        } else if (!data.status) {
+            callback(data);
+        } else {
+            //接口有返回,但是返回了错误状态,进入报错逻辑
+            callback(data);
+        }
+        window[cbName] = undefined;
+        try {
+            delete window[cbName];
+        } catch (e) {
+        }
+    };
+    load(config, config.protocol, domains, path, {
+        callback: '',
+        captcha_id: config.captchaId,
+        challenge: config.challenge || uuid(),
+        client_type: MOBILE? 'h5':'web',
+        risk_type: config.riskType,
+        user_info: config.userInfo,
+        call_type: config.callType,
+        lang: config.language? config.language : navigator.appName === 'Netscape' ? navigator.language.toLowerCase() : navigator.userLanguage.toLowerCase()
+    }, function (err) {
+        // 网络问题接口没有返回,直接使用本地验证码,走宕机模式
+        // 这里可以添加用户的逻辑
+            if(err && typeof config.offlineCb === 'function'){
+                // 执行自己的宕机
+                config.offlineCb();
+                return;
+            }
+           if(err){
+            callback(config._get_fallback_config());
+           }
+    }, handleCb);
+};
+
+var reportError = function (config, url) {
+    load(config, config.protocol, ['monitor.geetest.com'], '/monitor/send', {
+        time: Date.now().getTime(),
+        captcha_id: config.gt,
+        challenge: config.challenge,
+        exception_url: url,
+        error_code: config.error_code
+    }, function (err) {})
+}
+
+var throwError = function (errorType, config, errObj) {
+    var errors = {
+        networkError: '网络错误',
+        gtTypeError: 'gt字段不是字符串类型'
+    };
+    if (typeof config.onError === 'function') {
+        config.onError({
+            desc: errObj.desc,
+            msg: errObj.msg,
+            code: errObj.code
+        });
+    } else {
+        throw new Error(errors[errorType]);
+    }
+};
+
+var detect = function () {
+    return window.Captcha4 || document.getElementById("gt_lib");
+};
+
+if (detect()) {
+    status.slide = "loaded";
+}
+var Captcha4IsLoad = function (fname) {
+  var Captcha4IsLoad = false;
+  var tags = { js: 'script', css: 'link' };
+  var tagname = fname && tags[fname.split('.').pop()];
+  if (tagname !== undefined) {
+    var elts = document.getElementsByTagName(tagname);
+    for (var i in elts) {
+      if ((elts[i].href && elts[i].href.toString().indexOf(fname) > 0)
+              || (elts[i].src && elts[i].src.toString().indexOf(fname) > 0)) {
+        Captcha4IsLoad = true;
+      }
+    }
+  }
+  return Captcha4IsLoad;
+};
+window.initAlicom4 = function (userConfig,callback) {
+
+    var config = new Config(userConfig);
+    if (userConfig.https) {
+        config.protocol = 'https://';
+    } else if (!userConfig.protocol) {
+        config.protocol = window.location.protocol + '//';
+    }
+
+
+    if (isObject(userConfig.getType)) {
+        config._extend(userConfig.getType);
+    }
+
+    jsonp(config.apiServers , config.typePath, config, function (newConfig) {
+            
+            //错误捕获,第一个load请求可能直接报错
+            var newConfig = camelizeKeys(newConfig);
+
+            if(newConfig.status === 'error'){
+               return throwError('networkError', config, newConfig);
+            }
+
+            var type = newConfig.type;
+            
+            if(config.debug){
+                new _Object(newConfig)._extend(config.debug)
+            }
+            var init = function () {
+                config._extend(newConfig);
+                callback(new window.Captcha4(config));
+            };
+
+            callbacks[type] = callbacks[type] || [];
+
+            var s = status[type] || 'init';
+            if (s === 'init') {
+                status[type] = 'loading';
+
+                callbacks[type].push(init);
+
+                if(newConfig.gctPath){
+                    load(config, config.protocol, Object.hasOwnProperty.call(config, 'staticServers') ? config.staticServers  : newConfig.staticServers || config.staticServers , newConfig.gctPath, null, function (err){
+                        if(err){
+                            throwError('networkError', config, {
+                                code: '60205',
+                                msg: 'Network failure',
+                                desc: {
+                                    detail: 'gct resource load timeout'
+                                }
+                            });
+                        }
+                    })
+                }
+
+                load(config,  config.protocol, Object.hasOwnProperty.call(config, 'staticServers') ? config.staticServers  : newConfig.staticServers || config.staticServers, newConfig.bypass || (newConfig.staticPath + newConfig.js), null, function (err) {
+                    if (err) {
+                        status[type] = 'fail';
+                        throwError('networkError', config, {
+                            code: '60204',
+                            msg: 'Network failure',
+                            desc: {
+                                detail: 'js resource load timeout'
+                            }
+                        });
+                    } else {
+                        status[type] = 'loaded';
+                        var cbs = callbacks[type];
+                        for (var i = 0, len = cbs.length; i < len; i = i + 1) {
+                            var cb = cbs[i];
+                            if (isFunction(cb)) {
+                                cb();
+                            }
+                        }
+                        callbacks[type] = [];
+                    }
+                });
+            } else if (s === "loaded") {
+                // 判断gct是否需要重新加载
+                if(newConfig.gctPath && !Captcha4IsLoad(newConfig.gctPath)){
+
+                // if(!Captcha4IsLoad(newConfig.gctPath)){
+                  load(config, config.protocol, Object.hasOwnProperty.call(config, 'staticServers') ? config.staticServers  : newConfig.staticServers || config.staticServers , newConfig.gctPath, null, function (err){
+                      if(err){
+                          throwError('networkError', config, {
+                              code: '60205',
+                              msg: 'Network failure',
+                              desc: {
+                                  detail: 'gct resource load timeout'
+                              }
+                          });
+                      }
+                  })
+                }
+                return  init();
+            } else if (s === "fail") {
+              throwError('networkError', config, {
+                code: '60204',
+                msg: 'Network failure',
+                desc: {
+                    detail: 'js resource load timeout'
+                }
+              });
+            } else if (s === "loading") {
+                callbacks[type].push(init);
+            }
+        });
+
+};
+
+
+})(window);

BIN
hybrid/html/captcha4/gt4-loading.gif


+ 375 - 0
hybrid/html/captcha4/index.html

@@ -0,0 +1,375 @@
+<!doctype html>
+<html>
+
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="renderer" content="webkit">
+    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no, viewport-fit=cover" />
+    <title>请通过以下验证</title>
+    <style>
+        body {
+            margin: 0;
+        }
+
+        .title {
+            height: 18px;
+            margin: 15px;
+            font-size: 18px;
+            line-height: 18px;
+        }
+
+        #log {
+            display: none;
+            margin: 0;
+            word-break: break-all;
+        }
+
+        #log.log {
+            display: block;
+        }
+
+        #captcha_index_loading {
+            position: fixed;
+            top: 50%;
+            left: 50%;
+            overflow: hidden;
+            transform: translate(-50%, -50%);
+        }
+
+        #captcha {
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            width: 260px;
+            height: 50px;
+            transform: translate(-50%, -50%);
+        }
+
+        /* loading */
+        .loader {
+            width: 40px;
+            height: 40px;
+        }
+
+        svg path,
+        svg rect {
+            fill: #3973ff;
+        }
+    </style>
+</head>
+
+<body>
+    <div id="log"></div>
+    <div id="captcha"></div>
+
+    <div id="captcha_index_loading">
+        <img class="captcha_index_img loader" id="captcha_img_loading" alt="加载中" style="display: none;">
+    </div>
+    <script>
+        var debug = false;
+        var logEle = document.getElementById('log');
+        var isOffline = false;
+        var indexVersion = '1.0.0'; // 中间页版本号,每次修改文件要进行版本号升级
+        function log(str) {
+            if (!debug) {
+                return;
+            }
+            var p = document.createElement('p');
+            p.appendChild(document.createTextNode(str));
+            logEle.insertBefore(p, logEle.firstChild);
+            // 同时将错误输出到控制台
+            console.log(str);
+        }
+        // 错误构造函数
+        function newError(msg, code, detail) {
+                return {
+                    desc: {
+                        indexVersion: indexVersion,
+                        detail: detail
+                    },
+                    msg: msg,
+                    code: code
+                }
+            }
+            var plusReady = function (callback) {  
+    if (window.plus) {  
+        callback();  
+    } else {  
+        document.addEventListener('plusready', callback);  
+    }  
+};
+        (function () {
+            
+
+            var jsBridge = (function () {
+
+                var callbacks = {
+                    showBox: function () {
+                        captchaObj.showBox &&  captchaObj.showBox();
+                    }
+
+                };
+        
+
+                return {
+                    callback: function (type, data) {
+                        return callbacks[type](data);
+                    },
+                    callNative: function(data){
+                        plusReady(function () {  
+                            uni.postMessage({  
+                                data  
+                            }) 
+                        });
+                        
+                    }
+                }
+            })();
+            // 暴露 jsBridge
+            window.jsBridge = jsBridge;
+            // jsBridge 与 全局全局错误捕获要尽可能早的加载,防止gt4中的错误捕获不到;
+            if (window.addEventListener) {
+                window.addEventListener('error', function (e) {
+                    jsBridge.callNative({
+						time:new Date().getTime(),
+                        type: 'error',
+                        data: newError("gt4-index error", 60302, e.message)
+                    });
+                })
+            } else {
+                window.onerror = function (e) {
+                    jsBridge.callNative({
+						time:new Date().getTime(),
+                        type: 'error',
+                        data: newError("gt4-index error", 60302, e.message)
+                    });
+                }
+            }
+        })();
+    </script>
+
+    <!-- 此链接位置不要改变,防止上面页面错误catch 不到gt4的错误-->
+    <script src="./ct4.js"></script>
+    <script src="./uni.webview.1.5.1.js"></script> 
+    <script>
+        (function () {
+            var startTime = 0;
+            var clearID = 0;
+            var captcha = document.getElementById('captcha');
+            var loadingEle = document.getElementById('captcha_index_loading');
+            var img = document.getElementById('captcha_img_loading');
+
+            var query = location.href.split('?')[1];
+            // 兼容安卓4.3版本样式问题
+            var ua = navigator.userAgent.toLowerCase();
+            if(/Android/.test(window.navigator.userAgent) && /android\s([\w.]+)/.exec(ua)[1] <= 4.3) {
+                loadingEle.style.left = '45%';
+            }
+            
+            // 兼容低版本Object.assign
+            if (typeof Object.assign != 'function') {
+                // Must be writable: true, enumerable: false, configurable: true
+                Object.defineProperty(Object, "assign", {
+                    value: function assign(target, varArgs) { // .length of function is 2
+                    if (target == null) { // TypeError if undefined or null
+                        throw new TypeError('Cannot convert undefined or null to object');
+                    }
+
+                    var to = Object(target);
+
+                    for (var index = 1; index < arguments.length; index++) {
+                        var nextSource = arguments[index];
+
+                        if (nextSource != null) { // Skip over if undefined or null
+                        for (var nextKey in nextSource) {
+                            // Avoid bugs when hasOwnProperty is shadowed
+                            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
+                            to[nextKey] = nextSource[nextKey];
+                            }
+                        }
+                        }
+                    }
+                    return to;
+                    },
+                    writable: true,
+                    configurable: true
+                });
+            }
+            // 默认配置
+            var config = {
+                product: 'bind',
+                onError: function (e) {
+                    // 错误信息中插入版本号
+                    e.desc = Object.assign({}, e.desc, { indexVersion: indexVersion });
+                    jsBridge.callNative({
+						time:new Date().getTime(),
+                        type: 'error',
+                        data: e
+                    });
+                }
+            };
+            function setDebug() {
+                debug = true;
+                logEle.className = 'log';
+            }
+            
+            function paseURI() {
+                return JSON.parse(decodeURIComponent(query.split('=')[1]));
+            }
+
+            function checkArgs(args) {
+                //设置loading
+                img.src = args['loading'] ? args['loading'] : './gt4-loading.gif';
+
+                clearID = setTimeout(function () {
+                    img.style.display = 'inline-block';
+                }, 200);
+
+
+
+                // 是否开启debug
+                if (args['debug']) {
+                    setDebug(true);
+                    startTime = (new Date()).getTime();
+                    log(JSON.stringify(args))
+                }
+
+                // 设置title
+                if (args['title'] && args['title'] != "") {
+                    var h3 = document.createElement('h3');
+                    h3.className = 'title';
+                    h3.appendChild(document.createTextNode(decodeURIComponent(args['title'])));
+                    captcha.appendChild(h3);
+                }
+
+                // 检查必要参数
+                if (!args['captchaId']) {
+                    log('args error: ' + query);
+                }
+
+                // 通过useLocalOffline判断是否会加入宕机效验
+                if (args['useLocalOffline']) {
+                    //宕机启用自己的方法
+                    config.offlineCb = function () {
+
+                        isOffline = true;
+
+                        jsBridge.callNative({
+							time:new Date().getTime(),
+                            type: 'result',
+                            data: {
+                                captcha_id: args['captchaId'],
+                                challenge: args['challenge'],
+                                offline: true
+                            }
+                        });
+                    }
+                }
+            }
+
+            function mergeOptions(args) {
+                for (var k in args) {
+                    if (args.hasOwnProperty(k) &&
+                        ['debug', 'title',  args['type']].indexOf(k) === -1) {
+                        config[k] = args[k];
+                    }
+                }
+            }
+
+            if (!query) {
+                setDebug();
+                log('no query: ' + location.href);
+                return false;
+            }
+
+            // 解析参数
+            var args = paseURI(query);
+
+            // 检查参数
+            checkArgs(args);
+
+            // 合并配置项
+            mergeOptions(args);
+
+            // 初始化验证码
+            var handler = function (captchaObj) {
+                window.captchaObj = captchaObj;
+                captchaObj
+                    .appendTo(captcha)
+                    .onSuccess(function () {
+                        var result = captchaObj.getValidate();
+                        log('Success validate: ' + result);
+                        jsBridge.callNative({
+							time:new Date().getTime(),
+                            type: 'result',
+                            data: result
+                        });
+
+                    })
+                    .onReady(function () {
+                        log('load time: ' + ((new Date()).getTime() - (startTime || 0)));
+                        
+            
+                        jsBridge.callNative({
+							time:new Date().getTime(),
+                            type: 'ready',
+                            data: {
+                                ready: 0
+                            }
+                        })
+                        
+
+                        if (!isOffline) {
+                            // 非宕机模式下获取移动端coreSDK数据
+                            jsBridge.callNative({
+								time:new Date().getTime(),
+                                type: 'get'
+                            })
+                        }
+
+                        clearTimeout(clearID);
+                        loadingEle.style.display = 'none';
+                    })
+                    .onClose(function () {
+
+                        jsBridge.callNative({
+							time:new Date().getTime(),
+                            type: 'close'
+                        });
+                    })
+                    .onError(function (e) {
+                        e.desc && (e.desc.indexVersion = indexVersion);
+                     
+                        jsBridge.callNative({
+							time:new Date().getTime(),
+                            type: 'error',
+                            data: e
+                        });
+                    })
+                    .onFail(function (e) {
+                    
+                        jsBridge.callNative({
+							time:new Date().getTime(),
+                            type: 'fail',
+                            data: e
+                        });
+                    })
+            };
+            
+            try {
+              window.initAlicom4(config, handler);
+            } catch (error) {
+              jsBridge.callNative({
+				  time:new Date().getTime(),
+                  type: 'error',
+                  data: newError("gt4-index error", 60302, '加载验证过程中报错')
+              });
+            }
+
+        })();
+
+    </script>
+</body>
+
+</html>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
hybrid/html/captcha4/uni.webview.1.5.1.js


+ 46 - 25
pages/login/login.vue

@@ -19,7 +19,8 @@
 				<text class="login-text">客服电话:400-052-2130</text>
 			</view>
 		</view>
-		<sliderDialog ref="sliderDialogRef" @emitFun="emitFun" @sliderClose="sliderClose" v-if="sliderFlag"></sliderDialog>
+		<captcha ref="captcha" :config="config" @captchaSuccess="captchaSuccess" @captchaError="captchaError"
+			@captchaFail="captchaFail" @captchaReady="captchaReady" @captchaClose="captchaClose"></captcha>
 	</view>
 </template>
 
@@ -32,9 +33,11 @@
 		login,
 		sendCode
 	} from "@/api/login.js"
-	import sliderDialog from './sliderDialog.vue'
 	import cacheManager from "@/utils/cacheManager.js";
-
+	import captcha from "../../components/captcha4/index.vue";
+	import {
+		toast
+	} from "../../utils/common";
 	export default {
 		data() {
 			return {
@@ -50,40 +53,57 @@
 				},
 				sliderData: {},
 				sliderDialogRef: null,
-				sliderFlag: false,
+				config: {
+					captchaId: "16e4de331cee10dfe36bcf55810c6041",
+				},
 
 			}
-		},   
+		},
 		components: {
-			sliderDialog
-        },
+			captcha
+		},
 		onLoad(options) {
 			this.loginInit(options);
 		},
 		onReady() {},
 		methods: {
-			emitFun(data){
-				this.sliderFlag =false;
+
+			captchaSuccess(result) { // app端的回调
+				console.log(result)
 				this.startCountdown();
-				this.sliderData =data;
+				this.sliderData = result;
 				this.getYzmBtn();
+
+			},
+			captchaError(e) {
+				// app端的回调
+				toast(JSON.stringify(e))
 			},
-			sliderClose(){
-				this.sliderFlag =false;
+			captchaReady() {
+				// app端的回调
 			},
+			captchaFail() {
+				// app端的回调
+				toast('验证失败!')
+			},
+			captchaClose() {
+				uni.redirectTo({
+					url: `/pages/login/index`
+				})
+			},
+
 			loginInit(options) {
 				this.loginData.phoneNumber = options.telNum;
-				this.sliderFlag = true;
 			},
 			getYzmBtn() {
 				let req = {
-					appkey: "FFFF0N00000000007EC0",
 					phone: this.loginData.phoneNumber,
-					scene: "nc_message_h5',",
-					sessionid: this.sliderData.sessionId,
-					sig: this.sliderData.sig,
-					token: this.sliderData.token,
+					captchaOutput: this.sliderData.captcha_output,
+					genTime: this.sliderData.gen_time,
+					lotNumber: this.sliderData.lot_number,
+					passToken: this.sliderData.pass_token,
 				}
+				console.log('req', req);
 				sendCode(req).then(res => {
 
 				})
@@ -95,8 +115,8 @@
 				}
 				login(req).then(res => {
 					if (res.code == 0) {
-						cacheManager.set('auth',res.data)
-						if (res.data.cardId == 0 ) {
+						cacheManager.set('auth', res.data)
+						if (res.data.cardId == 0) {
 							uni.redirectTo({
 								url: `/pages/selectGradesTerms/index`
 							})
@@ -123,8 +143,8 @@
 				this.loginData.clearYzmIcon = false;
 			},
 			startCountdown() {
-				if(this.loginData.buttonText === '重新发送'){
-					this.sliderFlag = true;
+				if (this.loginData.buttonText === '重新发送') {
+					this.$refs.captcha.showCaptcha();
 				}
 				this.loginData.isDisabled = true;
 				this.loginData.buttonText = `重新发送(${this.loginData.timeLeft}S)`;
@@ -133,7 +153,7 @@
 				if (this.loginData.intervalId) {
 					clearInterval(this.loginData.intervalId);
 				}
-				
+
 				// 设置新的定时器
 				this.loginData.intervalId = setInterval(() => {
 					this.loginData.timeLeft--;
@@ -147,7 +167,7 @@
 					}
 				}, 1000);
 			},
-			
+
 			goIndex() {
 				uni.redirectTo({
 					url: `/pages/login/index`
@@ -156,6 +176,7 @@
 
 		},
 		mounted() {
+			this.$refs.captcha.showCaptcha();
 		},
 	}
-</script>
+</script>

+ 0 - 113
pages/login/sliderDialog.vue

@@ -1,113 +0,0 @@
-<template>
-	<view class="slider-check-dialog">
-		<view class="slider-check-content">
-			<view class="slider-close" @click="sliderClose(AWSC)"></view>
-			<view class="slider-check-tip" :class="{ 'slider-tip-red': isSlider}">请滑动下方滑块,完成验证</view>
-			<view id="yzm-slider"></view>
-			<text @click="AWSC.emitData" class="slider-check-btn"></text>
-		</view>
-	</view>
-</template>
-<script>
-	export default {
-		mounted() {
-		},
-		data() {
-			return {
-				sliderObj: {
-					sessionId: '',
-					sig: '',
-					token: '',
-				},
-				isSlider:false,
-			}
-		},
-		methods: {
-			receiveRenderData(data) {
-				this.$emit('emitFun', data)
-			},
-			sliderClose(AWSC) {
-				AWSC.getReset();
-				// this.$emit('sliderClose')
-				uni.redirectTo({
-					url: `/pages/login/index`
-				})
-			}
-		}
-	}
-</script>
-
-<script module="AWSC" lang="renderjs">
-	export default {
-		mounted() {
-			const script = document.createElement('script');
-			script.src = 'https://g.alicdn.com/AWSC/AWSC/awsc.js';
-			document.body.appendChild(script);
-			script.onload = () => {
-				this.init()
-			}
-		},
-		data() {
-			return {
-				sessionId: '',
-				sig: '',
-				token: '',
-				nc:null,
-			}
-		},
-		methods: {
-			init() {
-				let that  =this
-				AWSC.use("nc", function(state, module) {
-				that.nc = module.init({
-						// 应用类型标识。它和使用场景标识(scene字段)一起决定了滑动验证的业务场景与后端对应使用的策略模型。您可以在阿里云验证码控制台的配置管理页签找到对应的appkey字段值,请务必正确填写。
-						appkey: "FFFF0N00000000007EC0",
-						//使用场景标识。它和应用类型标识(appkey字段)一起决定了滑动验证的业务场景与后端对应使用的策略模型。您可以在阿里云验证码控制台的配置管理页签找到对应的scene值,请务必正确填写。
-						scene: "nc_message_h5",
-						// 声明滑动验证需要渲染的目标ID。
-						renderTo: "yzm-slider",
-						//前端滑动验证通过时会触发该回调参数。您可以在该回调参数中将会话ID(sessionId)、签名串(sig)、请求唯一标识(token)字段记录下来,随业务请求一同发送至您的服务端调用验签。
-						success: function(data) {
-							that.getData(data)
-						},
-						// 滑动验证失败时触发该回调参数。
-						fail: function(failCode) {
-							console.log('失败:' + failCode)
-						},
-						// 验证码加载出现异常时触发该回调参数。
-						error: function(errorCode) {
-							console.log('异常:' + errorCode)
-						}
-					});
-				})
-			},
-			getReset(){
-				this.sessionId = '';
-				this.sig = '';
-				this.token = '';
-				this.nc.reset();
-			},
-			getData(data){
-					this.isSlider = false;
-					console.log(data)
-					this.sessionId  =data.sessionId
-					this.sig  =data.sig
-					this.token  =data.token
-					AWSC.emitData;
-			},
-			emitData(e, ownerInstance) {
-				if(this.sessionId){
-					ownerInstance.callMethod('receiveRenderData', {
-						sessionId: this.sessionId,
-						sig: this.sig,
-						token: this.token
-					})
-				}else{
-					this.isSlider = true;
-				}
-				
-			}
-
-		}
-	}
-</script>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است