JavaScript 接口

打开/返回

原生支持 window.open / window.close 系统 js 函数。

App 默认会在新窗口中打开链接,并拥有原生的页面切换动画效果。

对于部分深度应用 ajax 加载的网站,App 可能无法准确截获用户操作的 URL 链接,也就无法在新窗口打开页面,此时推荐使用 open js方法。

点原生标题栏上的“后退/返回”按钮即可回到上一个页面,如未启用或隐藏了原生标题栏,执行 close js函数即可返回。

jsBridge

请下载 最新版 js SDK 解压并引入 jsbridge-mini.js 到您的网页。全部 js 接口请参考 DEMO 演示页


<script src="jsbridge-mini.js"></script>

一般情况下,App 会自动初始化 jsBridge 接口,在引用 jsbridge-mini.js 之后可以直接使用 jsBridge 下的方法。

但为保险起见,我们推荐你在 jsBridge.ready 之后调用接口方法,形如:


<script src="jsbridge-mini.js"></script>
<script>
    jsBridge.ready(function () {    
        //jsBridge.share();       //分享
        //jsBridge.wxPay();       //微信APP支付
        //jsBridge.aliPay();      //支付宝APP支付
        //...
    });
</script>
社交化分享 share

目前支持分享到 微信朋友圈、微信好友、QQ好友和QQ空间。

App 默认会在 “App 配置” - “原生标题栏” 显示分享按钮,一般无需在网站集成此 js 接口。


jsBridge.share({
    //分享到,0 微信朋友圈,1 微信好友,2 QQ好友,3 QQ空间;未指定则弹出分享菜单
    to    : 0,
    //标题,未指定则为当前页面 title 标题
    title : "可以指定标题",
    //链接,未指定则为当前页面链接
    link  : "http://m.baidu.com",
    //图标,未指定则为 App 图标
    imgUrl: "https://m.baidu.com/static/search/baiduapp_icon.png",
    //描述,如未指定,App 会尝试抓取页面 meta description content,<meta name="description" content="页面描述..." />
    //均无描述内容则显示链接
    desc: "摘要:内事问百度,外事找谷歌,你懂的。" 
}, function(succ) {
    alert(succ ? "分享成功" : "分享失败或取消了分享");
});

//弹出分享菜单,并处理分享结果 jsBridge.share(null, function(succ) { //do something... });
//弹出分享菜单,并指定分享标题 jsBridge.share({ title: "指定分享出去的标题" });
分享多张图片到微信朋友圈、QQ空间等

一键分享多图到微信朋友圈、QQ空间(iOS)等,即大家常说的朋友圈九宫格多图,最多支持9张一键分享。

jsBridge.shareImages({
    text  : "这是一小段说明文本",
    images: ["imageUrl1", "imageUrl2"] //以 http 打头的图片链接数组,最多9张
}, function(succ) {    
    //仅苹果版支持回调分享结果
    if (succ) {
        alert("发送成功");
    } else {
        alert("失败或取消了");
    }
});
多图浏览

一键分享多图到微信朋友圈、QQ空间(iOS)等,即大家常说的朋友圈九宫格多图,最多支持9张一键分享。


jsBridge.showImages({
  //屏幕方向 0自适应,1横屏,2竖屏,不提供则用APP设置值
  screenOrientation: 0,
  //显示保存到相册按钮,不提供则用APP设置值
  save: true,
  //显示一键分享多图按钮,不提供则用APP设置值
  share: true,
  //多图分享摘要文字,不提供则为网页标题+链接
  share_text: "WebApp快捷打包 多图分享摘要",
  //图片组, text 是文字说明
  items:[
    {
      url :"http://i.cdn.yimenapp.com/sys/1.jpg",
      text:"美丽的大自然 01"
    },
    {
      url :"http://i.cdn.yimenapp.com/sys/2.jpg",
      text:"美丽的大自然 02"
    },
    {
      url :"http://i.cdn.yimenapp.com/sys/3.jpg"
    },
    {
      url :"http://i.cdn.yimenapp.com/sys/4.jpg"
    },
    {
      url :"http://i.cdn.yimenapp.com/sys/5.jpg"
    },
    {
      url :"http://i.cdn.yimenapp.com/sys/6.jpg",
      text:"美丽的湖泊"
    },
    {
      url :"http://i.cdn.yimenapp.com/sys/7.jpg"
    }
  ]
});


