{"id":13487192,"url":"https://github.com/trheyi/xpmjs","last_synced_at":"2025-10-10T04:44:05.351Z","repository":{"id":86129637,"uuid":"77748162","full_name":"trheyi/xpmjs","owner":"trheyi","description":"微信小程序云端增强 SDK","archived":false,"fork":false,"pushed_at":"2019-04-28T01:57:28.000Z","size":156,"stargazers_count":177,"open_issues_count":0,"forks_count":27,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-08-04T09:01:59.673Z","etag":null,"topics":["baas","framework","javascript","wxapp"],"latest_commit_sha":null,"homepage":"https://www.jianmo.ink","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trheyi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-12-31T16:36:20.000Z","updated_at":"2024-08-04T09:01:59.674Z","dependencies_parsed_at":"2023-03-13T08:36:49.575Z","dependency_job_id":null,"html_url":"https://github.com/trheyi/xpmjs","commit_stats":null,"previous_names":["xpmjs/xpmjs"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trheyi%2Fxpmjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trheyi%2Fxpmjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trheyi%2Fxpmjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trheyi%2Fxpmjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trheyi","download_url":"https://codeload.github.com/trheyi/xpmjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247716142,"owners_count":20984178,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["baas","framework","javascript","wxapp"],"created_at":"2024-07-31T18:00:56.435Z","updated_at":"2025-10-10T04:44:00.320Z","avatar_url":"https://github.com/trheyi.png","language":"JavaScript","funding_links":[],"categories":["工具","JavaScript"],"sub_categories":[],"readme":"XpmJS - 小程序云端增强 SDK \n================\n\n## 最近更新\n\n### + React Native Support ( xpmse 1.6.5 + )\n\n`xpm.js` 配置\n\n```javascript\nimport xpm from './xpmjs/xpm.rn';\nlet host = 'wss.xpmjs.com';\nlet option = {\n    'app':1,\n    'host':host,\n    'https':host,\n    'wss': host + '/ws-server',\n    'table.prefix': '{none}',\n    \"appid\": \"wx0550a96041cf486c\",\n    \"secret\":\"151187416275946|0516fa148c2584028ee4a30157bfdc27\",\n    \"user\":\"/xpmsns/user/user/wxappLogin\"\n}\n\nxpm.option(option);\nexport default xpm;\n```\n\n`Home.js` JSX\n\n\n```javascript\n// ...\nimport xpm from './xpm';\n// ...\n\n\n/**\n * 页面数据驱动\n */\nclass __data {\n\n  @observable articles = [];\n  @observable loading = false;\n  @observable curr = null;\n\n  constructor() {\n     // mobx.autorun(() =\u003e console.log('auto run', this.page));\n  }\n\n\n  fetch( key = null ) {\n    this.loading = true;\n\n    let $search = xpm.api('/xpmsns/pages/article/search');\n    $search().get({perpage:20, page:2}).then(( resp )=\u003e{\n      console.log( resp );\n      this.articles = resp;\n    }).catch( (excp) =\u003e {\n      console.log( 'excp:',  excp );\n    });\n  }\n\n}\n\n// ....\n\n```\n\n\n\n### + config 更新 ( xpmjs-server 1.5.2+ )\n\n```javascript\nvar host = 'wss.xpmjs.com';\nvar option = {\n    'app':1,\n    'host':host,\n    'https':host,\n    'wss': host + '/ws-server',\n    'table.prefix': 'demo',\n    'user.table':'user', \n    \"appid\": \"wx0550a96041cf486c\",  // 新增\n    \"secret\":\"150698766059529|4990e4107dbfe85c045cf8bbd3508652\",  // 服务端  appid \u0026 secret\n    \"user\" : \"/mina/user/user/wxappLogin\" // 新增用户系统 handler api\n}\n\nvar xpm = require('xpmjs/xpm.js').option(option);\n```\n\n### + api 调用云端应用API (  xpmjs-server 1.5.2+ )\n \n```javascript\nvar $test = app.xpm.api('mina/user/user/test');\n\n$test({hello:'world'}).get()\n\n.then(function(resp){\n    console.log( resp );\n})\n.catch( function(excp){\n    console.log('excp', excp);\n});\n\n```\n\n### + MINA WEB (预览版)\n\n文档: http://book.tuanduimao.com/357326\n\n\n\n## 一、XpmJS 是啥\n\nXpmJS可以链接任何云端资源，为小程序、移动应用提供云资源通道和后端能力。降低开发门槛，提升小程序的开发效率。无需编写后端代码，即可实现用户登录、WebSocket 通信、微信支付、云端数据表格、文件存储等功能。虽然 PHP 是最好的编程语言, 但是使用 XpmJS 后, 无需学习包括 PHP 在内的任何后端语言，**用 Javascript 即可搞定一切，NodeJS 也不用！**\n\n\n## 二、为啥 XpmJS\n\n### 从代码结构上看 XpmJS 更优雅！因为使用了 Promise！ \n\n![无敌连环 CallBack VS Promise 图](http://of2is3ok3.bkt.clouddn.com/xcx/images/promise.png)\n\n\n### XpmJS 封装了常用后端操作，还提供一个管理后台，微信支付只要一行代码就可以实现！\n\n![微信支付代码示例，管理后台截图](http://of2is3ok3.bkt.clouddn.com/xcx/images/paynow.png)\n\n\n### 后端部署在你的云主机上！你可以完全掌控数据。\n\n\n**方法1: 一键安装**\n\n推荐使用[腾讯云一键安装链接](http://market.qcloud.com/products/1796)\n（ 访问微信接口快, 可以免费申请 Https 证书 ） \n\n\n**方法2: 安装脚本**\n\n安装前，先提前申请 Docker Hub 镜像\n[申请地址 https://www.daocloud.io/mirror](https://www.daocloud.io/mirror)\n\n```bash\n\n# 支持Ubunbu 16.04 \u0026 14.04 系统，推荐采用 Ubuntu 16.04 64位 LTS \ncurl -sSL http://tuanduimao.com/xpmjs-server-1.5.2.sh | sh -s yourdomain.com http://\u003cyour id\u003e.m.daocloud.io\n\n```\n\n**方法3: 使用 Docker 安装**\n\n```bash\n\n# 安装 Docker \ncurl -sSL https://get.daocloud.io/docker | sh\n\n# 启动容器\ndocker run -d --name=xpmjs-server  \\\n    -e \"HOST=yourdomain.com\" \\\n    -v /host/data:/data  \\\n    -v /host/apps:/apps  \\\n    -v /host/config:/config  \\\n    -p 80:80 -p 443:443  \\\n    hub.c.163.com/trheyi/xpmse:1.6.2\n\n```\n\n\n### XpmJS Server 升级 (1.0 ~ 1.5 需升级容器)\n\n第一步: 下载代码: \n\n```bash\ncurl http://xpmjs-1252011659.costj.myqcloud.com/xpmjs-server-1.0.tar.gz\n\n```\n\n第二步: 解压并更新:\n\n```bash\ntar xvfz xpmjs-server-1.0.tar.gz\ncd 1.0 \u0026\u0026 docker cp . xpmjs-server:/code\n\n```\n\n\n## 三、XpmJS 简明文档\n\n### 1. 用户 ( User )\n\n#### 用户登录 login()\n\n```javascript\nvar user = app.xpm.require('User');\n\nuser.login().then( function( userInfo ) { \n\n    console.log( '用户登录成功', userInfo );\n    app.session.set('loginUser', userInfo );\n})\n\n.catch( function( excp ) { \n    console.log('用户登录失败', excp );\n});\n\n```\n\n#### 用户退出 logout()\n\n```javascript\nvar user = app.xpm.require('User');\n\nuser.logout().then( function( userInfo ) { \n    console.log( '用户注销成功', userInfo );\n})\n\n.catch( function( excp ) { \n    console.log('用户注销失败', excp );\n});\n\n```\n\n#### 读取资料 get()\n\n来自微信客户端的用户信息 （ 非云端数据 ）\n\n```javascript\nvar user = app.xpm.require('User');\n\nuser.get().then( function( userInfo ) { \n    console.log( '读取成功', userInfo );\n})\n\n.catch( function( excp ) { \n    console.log('读取失败', excp );\n});\n\n```\n\n\n### 2. 信道（ Wss ）\n\n使用 Websocket 信道，可以实现双向实时通信。\n\n#### 打开信道 open()\n\n```javascript\nvar wss = app.xpm.require('Wss');\nwss.open('/wxapp').then(function( res ) {\n    console.log( '信道连接成功', res );\n})\n.catch( function( excp ) { \n    console.log('信道连接失败', excp );\n});\n```\n\n#### 在线用户 liveUsers ()\n\n```javascript\nvar wss = app.xpm.require('Wss');\nwss.liveUsers().then(function( users ) {\n    console.log( '读取在线用户成功', users );\n})\n.catch( function( excp ) { \n    console.log('读取在线用户失败', excp );\n});\n\n```\n\n用户信息数据结构\n\n| 字段 | 中文 |说明 |\n| :-: | :-: | :-: |\n| id | 客户端ID | |\n| _id | 用户ID |  |\n| nickName | 微信昵称 | |\n| gender | 性别 |  |\n| avatarUrl | 头像| |\n| language | 语言 | |\n| group | 用户组 | |\n| isadmin | 是否是管理员| 0 非管理员 1 管理员 |\n\n\n#### 检查用户是否在线 isOnline ( xpmjs-server 1.0rc4+  )\n\n```javascript\n\nvar user = app.xpm.require('User');\nvar wss = app.xpm.require('Wss');\n\nuser.login().then( function( userInfo ) { \n    return wss.isOnline( userInfo['_id'] )\n    \n}).then function( isOnline ) {\n    if ( isOnline ) {\n        console.log( '用户在线');\n    } else {\n        console.log( '用户离线');\n    }\n})\n.catch( function( excp ) { \n    console.log('出错啦', excp );\n});\n\n\n```\n\n\n#### 监听指令 listen()\n\n小程序仅提供 WebSocket 客户端 API，所以小程序本身无法实现 WebSocket服务器。 wss.listen() 方法并非启动 WebSocket Server, 而是用来接收云端信道转发的指令。\n\n```javascript\nvar wss = app.xpm.require('Wss');\nwss.listen('payment', function( res, status ){\n    // 当接收到 payment 指令后运行 \n    if ( status != 'success') return ;\n    console.log( res, status );\n});\n```\n\n\n#### 发送指令 send()\n\n```javascript\n\nvar wss = app.xpm.require('Wss');\nwss.liveUsers().then(function( users ) {\n    console.log( '读取在线用户成功', users );\n    // 向第一个用户发送 payment 指令\n    if ( users.length \u003e 0 )  {\n        return wss.send('payment', users[0], users[0]['id'] )\n    } else {\n        return {code:404, message:'no live user'};\n    }\n    \n}).then( function( res ){\n    console.log('发送完毕', res);\n});\n.catch( function( excp ) { \n    console.log('出错了', excp );\n});\n\n```\n\n#### 绑定事件 bind()\n\n接收并处理 websocket 服务器事件，有效值 ( open/close/message/error )\n\n```javascript\nvar wss = app.xpm.require('Wss');\nwss.bind('open', function(event) {\n    console.log('信道服务器开启', event );\n});\n\nwss.bind('close', function(event) {\n    console.log('信道服务器关闭', event );\n});\n\n```\n\n### 3. 会话 ( Session )\n\nSession 会话分为客户端和服务端两部分，客户端与服务端会话ID相同，客户端保存用户信息资料，服务端保存用户 openid 等敏感信息。与服务端通信，使用Sesssion ID 鉴权，通过服务器端验证后，请勿将 Session ID 发送给第三方。\n\n#### 启用会话 start()\n\n启用会话后，会自动创建一个会话ID\n\n```javascript\nvar session = app.xpm.require('session');\n    session.start();\n```\n\n#### 会话 ID id()\n\n```javascript\nvar session = app.xpm.require('session');\nvar sid = app.id();\nconsole.log( sid );\n\n```\n\n\n#### 客户端会话数据管理 set() \u0026 get()\n\n```javascript\nvar session = app.xpm.require('session');\nsession.set('hello', 'world');\nconsole.log( session.get('hello') );\n```\n\n### 4. 云端表格 ( Table )\n\n可以使用云端表格接口，将数据保存在 MySQL 中，可以通过 SQL 查询数据。\n\n#### 创建数据表 _schema()\n\n仅管理员帐号拥有创建数据表权限 ( 登录管理后台，打开用户表，将开发者对应帐号记录的 isadmin 字段数值设置为 1 )\n\n![配置管理员数值](http://of2is3ok3.bkt.clouddn.com/xpmjs/xpmjs/isadmin.png)\n\n\n```javascript\nvar table = app.xpm.require('Table', 'hello');\ntable._schema(\n    [  \n      {name:\"name\", type:'string', option:{length:80, require:true }, acl:\"rwd:r:-\" },\n      {name:\"company\", type:'string', option:{length:100}, acl:\"w:-:-\" }\n    ], \n    { record:\"rwd:rw:-\", table:\"rwd:-:-\", field:'rwd:r:-',  user:'admin', group:'member' }\n, true ).then( function( data ) {\n    console.log('数据表创建成功', data );\n})\n.catch( function( excp ) { \n    console.log('数据表创建失败', excp );\n});\n\n```\n\n字段配置参数\n\n| 参数 | 中文 |说明 |\n| :-: | :-: | :-: |\n| name | 字段名称 | |\n| type | 字段类型  | string/integer/text/boolean 等 |\n| option | 字段参数  |  index:true 索引 unique:true 唯一索引 length:80 字段长度 |\n| acl | 字段鉴权 | rw:rw:rw  r: 读取 w: 写入 -:无  user:group:other  |\n\n\n#### 数据增删改查 get() create() update() remove()\n\n```javascript\nvar table = app.xpm.require('Table', 'hello');\n\n// 创建\ntable.create( \n    {name:'张艺谋', company:'中国电影制片厂'}\n).then(function(data) { // 更新\n    return table.update(data['_id'], {name:'冯小刚'});\n    \n}).then(function(data) { // 读取\n    return table.get(data['_id']);\n    \n}).then(function(data) { // 删除\n    return table.remove(data['name'], 'name' );\n    \n}).then(function(resp) {\n    console.log( 'remove success', resp );\n    \n}).catch( function( excp ) { \n    console.log('出错了', excp );\n});\n\n```\n\n#### 数据查询 query()\n\n```javascript\nvar table = app.xpm.require('Table', 'hello');\ntable.query()\n    .where('name', '=', '冯小刚')\n    .orderby('name', 'asc')\n    .limit(2)  // 仅查询 2条 \n\n.fetch('name','company').then(function(data) {  \n    console.log( '查询结果', data ); \n})\n\n\ntable.query()\n    .where('name', '=', '冯小刚')\n    .orderby('name', 'asc')\n    .paginate(3, 2)  // 分3页，当前显示第 2页 \n\n.fetch('name','company').then(function(data) {  \n    console.log( '查询结果', data ); \n});\n    \n```\n\n#### 联合查询 join(), leftjoin(), rightjoin() (xpmjs-server 1.0rc4+) \n\n\nTable 1: `User`\n\n| id | name |title |\n| :-: | :-: | :-: |\n| 1   |  张三  | 产品经理 |\n| 2   |  李四  | 工程师 |\n| 3   |  王五  | 运维工程师 |\n\nTable 2: `Project`\n\n| id | name | uid |\n| :-: | :-: | :-: |\n| 1   |  小程序开发组 | 1 |\n| 2   |  网页开发组  | 3 |\n\n```javascript\nvar table = app.xpm.require('Table', 'Project');\ntable.query()\n    .join('User', 'User.id', '=', 'Project.uid' )  // leftjoin / rightjoin\n    .limit(1)  \n.fetch('User.id as userid', 'User.name as username', 'Project.*').then(function(data) {  \n    console.log( '查询结果', data ); \n})\n\n```\n\n返回值\n\n```json\n[\n\t{\n\t\t\"id\":1,\n\t\t\"name\":\"小程序开发组\"\n\t\t\"userid\":1,\n\t\t\"username\":\"产品经理\"\n\t\t\n\t}\n]\n```\n\n#### inWhere 查询 inWhere()\n\n\nTable 1: `User`\n\n| id | name |title |\n| :-: | :-: | :-: |\n| 1   |  张三  | 产品经理 |\n| 2   |  李四  | 工程师 |\n| 3   |  王五  | 运维工程师 |\n\nTable 2: `Project`\n\n| id | name | users |\n| :-: | :-: | :-: |\n| 1   |  小程序开发组 | [\"1\",\"2\",\"3\"] |\n| 2   |  网页开发组  |  [\"1\", \"3\"] |\n\n```javascript\nvar table = app.xpm.require('Table', 'Project');\ntable.query()\n    .inWhere('users', 'User', 'id', '*' )\n    .limit(1)  \n.fetch('User.id as userid', 'User.name as username', 'Project.*').then(function(data) {  \n    console.log( '查询结果', data ); \n})\n\n```\n\n返回值\n\n```json\n[\n\t{\n\t\t\"id\":1,\n\t\t\"name\":\"小程序开发组\"\n\t\t\"users\":[\n\t\t\t{\n\t\t\t\t\"id\":1,\n\t\t\t\t\"name\":\"张三\",\n\t\t\t\t\"title\":\"产品经理\"\n\t\t\t}\n\t\t\t...\n\t\t]\n\t\t\n\t}\n]\n```\n\n### 5. 微信支付 ( Pay )\n\n#### 发起支付 request();\n\n```javascript\nvar pay = app.xpm.require('Pay');\npay.request({\n    total_fee:500,  // 单位分\n    body:'算命、服务器开光',\n    attach:'HELLO XpmJS.com', \n    detail:'{id:888,desp:\"算命,抽SSR,赠送服务器开光\"}'\n}).then(function( data ){\n    console.log('Request Pay Success', data );\n}).catch( function( excp){\n    console.log('Request Pay Failure', excp );\n});\n\n```\n\n#### 云端事件 before(), success(), fail(), complete() (xpmjs-server 1.0rc4+)\n\n```javascript\npay.before('create', {  // 创建充值记录 (统一下单成功后, 发起支付前, 在云端运行 )\n\t'table':'income',\n\t'data': {\n\t\tsn:'{{sn}}',\n\t\torder_sn: data.order.sn,\n\t\tuid:data.order.uid,\n\t\tamount:data.order.sale_price,\n\t\tamount_free:0,\n\t\tstatus:'PENDING',\n\t\tstatus_tips:\"F请求付款\"\n\t}\n})\n\n.order({   // 生成订单  ( 统一下单接口, 仅设定并不发送请求 )\n    total_fee:data.order.sale_price,  // 单位分\n    body:data.order.show_name,\n    attach:'attach user is ' + mid,  // 应该是当前登录用户的 ID \n    detail:data\n})\n\n.success('update', { // 更新充值记录 （ 支付成功后回调，在云端运行 ）\n\t'table':'income',\n\t'data': {\n\t\tsn:'{{sn}}',\n\t\tstatus:'DONE',\n\t\tstatus_tips:\"income status_tips field\"\n\t},\n\t'unique':'sn'\n})\n\n.success('app', {   // 调用APP 示例 （ 支付成功后回调，在云端运行 ）\n\t'name':'xapp',\n\t'api':['ticket','index',{sn:'{{sn}}','status_tips':\"{{0.status_tips}}\"}],\n\t'data': {\n\t\tsn:'{{sn}}',\n\t\tstatus:'DONE'\n\t}\n})\n\n.success('update', {  // 更新订单状态 （ 支付成功后回调，在云端运行 ）\n\t'table':'order',\n\t'data': {\n\t\t_id:oid,\n\t\tstatus:'PENDING'\n\t}\n})\n\n.success('create', {   // 创建消费记录 （ 支付成功后回调，在云端运行 ）\n\t'table':'payout',\n\t'data': {\n\t\tsn:'{{sn}}',\n\t\torder_sn: data.order.sn,\n\t\tuid:data.order.uid,\n\t\tamount:data.order.sale_price,\n\t\tamount_free:0,\n\t\tstatus:'DONE',\n\t\tstatus_tips:\"F请求付款\"\n\t}\n})\n\n.request().then(function( payResp  ) {  // 发起请求\n\tconsole.log( payResp );\n})\n```\n\n\n### 6. 本地存储 ( Stor ) \n\n```javascript\nvar stor = app.xpm.require('Stor');\nstor.setSync('key','value');\nconsole.log(stor.getSync('key'));\n\nstor.setMapSync('map_name', 'key', 'value');\nconsole.log(stor.getMapSync('map_name','key'));\n\n```\n\n### 7. 云端应用 ( App ) (xpmjs-server 1.0rc3+)\n\n#### 调用示例\n\n```javascript\nvar xapp = app.xpm.require('App', 'xapp' );  // xapp 应用名称\n\nxapp.api( 'ticket', 'available' )  // ticket 控制器  available 方法名\n\n.post({\n    'train_date':'2017-01-26',\n    'from_station':'BJP',\n    'to_station':'SHH'\n})\n\n.then( function( resp ) {\n  console.log('POST RESP:', resp );\n})\n\n.catch( function( excp ) {\n  console.log('POST EXCP:', excp );\n});\n\n```\n\n#### XpmJS 云端应用开发\n\n参考云端应用 Demo [\u003c火车票余票查询接口实现\u003e](https://git.oschina.net/xpmjs/xapp)\n\nhttps://git.oschina.net/xpmjs/xapp\n\n\n![应用安装](http://of2is3ok3.bkt.clouddn.com/xpmjs/xpmjs/xappinstall.png)\n\n\n### 8. 云端队列 ( Que.js ) (xpmjs-server 1.0rc4+)\n\n```javascript\nvar que = app.xpm.require('Que', 'hello');\nque.select('world').push('create', {  // 增加数据\n\ttable:'payout',\n\tdata: {\n\t\tsn:'200193',\n\t\torder_sn:'test29993',\n\t\tamount:100,\n\t\tstatus:'DONE'\n\t}\n}).push('update', { // 更新数据\n\ttable:'order',\n\tdata: {\n\t\tsn:'148457330261256',\n\t\tstatus_tips:'{{0.sn}} {{0.status}}'\n\t},\n\tunique:'sn'\n}).push('app', {   // 调用APP 示例\n\t'name':'xapp',\n\t'api':['ticket','index',{sn:'{{0.sn}}'}],\n\t'data': {\n\t\tsn:'{{0.sn}} {{1.sn}}',\n\t\tstatus:'DONE'\n\t}\n}).run().then(function(resp){\n\tconsole.log( 'Response', resp );\n})\n.catch(function(excp){\n\tconsole.log( 'Error', excp );\n})\n```\n\n\n### 9. 文件上传 Utils.upload  \u0026  App.upload  (xpmjs-server 1.0+)\n\n上传文件到腾讯云对象存储 \n \n```javascript\nvar qcloud = app.xpm.require('app', 'xqcloud');\nqcloud.api(\"cos\",'upload')\n\n.upload( tempFilePaths[0] )\n.then(function(data){\n\tthat.setData({\n\t\t'rs.corver':data.access_url,\n\t\t'rs.images':[data.access_url]\n\t});\n})\n.catch( function(excp){\n\tconsole.log('Upload Fail', excp );\n});\n```\n\n\n### 10. 常用方法 (  Utils )\n\n  \n#### 请求网址 ( Utils.fetch ) (xpmjs-server 1.0rc3+)\n\n```javascript\nvar utils = app.xpm.require('Utils' );  \n\nutils.fetch( 'http://qcloud.com' ).then( function( resp ) {    \n    console.log('FETCH RESP:', resp );\n})\n\n.catch( function( excp ) {\n  console.log('FETCH EXCP:', excp );\n});\n\n```\n\n\n#### 生成二维码图片 ( Utils.qrImageUrl ) (xpmjs-server 1.0+)\n\n返回二维码图片地址\n\n```javascript\nvar utils = app.xpm.require('Utils' ); \nvar url = utils.qrImageUrl('hello world', {size:200});\nconsole.log( url );\n```\n\n\n#### 生成小程序页面二维码  ( Utils.qrcode ) ( xpmjs-server 1.0 )\n\n```javascript\nvar utils = app.xpm.require('Utils' ); \nvar url = utils.qrcode('/page/detail?id=1');\nconsole.log( url );\n\n```\n\n\n\n## 三、微信小程序 Demo\n\n![微信小程序 Demo](http://of2is3ok3.bkt.clouddn.com/xpmjs/xpmjs/wechat.demo.png)\n\n[小程序 Demo 源码](https://git.oschina.net/xpmjs/wxdemo)\n\n\n\n## 四、安装配置\n\n### 1. 云端配置\n\n**【安装后端程序】**\n\n推荐使用[腾讯云](http://market.qcloud.com/products/1796)（ 访问微信接口快, 可以免费申请 Https 证书 ） \n\n方法1: 使用脚本安装 （ **目前支持 Ubuntu 16.04/14.04 64 LTS 操作系统** ）\n\n创建一台云服务器，选择 **Ubuntu 16.04/14.04 64 LTS** 操作系统。 登录服务器运行以下脚本。\n\n安装前，先提前申请 Docker Hub 镜像\n[申请地址 https://www.daocloud.io/mirror](https://www.daocloud.io/mirror)\n\n```bash\ncurl -sSL http://tuanduimao.com/xpmjs-server.sh | sh -s yourdomain.com http://\u003cyour id\u003e.m.daocloud.io\n\n```\n\n方法2: 使用 Docker 安装\n\n```bash\ndocker run -d --name=xpmjs-server  \\\n    -e \"HOST=yourdomain.com\" \\\n    -v /host/data:/data  \\\n    -v /host/apps:/apps  \\\n    -v /host/config:/config  \\\n    -p 80:80 -p 443:443  \\\n    tuanduimao/xpmjs-server:1.0\n        \n```\n\n**【设置管理员名称和密码】**\n\n访问: http://yourdomian.com/setup.php\n\n1. 填写后台信息\n![setup-1.png](http://of2is3ok3.bkt.clouddn.com/xpmjs/xpmjs/setup-1.png)\n\n2. 填写管理员信息\n![setup-2.png](http://of2is3ok3.bkt.clouddn.com/xpmjs/xpmjs/setup-2.png)\n\n\n**【上传 HTTPS 证书 \u0026 微信支付证书】**\n\n访问：http://yourdomian.com/_a/baas-admin/cert/index\n上传 HTTPS 证书和证书密钥； 如已申请微信支付，建议尽量上传支付证书，用于双向验证证书和密钥，确保支付安全。\n\n![https-cert.png](http://of2is3ok3.bkt.clouddn.com/xpmjs/xpmjs/https-cert.png)\n\n上传好证书后，登录服务器，重启容器。\n\n```bash\ndocker restart xpmjs-server\n```\n\n访问： https://yourdomian.com  ( 有 **\"S\"**， 检查证书是否生效 ）\n\n\n**【设置小程序配置信息】**\n\n访问： https://yourdomian.com/_a/baas-admin/conf/index ( 有 **\"S\"**， 填写小程序和微信支付的信息 ）\n\n![wechat-conf](http://of2is3ok3.bkt.clouddn.com/xpmjs/xpmjs/wechat-conf.png)\n\n\n\n### 2. 使用 XpmJS \n\n**【下载代码】**\n\n使用  Git Bash , 进入小程序项目目录， 运行 git clone 拉去代码。（也可以\n使用 Git 等客户端 Clone 代码 ）\n\n```bash\ngit clone https://git.oschina.net/xpmjs/xpmjs.git xpmjs\n\n```\n\n克隆成功后的目录结构为: \n\n![tree](http://of2is3ok3.bkt.clouddn.com/xpmjs/xpmjs/tree.png)\n\n\n**【编写配置信息】**\n\n编辑 `app.js` 将域名更换为你的域名。（ 必须配置好 Https 证书 ）\n\n```javascript\nApp({\n\n  onLaunch: function () {\n\n    var that = this;\n\n    // 创建 xpm 对象\n    this.xpm = require('xpmjs/xpm.js').option({\n        'app':1,  // 对应后台 APP 配置，支持5个\n        'host':'yourdomian.com',\n        'https':'yourdomian.com',\n        'wss': 'yourdomian.com/ws-server',\n        'table.prefix': 'demo',\n        'user.table':'user'\n    });\n\n    // 创建全局对象\n    this.wss = this.xpm.require('wss');  // 信道\n    this.session = this.xpm.require('session');  // 会话\n    this.stor = this.xpm.require('stor'); // 存储\n\n  },\n\n  xpm:null,\n  session:null,\n  stor:null,\n  wss:null\n})\n\n```\n\n建议将 xpm、wss、session、stor 设定为全局变量。更多示例参考 [小程序Demo](https://git.oschina.net/xpmjs/wxdemo)\n\n\n## 五、XpmJS 交流群\n\nXpmJS 小程序开发微信交流群\n\n![小程序开发交流群三](http://of2is3ok3.bkt.clouddn.com/xqun3.png)\n\n\n## 六、F.A.Q.\n\n待整理\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrheyi%2Fxpmjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrheyi%2Fxpmjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrheyi%2Fxpmjs/lists"}