支付宝H5 jssdk 代码详细注释 - 压缩变量已重命名

110 阅读6分钟

支付宝H5 jssdk: as.alipayobjects.com/g/component…

/**
 * 支付宝 H5 端 JS SDK 核心库
 * 提供与支付宝客户端原生功能的交互能力
 */
!function(global, factory) {
  // 模块化支持:CommonJS/AMD/CMD/全局变量
  "undefined" != typeof module && module.exports 
    ? module.exports = factory() 
    : "function" == typeof define && (define.amd || define.cmd) 
      ? define(factory) 
      : (global.ant = global.Ali = global.Ali || {}, factory.call(global, global.Ali));
}(this, function(Alipay) {
  "use strict";

  // 设备检测工具方法
  function isAndroid() {
    return /android/i.test(Alipay.ua);
  }

  function isiOS() {
    return /iphone|ipad/i.test(Alipay.ua);
  }

  // 类型检查工具方法
  function isFunction(obj) {
    return "function" === getType(obj);
  }

  function isString(obj) {
    return "string" === getType(obj);
  }

  function isObject(obj) {
    return "object" === getType(obj);
  }

  function isNumber(obj) {
    return "number" === getType(obj);
  }

  // 获取对象类型的基础方法
  function getType(obj) {
    return Object.prototype.toString.call(obj).replace(/\[object (\w+)\]/, "$1").toLowerCase();
  }

  // 对象属性合并方法
  function mergeOptions(target, source) {
    if (source) {
      for (var key in source) {
        target[key] = source[key];
      }
    }
    return target;
  }

  // 调试日志记录方法
  function logDebug() {
    if (Alipay.debug > 0) {
      var timestamp = +new Date;
      var args = [].slice.call(arguments);
      console.log(timestamp, args);
      
      // 更高级别调试模式下记录诊断信息
      if (Alipay.debug > 1) {
        Alipay.diagnose(timestamp + "^" + JSON.stringify(args));
      }
    }
  }

  // 回调处理统一方法
  function processCallback(result, apiName) {
    result = result || {};
    result.errorCode = result.error || 0;
    
    // 错误码处理
    if (result.errorCode > 0 && result.errorCode < 10) {
      console.error(apiName + " error: errorCode: " + result.errorCode + ", errorMessage: " + result.errorMessage);
    } else {
      logDebug(apiName + ", callback:", result);
    }
    
    return result;
  }

  // 版本比较方法
  function compareVersion(requiredVersion) {
    var currentVersionParts = Alipay.alipayVersion.split(".");
    requiredVersion = requiredVersion.split(".");
    
    for (var i = 0; i < currentVersionParts.length; i++) {
      var requiredPart = parseInt(requiredVersion[i], 10) || 0;
      var currentPart = parseInt(currentVersionParts[i], 10) || 0;
      
      if (requiredPart > currentPart) return -1; // 当前版本低于要求
      if (currentPart > requiredPart) return 1;  // 当前版本高于要求
    }
    
    return 0; // 版本相同
  }

  // 初始化 SDK
  Alipay = Alipay || {};
  
  // 基础环境信息
  Alipay.ua = navigator.userAgent;
  Alipay.version = "1.1.0";
  Alipay.isAlipay = Alipay.ua.indexOf("AlipayClient") > -1 || Alipay.ua.indexOf("AliApp(AP") > -1;
  
  // 非支付宝环境警告
  if (!Alipay.isAlipay) {
    console.warn("请在支付宝客户端中运行 antBridge.js!");
  }
  
  // 获取支付宝版本号
  Alipay.alipayVersion = function() {
    if (Alipay.isAlipay) {
      var matchResult = Alipay.ua.match(/AlipayClient\/(.*)/);
      return matchResult && matchResult.length ? matchResult[1] : "";
    }
  }();
  
  // 应用信息
  Alipay.appinfo = {
    engine: "alipay",
    engineVer: Alipay.alipayVersion,
    name: "alipay",
    ver: Alipay.alipayVersion
  };

  // 事件绑定方法
  Alipay.on = function(eventNames, callback) {
    eventNames.split(/\s+/g).forEach(function(eventName) {
      document.addEventListener(eventName, callback, !1);
    });
  };

  // 调用支付宝原生API
  Alipay.call = function() {
    var args = [].slice.call(arguments);
    
    // 检查支付宝JSBridge是否已加载
    if (window.AlipayJSBridge && window.AlipayJSBridge.call) {
      var apiName = args[0];
      var options = args[1] || {};
      var callback = args[2];
      
      // 参数验证
      if (!isString(apiName)) {
        return void console.error("apiName错误:", apiName);
      }
      
      // 处理回调函数位置
      if (typeof callback === "undefined" && isFunction(options)) {
        callback = options;
        options = {};
      }
      
      if (!isObject(options)) {
        return void console.error(apiName + ": options必须是对象");
      }
      
      // 包装回调函数进行统一错误处理
      var originalCallback = callback;
      callback = function(result) {
        result = processCallback(result, apiName);
        originalCallback && originalCallback(result);
      };
      
      // 记录API调用日志(除远程日志外)
      if ("remoteLog" !== apiName) {
        logDebug("AlipayJSBridge.call:", apiName, options, originalCallback);
      }
      
      // 调用原生API
      window.AlipayJSBridge.call(apiName, options, callback);
    } else {
      // 桥接未准备好时缓存API调用
      Alipay._apiQueue = Alipay._apiQueue || [];
      Alipay._apiQueue.push(args);
    }
  };

  // JSBridge就绪处理
  Alipay._ready = function(callback) {
    if (window.AlipayJSBridge && window.AlipayJSBridge.call) {
      callback && callback();
    } else {
      Alipay.on("AlipayJSBridgeReady", callback);
    }
  };
  
  // 兼容旧版本API
  Alipay.ready = Alipay.ready || Alipay._ready;

  // 显示提示框
  Alipay.toast = function(message, callback) {
    if (isString(message) || isNumber(message)) {
      message = { text: message + "" };
    }
    
    message = message || {};
    message.content = message.text;
    message.duration = message.duration || 2000;
    
    // 安卓环境下对duration的特殊处理
    if (callback && isNumber(message.duration) && isAndroid()) {
      message.duration = message.duration < 2500 ? 2000 : 3000;
      Alipay.call("toast", message);
      setTimeout(callback, message.duration);
    } else {
      Alipay.call("toast", message, callback);
    }
  };

  // 设置标题栏
  Alipay.setTitle = function(options, callback) {
    var params = { type: "title" };
    
    if (isString(options)) {
      options = { title: options };
    }
    
    options.title = options.title || options.text;
    mergeOptions(params, options);
    
    if (params.title === null) {
      console.error("setTitle: title是必需参数!");
      return false;
    }
    
    Alipay.call("setTitle", params, callback);
  };

  // 显示标题栏
  Alipay.showTitle = function(callback) {
    Alipay.call("showTitlebar", callback);
  };

  // 隐藏标题栏
  Alipay.hideTitle = function(callback) {
    Alipay.call("hideTitlebar", callback);
  };

  // 显示加载提示
  Alipay.showLoading = function(options, callback) {
    if (isString(options) || isNumber(options)) {
      options = { text: options + "" };
    }
    
    options = options || {};
    options.delay = options.delay || 1000;
    
    // iOS环境下的延迟处理
    if (isNumber(options.delay) && isiOS()) {
      var delayTime = options.delay;
      delete options.delay;
      
      var timerId = setTimeout(function() {
        Alipay.call("showLoading", options, callback);
      }, delayTime);
      
      // 存储定时器ID以便后续清除
      Alipay._stLoadingQueue = Alipay._stLoadingQueue || [];
      Alipay._stLoadingQueue.push(timerId);
      return timerId;
    }
    
    Alipay.call("showLoading", options, callback);
  };

  // 隐藏加载提示
  Alipay.hideLoading = function(callback) {
    // 清除所有待执行的加载提示
    if (Array.isArray(Alipay._stLoadingQueue) && Alipay._stLoadingQueue.length) {
      logDebug("clearLoadingCount: " + Alipay._stLoadingQueue.length);
      while (Alipay._stLoadingQueue.length) {
        clearTimeout(Alipay._stLoadingQueue.shift());
      }
    }
    
    Alipay.call("hideLoading", callback);
  };

  // 页面跳转
  Alipay.pushWindow = function(options, callback) {
    if (isString(options)) {
      options = { url: options };
    }
    
    options = options || {};
    
    if (options.url) {
      // 安卓8.3以下版本不支持param参数警告
      if (options.param && isAndroid() && compareVersion("8.3") < 0) {
        console.warn('Ali.pushWindow: 安卓8.3以下客户端不支持使用"param"参数');
      }
      
      Alipay.call("pushWindow", options, callback);
    } else {
      console.error("Ali.pushWindow: url是必需参数!");
      return false;
    }
  };

  // 返回上一页
  Alipay.popWindow = function(options, callback) {
    Alipay.call("popWindow", options, callback);
  };

  // 返回指定页面
  Alipay.popTo = function(options, callback) {
    if (isNumber(options)) {
      options = { step: options };
    } else if (isString(options)) {
      options = { urlPattern: options };
    }
    
    if (typeof options.step !== "undefined") {
      options.index = options.step;
    }
    
    Alipay.call("popTo", options, callback);
  };

  // 登录接口
  Alipay.login = function(callback) {
    Alipay.call("login", callback);
  };

  // 交易支付
  Alipay.tradePay = function(options, callback) {
    Alipay.call("tradePay", options, callback);
  };

  // H5交易支付(不支持,提示错误)
  Alipay.h5TradePay = function(options, callback) {
    console.error("支付宝客户端不支持Ali.h5TradePay,请使用Ali.tradePay");
    callback && callback({ errorCode: 1, errorMessage: "接口不存在" });
  };

  // 地理位置相关API
  Alipay.geolocation = {};
  Alipay.geolocation.getCurrentPosition = function(options, callback) {
    if (typeof callback === "undefined" && isFunction(options)) {
      callback = options;
      options = null;
    }
    
    options = options || { timeout: 15000 };
    
    // 设置超时处理
    var timeoutTimer = setTimeout(function() {
      timeoutTimer = null;
      console.error("geolocation.getCurrentPosition: 调用超时");
      var errorResult = { errorCode: 5, errorMessage: "调用超时" };
      callback && callback(errorResult);
    }, options.timeout);
    
    Alipay.call("getLocation", function(result) {
      if (timeoutTimer) {
        clearTimeout(timeoutTimer);
        
        // 规范化返回结果
        result.coords = {};
        result.coords.latitude = +result.latitude;
        result.coords.longitude = +result.longitude;
        result.city = result.city ? result.city : result.province;
        result.cityCode = result.citycode;
        result.address = result.pois;
        
        callback && callback(result);
      }
    });
  };

  // 摇一摇功能
  Alipay.shake = {};
  Alipay.shake.watch = function(options, callback) {
    Alipay.call("watchShake", options, callback);
  };

  // 振动功能
  Alipay.vibration = {};
  Alipay.vibration.vibrate = function(options, callback) {
    if (isNumber(options)) {
      options = { duration: options };
    }
    
    Alipay.call("vibrate", options, callback);
  };

  // 网络相关API
  Alipay.network = {};
  Alipay.network.getType = function(options, callback) {
    if (typeof callback === "undefined" && isFunction(options)) {
      callback = options;
      options = null;
    }
    
    options = options || { timeout: 15000 };
    
    // 设置超时处理
    var timeoutTimer = setTimeout(function() {
      timeoutTimer = null;
      console.error("network.getType: 调用超时");
      var errorResult = { errorCode: 5, errorMessage: "调用超时" };
      callback && callback(errorResult);
    }, options.timeout);
    
    Alipay.call("getNetworkType", function(result) {
      if (timeoutTimer) {
        clearTimeout(timeoutTimer);
        
        // 规范化返回结果
        result.networkAvailable = "fail" !== result.networkType;
        result.is3G = result.is2G = result.isE = result.isG = result.isH = false;
        result.isWifi = "wifi" === result.networkType;
        result.isOnline = result.networkAvailable;
        result.type = result.networkType;
        
        callback && callback(result, result.networkAvailable);
      }
    });
  };

  // 日历相关API
  Alipay.calendar = {};
  Alipay.calendar.add = function(options, callback) {
    if (compareVersion("8.3") < 0) {
      console.error("Ali.calendar.add: 请在8.3及以上版本使用");
      callback && callback({ errorCode: 1, errorMessage: "接口不存在" });
    } else {
      Alipay.call("addEventCal", options, callback);
    }
  };

  // 拍照/选图功能
  Alipay.photo = function(options, callback) {
    if (typeof callback === "undefined" && isFunction(options)) {
      callback = options;
      options = {};
    }
    
    // 设置默认参数
    var defaultOptions = {
      format: "jpg",
      dataType: "dataurl",
      quality: 50,
      allowEdit: false,
      src: undefined,
      cameraType: undefined,
      maskImg: undefined,
      maskWidth: undefined,
      maskHeight: undefined
    };
    
    options = mergeOptions(defaultOptions, options);
    options.imageFormat = options.format;
    
    // 兼容处理
    if ("remoteurl" == options.dataType) {
      options.dataType = "dataurl";
    }
    
    options.dataType = options.dataType.slice(0, -3) + options.dataType.slice(-3).toUpperCase();
    
    Alipay.call("photo", options, function(result) {
      if (result.dataURL) {
        result.dataURL = "data:image/" + options.imageFormat + ";base64," + result.dataURL;
      }
      
      result.photo = result.dataURL || result.fileURL;
      result.errorMessage = 10 == result.error ? "用户取消" : result.errorMessage;
      
      callback && callback(result);
    });
  };

  // 联系人相关API
  Alipay.contacts = {};
  Alipay.contacts.get = function(options, callback) {
    if (typeof callback === "undefined" && isFunction(options)) {
      callback = options;
      options = null;
    }
    
    options = options || {};
    
    // 仅支持单选
    if (options.multiple) {
      console.error("仅支持单选");
    }
    
    Alipay.call("contact", options, function(result) {
      // 规范化返回结果
      result.results = [];
      result.results[0] = {
        phoneNumber: result.mobile,
        email: undefined,
        name: result.name
      };
      
      // 错误码处理
      switch (result.errorCode) {
        case 10:
          result.errorMessage = "没有权限";
          break;
        case 11:
          result.errorMessage = "用户取消操作";
          break;
      }
      
      callback && callback(result);
    });
  };

  // 分享功能
  Alipay.share = function(options, callback) {
    // 分享渠道映射表
    var channelMap = {
      1: "Weixin",
      2: "Weibo",
      4: "SMS",
      8: "LaiwangContacts",
      16: "LaiwangTimeline",
      32: "WeixinTimeLine",
      64: "CopyLink"
    };
    
    options = options || {};
    
    // 处理特定渠道兼容性
    if (options.channels && options.channels.length > 0) {
      if (isAndroid()) {
        options.channels.forEach(function(channel) {
          if ("qzone" === channel.name.toLowerCase()) {
            channel.name = "QQZone";
          }
        });
      }
    } else {
      // 兼容旧版分享方式
      options.title = options.title || "";
      options.content = options.text;
      options.imageUrl = options.image;
      options.captureScreen = !!options.captureScreen;
      options.url = options.url || "";
      
      var newOptions = { channels: [] };
      
      if (typeof options.shareType === "undefined") {
        options.shareType = -1;
      }
      
      // 生成渠道列表
      for (var key in channelMap) {
        if (Number(key) & options.shareType) {
          newOptions.channels.push({
            name: channelMap[key],
            param: options
          });
        }
      }
      
      options = newOptions;
    }
    
    Alipay.call("share", options, callback);
  };

  // 调试模式设置
  Alipay.debugEnabled = function(enabled) {
    Alipay.debug = enabled === true ? 2 : 1;
  };

  // 获取启动参数
  Alipay.getLaunchParams = function(callback) {
    Alipay._ready(function() {
      Alipay.launchParams = AlipayJSBridge.startupParams;
      callback && callback(Alipay.launchParams);
    });
  };

  // 设置选项菜单
  Alipay.setOptionMenu = function(options, callback) {
    if (isString(options)) {
      options = /^http/i.test(options) ? { icon: options } : { title: options };
    }
    
    Alipay.call("setOptionMenu", options, callback);
  };

  // 显示提示对话框
  Alipay.alert = function(options, callback) {
    if (isString(options) || isNumber(options)) {
      options = { message: options + "" };
    }
    
    Alipay.call("alert", options, callback);
  };

  // 显示确认对话框
  Alipay.confirm = function(options, callback) {
    if (isString(options) || isNumber(options)) {
      options = { message: options + "" };
    }
    
    Alipay.call("confirm", options, callback);
  };

  // 在浏览器中打开
  Alipay.openInBrowser = function(options, callback) {
    if (isString(options)) {
      options = { url: options };
    }
    
    Alipay.call("openInBrowser", options, callback);
  };

  // 诊断信息上报
  Alipay.diagnose = function(message) {
    // iOS环境下可用
    if (!isiOS()) {
      return console.warn("diagnose方法仅在iOS环境可用");
    }
    
    // 处理不同类型的消息
    if (isObject(message) || Array.isArray(message)) {
      message = JSON.stringify(message);
    } else if (!isString(message) && !isNumber(message)) {
      return console.error("diagnose参数必须是字符串或JSON对象");
    }
    
    // 构建上报数据
    message = location.href + ": " + message;
    var params = {
      type: "diagnose",
      seedId: "H5_DIAGNOSED_JSLOG",
      param1: message
    };
    
    var apiCall = ["remoteLog", params];
    
    // 调用原生API
    if (window.AlipayJSBridge && window.AlipayJSBridge.call) {
      window.AlipayJSBridge.call("remoteLog", params);
    } else {
      Alipay._apiQueue = Alipay._apiQueue || [];
      Alipay._apiQueue.push(apiCall);
    }
  };

  // 动画帧请求
  Alipay.requestAnimationFrame = function(callback) {
    var requestFunc = window.requestAnimationFrame || 
                      window.webkitRequestAnimationFrame || 
                      window.mozRequestAnimationFrame;
    
    return requestFunc ? requestFunc(callback) : console.error("不支持requestAnimationFrame!");
  };

  // mtop API调用
  Alipay.mtop = function(options, callback) {
    // 兼容旧版参数名
    if (typeof options.needWua !== "undefined" && typeof options.isNeedWua === "undefined") {
      options.isNeedWua = options.needWua;
    }
    
    Alipay.call("mtop", options, callback);
  };

  // 操作菜单
  Alipay.actionSheet = function(options, callback) {
    // 安卓环境下强制设置标题(原生要求)
    if (isAndroid() && (typeof options.title === "undefined" || options.title === "")) {
      options.title = " ";
    }
    
    Alipay.call("actionSheet", options, callback);
  };

  // JSBridge就绪后处理队列中的API调用
  Alipay._ready(function() {
    function processApiQueue() {
      Alipay.requestAnimationFrame(function() {
        var apiCall = apiQueue.shift();
        Alipay.call.apply(null, apiCall);
        if (apiQueue.length) {
          processApiQueue();
        }
      });
    }
    
    logDebug("AlipayJSBridgeReady");
    var apiQueue = Alipay._apiQueue || [];
    
    // 处理缓存的API调用
    if (!!apiQueue.length) {
      processApiQueue();
    }
  });

  // 批量注册其他API
  [
    "startApp", "showOptionMenu", "hideOptionMenu", "showToolbar", "hideToolbar", 
    "closeWebview", "sendSMS", "scan", "getSessionData", "setSessionData", 
    "checkJSAPI", "checkApp", "isInstalledApp", "deposit", "chooseContact", 
    "alipayContact", "getConfig", "getCities", "rsa", "getWifiList", 
    "connectWifi", "notifyWifiShared", "thirdPartyAuth", "getThirdPartyAuthcode", 
    "setToolbarMenu", "exitApp", "hideBackButton", "startApp", "startPackage", 
    "getSharedData", "setSharedData", "removeSharedData", "setClipboard", 
    "startDownload", "stopDownload", "getDownloadInfo", "detectBeacons", 
    "startBeaconsBeep", "stopBeaconsBeep", "startIndoorLocation", "stopIndoorLocation", 
    "addEventCal", "startSpeech", "stopSpeech", "cancelSpeech", "getWifiInfo", 
    "clearAllCookie", "getMtopToken", "getClientInfo", "sinasso", "getClipboard", 
    "checkBLEAvalability", "scanBeacons", "isSpeechAvailable", "speechRecognizer", 
    "contactSync", "setGestureBack", "remoteLog", "httpRequest", "rpc", "ping", 
    "snapshot", "imageViewer", "upload", "networkAnalysis", "showTitleLoading", 
    "hideTitleLoading", "getLocation"
  ].forEach(function(apiName) {
    Alipay[apiName] = function() {
      var args = [].slice.call(arguments);
      Alipay.call.apply(null, [apiName].concat(args));
    };
  });

  return Alipay;
});