//如果启用双击屏幕自动触发多图浏览,APP会用如下函数获取图片数据,请注意 HTML 页面结构; //minWidth、minHeight参数分别为你设置的图片最小高、宽 (px像素),注意是图显示高宽,不是图片实际尺寸; (function (w, h) { var r = { share_text: document.title + ' ' + location.href, items: [] }; var imgs = document.getElementsByTagName('img'); for (var i = 0; i < imgs.length; i++) { var img = imgs[i]; if ((img.width >= w) && (img.height >= h)) { r.items.push({ url: img.src }); } } return r; })(minWidth, minHeight);
扫一扫 scan

使用相机扫码,兼容二维码与条码。

可以在 “App 配置” - “原生标题栏” - “首页标题栏显示 扫一扫 按钮”,无需在网站集成此 js 接口。


jsBridge.scan({
    needResult: true, //默认为false,扫描结果由App处理;true则直接返回扫描结果
}, function(code) {
    if (code) {
        alert(code);
    } else {
        alert("扫码失败或取消了扫码");
    }
});

//直接启动扫码,扫码结果由 App 处理(如果是链接则打开链接,否则显示扫码内容) jsBridge.scan();
缓存 cacheSize/clearCache

cacheSize 获取 App 本地缓存大小,clearCache 清除缓存。

可以在 “App 配置” - “缓存管理” - “打开首页前先自动清除缓存”,无需在网站集成此 js 接口。


jsBridge.cacheSize(function(size) {
    alert(size + "字节");
});

jsBridge.clearCache(function() { alert("本地缓存已清除"); });
微信APP wxAppInstalled

判断用户设备是否安装了微信APP

为遵守苹果APP上架审核政策,请最好调用此函数判断设备是否已安装了微信客户端,如果没安装微信,就不要呈现微信登录等功能,以免因此被拒。


jsBridge.wxAppInstalled(function(installed) {
    alert(installed ? "安装了微信客户端" : "没有安装");
});
微信登录 wxLogin

呼出微信APP,授权同步登录。参考官方文档

jsBridge.wxLogin(callback); callback 参数可以是一个 url 字符串或者是 function 回调函数。
♦ callback 是个 url 字符串: 登录授权成功后App会将用于换取access_token的code附加到url并跳转到这个地址;
♦ callback 是个 function 函数: function(success, object){} , success - 是否成功授权登录,object - 错误信息或授权登录数据;

如果你在“APP 配置” - “微信分享”表单填写了有效的“AppSecret”,APP会自动帮你用授权code及AppSecret获取access_token和userinfo用户信息返回给你,免去重写代码的麻烦; 如果觉得这种方式不够安全,你可以把 AppSecret 留空,拿到 code 过后自己在服务器上去调用微信接口获取 access_token

注意:要在 微信开放平台 一年交300元钱通过认证之后,你的移动应用才能获得微信的登录接口。


//通过 url 跳转回调
//必有参数 code (用于换取 access_token)
//如果配置了有效的 AppSecret ,还会返回 openid, access_token, userinfo(json字符串 JSON.stringify(userinfo))
jsBridge.wxLogin("/doc/u.cshtml");

//通过 function 回调 jsBridge.wxLogin(function(succ, obj) { if (succ) { //obj 是个 json 对象,如 // { // code: "qqqqqqqqqqqqqqq", // openid: "wwwwwwwwwwwwwww", // access_token: "aaaaaaaaaaaaaaa", // userinfo: { // nickname: "sssssss" // //... // } // } // alert(JSON.stringify(obj)); } });
QQ登录 qqLogin

呼出手机QQ,授权同步登录。参考官方文档

jsBridge.qqLogin(callback); callback 与微信登录雷同,可以是个 url 字符串或者 function 函数

注意:QQ登录需要在 http://open.qq.com/ 提交移动应用上架审核通过后才能被普通用户使用, 测试期间要在腾讯开放平台点进你的移动应用 - “基础服务” - “QQ登录” - “应用调试者”填写测试用的QQ号。


//通过 url 跳转回调
//返回的参数有 openid, access_token, userinfo(json字符串 JSON.stringify(userinfo))
jsBridge.qqLogin("/doc/u.cshtml");

//通过 function 回调 jsBridge.qqLogin(function(succ, obj) { if (succ) { //obj 是个 json 对象,如 // { // openid: "wwwwwwwwwwwwwww", // access_token: "aaaaaaaaaaaaaaa", // userinfo: { // nickname: "sssssss" // //... // } // } // alert(JSON.stringify(obj)); } });
微信App支付 wxPay

微信 App 支付的相关说明 请参考腾讯官方

接入方式一: 需要在 “App 配置” - “微信支付” 提交账户信息

URL 支付,将支付信息提交到本平台地址 https://g.yimenyun.net/pay/ , POST/GET 方式均可。
参数说明:
 channel: 支付渠道, 0 微信, 1 支付宝
 orderid: 订单号
 title: 订单名称
 amount: 支付金额(元)
 url_succ: 支付成功后跳转的链接
 url_fail: 支付失败跳转的链接
注意,要对各参数进行 UrlEncode UTF-8 编码

收到支付通知一定要比对支付金额与订单应付金额是否相符,切记。

  
//示例:调用微信App完成名称为 购买VIP会员 的订单 201701010001 0.01元支付;
支付成功跳转到https://m.baidu.com/,失败跳转到 https://xw.qq.com/

https://g.yimenyun.net/pay/?channel=0&orderid=201701010001&title=%e8%b4%ad%e4%b9%b0VIP%e4%bc%9a%e5%91%98&amount=0.01&url_succ=https%3A%2F%2Fm.baidu.com%2F&url_fail=https%3A%2F%2Fxw.qq.com%2F

接入方式二: 需要在 “App 配置” - “微信支付” 提交账户信息

js 便捷支付

收到支付通知一定要比对支付金额与订单应付金额是否相符,切记。


jsBridge.pay({
    channel: 0,              //integer, 支付渠道, 0微信,1支付宝
    orderid: "201601010001", //string(64), 订单号
    title  : "购买VIP会员",  //string(128), 订单名称
    amount : 12.3            //decimal,支付金额(元)
}, function(succ) {
    if (succ) {
        alert("支付成功");
    } else {    
        alert("支付失败或取消了支付");
    }
});

接入方式三: 仅需在 “微信分享” 功能处配置 “微信 AppID”,不需提交账户信息给本平台,自己处理各种签名验证与请求

在你服务器上请求 微信统一支付接口, 拿到预支付 prepayid 后按官方说明 构造支付参数, 将支付参数传给本接口函数。


//注意:支付参数名称(全部小写)和类型应与官方说明完全相同
jsBridge.wxPay({
    appid    : "应用ID",
    partnerid: "商户号",
    prepayid : "预支付交易会话ID",
    package  : "扩展字段",
    noncestr : "随机字符串",
    timestamp: "时间戳(单位是秒,不是毫秒,切记)",
    sign:      "签名"
}, function (succ, text) {
    if (succ) {
        alert("支付成功");
    } else {    
        alert("支付失败或取消了支付");
    }
});
支付宝App支付 aliPay

支付宝 App 支付的相关说明 请参考官网

接入方式一: 需要在 “App 配置” - “支付宝支付” 提交账户信息

请参考 微信接入方式一 只需将 channel 参数值改为 1 即可。


接入方式二: 需要在 “App 配置” - “支付宝支付” 提交账户信息

请参考 微信接入方式二 只需将 channel 参数值改为 1 即可。


接入方式三: 不需提交账户信息给本平台,自己处理各种签名验证与请求

请参考 官方手册 构造订单字符串,作为参数传递给本接口。


jsBridge.aliPay({
    orderString: "按照官方手册构造的订单字符串"
}, function (succ, text) {
    if (succ) {
        alert("支付成功");
    } else {    
        alert("支付失败或取消了支付");
    }
});
银联App支付 upay

银联 App 支付的相关说明 请参考官网

接入方式一: 需要在 “App 配置” - “银联云闪付” 提交账户信息

请参考 微信接入方式一 只需将 channel 参数值改为 2 即可。


接入方式二: 需要在 “App 配置” - “银联云闪付” 提交账户信息

请参考 微信接入方式二 只需将 channel 参数值改为 2 即可。


接入方式三: 不需提交商户私钥证书给本平台,自己处理各种签名验证与请求。

请参考 官方手册 获取银联受理订单号 tn,作为参数传递给本接口。


jsBridge.unionPay({
  tn: "替换成你的银联受理订单号"
  //当前手机厂商 pay 类型,可选,仅支持安卓
  //用 jsBridge.unionSeInfo 函数获取
  //, seType : ""
}, function (succ, text) {
  if (succ) {
    alert("支付成功");
  } else {    
    alert("支付失败或取消了支付");
  }
});
支付异步通知

如果你采用 “方式一” 或 “方式二” 接入支付,本平台会将来自微信/支付宝/银联官方的支付结果确认信息以 POST 方式转发到你在 “App 设置” 里填写的 “支付通知地址”。 请以此通知为准来判定用户是否真实完成了支付,切记。

通知参数说明:
 channel: 支付渠道, 0 微信, 1 支付宝, 2 银联云闪付, 3 银联全民付
 tradeid: 微信/支付宝平台返回的交易号
 orderid: 订单号
 amount: 支付金额(元)
 attach: 原样返回发起支付时的附加字段(使用V2版通知时)
 timestamp: 发送通知时的 Unix 时间戳,可用于处理通知过期策略
 nonce: 随机串
 sign: MD5签名串,参数名=参数值 按参数名升序排列用 & 符号连接,最后加上 App 设置 处的 AppSecret,计算 md5 值

ASP.NET 示例

@using System.Linq;
@using System.Text;
@using System.Collections.Generic;
@using System.Security.Cryptography;
@{
    //这是签名验证串,请在本平台 App设置 查看或重置
    const string APP_SECRET = "sdfsadsfasdfwefafsdv03849034urfwi";
    const int CH_WeiXin   = 0;    //支付渠道:微信
    const int CH_Alipay   = 1;    //支付渠道:支付宝
    const int CH_UnionPay = 2;    //支付渠道:银联云闪付
    const int CH_UnionPay = 3;    //支付渠道:银联全民付
    Response.Clear();
    if (!"POST".Equals(Request.HttpMethod, StringComparison.OrdinalIgnoreCase))
    {    
        //不是 POST 方法
        return;
    }
    //发送通知时的 Unix 时间戳,可用于处理通知过期策略
    long timestamp;
    if (!long.TryParse(Request.Form["timestamp"], out timestamp))
    {
        timestamp = 0;
    }
    //假定15分钟内有效
    if ((timestamp + 15 * 60) < (DateTime.Now.ToUniversalTime() - DateTime.Parse("1970-01-01")).TotalSeconds)
    {
        //通知已过期
        return;
    }

    string sign = "";
    var dict = new SortedDictionary<string, string>();
    //遍历 form 表单
    foreach (var k in Request.Form.AllKeys)
    {
        if (k == "sign")
        {
            sign = Request.Form[k];
            continue;
        }
        dict.Add(k, Request.Form[k]);
    }
    if (string.IsNullOrEmpty(sign) || (dict.Count == 0))
    {                                       
        //没有签名信息
        return;
    }
    //验证签名
    var s = string.Join("&", dict.Select(x => x.Key + "=" + x.Value)) + APP_SECRET;
    var md5 = MD5.Create();
    var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(s));
    var sn = BitConverter.ToString(bs, 0).Replace("-", "");
    if (!sign.Equals(sn, StringComparison.OrdinalIgnoreCase))
    {                                       
        //签名错误
        return;
    }
 
    //获取有效的参数值
    var tradeid   = dict["tradeid"];  //支付平台上的交易号
    var orderid   = dict["orderid"];  //订单号
    var amount    = Convert.ToDecimal(dict["amount"]); //支付金额
    var channel   = Convert.ToInt32(dict["channel"]);  //支付渠道
    var attach    = dict["attach"];   //原样返回发起支付时的附加字段(使用V2版通知时)
 
    //切记,一定要比对金额:
    //比对实付金额与订单应付金额是否相符,不相等直接退出
    if (amount != [订单应付金额]) return;

//用上面的参数处理支付成功的后续业务 //请在这里自由发挥,尽量不要修改其他地方 //do something... //处理成功后,http 要返回 OK 字符,否则你的服务器可能会多次收到确认通知 Response.Write("OK"); Response.End(); }

PHP 示例

<?php

//这是签名验证串,在 App配置 查询或重置
$secretKey = "CDg3yXFcVFDHBjdFu12lVAb3qinHYb1Ib";

//发送通知时的 Unix 时间戳,可用于处理通知过期策略
$timestamp = intval($_POST["timestamp"]);
//假定15分钟内有效
if (($timestamp + 15 * 60) < date_timestamp_get(date_create())) {
    //通知已过期
    return;
}

$kv = array();
//遍历 form 表单
foreach ($_POST as $key => $val) {
    $kv[$key] = $val;
}
ksort($kv);
reset($kv);
$param = '';
foreach ($kv AS $key => $val) {
    if ($key != 'sign') {
        $param .= "$key=$val&";
    }
}
$param = substr($param, 0, -1).$secretKey;
$verify_result = (md5($param) == strtolower($kv["sign"]));
if ($verify_result) {
    //获取有效的参数值
    $tradeid = $kv["tradeid"];  //支付平台上的交易号
    $orderid = $kv["orderid"];  //订单号
    $amount  = $kv["amount"] ;  //支付金额
    $channel = $kv["channel"];  //支付渠道, 0 微信,1 支付宝, 2 银联云闪付, 3 银联全民付
    $attach  = $kv["attach"];   //原样返回发起支付时的附加字段(使用V2版通知时)
 
    //切记,一定要比对金额:
    //实付金额与订单应付金额是否相符,不相等直接退出
    if ($amount != [订单应付金额]) exit();

//用上面的参数处理支付成功的后续业务 //请在这里自由发挥,尽量不要修改其他地方 //do something... //处理成功后,http 要返回 OK 字符,否则你的服务器可能会多次收到确认通知 exit("OK"); } else { //签名验证失败 } ?>

Java 示例

即将到来...

Node.js 示例

// 引入md5加密库
const md5 = require('md5')

//这是签名验证串,在 App配置 查询或重置
const secretKey = 'xxxx'

// 假如 你的 nodejs 后端是通过request.post获取post参数 response.end 是输出

const timestamp = parseInt(request.post.timestamp)

// 获取当前时间戳
const nowTimestamp = parseInt(new Date().getTime() / 1000)

if (timestamp + 15 * 60 < nowTimestamp) {
  //通知已过期
  response.end('timestamp error')
  return
}

// 对象排序

const sort = Object.keys(request.post).sort()

// //遍历 post 进行参数拼接
let params = ''

sort.forEach((key) => {
  params += `${key}=${request.post[key]}&`
})

params = params.substring(0, params.length - 1) + secretKey

const verify_result = md5(param) == request.post.sign
if (verify_result) {
  //获取有效的参数值
  const tradeid = request.post.tradeid //支付平台上的交易号
  const orderid = request.post.orderid //订单号
  const amount = request.post.amount //支付金额
  const channel = request.post.channel //支付渠道, 0 微信,1 支付宝, 2 银联云闪付, 3 银联全民付
  const attach = request.post.attach //原样返回发起支付时的附加字段(使用V2版通知时)

  //切记,一定要比对金额:
  //实付金额与订单应付金额是否相符,不相等直接退出
  if (amount != '实际的金额') {
    // 错误返回
  }
  // 处理成功后,http 要返回 OK 字符,否则你的服务器可能会多次收到确认通知
  response.end('OK')
  return
}

response.end('error')

网络访问 net

发起网络访问,这个函数能有效的解决 ajax 跨域限制问题(jsonp 也总有些限制),原生网络请求,性能也会比较好。


jsBridge.net({
    //必须 (string, 网络请求地址)
    url: "http://.....",
    //可选 (string, HTTP Request Method,GET/POST/PUT/DELETE 之一,默认 GET)
    method: "POST",
    //可选 (json object,请求参数)
    params: {
    //...
    },
    //可选 (json object, HTTP Request Header,自定义HTTP请求头)
    headers: {
        //...
    },
    //可选 (boolean, 是否需要显示 Loading 指示器,默认 true)
    indicator: true
}, function (succ, text) {
    if (succ) {
        console.log("服务器返回的字符串:" + text);
    } else {
        var err = JSON.parse(text);
        alert(err.errorCode + ":" + err.errorMessage);
    }
});
剪贴板复制粘贴 setClipboardText / getClipboardText

剪贴板操作,setClipboardText 复制文本到剪贴板,getClipboardText 获取剪贴板文本。

集成本js函数就不必让用户操作 长按-选中-复制 了,典型应用是在页面上放置一个按钮,点击按钮调用 setClipboardText 函数,你可以设置任何文本内容到剪贴板,用户可以在任何地方粘贴文本。


//复制文本到剪贴板
jsBridge.setClipboardText("Hello 世界!");

//获取剪贴板文本 jsBridge.getClipboardText(function(text) { alert(text); });
通讯录 contactOne / contactAll

contactOne 弹出系统通讯录列表,供用户选择一个联系人;

contactAll 获取通讯录里所有联系人信息;

//选择一个联系人
//回调参数为 person 对象,没选择或没权限则返回 null
jsBridge.contactOne(function(person) {
  if (person) {
    alert(JSON.stringify(person));
  } else {
    alert("取消了选择或没有使用通讯录的权限");
  }
});

//获取通讯录里所有联系人信息 //回调参数为 person 数组,没权限则返回 null jsBridge.contactAll(function(persons) { if (persons) { alert("获取到" + persons.length + "个联系人信息\n第一个是\n" + JSON.stringify(persons[0])); } else { alert("没有使用通讯录的权限"); } });

//person 对象字段说明 { id : "联系人编号", //字符串 name : "姓名", //字符串 familyName: "姓", //字符串 givenName : "名", //字符串 phones : [ "电话号码1", "电话号码2", ...], //字符串数组 emails : [ "电子邮箱1", "电子邮箱2", ...] //字符串数组 }
属性 inApp / version / appVersion

浏览器端 jsBridge.inApp 属性返回页面是否在 App 中打开。


if (jsBridge.inApp) {
    alert("在App中");
} else {    
    alert("不在App中");
}

服务器端可以通过检查 Request Header 的 UserAgent 是否包含 LT-APP 字符来判定页面是否在 App 中打开的。


浏览器端 jsBridge.version 属性返回 App 内核版本号,如不在 App 内则返回 0


alert("App内核版本 " + jsBridge.version);

服务器端可以用 LT-APP/(\d+) 正则匹配 Request Header 的 UserAgent 取得 App 内核版本号。


浏览器端 jsBridge.appVersion 属性返回 App 打包版本号,如 102 表示 1.0.2

alert("App打包版本 " + jsBridge.appVersion);