Repository: Taoshaoji/used-book-secondhand Branch: master Commit: ee31e684f858 Files: 564 Total size: 726.0 KB Directory structure: gitextract_m91prd5v/ ├── .gitignore ├── .vscode/ │ └── settings.json ├── README.md ├── cloudfunctions/ │ ├── his/ │ │ ├── index.js │ │ └── package.json │ ├── imgSecCheck/ │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── login/ │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── node/ │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── pay/ │ │ ├── index.js │ │ └── package.json │ ├── poking/ │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── ref/ │ │ ├── index.js │ │ └── package.json │ ├── regist/ │ │ ├── RdWXBizDataCrypt.js │ │ ├── cryptojs/ │ │ │ ├── cryptojs.js │ │ │ ├── lib/ │ │ │ │ ├── AES.js │ │ │ │ ├── BlockModes.js │ │ │ │ ├── Crypto.js │ │ │ │ ├── CryptoMath.js │ │ │ │ ├── DES.js │ │ │ │ ├── HMAC.js │ │ │ │ ├── MARC4.js │ │ │ │ ├── MD5.js │ │ │ │ ├── PBKDF2.js │ │ │ │ ├── PBKDF2Async.js │ │ │ │ ├── Rabbit.js │ │ │ │ ├── SHA1.js │ │ │ │ └── SHA256.js │ │ │ ├── package.json │ │ │ └── test/ │ │ │ └── PBKDF2-test.js │ │ ├── index.js │ │ └── package.json │ ├── removeChat/ │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── removeOrder/ │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── sell/ │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── sendMsg/ │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ └── sendTip/ │ ├── config.json │ ├── index.js │ └── package.json ├── miniprogram/ │ ├── app.js │ ├── app.json │ ├── app.wxss │ ├── common.wxml │ ├── common.wxs │ ├── components/ │ │ ├── add_tips/ │ │ │ ├── README.md │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── canvasdrawer/ │ │ │ ├── canvasdrawer.js │ │ │ ├── canvasdrawer.json │ │ │ ├── canvasdrawer.wxml │ │ │ └── canvasdrawer.wxss │ │ ├── chatroom/ │ │ │ ├── chatroom.js │ │ │ ├── chatroom.json │ │ │ ├── chatroom.wxml │ │ │ └── chatroom.wxss │ │ └── welcome/ │ │ ├── welcome.js │ │ ├── welcome.json │ │ ├── welcome.wxml │ │ └── welcome.wxss │ ├── config.js │ ├── pages/ │ │ ├── about/ │ │ │ ├── about.js │ │ │ ├── about.json │ │ │ ├── about.wxml │ │ │ └── about.wxss │ │ ├── appreciateCode/ │ │ │ ├── appreciateCode.js │ │ │ ├── appreciateCode.json │ │ │ ├── appreciateCode.wxml │ │ │ └── appreciateCode.wxss │ │ ├── detail/ │ │ │ ├── detail.js │ │ │ ├── detail.json │ │ │ ├── detail.wxml │ │ │ ├── detail.wxss │ │ │ └── room/ │ │ │ ├── room.js │ │ │ ├── room.json │ │ │ ├── room.wxml │ │ │ └── room.wxss │ │ ├── edit/ │ │ │ ├── edit.js │ │ │ ├── edit.json │ │ │ ├── edit.wxml │ │ │ └── edit.wxss │ │ ├── help/ │ │ │ ├── help.js │ │ │ ├── help.json │ │ │ ├── help.wxml │ │ │ └── help.wxss │ │ ├── index/ │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── kefu/ │ │ │ ├── kefu.js │ │ │ ├── kefu.json │ │ │ ├── kefu.wxml │ │ │ └── kefu.wxss │ │ ├── login/ │ │ │ ├── login.js │ │ │ ├── login.json │ │ │ ├── login.wxml │ │ │ └── login.wxss │ │ ├── message/ │ │ │ ├── message.js │ │ │ ├── message.json │ │ │ ├── message.wxml │ │ │ └── message.wxss │ │ ├── my/ │ │ │ ├── my.js │ │ │ ├── my.json │ │ │ ├── my.wxml │ │ │ └── my.wxss │ │ ├── order/ │ │ │ ├── detail/ │ │ │ │ ├── detail.js │ │ │ │ ├── detail.json │ │ │ │ ├── detail.wxml │ │ │ │ └── detail.wxss │ │ │ └── list/ │ │ │ ├── list.js │ │ │ ├── list.json │ │ │ ├── list.wxml │ │ │ └── list.wxss │ │ ├── publish/ │ │ │ ├── publish.js │ │ │ ├── publish.json │ │ │ ├── publish.wxml │ │ │ └── publish.wxss │ │ ├── search/ │ │ │ ├── search.js │ │ │ ├── search.json │ │ │ ├── search.wxml │ │ │ └── search.wxss │ │ ├── sell/ │ │ │ ├── detail/ │ │ │ │ ├── detail.js │ │ │ │ ├── detail.json │ │ │ │ ├── detail.wxml │ │ │ │ └── detail.wxss │ │ │ └── list/ │ │ │ ├── list.js │ │ │ ├── list.json │ │ │ ├── list.wxml │ │ │ └── list.wxss │ │ ├── start/ │ │ │ ├── start.js │ │ │ ├── start.json │ │ │ ├── start.wxml │ │ │ └── start.wxss │ │ ├── use/ │ │ │ ├── use.js │ │ │ ├── use.json │ │ │ ├── use.wxml │ │ │ └── use.wxss │ │ └── web/ │ │ ├── web.js │ │ ├── web.json │ │ ├── web.wxml │ │ └── web.wxss │ ├── sitemap.json │ ├── utils/ │ │ └── util.js │ └── vant/ │ ├── action-sheet/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── area/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── button/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── calendar/ │ │ ├── calendar.wxml │ │ ├── components/ │ │ │ ├── header/ │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.js │ │ │ │ ├── index.json │ │ │ │ ├── index.wxml │ │ │ │ └── index.wxss │ │ │ └── month/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ ├── index.wxss │ │ ├── utils.d.ts │ │ ├── utils.js │ │ └── utils.wxs │ ├── card/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── cell/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── cell-group/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── checkbox/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ └── index.wxss │ ├── checkbox-group/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── circle/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── col/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── collapse/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── collapse-item/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── common/ │ │ ├── color.d.ts │ │ ├── color.js │ │ ├── component.d.ts │ │ ├── component.js │ │ ├── index.wxss │ │ ├── style/ │ │ │ ├── clearfix.wxss │ │ │ ├── ellipsis.wxss │ │ │ ├── hairline.wxss │ │ │ ├── mixins/ │ │ │ │ ├── clearfix.wxss │ │ │ │ ├── ellipsis.wxss │ │ │ │ └── hairline.wxss │ │ │ ├── theme.wxss │ │ │ └── var.wxss │ │ ├── utils.d.ts │ │ ├── utils.js │ │ ├── version.d.ts │ │ └── version.js │ ├── count-down/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── utils.d.ts │ │ └── utils.js │ ├── datetime-picker/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── definitions/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── weapp.d.ts │ │ └── weapp.js │ ├── dialog/ │ │ ├── dialog.d.ts │ │ ├── dialog.js │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── divider/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── dropdown-item/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── dropdown-menu/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ └── index.wxss │ ├── field/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ ├── index.wxss │ │ ├── props.d.ts │ │ └── props.js │ ├── goods-action/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── goods-action-button/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── goods-action-icon/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── grid/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── grid-item/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── icon/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── image/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── index-anchor/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── index-bar/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── info/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── loading/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── mixins/ │ │ ├── basic.d.ts │ │ ├── basic.js │ │ ├── button.d.ts │ │ ├── button.js │ │ ├── link.d.ts │ │ ├── link.js │ │ ├── open-type.d.ts │ │ ├── open-type.js │ │ ├── page-scroll.d.ts │ │ ├── page-scroll.js │ │ ├── touch.d.ts │ │ ├── touch.js │ │ ├── transition.d.ts │ │ └── transition.js │ ├── nav-bar/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── notice-bar/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── notify/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── notify.d.ts │ │ └── notify.js │ ├── overlay/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── panel/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── picker/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── shared.d.ts │ │ ├── shared.js │ │ └── toolbar.wxml │ ├── picker-column/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ └── index.wxss │ ├── popup/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── progress/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ └── index.wxss │ ├── radio/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── radio-group/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── rate/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── row/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── search/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── sidebar/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── sidebar-item/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── skeleton/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── slider/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ └── index.wxss │ ├── stepper/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── steps/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── sticky/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ └── index.wxss │ ├── submit-bar/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── swipe-cell/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── switch/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── tab/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── tabbar/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── tabbar-item/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── tabs/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ └── index.wxss │ ├── tag/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── toast/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── toast.d.ts │ │ └── toast.js │ ├── transition/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── tree-select/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxs │ │ └── index.wxss │ ├── uploader/ │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── shared.d.ts │ │ ├── shared.js │ │ ├── utils.d.ts │ │ └── utils.js │ └── wxs/ │ ├── add-unit.wxs │ ├── array.wxs │ ├── bem.wxs │ ├── memoize.wxs │ ├── object.wxs │ └── utils.wxs └── project.config.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ node_modules/* ================================================ FILE: .vscode/settings.json ================================================ { "git.ignoreLimitWarning": true } ================================================ FILE: README.md ================================================ # Secondary_trading_applet 基于微信小程序的校园二手交易平台 ## 校园二手商城微信小程序成果(云开发) 图片看不到可在B站搜索易珠观看效果 ### 功能 **(1)用户登陆注册**:在小程序个人主页点击登录或注册,填写相关信息,即可登录或注册,拥有个人账号进行买卖操作。后续也可以修改用户资料。 **(2)用户(卖家)出售商品**:在小程序发布页面,上传商品图片,填写商品各种详细即可发布商品。在个人主页的发布信息中即可查看商品交易信息,可以删除订单,重新上架商品,删除商品。 **(3)用户浏览商品**:商城主页,用户可以通过分类查看各个商品信息,也可以搜索商品名,得到筛选后的商品。点击商品进入商品详情页,可查看商品详细信息。 **(4)用户(买家)购买商品**:在商品详情页,买家可点击立即购买,预定这个商品,可在个人主页的购买信息中查看自己的购买记录,也可以在放弃购买时删除该订单,或在收到商品交易达成后,点击确认收货。交易完成。 **(5)用户交流**:买家可在商品详情页点击聊天与卖家进行沟通。在个人主页的消息中心中,都可以查看聊天信息,进入聊天室。 ### 用户操作举例 首先进入小程序进行登录授权,授权进入后,显示商城主页,当前为未登陆注册状态不能发布和购买商品。 image-20200920220005803 image-20200920220722873 点击下方导航栏‘我的’进入个人主页,点击**登录**,填写信息,注册或登录账号,登录注册成功,个人主页显示用户微信头像及昵称 image-20200920220841085image-20200920220948222 用户想要**出售商品**,可在商城主页导航栏点击‘发布’,填写信息发布商品,在个人主页我的发布中查看出售情况,如不想出售也可在我的发布处点击删除,商品下架。 image-20200920221442425image-20200920221738182image-20200920221751633 用户想要**入手商品**,可回到商城首页,分类浏览商品,也可以通过上方搜索栏搜索商品,用户可以点击商品,进入商品详情页,查看物品详情,卖家信息,备注等等 image-20200920221852958image-20200920221938299image-20200920222108667 买卖双方**交易过程:** 1.买家购买商品: 买家购买商品后,如在线下收到商品,则可以通过确认收货通知卖家 image-20200920222151402image-20200920222300547image-20200920222352110 2.买家中止交易: 买家可以点击取消订单按钮中途取消交易,卖家会收到消息提醒。商品会自动上架。 image-20200920222529192 3.卖家中止交易: 卖家可中途中止交易。然后点击重新上架按钮,重新发布到首页展示。 image-20200920222737231image-20200920222748670image-20200920222804302 买家可在商品详情页点击‘聊天’与卖家沟通 image-20200920222934149 卖家可在个人主页消息中心中,看到买家的信息,进入聊天室与之交流。 image-20200920223013113 ### 部署教程: 本小程序已经上线,可先预览: image-20200920223554236 ## 一、小程序端 ### 1、下载导入 直接下载到本地,然后导入开发者工具 > 小程序开发综合文档地址:https://developers.weixin.qq.com/miniprogram/dev/framework/ ### 2、开通云环境 不罗嗦,这都是基础,直接看官方说明操作即可 > 云开发官方文档说明:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html ### 3、配置前端config 找到config.js文件,然后按照我写的注释更改为你自己的 image-20200920223633305 ## 二、云函数 ### 1、修改基础信息 每个云函数要修改的部分,我都捻出来放在了顶部,直接根据我做的注释信息进行修改,如下图所示 image-20200920223729148 ### 2、上传全部文件 挨个提交每个云函数,其中依赖包我已经一起上传了,无需再挨个本地去安装,直接上传所有文件即可 image-20200920223930768 ## 三、云开发数据库 ### 1、创建集合 设置权限 分别创建下图所示的集合,然后将所有集合的权限设置为所有可读 image-20200920224111392 ### 2、设置banner #### ①在banner集合下新增一条记录 #### ②按照下图所示添加字段 image-20200920224159506 #### 补充说明 list数组下的img为图片地址,id为唯一区分字段,url为点击轮播后跳转的地址,这个地址必须为与此小程序关联的公众号文章或者为业务域名地址,如果没有就留空即可 ### 3、设置启动页图片 #### ①在start集合下新增一条记录 #### ②按照下图所示添加字段 image-20200920224235782 ## 四、公众平台配置(小程序不上线则不需要执行此步骤) ### 1、设置基本信息 | 名称 | 配置 | | ------ | ---------------------------- | | 类目 | 生活服务 > 环保回收/废品回收 | | 基础库 | 2.4.3 | ### 2、提交审核 审核页面路径:pages/index/index ### 3、设置在线客服 打开【设置】--【客服】--【添加】,绑定成功后,打开小程序【客服小助手】,状态设置为在线即可,到时候有客户咨询自动会推送到你的微信号上的 image-20200920224525938 ## 五、服务与反馈 #### 如果需要提供安装服务,直接联系我微信:XXXXXXXXXX 如果觉得对你有帮助可以支持一下!感谢!**(代码开源,但时间不“开源”,伸手党勿扰!)** image-2020092022458 ================================================ FILE: cloudfunctions/his/index.js ================================================ const envid = 'taoshaoji-46f0r'; //云开发环境id /* 下 面 不 用 管 */ // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init({ env: envid, }) const TcbRouter = require('tcb-router'); //云函数路由 const db = cloud.database(); // 云函数入口函数 exports.main = async(event, context) => { const app = new TcbRouter({ event }); //钱包充值 app.router('recharge', async(ctx) => { const wxContext = cloud.getWXContext() const openid = wxContext.OPENID; const userinfo = await db.collection('user').where({ _openid: openid // 填入当前用户 openid }).get() try { ctx.body = await db.collection('user').doc(userinfo.data[0]._id).update({ data: { parse: userinfo.data[0].parse + parseInt(event.num) } }); } catch (e) { console.error(e) } }); //买家确认收货 app.router('toseller', async(ctx) => { //先增加历史记录 await db.collection('history').add({ // data 字段表示需新增的 JSON 数据 data: { oid: event.seller, name: '出售书籍', num: event.num, stamp: new Date().getTime(), type: 1, } }) //再修改钱包值 let userinfo = await db.collection('user').where({ _openid: event.seller, // 卖家openid }).get() ctx.body = await db.collection('user').doc(userinfo.data[0]._id).update({ data: { parse: userinfo.data[0].parse + parseInt(event.num) } }); }); //卖家取消订单退款 app.router('tobuyer', async(ctx) => { //先增加历史记录 await db.collection('history').add({ // data 字段表示需新增的 JSON 数据 data: { oid: event.buyer, name: '卖家取消交易退款', num: event.num, stamp: new Date().getTime(), type: 1, } }) //再修改钱包值 let userinfo = await db.collection('user').where({ _openid: event.buyer, }).get() ctx.body = await db.collection('user').doc(userinfo.data[0]._id).update({ data: { parse: userinfo.data[0].parse + parseInt(event.num) } }); }); return app.serve(); } ================================================ FILE: cloudfunctions/his/package.json ================================================ { "name": "his", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "tcb-router": "^1.1.2", "wx-server-sdk": "^1.1.0" } } ================================================ FILE: cloudfunctions/imgSecCheck/config.json ================================================ { "permissions": { "openapi": [ "security.imgSecCheck" ] } } ================================================ FILE: cloudfunctions/imgSecCheck/index.js ================================================ // 云函数入口文件 const cloud = require('wx-server-sdk'); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() try { const result = await cloud.openapi.security.imgSecCheck({ media: { contentType: 'image/png', value: Buffer.from(event.img) // 这里必须要将小程序端传过来的进行Buffer转化,否则就会报错,接口异常 } }) if (result && result.errCode.toString() === '87014') { return { code: 500, msg: '内容含有违法违规内容', data: result } } else { return { code: 200, msg: '内容ok', data: result } } } catch (err) { // 错误处理 if (err.errCode.toString() === '87014') { return { code: 500, msg: '内容含有违法违规内容', data: err } } return { code: 502, msg: '调用imgSecCheck接口异常', data: err } } } ================================================ FILE: cloudfunctions/imgSecCheck/package.json ================================================ { "name": "imgSecCheck", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "~2.2.0" } } ================================================ FILE: cloudfunctions/login/config.json ================================================ { "permissions": { "openapi": [] } } ================================================ FILE: cloudfunctions/login/index.js ================================================ // 云函数模板 // 部署:在 cloud-functions/login 文件夹右击选择 “上传并部署” const cloud = require('wx-server-sdk') // 初始化 cloud cloud.init({ // API 调用都保持和云函数当前所在环境一致 env: "taoshaoji-46f0r" }) /** * 这个示例将经自动鉴权过的小程序用户 openid 返回给小程序端 * * event 参数包含小程序端调用传入的 data * */ exports.main = (event, context) => { console.log(event) console.log(context) // 可执行其他自定义逻辑 // console.log 的内容可以在云开发云函数调用日志查看 // 获取 WX Context (微信调用上下文),包括 OPENID、APPID、及 UNIONID(需满足 UNIONID 获取条件)等信息 const wxContext = cloud.getWXContext() return { event, openid: wxContext.OPENID, appid: wxContext.appid, unionid: wxContext.UNIONID, env: wxContext.ENV, } } ================================================ FILE: cloudfunctions/login/package.json ================================================ { "name": "login", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "latest" } } ================================================ FILE: cloudfunctions/node/config.json ================================================ { "permissions": { "openapi": [ ] } } ================================================ FILE: cloudfunctions/node/index.js ================================================ // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() const _ = db.command // 云函数入口函数 exports.main = async (event, _context) => { try { return await db.collection('publish').doc(event._id).update({ // data 传入需要局部更新的数据 data: { status:event.status } }) } catch (e) { console.error(e) } } ================================================ FILE: cloudfunctions/node/package.json ================================================ { "name": "node", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "~2.1.2" } } ================================================ FILE: cloudfunctions/pay/index.js ================================================ const config = { appid: 'xxxxxxx', //服务商公众号Appid envName: 'taoshaoji-46f0r', // 小程序云开发环境ID mchid: 'xxxxxxxx', //商户号 partnerKey: 'xxxxxxxxxxxxx', //此处填服务商密钥 notify_url: 'https://mp.weixin.qq.com', //这个不要管 spbill_create_ip: '127.0.0.1'//这个不要管 }; /* 下 面 不 用 管 */ const cloud = require('wx-server-sdk'); cloud.init({ env: config.envName }) const db = cloud.database(); const TcbRouter = require('tcb-router'); //云函数路由 const rq = require('request'); const tenpay = require('tenpay');//支付核心模块 exports.main = async (event, context) => { const app = new TcbRouter({ event }); //支付回调 app.router('pay', async (ctx) => { const wxContext = cloud.getWXContext(); // 在云函数参数中,提取商品 ID const goodId = event.goodId; // 根据商品的数据库_id将其它数据提取出来 let goods = await db.collection('publish').doc(goodId).get(); // 在云函数中提取数据,包括名称、价格才更合理安全, // 因为从端里传过来的商品数据都是不可靠的 let good=goods.data; const curTime = Date.now(); const api = tenpay.init(config) let result = await api.getPayParams({ //商户订单号,我这里是定义的boolk+商品发布时间+当前时间戳 //微信这里限制订单号一次性不能重复,只需要唯一即可 out_trade_no: 'book'+good.creat + '' + curTime, body: good.bookinfo.title, //商品名称,我设置的书名 total_fee: parseInt(good.price)*100, //金额,注意是数字,不是字符串 openid: wxContext.OPENID //***用户的openid }); ctx.body = result;//返回前端结果 }); //充值钱包 app.router('recharge', async (ctx) => { const wxContext = cloud.getWXContext(); const curTime = Date.now(); const api = tenpay.init(config) let result = await api.getPayParams({ //商户订单号 out_trade_no: 'bookcz' + event.num + '' + curTime, body: '充值钱包', //商品名称 total_fee: parseInt(event.num)*100, //金额,注意是数字,不是字符串 openid: wxContext.OPENID //***用户的openid }); ctx.body = result;//返回前端结果 }); //修改卖家在售状态 app.router('changeP', async (ctx) => { try { return await db.collection('publish').doc(event._id).update({ data: { status:event.status } }) } catch (e) { console.error(e) } }); //修改订单状态 app.router('changeO', async (ctx) => { try { return await db.collection('order').doc(event._id).update({ data: { status: event.status } }) } catch (e) { console.error(e) } }); return app.serve(); } ================================================ FILE: cloudfunctions/pay/package.json ================================================ { "name": "pay", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "request": "^2.88.0", "tcb-router": "^1.1.2", "tenpay": "^2.1.18", "wx-server-sdk": "latest" } } ================================================ FILE: cloudfunctions/poking/config.json ================================================ { "permissions": { "openapi": [ ] } } ================================================ FILE: cloudfunctions/poking/index.js ================================================ const cloud = require('wx-server-sdk') cloud.init() exports.main = async(event, context) => { try { const result = await cloud.openapi.subscribeMessage.send({ touser: event.openid, //要推送给那个用户 page: 'pages/index/index', //要跳转到那个小程序页面 data: {//推送的内容 thing1: { value: event.nickName }, phrase2: { value: event.phrase, }, thing3: { value: event.tip } }, templateId: 'XXmEjf37meLWQaEsOX6qkkufcVH-YKAL3cHyY9Lru0Q' //模板id }) console.log(result) return result } catch (err) { console.log(err) return err } } ================================================ FILE: cloudfunctions/poking/package.json ================================================ { "name": "poking", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "~2.2.0" } } ================================================ FILE: cloudfunctions/ref/index.js ================================================ const config = { appid: 'wxd6beb52c8602bff4', //小程序Appid envName: 'taoshaoji-46f0r', // 小程序云开发环境ID mchid: '1111111111', //商户号 partnerKey: '1111111111111111111111', //此处填服务商密钥 pfx: '', //证书初始化 fileID: 'cloud://taoshaoji-46f0r.7461-taoshaoji-46f0r-1302243411/apiclient_cert.p12', //证书云存储id actionName:'吉珠二手书商城小程序提现', rate:1 //提现收取利率,1指的是每笔收取1% }; /* 下 面 不 用 管 */ const cloud = require('wx-server-sdk') cloud.init({ env: config.envName }) const db = cloud.database(); const tenpay = require('tenpay'); //支付核心模块 exports.main = async(event, context) => { let userInfo = (await db.collection('user').doc(event.userid).get()).data; if (parseInt(userInfo.parse)<=parseInt(event.num)){ return 0; } //首先获取证书文件 let fileres = await cloud.downloadFile({ fileID: config.fileID, }) config.pfx = fileres.fileContent let pay = new tenpay(config,true) let result = await pay.transfers({ partner_trade_no: 'bookreflect' + Date.now() + event.num, openid: userInfo._openid, check_name: 'NO_CHECK', amount: parseInt(event.num) * (100 - config.rate), desc: config.actionName, }); if (result.result_code == 'SUCCESS') { //成功后操作 //以下是进行余额计算 let re=await db.collection('user').doc(event.userid).update({ data: { parse: userInfo.parse - parseInt(event.num) } }); return re } } ================================================ FILE: cloudfunctions/ref/package.json ================================================ { "name": "ref", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "tenpay": "^2.1.18", "wx-server-sdk": "^1.2.1" } } ================================================ FILE: cloudfunctions/regist/RdWXBizDataCrypt.js ================================================ // 引入CryptoJS var Crypto = require('cryptojs/cryptojs.js').Crypto; function RdWXBizDataCrypt(appId, sessionKey) { this.appId = appId this.sessionKey = sessionKey } RdWXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) { encryptedData = encryptedData.replace(/%/g, '%25') // base64 decode :使用 CryptoJS 中 Crypto.util.base64ToBytes()进行 base64解码 var encryptedData = Crypto.util.base64ToBytes(encryptedData) var key = Crypto.util.base64ToBytes(this.sessionKey); var iv = Crypto.util.base64ToBytes(iv); // 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充 var mode = new Crypto.mode.CBC(Crypto.pad.pkcs7); try { // 解密 var bytes = Crypto.AES.decrypt(encryptedData, key, { asBpytes: true, iv: iv, mode: mode }); var decryptResult = JSON.parse(bytes); } catch (err) { console.log(err) } if (decryptResult.watermark.appid !== this.appId) { console.log(err) } return decryptResult } module.exports = RdWXBizDataCrypt ================================================ FILE: cloudfunctions/regist/cryptojs/cryptojs.js ================================================ var Crypto = exports.Crypto = require('./lib/Crypto').Crypto; [ 'CryptoMath' , 'BlockModes' , 'DES' , 'AES' , 'HMAC' , 'MARC4' , 'MD5' , 'PBKDF2' , 'PBKDF2Async' , 'Rabbit' , 'SHA1' , 'SHA256' ].forEach( function (path) { require('./lib/' + path); }); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/AES.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8; // Precomputed SBOX var SBOX = [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ]; // Compute inverse SBOX lookup table for (var INVSBOX = [], i = 0; i < 256; i++) INVSBOX[SBOX[i]] = i; // Compute mulitplication in GF(2^8) lookup tables var MULT2 = [], MULT3 = [], MULT9 = [], MULTB = [], MULTD = [], MULTE = []; function xtime(a, b) { for (var result = 0, i = 0; i < 8; i++) { if (b & 1) result ^= a; var hiBitSet = a & 0x80; a = (a << 1) & 0xFF; if (hiBitSet) a ^= 0x1b; b >>>= 1; } return result; } for (var i = 0; i < 256; i++) { MULT2[i] = xtime(i,2); MULT3[i] = xtime(i,3); MULT9[i] = xtime(i,9); MULTB[i] = xtime(i,0xB); MULTD[i] = xtime(i,0xD); MULTE[i] = xtime(i,0xE); } // Precomputed RCon lookup var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; // Inner state var state = [[], [], [], []], keylength, nrounds, keyschedule; var AES = C.AES = { /** * Public API */ encrypt: function (message, password, options) { options = options || {}; // Determine mode var mode = options.mode || new C.mode.OFB; // Allow mode to override options if (mode.fixOptions) mode.fixOptions(options); var // Convert to bytes if message is a string m = ( message.constructor == String ? UTF8.stringToBytes(message) : message ), // Generate random IV iv = options.iv || util.randomBytes(AES._blocksize * 4), // Generate key k = ( password.constructor == String ? // Derive key from passphrase C.PBKDF2(password, iv, 32, { asBytes: true }) : // else, assume byte array representing cryptographic key password ); // Encrypt AES._init(k); mode.encrypt(AES, m, iv); // Return ciphertext m = options.iv ? m : iv.concat(m); return (options && options.asBytes) ? m : util.bytesToBase64(m); }, decrypt: function (ciphertext, password, options) { options = options || {}; // Determine mode var mode = options.mode || new C.mode.OFB; // Allow mode to override options if (mode.fixOptions) mode.fixOptions(options); var // Convert to bytes if ciphertext is a string c = ( ciphertext.constructor == String ? util.base64ToBytes(ciphertext): ciphertext ), // Separate IV and message iv = options.iv || c.splice(0, AES._blocksize * 4), // Generate key k = ( password.constructor == String ? // Derive key from passphrase C.PBKDF2(password, iv, 32, { asBytes: true }) : // else, assume byte array representing cryptographic key password ); // Decrypt AES._init(k); mode.decrypt(AES, c, iv); // Return plaintext return (options && options.asBytes) ? c : UTF8.bytesToString(c); }, /** * Package private methods and properties */ _blocksize: 4, _encryptblock: function (m, offset) { // Set input for (var row = 0; row < AES._blocksize; row++) { for (var col = 0; col < 4; col++) state[row][col] = m[offset + col * 4 + row]; } // Add round key for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] ^= keyschedule[col][row]; } for (var round = 1; round < nrounds; round++) { // Sub bytes for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] = SBOX[state[row][col]]; } // Shift rows state[1].push(state[1].shift()); state[2].push(state[2].shift()); state[2].push(state[2].shift()); state[3].unshift(state[3].pop()); // Mix columns for (var col = 0; col < 4; col++) { var s0 = state[0][col], s1 = state[1][col], s2 = state[2][col], s3 = state[3][col]; state[0][col] = MULT2[s0] ^ MULT3[s1] ^ s2 ^ s3; state[1][col] = s0 ^ MULT2[s1] ^ MULT3[s2] ^ s3; state[2][col] = s0 ^ s1 ^ MULT2[s2] ^ MULT3[s3]; state[3][col] = MULT3[s0] ^ s1 ^ s2 ^ MULT2[s3]; } // Add round key for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] ^= keyschedule[round * 4 + col][row]; } } // Sub bytes for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] = SBOX[state[row][col]]; } // Shift rows state[1].push(state[1].shift()); state[2].push(state[2].shift()); state[2].push(state[2].shift()); state[3].unshift(state[3].pop()); // Add round key for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] ^= keyschedule[nrounds * 4 + col][row]; } // Set output for (var row = 0; row < AES._blocksize; row++) { for (var col = 0; col < 4; col++) m[offset + col * 4 + row] = state[row][col]; } }, _decryptblock: function (c, offset) { // Set input for (var row = 0; row < AES._blocksize; row++) { for (var col = 0; col < 4; col++) state[row][col] = c[offset + col * 4 + row]; } // Add round key for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] ^= keyschedule[nrounds * 4 + col][row]; } for (var round = 1; round < nrounds; round++) { // Inv shift rows state[1].unshift(state[1].pop()); state[2].push(state[2].shift()); state[2].push(state[2].shift()); state[3].push(state[3].shift()); // Inv sub bytes for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] = INVSBOX[state[row][col]]; } // Add round key for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] ^= keyschedule[(nrounds - round) * 4 + col][row]; } // Inv mix columns for (var col = 0; col < 4; col++) { var s0 = state[0][col], s1 = state[1][col], s2 = state[2][col], s3 = state[3][col]; state[0][col] = MULTE[s0] ^ MULTB[s1] ^ MULTD[s2] ^ MULT9[s3]; state[1][col] = MULT9[s0] ^ MULTE[s1] ^ MULTB[s2] ^ MULTD[s3]; state[2][col] = MULTD[s0] ^ MULT9[s1] ^ MULTE[s2] ^ MULTB[s3]; state[3][col] = MULTB[s0] ^ MULTD[s1] ^ MULT9[s2] ^ MULTE[s3]; } } // Inv shift rows state[1].unshift(state[1].pop()); state[2].push(state[2].shift()); state[2].push(state[2].shift()); state[3].push(state[3].shift()); // Inv sub bytes for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] = INVSBOX[state[row][col]]; } // Add round key for (var row = 0; row < 4; row++) { for (var col = 0; col < 4; col++) state[row][col] ^= keyschedule[col][row]; } // Set output for (var row = 0; row < AES._blocksize; row++) { for (var col = 0; col < 4; col++) c[offset + col * 4 + row] = state[row][col]; } }, /** * Private methods */ _init: function (k) { keylength = k.length / 4; nrounds = keylength + 6; AES._keyexpansion(k); }, // Generate a key schedule _keyexpansion: function (k) { keyschedule = []; for (var row = 0; row < keylength; row++) { keyschedule[row] = [ k[row * 4], k[row * 4 + 1], k[row * 4 + 2], k[row * 4 + 3] ]; } for (var row = keylength; row < AES._blocksize * (nrounds + 1); row++) { var temp = [ keyschedule[row - 1][0], keyschedule[row - 1][1], keyschedule[row - 1][2], keyschedule[row - 1][3] ]; if (row % keylength == 0) { // Rot word temp.push(temp.shift()); // Sub word temp[0] = SBOX[temp[0]]; temp[1] = SBOX[temp[1]]; temp[2] = SBOX[temp[2]]; temp[3] = SBOX[temp[3]]; temp[0] ^= RCON[row / keylength]; } else if (keylength > 6 && row % keylength == 4) { // Sub word temp[0] = SBOX[temp[0]]; temp[1] = SBOX[temp[1]]; temp[2] = SBOX[temp[2]]; temp[3] = SBOX[temp[3]]; } keyschedule[row] = [ keyschedule[row - keylength][0] ^ temp[0], keyschedule[row - keylength][1] ^ temp[1], keyschedule[row - keylength][2] ^ temp[2], keyschedule[row - keylength][3] ^ temp[3] ]; } } }; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/BlockModes.js ================================================ /*! * Crypto-JS contribution from Simon Greatrix */ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Create pad namespace var C_pad = C.pad = {}; // Calculate the number of padding bytes required. function _requiredPadding(cipher, message) { var blockSizeInBytes = cipher._blocksize * 4; var reqd = blockSizeInBytes - message.length % blockSizeInBytes; return reqd; }; // Remove padding when the final byte gives the number of padding bytes. var _unpadLength = function (message) { var pad = message.pop(); for (var i = 1; i < pad; i++) { message.pop(); } }; // No-operation padding, used for stream ciphers C_pad.NoPadding = { pad : function (cipher,message) {}, unpad : function (message) {} }; // Zero Padding. // // If the message is not an exact number of blocks, the final block is // completed with 0x00 bytes. There is no unpadding. C_pad.ZeroPadding = { pad : function (cipher, message) { var blockSizeInBytes = cipher._blocksize * 4; var reqd = message.length % blockSizeInBytes; if( reqd!=0 ) { for(reqd = blockSizeInBytes - reqd; reqd>0; reqd--) { message.push(0x00); } } }, unpad : function (message) {} }; // ISO/IEC 7816-4 padding. // // Pads the plain text with an 0x80 byte followed by as many 0x00 // bytes are required to complete the block. C_pad.iso7816 = { pad : function (cipher, message) { var reqd = _requiredPadding(cipher, message); message.push(0x80); for (; reqd > 1; reqd--) { message.push(0x00); } }, unpad : function (message) { while (message.pop() != 0x80) {} } }; // ANSI X.923 padding // // The final block is padded with zeros except for the last byte of the // last block which contains the number of padding bytes. C_pad.ansix923 = { pad : function (cipher, message) { var reqd = _requiredPadding(cipher, message); for (var i = 1; i < reqd; i++) { message.push(0x00); } message.push(reqd); }, unpad : _unpadLength }; // ISO 10126 // // The final block is padded with random bytes except for the last // byte of the last block which contains the number of padding bytes. C_pad.iso10126 = { pad : function (cipher, message) { var reqd = _requiredPadding(cipher, message); for (var i = 1; i < reqd; i++) { message.push(Math.floor(Math.random() * 256)); } message.push(reqd); }, unpad : _unpadLength }; // PKCS7 padding // // PKCS7 is described in RFC 5652. Padding is in whole bytes. The // value of each added byte is the number of bytes that are added, // i.e. N bytes, each of value N are added. C_pad.pkcs7 = { pad : function (cipher, message) { var reqd = _requiredPadding(cipher, message); for (var i = 0; i < reqd; i++) { message.push(reqd); } }, unpad : _unpadLength }; // Create mode namespace var C_mode = C.mode = {}; /** * Mode base "class". */ var Mode = C_mode.Mode = function (padding) { if (padding) { this._padding = padding; } }; Mode.prototype = { encrypt: function (cipher, m, iv) { this._padding.pad(cipher, m); this._doEncrypt(cipher, m, iv); }, decrypt: function (cipher, m, iv) { this._doDecrypt(cipher, m, iv); this._padding.unpad(m); }, // Default padding _padding: C_pad.iso7816 }; /** * Electronic Code Book mode. * * ECB applies the cipher directly against each block of the input. * * ECB does not require an initialization vector. */ var ECB = C_mode.ECB = function () { // Call parent constructor Mode.apply(this, arguments); }; // Inherit from Mode var ECB_prototype = ECB.prototype = new Mode; // Concrete steps for Mode template ECB_prototype._doEncrypt = function (cipher, m, iv) { var blockSizeInBytes = cipher._blocksize * 4; // Encrypt each block for (var offset = 0; offset < m.length; offset += blockSizeInBytes) { cipher._encryptblock(m, offset); } }; ECB_prototype._doDecrypt = function (cipher, c, iv) { var blockSizeInBytes = cipher._blocksize * 4; // Decrypt each block for (var offset = 0; offset < c.length; offset += blockSizeInBytes) { cipher._decryptblock(c, offset); } }; // ECB never uses an IV ECB_prototype.fixOptions = function (options) { options.iv = []; }; /** * Cipher block chaining * * The first block is XORed with the IV. Subsequent blocks are XOR with the * previous cipher output. */ var CBC = C_mode.CBC = function () { // Call parent constructor Mode.apply(this, arguments); }; // Inherit from Mode var CBC_prototype = CBC.prototype = new Mode; // Concrete steps for Mode template CBC_prototype._doEncrypt = function (cipher, m, iv) { var blockSizeInBytes = cipher._blocksize * 4; // Encrypt each block for (var offset = 0; offset < m.length; offset += blockSizeInBytes) { if (offset == 0) { // XOR first block using IV for (var i = 0; i < blockSizeInBytes; i++) m[i] ^= iv[i]; } else { // XOR this block using previous crypted block for (var i = 0; i < blockSizeInBytes; i++) m[offset + i] ^= m[offset + i - blockSizeInBytes]; } // Encrypt block cipher._encryptblock(m, offset); } }; CBC_prototype._doDecrypt = function (cipher, c, iv) { var blockSizeInBytes = cipher._blocksize * 4; // At the start, the previously crypted block is the IV var prevCryptedBlock = iv; // Decrypt each block for (var offset = 0; offset < c.length; offset += blockSizeInBytes) { // Save this crypted block var thisCryptedBlock = c.slice(offset, offset + blockSizeInBytes); // Decrypt block cipher._decryptblock(c, offset); // XOR decrypted block using previous crypted block for (var i = 0; i < blockSizeInBytes; i++) { c[offset + i] ^= prevCryptedBlock[i]; } prevCryptedBlock = thisCryptedBlock; } }; /** * Cipher feed back * * The cipher output is XORed with the plain text to produce the cipher output, * which is then fed back into the cipher to produce a bit pattern to XOR the * next block with. * * This is a stream cipher mode and does not require padding. */ var CFB = C_mode.CFB = function () { // Call parent constructor Mode.apply(this, arguments); }; // Inherit from Mode var CFB_prototype = CFB.prototype = new Mode; // Override padding CFB_prototype._padding = C_pad.NoPadding; // Concrete steps for Mode template CFB_prototype._doEncrypt = function (cipher, m, iv) { var blockSizeInBytes = cipher._blocksize * 4, keystream = iv.slice(0); // Encrypt each byte for (var i = 0; i < m.length; i++) { var j = i % blockSizeInBytes; if (j == 0) cipher._encryptblock(keystream, 0); m[i] ^= keystream[j]; keystream[j] = m[i]; } }; CFB_prototype._doDecrypt = function (cipher, c, iv) { var blockSizeInBytes = cipher._blocksize * 4, keystream = iv.slice(0); // Encrypt each byte for (var i = 0; i < c.length; i++) { var j = i % blockSizeInBytes; if (j == 0) cipher._encryptblock(keystream, 0); var b = c[i]; c[i] ^= keystream[j]; keystream[j] = b; } }; /** * Output feed back * * The cipher repeatedly encrypts its own output. The output is XORed with the * plain text to produce the cipher text. * * This is a stream cipher mode and does not require padding. */ var OFB = C_mode.OFB = function () { // Call parent constructor Mode.apply(this, arguments); }; // Inherit from Mode var OFB_prototype = OFB.prototype = new Mode; // Override padding OFB_prototype._padding = C_pad.NoPadding; // Concrete steps for Mode template OFB_prototype._doEncrypt = function (cipher, m, iv) { var blockSizeInBytes = cipher._blocksize * 4, keystream = iv.slice(0); // Encrypt each byte for (var i = 0; i < m.length; i++) { // Generate keystream if (i % blockSizeInBytes == 0) cipher._encryptblock(keystream, 0); // Encrypt byte m[i] ^= keystream[i % blockSizeInBytes]; } }; OFB_prototype._doDecrypt = OFB_prototype._doEncrypt; /** * Counter * @author Gergely Risko * * After every block the last 4 bytes of the IV is increased by one * with carry and that IV is used for the next block. * * This is a stream cipher mode and does not require padding. */ var CTR = C_mode.CTR = function () { // Call parent constructor Mode.apply(this, arguments); }; // Inherit from Mode var CTR_prototype = CTR.prototype = new Mode; // Override padding CTR_prototype._padding = C_pad.NoPadding; CTR_prototype._doEncrypt = function (cipher, m, iv) { var blockSizeInBytes = cipher._blocksize * 4; var counter = iv.slice(0); for (var i = 0; i < m.length;) { // do not lose iv var keystream = counter.slice(0); // Generate keystream for next block cipher._encryptblock(keystream, 0); // XOR keystream with block for (var j = 0; i < m.length && j < blockSizeInBytes; j++, i++) { m[i] ^= keystream[j]; } // Increase counter if(++(counter[blockSizeInBytes-1]) == 256) { counter[blockSizeInBytes-1] = 0; if(++(counter[blockSizeInBytes-2]) == 256) { counter[blockSizeInBytes-2] = 0; if(++(counter[blockSizeInBytes-3]) == 256) { counter[blockSizeInBytes-3] = 0; ++(counter[blockSizeInBytes-4]); } } } } }; CTR_prototype._doDecrypt = CTR_prototype._doEncrypt; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/Crypto.js ================================================ if (typeof Crypto == "undefined" || ! Crypto.util) { (function(){ var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // Global Crypto object // with browser window or with node module var Crypto = (typeof window === 'undefined') ? exports.Crypto = {} : window.Crypto = {}; // Crypto utilities var util = Crypto.util = { // Bit-wise rotate left rotl: function (n, b) { return (n << b) | (n >>> (32 - b)); }, // Bit-wise rotate right rotr: function (n, b) { return (n << (32 - b)) | (n >>> b); }, // Swap big-endian to little-endian and vice versa endian: function (n) { // If number given, swap endian if (n.constructor == Number) { return util.rotl(n, 8) & 0x00FF00FF | util.rotl(n, 24) & 0xFF00FF00; } // Else, assume array and swap all items for (var i = 0; i < n.length; i++) n[i] = util.endian(n[i]); return n; }, // Generate an array of any length of random bytes randomBytes: function (n) { for (var bytes = []; n > 0; n--) bytes.push(Math.floor(Math.random() * 256)); return bytes; }, // Convert a byte array to big-endian 32-bit words bytesToWords: function (bytes) { for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) words[b >>> 5] |= (bytes[i] & 0xFF) << (24 - b % 32); return words; }, // Convert big-endian 32-bit words to a byte array wordsToBytes: function (words) { for (var bytes = [], b = 0; b < words.length * 32; b += 8) bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); return bytes; }, // Convert a byte array to a hex string bytesToHex: function (bytes) { for (var hex = [], i = 0; i < bytes.length; i++) { hex.push((bytes[i] >>> 4).toString(16)); hex.push((bytes[i] & 0xF).toString(16)); } return hex.join(""); }, // Convert a hex string to a byte array hexToBytes: function (hex) { for (var bytes = [], c = 0; c < hex.length; c += 2) bytes.push(parseInt(hex.substr(c, 2), 16)); return bytes; }, // Convert a byte array to a base-64 string bytesToBase64: function (bytes) { // Use browser-native function if it exists if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes)); for(var base64 = [], i = 0; i < bytes.length; i += 3) { var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; for (var j = 0; j < 4; j++) { if (i * 8 + j * 6 <= bytes.length * 8) base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); else base64.push("="); } } return base64.join(""); }, // Convert a base-64 string to a byte array base64ToBytes: function (base64) { // Use browser-native function if it exists if (typeof atob == "function") return Binary.stringToBytes(atob(base64)); // Remove non-base-64 characters base64 = base64.replace(/[^A-Z0-9+\/]/ig, ""); for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) { if (imod4 == 0) continue; bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); } return bytes; } }; // Crypto character encodings var charenc = Crypto.charenc = {}; // UTF-8 encoding var UTF8 = charenc.UTF8 = { // Convert a string to a byte array stringToBytes: function (str) { return Binary.stringToBytes(unescape(encodeURIComponent(str))); }, // Convert a byte array to a string bytesToString: function (bytes) { return decodeURIComponent(escape(Binary.bytesToString(bytes))); } }; // Binary encoding var Binary = charenc.Binary = { // Convert a string to a byte array stringToBytes: function (str) { for (var bytes = [], i = 0; i < str.length; i++) bytes.push(str.charCodeAt(i) & 0xFF); return bytes; }, // Convert a byte array to a string bytesToString: function (bytes) { for (var str = [], i = 0; i < bytes.length; i++) str.push(String.fromCharCode(bytes[i])); return str.join(""); } }; })(); } ================================================ FILE: cloudfunctions/regist/cryptojs/lib/CryptoMath.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcut var util = C.util; // Convert n to unsigned 32-bit integer util.u32 = function (n) { return n >>> 0; }; // Unsigned 32-bit addition util.add = function () { var result = this.u32(arguments[0]); for (var i = 1; i < arguments.length; i++) result = this.u32(result + this.u32(arguments[i])); return result; }; // Unsigned 32-bit multiplication util.mult = function (m, n) { return this.add((n & 0xFFFF0000) * m, (n & 0x0000FFFF) * m); }; // Unsigned 32-bit greater than (>) comparison util.gt = function (m, n) { return this.u32(m) > this.u32(n); }; // Unsigned 32-bit less than (<) comparison util.lt = function (m, n) { return this.u32(m) < this.u32(n); }; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/DES.js ================================================ /** * Definition of Data Encryption Standard (DES) taken from: * http://www.itl.nist.gov/fipspubs/fip46-2.htm */ (function() { var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8; /*************************************************************************** * * DES Key Schedule. * * The Key consists of 16 sub-keys of 48 bits each. As each sub-key is * applied to an expanded 32-bit value where each 4 bits of input is * expanded into 6 bits of output the sub-key can be broken down into 8 * 32-bit values which allows the key to be used without expansion. * * To create the 16 sub-keys, 56 bits are selected from the input 64 bit key * according to PC1. Each sub-key is generated by left rotating the * bits a different amount and then selecting 48 bits according to PC2. * **************************************************************************/ var KeySchedule; /** * Representation of a DES key schedule. * * @param {Array * of 8 bytes} key The cipher key * * @constructor */ KeySchedule = function(key) { /** * The schedule of 16 keys */ this.keys = new Array(16); this._initialiseKeys(key); }; /** * Permuted Choice 1 (PC1) byte offsets into the key. Each of the 56 entries * selects one bit of DES's 56 bit key. *

* *

     * The PC1 is defined as:
     * 
     * 57,   49,    41,   33,    25,    17,    9,
     *  1,   58,    50,   42,    34,    26,   18,
     * 10,    2,    59,   51,    43,    35,   27,
     * 19,   11,     3,   60,    52,    44,   36,
     * 63,   55,    47,   39,    31,    23,   15,
     *  7,   62,    54,   46,    38,    30,   22,
     * 14,    6,    61,   53,    45,    37,   29,
     * 21,   13,     5,   28,    20,    12,    4
     * 
* * We represent this as an offset into an 8-byte array and a bit mask upon * that byte. For example 57=(7*8)+1 so is the first (MSB) of the 7th byte. * * @constant */ KeySchedule.PC1_offsets = [ 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 3, 2, 1, 0 ]; /** * Permuted Choice 1 (PC1) bit masks. Each of the 56 entries selects one bit * of DES's 56 bit key. * * @constant */ KeySchedule.PC1_masks = [ 128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64, 32, 32, 32, 32, 32, 32, 32, 32, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16 ]; /** * Permuted Choice 2 (PC2) selects the active 48 bits from the 56 bits of * the key. *

* *

     * The PC2 is defined as:
     * 
     * 14,   17,   11,   24,    1,    5,
     *  3,   28,   15,    6,   21,   10,
     * 23,   19,   12,    4,   26,    8,
     * 16,    7,   27,   20,   13,    2,
     * 41,   52,   31,   37,   47,   55,
     * 30,   40,   51,   45,   33,   48,
     * 44,   49,   39,   56,   34,   53,
     * 46,   42,   50,   36,   29,   32
     * 
* * We invert the choice to specify what each bit adds to each 6-bit value of * the key. For example, bit 1 is the 5th bit selected so this add 2 to the * first 6-bit value. * * @constant */ KeySchedule.PC2_offsets1 = [ 0, 3, 1, 2, 0, 1, 3, 2, 0, 1, 0, 2, 3, 0, 1, 3, 0, 0, 2, 3, 1, 0, 2, 0, 0, 2, 3, 1 ]; /** * PC2 offsets for 2nd block. * * @constant */ KeySchedule.PC2_offsets2 = [ 7, 5, 4, 7, 5, 6, 0, 7, 4, 0, 6, 5, 4, 7, 0, 6, 5, 7, 4, 5, 6, 7, 5, 4, 6, 0, 4, 6 ]; /** * Permuted Choice 2 (PC2) masks for 1st block. * * @constant */ KeySchedule.PC2_masks1 = [ 2, 1, 32, 4, 1, 4, 16, 1, 0, 1, 8, 8, 2, 32, 8, 32, 16, 0, 16, 4, 2, 0, 32, 4, 0, 2, 8, 16 ]; /** * PC2 masks for 2nd block. * * @constant */ KeySchedule.PC2_masks2 = [ 2, 32, 8, 1, 2, 2, 0, 4, 4, 0, 8, 16, 32, 16, 0, 32, 4, 32, 2, 1, 16, 8, 8, 16, 1, 0, 1, 4 ]; /** * Cumulative key shifts. * * @constant */ KeySchedule.keyShifts = [ 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 ]; KeySchedule.prototype._initialiseKeys = function(key) { var i; // extract 56 key bits in order determined by PC1 var bits = new Array(56); for (i = 0; i < 56; i++) { bits[i] = (key[KeySchedule.PC1_offsets[i]] & KeySchedule.PC1_masks[i]) != 0; } // split 56 bits into two 28-bit chunks var bits1 = bits.slice(0, 28); var bits2 = bits.slice(28, 56); // duplicate each half to allow for easy bit shifts bits1 = bits1.concat(bits1); bits2 = bits2.concat(bits2); // assemble the 16 keys for (i = 0; i < 16; i++) { var k = [ 0, 0, 0, 0, 0, 0, 0, 0 ]; // select the bits of the key according to PC2 var s = KeySchedule.keyShifts[i]; for ( var j = 0; j < 28; j++) { if (bits1[j + s]) { k[KeySchedule.PC2_offsets1[j]] += KeySchedule.PC2_masks1[j]; } if (bits2[j + s]) { k[KeySchedule.PC2_offsets2[j]] += KeySchedule.PC2_masks2[j]; } } // Scale each of the 8 blocks to a 32-bit mask. k[0] = ((k[0] & 0x1f) << 27) + ((k[0] & 0x20) >> 5); for ( var j = 1; j <= 6; j++) { k[j] = k[j] << (27 - 4 * j); } k[7] = ((k[7] & 0x3e) >> 1) + ((k[7] & 0x1) << 31); this.keys[i] = k; } }; /** * Retrieve the key for a specified round * * @param i * the round * @returns the key */ KeySchedule.prototype.getKey = function(i) { return this.keys[i]; }; /*************************************************************************** * * DES Engine State * **************************************************************************/ var State; /** * The algorithm's state. DES operates on two sets of 32-bits, with each * block of 32-bits treated as a single number. * * @class */ State = function() { /** The LHS of the Feistel scheme */ this.lhs = 0; /** The RHS of the Feistel scheme */ this.rhs = 0; }; /** * The masks that select the SBOX input. Each SBOX accepts 6 bits from the * input. * * @constant */ State.SBOX_MASK = [ 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f ]; /** * The SBOXes. The 8 SBOXes each map 6 bit masked bit of the input to 4 bits * of output. These SBOXes include the post SBOX permutation and benefit * from JavaScript's sparse arrays to make specifying the input match * simple. * * @constant */ State.SBOX = new Array(8); var SBOX = State.SBOX; SBOX[0] = new Array(); SBOX[0][0] = 0x808200; // 0 (0, 0) = 14 SBOX[0][268435456] = 0x8000; // 10000000 (0, 1) = 4 SBOX[0][536870912] = 0x808002; // 20000000 (0, 2) = 13 SBOX[0][805306368] = 0x2; // 30000000 (0, 3) = 1 SBOX[0][1073741824] = 0x200; // 40000000 (0, 4) = 2 SBOX[0][1342177280] = 0x808202; // 50000000 (0, 5) = 15 SBOX[0][1610612736] = 0x800202; // 60000000 (0, 6) = 11 SBOX[0][1879048192] = 0x800000; // 70000000 (0, 7) = 8 SBOX[0][-2147483648] = 0x202; // 80000000 (0, 8) = 3 SBOX[0][-1879048192] = 0x800200; // 90000000 (0, 9) = 10 SBOX[0][-1610612736] = 0x8200; // a0000000 (0, 10) = 6 SBOX[0][-1342177280] = 0x808000; // b0000000 (0, 11) = 12 SBOX[0][-1073741824] = 0x8002; // c0000000 (0, 12) = 5 SBOX[0][-805306368] = 0x800002; // d0000000 (0, 13) = 9 SBOX[0][-536870912] = 0x0; // e0000000 (0, 14) = 0 SBOX[0][-268435456] = 0x8202; // f0000000 (0, 15) = 7 SBOX[0][134217728] = 0x0; // 8000000 (1, 0) = 0 SBOX[0][402653184] = 0x808202; // 18000000 (1, 1) = 15 SBOX[0][671088640] = 0x8202; // 28000000 (1, 2) = 7 SBOX[0][939524096] = 0x8000; // 38000000 (1, 3) = 4 SBOX[0][1207959552] = 0x808200; // 48000000 (1, 4) = 14 SBOX[0][1476395008] = 0x200; // 58000000 (1, 5) = 2 SBOX[0][1744830464] = 0x808002; // 68000000 (1, 6) = 13 SBOX[0][2013265920] = 0x2; // 78000000 (1, 7) = 1 SBOX[0][-2013265920] = 0x800200; // 88000000 (1, 8) = 10 SBOX[0][-1744830464] = 0x8200; // 98000000 (1, 9) = 6 SBOX[0][-1476395008] = 0x808000; // a8000000 (1, 10) = 12 SBOX[0][-1207959552] = 0x800202; // b8000000 (1, 11) = 11 SBOX[0][-939524096] = 0x800002; // c8000000 (1, 12) = 9 SBOX[0][-671088640] = 0x8002; // d8000000 (1, 13) = 5 SBOX[0][-402653184] = 0x202; // e8000000 (1, 14) = 3 SBOX[0][-134217728] = 0x800000; // f8000000 (1, 15) = 8 SBOX[0][1] = 0x8000; // 1 (2, 0) = 4 SBOX[0][268435457] = 0x2; // 10000001 (2, 1) = 1 SBOX[0][536870913] = 0x808200; // 20000001 (2, 2) = 14 SBOX[0][805306369] = 0x800000; // 30000001 (2, 3) = 8 SBOX[0][1073741825] = 0x808002; // 40000001 (2, 4) = 13 SBOX[0][1342177281] = 0x8200; // 50000001 (2, 5) = 6 SBOX[0][1610612737] = 0x200; // 60000001 (2, 6) = 2 SBOX[0][1879048193] = 0x800202; // 70000001 (2, 7) = 11 SBOX[0][-2147483647] = 0x808202; // 80000001 (2, 8) = 15 SBOX[0][-1879048191] = 0x808000; // 90000001 (2, 9) = 12 SBOX[0][-1610612735] = 0x800002; // a0000001 (2, 10) = 9 SBOX[0][-1342177279] = 0x8202; // b0000001 (2, 11) = 7 SBOX[0][-1073741823] = 0x202; // c0000001 (2, 12) = 3 SBOX[0][-805306367] = 0x800200; // d0000001 (2, 13) = 10 SBOX[0][-536870911] = 0x8002; // e0000001 (2, 14) = 5 SBOX[0][-268435455] = 0x0; // f0000001 (2, 15) = 0 SBOX[0][134217729] = 0x808202; // 8000001 (3, 0) = 15 SBOX[0][402653185] = 0x808000; // 18000001 (3, 1) = 12 SBOX[0][671088641] = 0x800000; // 28000001 (3, 2) = 8 SBOX[0][939524097] = 0x200; // 38000001 (3, 3) = 2 SBOX[0][1207959553] = 0x8000; // 48000001 (3, 4) = 4 SBOX[0][1476395009] = 0x800002; // 58000001 (3, 5) = 9 SBOX[0][1744830465] = 0x2; // 68000001 (3, 6) = 1 SBOX[0][2013265921] = 0x8202; // 78000001 (3, 7) = 7 SBOX[0][-2013265919] = 0x8002; // 88000001 (3, 8) = 5 SBOX[0][-1744830463] = 0x800202; // 98000001 (3, 9) = 11 SBOX[0][-1476395007] = 0x202; // a8000001 (3, 10) = 3 SBOX[0][-1207959551] = 0x808200; // b8000001 (3, 11) = 14 SBOX[0][-939524095] = 0x800200; // c8000001 (3, 12) = 10 SBOX[0][-671088639] = 0x0; // d8000001 (3, 13) = 0 SBOX[0][-402653183] = 0x8200; // e8000001 (3, 14) = 6 SBOX[0][-134217727] = 0x808002; // f8000001 (3, 15) = 13 SBOX[1] = new Array(); SBOX[1][0] = 0x40084010; // 0 (0, 0) = 15 SBOX[1][16777216] = 0x4000; // 1000000 (0, 1) = 1 SBOX[1][33554432] = 0x80000; // 2000000 (0, 2) = 8 SBOX[1][50331648] = 0x40080010; // 3000000 (0, 3) = 14 SBOX[1][67108864] = 0x40000010; // 4000000 (0, 4) = 6 SBOX[1][83886080] = 0x40084000; // 5000000 (0, 5) = 11 SBOX[1][100663296] = 0x40004000; // 6000000 (0, 6) = 3 SBOX[1][117440512] = 0x10; // 7000000 (0, 7) = 4 SBOX[1][134217728] = 0x84000; // 8000000 (0, 8) = 9 SBOX[1][150994944] = 0x40004010; // 9000000 (0, 9) = 7 SBOX[1][167772160] = 0x40000000; // a000000 (0, 10) = 2 SBOX[1][184549376] = 0x84010; // b000000 (0, 11) = 13 SBOX[1][201326592] = 0x80010; // c000000 (0, 12) = 12 SBOX[1][218103808] = 0x0; // d000000 (0, 13) = 0 SBOX[1][234881024] = 0x4010; // e000000 (0, 14) = 5 SBOX[1][251658240] = 0x40080000; // f000000 (0, 15) = 10 SBOX[1][8388608] = 0x40004000; // 800000 (1, 0) = 3 SBOX[1][25165824] = 0x84010; // 1800000 (1, 1) = 13 SBOX[1][41943040] = 0x10; // 2800000 (1, 2) = 4 SBOX[1][58720256] = 0x40004010; // 3800000 (1, 3) = 7 SBOX[1][75497472] = 0x40084010; // 4800000 (1, 4) = 15 SBOX[1][92274688] = 0x40000000; // 5800000 (1, 5) = 2 SBOX[1][109051904] = 0x80000; // 6800000 (1, 6) = 8 SBOX[1][125829120] = 0x40080010; // 7800000 (1, 7) = 14 SBOX[1][142606336] = 0x80010; // 8800000 (1, 8) = 12 SBOX[1][159383552] = 0x0; // 9800000 (1, 9) = 0 SBOX[1][176160768] = 0x4000; // a800000 (1, 10) = 1 SBOX[1][192937984] = 0x40080000; // b800000 (1, 11) = 10 SBOX[1][209715200] = 0x40000010; // c800000 (1, 12) = 6 SBOX[1][226492416] = 0x84000; // d800000 (1, 13) = 9 SBOX[1][243269632] = 0x40084000; // e800000 (1, 14) = 11 SBOX[1][260046848] = 0x4010; // f800000 (1, 15) = 5 SBOX[1][268435456] = 0x0; // 10000000 (2, 0) = 0 SBOX[1][285212672] = 0x40080010; // 11000000 (2, 1) = 14 SBOX[1][301989888] = 0x40004010; // 12000000 (2, 2) = 7 SBOX[1][318767104] = 0x40084000; // 13000000 (2, 3) = 11 SBOX[1][335544320] = 0x40080000; // 14000000 (2, 4) = 10 SBOX[1][352321536] = 0x10; // 15000000 (2, 5) = 4 SBOX[1][369098752] = 0x84010; // 16000000 (2, 6) = 13 SBOX[1][385875968] = 0x4000; // 17000000 (2, 7) = 1 SBOX[1][402653184] = 0x4010; // 18000000 (2, 8) = 5 SBOX[1][419430400] = 0x80000; // 19000000 (2, 9) = 8 SBOX[1][436207616] = 0x80010; // 1a000000 (2, 10) = 12 SBOX[1][452984832] = 0x40000010; // 1b000000 (2, 11) = 6 SBOX[1][469762048] = 0x84000; // 1c000000 (2, 12) = 9 SBOX[1][486539264] = 0x40004000; // 1d000000 (2, 13) = 3 SBOX[1][503316480] = 0x40000000; // 1e000000 (2, 14) = 2 SBOX[1][520093696] = 0x40084010; // 1f000000 (2, 15) = 15 SBOX[1][276824064] = 0x84010; // 10800000 (3, 0) = 13 SBOX[1][293601280] = 0x80000; // 11800000 (3, 1) = 8 SBOX[1][310378496] = 0x40080000; // 12800000 (3, 2) = 10 SBOX[1][327155712] = 0x4000; // 13800000 (3, 3) = 1 SBOX[1][343932928] = 0x40004000; // 14800000 (3, 4) = 3 SBOX[1][360710144] = 0x40084010; // 15800000 (3, 5) = 15 SBOX[1][377487360] = 0x10; // 16800000 (3, 6) = 4 SBOX[1][394264576] = 0x40000000; // 17800000 (3, 7) = 2 SBOX[1][411041792] = 0x40084000; // 18800000 (3, 8) = 11 SBOX[1][427819008] = 0x40000010; // 19800000 (3, 9) = 6 SBOX[1][444596224] = 0x40004010; // 1a800000 (3, 10) = 7 SBOX[1][461373440] = 0x80010; // 1b800000 (3, 11) = 12 SBOX[1][478150656] = 0x0; // 1c800000 (3, 12) = 0 SBOX[1][494927872] = 0x4010; // 1d800000 (3, 13) = 5 SBOX[1][511705088] = 0x40080010; // 1e800000 (3, 14) = 14 SBOX[1][528482304] = 0x84000; // 1f800000 (3, 15) = 9 SBOX[2] = new Array(); SBOX[2][0] = 0x104; // 0 (0, 0) = 10 SBOX[2][1048576] = 0x0; // 100000 (0, 1) = 0 SBOX[2][2097152] = 0x4000100; // 200000 (0, 2) = 9 SBOX[2][3145728] = 0x10104; // 300000 (0, 3) = 14 SBOX[2][4194304] = 0x10004; // 400000 (0, 4) = 6 SBOX[2][5242880] = 0x4000004; // 500000 (0, 5) = 3 SBOX[2][6291456] = 0x4010104; // 600000 (0, 6) = 15 SBOX[2][7340032] = 0x4010000; // 700000 (0, 7) = 5 SBOX[2][8388608] = 0x4000000; // 800000 (0, 8) = 1 SBOX[2][9437184] = 0x4010100; // 900000 (0, 9) = 13 SBOX[2][10485760] = 0x10100; // a00000 (0, 10) = 12 SBOX[2][11534336] = 0x4010004; // b00000 (0, 11) = 7 SBOX[2][12582912] = 0x4000104; // c00000 (0, 12) = 11 SBOX[2][13631488] = 0x10000; // d00000 (0, 13) = 4 SBOX[2][14680064] = 0x4; // e00000 (0, 14) = 2 SBOX[2][15728640] = 0x100; // f00000 (0, 15) = 8 SBOX[2][524288] = 0x4010100; // 80000 (1, 0) = 13 SBOX[2][1572864] = 0x4010004; // 180000 (1, 1) = 7 SBOX[2][2621440] = 0x0; // 280000 (1, 2) = 0 SBOX[2][3670016] = 0x4000100; // 380000 (1, 3) = 9 SBOX[2][4718592] = 0x4000004; // 480000 (1, 4) = 3 SBOX[2][5767168] = 0x10000; // 580000 (1, 5) = 4 SBOX[2][6815744] = 0x10004; // 680000 (1, 6) = 6 SBOX[2][7864320] = 0x104; // 780000 (1, 7) = 10 SBOX[2][8912896] = 0x4; // 880000 (1, 8) = 2 SBOX[2][9961472] = 0x100; // 980000 (1, 9) = 8 SBOX[2][11010048] = 0x4010000; // a80000 (1, 10) = 5 SBOX[2][12058624] = 0x10104; // b80000 (1, 11) = 14 SBOX[2][13107200] = 0x10100; // c80000 (1, 12) = 12 SBOX[2][14155776] = 0x4000104; // d80000 (1, 13) = 11 SBOX[2][15204352] = 0x4010104; // e80000 (1, 14) = 15 SBOX[2][16252928] = 0x4000000; // f80000 (1, 15) = 1 SBOX[2][16777216] = 0x4010100; // 1000000 (2, 0) = 13 SBOX[2][17825792] = 0x10004; // 1100000 (2, 1) = 6 SBOX[2][18874368] = 0x10000; // 1200000 (2, 2) = 4 SBOX[2][19922944] = 0x4000100; // 1300000 (2, 3) = 9 SBOX[2][20971520] = 0x100; // 1400000 (2, 4) = 8 SBOX[2][22020096] = 0x4010104; // 1500000 (2, 5) = 15 SBOX[2][23068672] = 0x4000004; // 1600000 (2, 6) = 3 SBOX[2][24117248] = 0x0; // 1700000 (2, 7) = 0 SBOX[2][25165824] = 0x4000104; // 1800000 (2, 8) = 11 SBOX[2][26214400] = 0x4000000; // 1900000 (2, 9) = 1 SBOX[2][27262976] = 0x4; // 1a00000 (2, 10) = 2 SBOX[2][28311552] = 0x10100; // 1b00000 (2, 11) = 12 SBOX[2][29360128] = 0x4010000; // 1c00000 (2, 12) = 5 SBOX[2][30408704] = 0x104; // 1d00000 (2, 13) = 10 SBOX[2][31457280] = 0x10104; // 1e00000 (2, 14) = 14 SBOX[2][32505856] = 0x4010004; // 1f00000 (2, 15) = 7 SBOX[2][17301504] = 0x4000000; // 1080000 (3, 0) = 1 SBOX[2][18350080] = 0x104; // 1180000 (3, 1) = 10 SBOX[2][19398656] = 0x4010100; // 1280000 (3, 2) = 13 SBOX[2][20447232] = 0x0; // 1380000 (3, 3) = 0 SBOX[2][21495808] = 0x10004; // 1480000 (3, 4) = 6 SBOX[2][22544384] = 0x4000100; // 1580000 (3, 5) = 9 SBOX[2][23592960] = 0x100; // 1680000 (3, 6) = 8 SBOX[2][24641536] = 0x4010004; // 1780000 (3, 7) = 7 SBOX[2][25690112] = 0x10000; // 1880000 (3, 8) = 4 SBOX[2][26738688] = 0x4010104; // 1980000 (3, 9) = 15 SBOX[2][27787264] = 0x10104; // 1a80000 (3, 10) = 14 SBOX[2][28835840] = 0x4000004; // 1b80000 (3, 11) = 3 SBOX[2][29884416] = 0x4000104; // 1c80000 (3, 12) = 11 SBOX[2][30932992] = 0x4010000; // 1d80000 (3, 13) = 5 SBOX[2][31981568] = 0x4; // 1e80000 (3, 14) = 2 SBOX[2][33030144] = 0x10100; // 1f80000 (3, 15) = 12 SBOX[3] = new Array(); SBOX[3][0] = 0x80401000; // 0 (0, 0) = 7 SBOX[3][65536] = 0x80001040; // 10000 (0, 1) = 13 SBOX[3][131072] = 0x401040; // 20000 (0, 2) = 14 SBOX[3][196608] = 0x80400000; // 30000 (0, 3) = 3 SBOX[3][262144] = 0x0; // 40000 (0, 4) = 0 SBOX[3][327680] = 0x401000; // 50000 (0, 5) = 6 SBOX[3][393216] = 0x80000040; // 60000 (0, 6) = 9 SBOX[3][458752] = 0x400040; // 70000 (0, 7) = 10 SBOX[3][524288] = 0x80000000; // 80000 (0, 8) = 1 SBOX[3][589824] = 0x400000; // 90000 (0, 9) = 2 SBOX[3][655360] = 0x40; // a0000 (0, 10) = 8 SBOX[3][720896] = 0x80001000; // b0000 (0, 11) = 5 SBOX[3][786432] = 0x80400040; // c0000 (0, 12) = 11 SBOX[3][851968] = 0x1040; // d0000 (0, 13) = 12 SBOX[3][917504] = 0x1000; // e0000 (0, 14) = 4 SBOX[3][983040] = 0x80401040; // f0000 (0, 15) = 15 SBOX[3][32768] = 0x80001040; // 8000 (1, 0) = 13 SBOX[3][98304] = 0x40; // 18000 (1, 1) = 8 SBOX[3][163840] = 0x80400040; // 28000 (1, 2) = 11 SBOX[3][229376] = 0x80001000; // 38000 (1, 3) = 5 SBOX[3][294912] = 0x401000; // 48000 (1, 4) = 6 SBOX[3][360448] = 0x80401040; // 58000 (1, 5) = 15 SBOX[3][425984] = 0x0; // 68000 (1, 6) = 0 SBOX[3][491520] = 0x80400000; // 78000 (1, 7) = 3 SBOX[3][557056] = 0x1000; // 88000 (1, 8) = 4 SBOX[3][622592] = 0x80401000; // 98000 (1, 9) = 7 SBOX[3][688128] = 0x400000; // a8000 (1, 10) = 2 SBOX[3][753664] = 0x1040; // b8000 (1, 11) = 12 SBOX[3][819200] = 0x80000000; // c8000 (1, 12) = 1 SBOX[3][884736] = 0x400040; // d8000 (1, 13) = 10 SBOX[3][950272] = 0x401040; // e8000 (1, 14) = 14 SBOX[3][1015808] = 0x80000040; // f8000 (1, 15) = 9 SBOX[3][1048576] = 0x400040; // 100000 (2, 0) = 10 SBOX[3][1114112] = 0x401000; // 110000 (2, 1) = 6 SBOX[3][1179648] = 0x80000040; // 120000 (2, 2) = 9 SBOX[3][1245184] = 0x0; // 130000 (2, 3) = 0 SBOX[3][1310720] = 0x1040; // 140000 (2, 4) = 12 SBOX[3][1376256] = 0x80400040; // 150000 (2, 5) = 11 SBOX[3][1441792] = 0x80401000; // 160000 (2, 6) = 7 SBOX[3][1507328] = 0x80001040; // 170000 (2, 7) = 13 SBOX[3][1572864] = 0x80401040; // 180000 (2, 8) = 15 SBOX[3][1638400] = 0x80000000; // 190000 (2, 9) = 1 SBOX[3][1703936] = 0x80400000; // 1a0000 (2, 10) = 3 SBOX[3][1769472] = 0x401040; // 1b0000 (2, 11) = 14 SBOX[3][1835008] = 0x80001000; // 1c0000 (2, 12) = 5 SBOX[3][1900544] = 0x400000; // 1d0000 (2, 13) = 2 SBOX[3][1966080] = 0x40; // 1e0000 (2, 14) = 8 SBOX[3][2031616] = 0x1000; // 1f0000 (2, 15) = 4 SBOX[3][1081344] = 0x80400000; // 108000 (3, 0) = 3 SBOX[3][1146880] = 0x80401040; // 118000 (3, 1) = 15 SBOX[3][1212416] = 0x0; // 128000 (3, 2) = 0 SBOX[3][1277952] = 0x401000; // 138000 (3, 3) = 6 SBOX[3][1343488] = 0x400040; // 148000 (3, 4) = 10 SBOX[3][1409024] = 0x80000000; // 158000 (3, 5) = 1 SBOX[3][1474560] = 0x80001040; // 168000 (3, 6) = 13 SBOX[3][1540096] = 0x40; // 178000 (3, 7) = 8 SBOX[3][1605632] = 0x80000040; // 188000 (3, 8) = 9 SBOX[3][1671168] = 0x1000; // 198000 (3, 9) = 4 SBOX[3][1736704] = 0x80001000; // 1a8000 (3, 10) = 5 SBOX[3][1802240] = 0x80400040; // 1b8000 (3, 11) = 11 SBOX[3][1867776] = 0x1040; // 1c8000 (3, 12) = 12 SBOX[3][1933312] = 0x80401000; // 1d8000 (3, 13) = 7 SBOX[3][1998848] = 0x400000; // 1e8000 (3, 14) = 2 SBOX[3][2064384] = 0x401040; // 1f8000 (3, 15) = 14 SBOX[4] = new Array(); SBOX[4][0] = 0x80; // 0 (0, 0) = 2 SBOX[4][4096] = 0x1040000; // 1000 (0, 1) = 12 SBOX[4][8192] = 0x40000; // 2000 (0, 2) = 4 SBOX[4][12288] = 0x20000000; // 3000 (0, 3) = 1 SBOX[4][16384] = 0x20040080; // 4000 (0, 4) = 7 SBOX[4][20480] = 0x1000080; // 5000 (0, 5) = 10 SBOX[4][24576] = 0x21000080; // 6000 (0, 6) = 11 SBOX[4][28672] = 0x40080; // 7000 (0, 7) = 6 SBOX[4][32768] = 0x1000000; // 8000 (0, 8) = 8 SBOX[4][36864] = 0x20040000; // 9000 (0, 9) = 5 SBOX[4][40960] = 0x20000080; // a000 (0, 10) = 3 SBOX[4][45056] = 0x21040080; // b000 (0, 11) = 15 SBOX[4][49152] = 0x21040000; // c000 (0, 12) = 13 SBOX[4][53248] = 0x0; // d000 (0, 13) = 0 SBOX[4][57344] = 0x1040080; // e000 (0, 14) = 14 SBOX[4][61440] = 0x21000000; // f000 (0, 15) = 9 SBOX[4][2048] = 0x1040080; // 800 (1, 0) = 14 SBOX[4][6144] = 0x21000080; // 1800 (1, 1) = 11 SBOX[4][10240] = 0x80; // 2800 (1, 2) = 2 SBOX[4][14336] = 0x1040000; // 3800 (1, 3) = 12 SBOX[4][18432] = 0x40000; // 4800 (1, 4) = 4 SBOX[4][22528] = 0x20040080; // 5800 (1, 5) = 7 SBOX[4][26624] = 0x21040000; // 6800 (1, 6) = 13 SBOX[4][30720] = 0x20000000; // 7800 (1, 7) = 1 SBOX[4][34816] = 0x20040000; // 8800 (1, 8) = 5 SBOX[4][38912] = 0x0; // 9800 (1, 9) = 0 SBOX[4][43008] = 0x21040080; // a800 (1, 10) = 15 SBOX[4][47104] = 0x1000080; // b800 (1, 11) = 10 SBOX[4][51200] = 0x20000080; // c800 (1, 12) = 3 SBOX[4][55296] = 0x21000000; // d800 (1, 13) = 9 SBOX[4][59392] = 0x1000000; // e800 (1, 14) = 8 SBOX[4][63488] = 0x40080; // f800 (1, 15) = 6 SBOX[4][65536] = 0x40000; // 10000 (2, 0) = 4 SBOX[4][69632] = 0x80; // 11000 (2, 1) = 2 SBOX[4][73728] = 0x20000000; // 12000 (2, 2) = 1 SBOX[4][77824] = 0x21000080; // 13000 (2, 3) = 11 SBOX[4][81920] = 0x1000080; // 14000 (2, 4) = 10 SBOX[4][86016] = 0x21040000; // 15000 (2, 5) = 13 SBOX[4][90112] = 0x20040080; // 16000 (2, 6) = 7 SBOX[4][94208] = 0x1000000; // 17000 (2, 7) = 8 SBOX[4][98304] = 0x21040080; // 18000 (2, 8) = 15 SBOX[4][102400] = 0x21000000; // 19000 (2, 9) = 9 SBOX[4][106496] = 0x1040000; // 1a000 (2, 10) = 12 SBOX[4][110592] = 0x20040000; // 1b000 (2, 11) = 5 SBOX[4][114688] = 0x40080; // 1c000 (2, 12) = 6 SBOX[4][118784] = 0x20000080; // 1d000 (2, 13) = 3 SBOX[4][122880] = 0x0; // 1e000 (2, 14) = 0 SBOX[4][126976] = 0x1040080; // 1f000 (2, 15) = 14 SBOX[4][67584] = 0x21000080; // 10800 (3, 0) = 11 SBOX[4][71680] = 0x1000000; // 11800 (3, 1) = 8 SBOX[4][75776] = 0x1040000; // 12800 (3, 2) = 12 SBOX[4][79872] = 0x20040080; // 13800 (3, 3) = 7 SBOX[4][83968] = 0x20000000; // 14800 (3, 4) = 1 SBOX[4][88064] = 0x1040080; // 15800 (3, 5) = 14 SBOX[4][92160] = 0x80; // 16800 (3, 6) = 2 SBOX[4][96256] = 0x21040000; // 17800 (3, 7) = 13 SBOX[4][100352] = 0x40080; // 18800 (3, 8) = 6 SBOX[4][104448] = 0x21040080; // 19800 (3, 9) = 15 SBOX[4][108544] = 0x0; // 1a800 (3, 10) = 0 SBOX[4][112640] = 0x21000000; // 1b800 (3, 11) = 9 SBOX[4][116736] = 0x1000080; // 1c800 (3, 12) = 10 SBOX[4][120832] = 0x40000; // 1d800 (3, 13) = 4 SBOX[4][124928] = 0x20040000; // 1e800 (3, 14) = 5 SBOX[4][129024] = 0x20000080; // 1f800 (3, 15) = 3 SBOX[5] = new Array(); SBOX[5][0] = 0x10000008; // 0 (0, 0) = 12 SBOX[5][256] = 0x2000; // 100 (0, 1) = 1 SBOX[5][512] = 0x10200000; // 200 (0, 2) = 10 SBOX[5][768] = 0x10202008; // 300 (0, 3) = 15 SBOX[5][1024] = 0x10002000; // 400 (0, 4) = 9 SBOX[5][1280] = 0x200000; // 500 (0, 5) = 2 SBOX[5][1536] = 0x200008; // 600 (0, 6) = 6 SBOX[5][1792] = 0x10000000; // 700 (0, 7) = 8 SBOX[5][2048] = 0x0; // 800 (0, 8) = 0 SBOX[5][2304] = 0x10002008; // 900 (0, 9) = 13 SBOX[5][2560] = 0x202000; // a00 (0, 10) = 3 SBOX[5][2816] = 0x8; // b00 (0, 11) = 4 SBOX[5][3072] = 0x10200008; // c00 (0, 12) = 14 SBOX[5][3328] = 0x202008; // d00 (0, 13) = 7 SBOX[5][3584] = 0x2008; // e00 (0, 14) = 5 SBOX[5][3840] = 0x10202000; // f00 (0, 15) = 11 SBOX[5][128] = 0x10200000; // 80 (1, 0) = 10 SBOX[5][384] = 0x10202008; // 180 (1, 1) = 15 SBOX[5][640] = 0x8; // 280 (1, 2) = 4 SBOX[5][896] = 0x200000; // 380 (1, 3) = 2 SBOX[5][1152] = 0x202008; // 480 (1, 4) = 7 SBOX[5][1408] = 0x10000008; // 580 (1, 5) = 12 SBOX[5][1664] = 0x10002000; // 680 (1, 6) = 9 SBOX[5][1920] = 0x2008; // 780 (1, 7) = 5 SBOX[5][2176] = 0x200008; // 880 (1, 8) = 6 SBOX[5][2432] = 0x2000; // 980 (1, 9) = 1 SBOX[5][2688] = 0x10002008; // a80 (1, 10) = 13 SBOX[5][2944] = 0x10200008; // b80 (1, 11) = 14 SBOX[5][3200] = 0x0; // c80 (1, 12) = 0 SBOX[5][3456] = 0x10202000; // d80 (1, 13) = 11 SBOX[5][3712] = 0x202000; // e80 (1, 14) = 3 SBOX[5][3968] = 0x10000000; // f80 (1, 15) = 8 SBOX[5][4096] = 0x10002000; // 1000 (2, 0) = 9 SBOX[5][4352] = 0x10200008; // 1100 (2, 1) = 14 SBOX[5][4608] = 0x10202008; // 1200 (2, 2) = 15 SBOX[5][4864] = 0x2008; // 1300 (2, 3) = 5 SBOX[5][5120] = 0x200000; // 1400 (2, 4) = 2 SBOX[5][5376] = 0x10000000; // 1500 (2, 5) = 8 SBOX[5][5632] = 0x10000008; // 1600 (2, 6) = 12 SBOX[5][5888] = 0x202000; // 1700 (2, 7) = 3 SBOX[5][6144] = 0x202008; // 1800 (2, 8) = 7 SBOX[5][6400] = 0x0; // 1900 (2, 9) = 0 SBOX[5][6656] = 0x8; // 1a00 (2, 10) = 4 SBOX[5][6912] = 0x10200000; // 1b00 (2, 11) = 10 SBOX[5][7168] = 0x2000; // 1c00 (2, 12) = 1 SBOX[5][7424] = 0x10002008; // 1d00 (2, 13) = 13 SBOX[5][7680] = 0x10202000; // 1e00 (2, 14) = 11 SBOX[5][7936] = 0x200008; // 1f00 (2, 15) = 6 SBOX[5][4224] = 0x8; // 1080 (3, 0) = 4 SBOX[5][4480] = 0x202000; // 1180 (3, 1) = 3 SBOX[5][4736] = 0x200000; // 1280 (3, 2) = 2 SBOX[5][4992] = 0x10000008; // 1380 (3, 3) = 12 SBOX[5][5248] = 0x10002000; // 1480 (3, 4) = 9 SBOX[5][5504] = 0x2008; // 1580 (3, 5) = 5 SBOX[5][5760] = 0x10202008; // 1680 (3, 6) = 15 SBOX[5][6016] = 0x10200000; // 1780 (3, 7) = 10 SBOX[5][6272] = 0x10202000; // 1880 (3, 8) = 11 SBOX[5][6528] = 0x10200008; // 1980 (3, 9) = 14 SBOX[5][6784] = 0x2000; // 1a80 (3, 10) = 1 SBOX[5][7040] = 0x202008; // 1b80 (3, 11) = 7 SBOX[5][7296] = 0x200008; // 1c80 (3, 12) = 6 SBOX[5][7552] = 0x0; // 1d80 (3, 13) = 0 SBOX[5][7808] = 0x10000000; // 1e80 (3, 14) = 8 SBOX[5][8064] = 0x10002008; // 1f80 (3, 15) = 13 SBOX[6] = new Array(); SBOX[6][0] = 0x100000; // 0 (0, 0) = 4 SBOX[6][16] = 0x2000401; // 10 (0, 1) = 11 SBOX[6][32] = 0x400; // 20 (0, 2) = 2 SBOX[6][48] = 0x100401; // 30 (0, 3) = 14 SBOX[6][64] = 0x2100401; // 40 (0, 4) = 15 SBOX[6][80] = 0x0; // 50 (0, 5) = 0 SBOX[6][96] = 0x1; // 60 (0, 6) = 8 SBOX[6][112] = 0x2100001; // 70 (0, 7) = 13 SBOX[6][128] = 0x2000400; // 80 (0, 8) = 3 SBOX[6][144] = 0x100001; // 90 (0, 9) = 12 SBOX[6][160] = 0x2000001; // a0 (0, 10) = 9 SBOX[6][176] = 0x2100400; // b0 (0, 11) = 7 SBOX[6][192] = 0x2100000; // c0 (0, 12) = 5 SBOX[6][208] = 0x401; // d0 (0, 13) = 10 SBOX[6][224] = 0x100400; // e0 (0, 14) = 6 SBOX[6][240] = 0x2000000; // f0 (0, 15) = 1 SBOX[6][8] = 0x2100001; // 8 (1, 0) = 13 SBOX[6][24] = 0x0; // 18 (1, 1) = 0 SBOX[6][40] = 0x2000401; // 28 (1, 2) = 11 SBOX[6][56] = 0x2100400; // 38 (1, 3) = 7 SBOX[6][72] = 0x100000; // 48 (1, 4) = 4 SBOX[6][88] = 0x2000001; // 58 (1, 5) = 9 SBOX[6][104] = 0x2000000; // 68 (1, 6) = 1 SBOX[6][120] = 0x401; // 78 (1, 7) = 10 SBOX[6][136] = 0x100401; // 88 (1, 8) = 14 SBOX[6][152] = 0x2000400; // 98 (1, 9) = 3 SBOX[6][168] = 0x2100000; // a8 (1, 10) = 5 SBOX[6][184] = 0x100001; // b8 (1, 11) = 12 SBOX[6][200] = 0x400; // c8 (1, 12) = 2 SBOX[6][216] = 0x2100401; // d8 (1, 13) = 15 SBOX[6][232] = 0x1; // e8 (1, 14) = 8 SBOX[6][248] = 0x100400; // f8 (1, 15) = 6 SBOX[6][256] = 0x2000000; // 100 (2, 0) = 1 SBOX[6][272] = 0x100000; // 110 (2, 1) = 4 SBOX[6][288] = 0x2000401; // 120 (2, 2) = 11 SBOX[6][304] = 0x2100001; // 130 (2, 3) = 13 SBOX[6][320] = 0x100001; // 140 (2, 4) = 12 SBOX[6][336] = 0x2000400; // 150 (2, 5) = 3 SBOX[6][352] = 0x2100400; // 160 (2, 6) = 7 SBOX[6][368] = 0x100401; // 170 (2, 7) = 14 SBOX[6][384] = 0x401; // 180 (2, 8) = 10 SBOX[6][400] = 0x2100401; // 190 (2, 9) = 15 SBOX[6][416] = 0x100400; // 1a0 (2, 10) = 6 SBOX[6][432] = 0x1; // 1b0 (2, 11) = 8 SBOX[6][448] = 0x0; // 1c0 (2, 12) = 0 SBOX[6][464] = 0x2100000; // 1d0 (2, 13) = 5 SBOX[6][480] = 0x2000001; // 1e0 (2, 14) = 9 SBOX[6][496] = 0x400; // 1f0 (2, 15) = 2 SBOX[6][264] = 0x100400; // 108 (3, 0) = 6 SBOX[6][280] = 0x2000401; // 118 (3, 1) = 11 SBOX[6][296] = 0x2100001; // 128 (3, 2) = 13 SBOX[6][312] = 0x1; // 138 (3, 3) = 8 SBOX[6][328] = 0x2000000; // 148 (3, 4) = 1 SBOX[6][344] = 0x100000; // 158 (3, 5) = 4 SBOX[6][360] = 0x401; // 168 (3, 6) = 10 SBOX[6][376] = 0x2100400; // 178 (3, 7) = 7 SBOX[6][392] = 0x2000001; // 188 (3, 8) = 9 SBOX[6][408] = 0x2100000; // 198 (3, 9) = 5 SBOX[6][424] = 0x0; // 1a8 (3, 10) = 0 SBOX[6][440] = 0x2100401; // 1b8 (3, 11) = 15 SBOX[6][456] = 0x100401; // 1c8 (3, 12) = 14 SBOX[6][472] = 0x400; // 1d8 (3, 13) = 2 SBOX[6][488] = 0x2000400; // 1e8 (3, 14) = 3 SBOX[6][504] = 0x100001; // 1f8 (3, 15) = 12 SBOX[7] = new Array(); SBOX[7][0] = 0x8000820; // 0 (0, 0) = 13 SBOX[7][1] = 0x20000; // 1 (0, 1) = 2 SBOX[7][2] = 0x8000000; // 2 (0, 2) = 8 SBOX[7][3] = 0x20; // 3 (0, 3) = 4 SBOX[7][4] = 0x20020; // 4 (0, 4) = 6 SBOX[7][5] = 0x8020820; // 5 (0, 5) = 15 SBOX[7][6] = 0x8020800; // 6 (0, 6) = 11 SBOX[7][7] = 0x800; // 7 (0, 7) = 1 SBOX[7][8] = 0x8020000; // 8 (0, 8) = 10 SBOX[7][9] = 0x8000800; // 9 (0, 9) = 9 SBOX[7][10] = 0x20800; // a (0, 10) = 3 SBOX[7][11] = 0x8020020; // b (0, 11) = 14 SBOX[7][12] = 0x820; // c (0, 12) = 5 SBOX[7][13] = 0x0; // d (0, 13) = 0 SBOX[7][14] = 0x8000020; // e (0, 14) = 12 SBOX[7][15] = 0x20820; // f (0, 15) = 7 SBOX[7][-2147483648] = 0x800; // 80000000 (1, 0) = 1 SBOX[7][-2147483647] = 0x8020820; // 80000001 (1, 1) = 15 SBOX[7][-2147483646] = 0x8000820; // 80000002 (1, 2) = 13 SBOX[7][-2147483645] = 0x8000000; // 80000003 (1, 3) = 8 SBOX[7][-2147483644] = 0x8020000; // 80000004 (1, 4) = 10 SBOX[7][-2147483643] = 0x20800; // 80000005 (1, 5) = 3 SBOX[7][-2147483642] = 0x20820; // 80000006 (1, 6) = 7 SBOX[7][-2147483641] = 0x20; // 80000007 (1, 7) = 4 SBOX[7][-2147483640] = 0x8000020; // 80000008 (1, 8) = 12 SBOX[7][-2147483639] = 0x820; // 80000009 (1, 9) = 5 SBOX[7][-2147483638] = 0x20020; // 8000000a (1, 10) = 6 SBOX[7][-2147483637] = 0x8020800; // 8000000b (1, 11) = 11 SBOX[7][-2147483636] = 0x0; // 8000000c (1, 12) = 0 SBOX[7][-2147483635] = 0x8020020; // 8000000d (1, 13) = 14 SBOX[7][-2147483634] = 0x8000800; // 8000000e (1, 14) = 9 SBOX[7][-2147483633] = 0x20000; // 8000000f (1, 15) = 2 SBOX[7][16] = 0x20820; // 10 (2, 0) = 7 SBOX[7][17] = 0x8020800; // 11 (2, 1) = 11 SBOX[7][18] = 0x20; // 12 (2, 2) = 4 SBOX[7][19] = 0x800; // 13 (2, 3) = 1 SBOX[7][20] = 0x8000800; // 14 (2, 4) = 9 SBOX[7][21] = 0x8000020; // 15 (2, 5) = 12 SBOX[7][22] = 0x8020020; // 16 (2, 6) = 14 SBOX[7][23] = 0x20000; // 17 (2, 7) = 2 SBOX[7][24] = 0x0; // 18 (2, 8) = 0 SBOX[7][25] = 0x20020; // 19 (2, 9) = 6 SBOX[7][26] = 0x8020000; // 1a (2, 10) = 10 SBOX[7][27] = 0x8000820; // 1b (2, 11) = 13 SBOX[7][28] = 0x8020820; // 1c (2, 12) = 15 SBOX[7][29] = 0x20800; // 1d (2, 13) = 3 SBOX[7][30] = 0x820; // 1e (2, 14) = 5 SBOX[7][31] = 0x8000000; // 1f (2, 15) = 8 SBOX[7][-2147483632] = 0x20000; // 80000010 (3, 0) = 2 SBOX[7][-2147483631] = 0x800; // 80000011 (3, 1) = 1 SBOX[7][-2147483630] = 0x8020020; // 80000012 (3, 2) = 14 SBOX[7][-2147483629] = 0x20820; // 80000013 (3, 3) = 7 SBOX[7][-2147483628] = 0x20; // 80000014 (3, 4) = 4 SBOX[7][-2147483627] = 0x8020000; // 80000015 (3, 5) = 10 SBOX[7][-2147483626] = 0x8000000; // 80000016 (3, 6) = 8 SBOX[7][-2147483625] = 0x8000820; // 80000017 (3, 7) = 13 SBOX[7][-2147483624] = 0x8020820; // 80000018 (3, 8) = 15 SBOX[7][-2147483623] = 0x8000020; // 80000019 (3, 9) = 12 SBOX[7][-2147483622] = 0x8000800; // 8000001a (3, 10) = 9 SBOX[7][-2147483621] = 0x0; // 8000001b (3, 11) = 0 SBOX[7][-2147483620] = 0x20800; // 8000001c (3, 12) = 3 SBOX[7][-2147483619] = 0x820; // 8000001d (3, 13) = 5 SBOX[7][-2147483618] = 0x20020; // 8000001e (3, 14) = 6 SBOX[7][-2147483617] = 0x8020800; // 8000001f (3, 15) = 11 State.prototype._exchangeLR = function(v, m) { var t = ((this.lhs >> v) ^ this.rhs) & m; this.rhs ^= t; this.lhs ^= (t << v); }; State.prototype._exchangeRL = function(v, m) { var t = ((this.rhs >> v) ^ this.lhs) & m; this.lhs ^= t; this.rhs ^= (t << v); }; /** * Perform the initial permutation of the input to create the starting state * of the algorithm. The initial permutation maps each consecutive bit of * the input into a different byte of the state. * *
     * The initial permutation is defined to be:
     * 
     *      58    50   42    34    26   18    10    2  
     *      60    52   44    36    28   20    12    4
     *      62    54   46    38    30   22    14    6
     *      64    56   48    40    32   24    16    8
     *      57    49   41    33    25   17     9    1
     *      59    51   43    35    27   19    11    3
     *      61    53   45    37    29   21    13    5
     *      63    55   47    39    31   23    15    7
     * 
* * * @param message * The message as an array of unsigned bytes. * @param offset * The offset into the message that the current 64-bit block * begins. * @returns the initial engine state */ State.prototype.initialPerm = function(message, offset) { var input = message.slice(offset, offset + 8); this.lhs = (input[0] << 24) + (input[1] << 16) + (input[2] << 8) + input[3]; this.rhs = (input[4] << 24) + (input[5] << 16) + (input[6] << 8) + input[7]; this._exchangeLR(4, 0x0f0f0f0f); this._exchangeLR(16, 0x0000ffff); this._exchangeRL(2, 0x33333333); this._exchangeRL(8, 0x00ff00ff); this._exchangeLR(1, 0x55555555); }; /** * Perform one round of the DES algorithm using the given key. A round is * defined as: * *
     * L&rsquo = R
     * R&rsquo = L ˆ f(R, k)
     * 
* * where f consists of expanding, XORing with the key and contracting back * with the SBOXes. * * Note that the final round is defined slightly differently as: * *
     * L&rsquo = L ˆ f(R, k)
     * R&rsquo = R
     * 
* * Therefore in the final round this function produces LHS and RHS the wrong * way around. * * @param k * the key */ State.prototype.round = function(k) { var r = this.rhs, l = this.lhs; var f = 0; for ( var i = 0; i < 8; i++) { var v = (r ^ k[i]) & State.SBOX_MASK[i]; f += State.SBOX[i][v]; } this.lhs = r; this.rhs = l ^ f; }; /** * Apply the inverse of the initial permutation. * *
     * The inverse is defined to be:
     * 
     *      40     8   48    16    56   24    64   32
     *      39     7   47    15    55   23    63   31
     *      38     6   46    14    54   22    62   30
     *      37     5   45    13    53   21    61   29
     *      36     4   44    12    52   20    60   28
     *      35     3   43    11    51   19    59   27
     *      34     2   42    10    50   18    58   26
     *      33     1   41     9    49   17    57   25
     * 
* * @param cipherText * @param offset */ State.prototype.finalPerm = function(cipherText, offset) { var t = this.lhs; this.lhs = this.rhs; this.rhs = t; this._exchangeLR(1, 0x55555555); this._exchangeRL(8, 0x00ff00ff); this._exchangeRL(2, 0x33333333); this._exchangeLR(16, 0x0000ffff); this._exchangeLR(4, 0x0f0f0f0f); cipherText[offset] = (this.lhs >> 24) & 0xff; cipherText[offset + 1] = (this.lhs >> 16) & 0xff; cipherText[offset + 2] = (this.lhs >> 8) & 0xff; cipherText[offset + 3] = (this.lhs) & 0xff; cipherText[offset + 4] = (this.rhs >> 24) & 0xff; cipherText[offset + 5] = (this.rhs >> 16) & 0xff; cipherText[offset + 6] = (this.rhs >> 8) & 0xff; cipherText[offset + 7] = (this.rhs) & 0xff; }; /** * DES cipher */ var DES = C.DES = { _blocksize : 2, _keyschedule : null, _state : new State(), _init : function(k) { this._keyschedule = new KeySchedule(k); }, encrypt : function(message, password, options) { options = options || {}; // Determine mode var mode = options.mode || new C.mode.OFB; // Allow mode to override options if (mode.fixOptions) mode.fixOptions(options); var // Convert to bytes if message is a string m = (message.constructor == String ? UTF8.stringToBytes(message) : message), // Generate random IV iv = options.iv || util.randomBytes(8), // Generate key k = (password.constructor == String ? // Derive key from passphrase C.PBKDF2(password, iv, 8, { asBytes : true }) : // else, assume byte array representing cryptographic key password); // Create key schedule this._keyschedule = new KeySchedule(k); // Encrypt mode.encrypt(DES, m, iv); // Return ciphertext m = options.iv ? m : iv.concat(m); return (options && options.asBytes) ? m : util.bytesToBase64(m); }, _encryptblock : function(message, offset) { this._state.initialPerm(message, offset); for ( var i = 0; i <= 15; i++) { this._state.round(this._keyschedule.getKey(i)); } this._state.finalPerm(message, offset); }, decrypt : function(ciphertext, password, options) { options = options || {}; // Determine mode var mode = options.mode || new C.mode.OFB; // Allow mode to override options if (mode.fixOptions) mode.fixOptions(options); var // Convert to bytes if ciphertext is a string c = (ciphertext.constructor == String ? util .base64ToBytes(ciphertext) : ciphertext), // Separate IV and message iv = options.iv || c.splice(0, 8), // Generate key k = (password.constructor == String ? // Derive key from passphrase C.PBKDF2(password, iv, 32, { asBytes : true }) : // else, assume byte array representing cryptographic key password); // Create key schedule this._keyschedule = new KeySchedule(k); mode.decrypt(DES, c, iv); // Return plaintext return (options && options.asBytes) ? c : UTF8.bytesToString(c); }, _decryptblock : function(message, offset) { this._state.initialPerm(message, offset); for ( var i = 15; i >= 0; i--) { this._state.round(this._keyschedule.getKey(i)); } this._state.finalPerm(message, offset); } }; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/HMAC.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8, Binary = charenc.Binary; C.HMAC = function (hasher, message, key, options) { // Convert to byte arrays if (message.constructor == String) message = UTF8.stringToBytes(message); if (key.constructor == String) key = UTF8.stringToBytes(key); /* else, assume byte arrays already */ // Allow arbitrary length keys if (key.length > hasher._blocksize * 4) key = hasher(key, { asBytes: true }); // XOR keys with pad constants var okey = key.slice(0), ikey = key.slice(0); for (var i = 0; i < hasher._blocksize * 4; i++) { okey[i] ^= 0x5C; ikey[i] ^= 0x36; } var hmacbytes = hasher(okey.concat(hasher(ikey.concat(message), { asBytes: true })), { asBytes: true }); return options && options.asBytes ? hmacbytes : options && options.asString ? Binary.bytesToString(hmacbytes) : util.bytesToHex(hmacbytes); }; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/MARC4.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8, Binary = charenc.Binary; var MARC4 = C.MARC4 = { /** * Public API */ encrypt: function (message, password) { var // Convert to bytes m = UTF8.stringToBytes(message), // Generate random IV iv = util.randomBytes(16), // Generate key k = password.constructor == String ? // Derive key from passphrase C.PBKDF2(password, iv, 32, { asBytes: true }) : // else, assume byte array representing cryptographic key password; // Encrypt MARC4._marc4(m, k, 1536); // Return ciphertext return util.bytesToBase64(iv.concat(m)); }, decrypt: function (ciphertext, password) { var // Convert to bytes c = util.base64ToBytes(ciphertext), // Separate IV and message iv = c.splice(0, 16), // Generate key k = password.constructor == String ? // Derive key from passphrase C.PBKDF2(password, iv, 32, { asBytes: true }) : // else, assume byte array representing cryptographic key password; // Decrypt MARC4._marc4(c, k, 1536); // Return plaintext return UTF8.bytesToString(c); }, /** * Internal methods */ // The core _marc4: function (m, k, drop) { // State variables var i, j, s, temp; // Key setup for (i = 0, s = []; i < 256; i++) s[i] = i; for (i = 0, j = 0; i < 256; i++) { j = (j + s[i] + k[i % k.length]) % 256; // Swap temp = s[i]; s[i] = s[j]; s[j] = temp; } // Clear counters i = j = 0; // Encryption for (var k = -drop; k < m.length; k++) { i = (i + 1) % 256; j = (j + s[i]) % 256; // Swap temp = s[i]; s[i] = s[j]; s[j] = temp; // Stop here if we're still dropping keystream if (k < 0) continue; // Encrypt m[k] ^= s[(s[i] + s[j]) % 256]; } } }; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/MD5.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8, Binary = charenc.Binary; // Public API var MD5 = C.MD5 = function (message, options) { var digestbytes = util.wordsToBytes(MD5._md5(message)); return options && options.asBytes ? digestbytes : options && options.asString ? Binary.bytesToString(digestbytes) : util.bytesToHex(digestbytes); }; // The core MD5._md5 = function (message) { // Convert to byte array if (message.constructor == String) message = UTF8.stringToBytes(message); /* else, assume byte array already */ var m = util.bytesToWords(message), l = message.length * 8, a = 1732584193, b = -271733879, c = -1732584194, d = 271733878; // Swap endian for (var i = 0; i < m.length; i++) { m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF | ((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00; } // Padding m[l >>> 5] |= 0x80 << (l % 32); m[(((l + 64) >>> 9) << 4) + 14] = l; // Method shortcuts var FF = MD5._ff, GG = MD5._gg, HH = MD5._hh, II = MD5._ii; for (var i = 0; i < m.length; i += 16) { var aa = a, bb = b, cc = c, dd = d; a = FF(a, b, c, d, m[i+ 0], 7, -680876936); d = FF(d, a, b, c, m[i+ 1], 12, -389564586); c = FF(c, d, a, b, m[i+ 2], 17, 606105819); b = FF(b, c, d, a, m[i+ 3], 22, -1044525330); a = FF(a, b, c, d, m[i+ 4], 7, -176418897); d = FF(d, a, b, c, m[i+ 5], 12, 1200080426); c = FF(c, d, a, b, m[i+ 6], 17, -1473231341); b = FF(b, c, d, a, m[i+ 7], 22, -45705983); a = FF(a, b, c, d, m[i+ 8], 7, 1770035416); d = FF(d, a, b, c, m[i+ 9], 12, -1958414417); c = FF(c, d, a, b, m[i+10], 17, -42063); b = FF(b, c, d, a, m[i+11], 22, -1990404162); a = FF(a, b, c, d, m[i+12], 7, 1804603682); d = FF(d, a, b, c, m[i+13], 12, -40341101); c = FF(c, d, a, b, m[i+14], 17, -1502002290); b = FF(b, c, d, a, m[i+15], 22, 1236535329); a = GG(a, b, c, d, m[i+ 1], 5, -165796510); d = GG(d, a, b, c, m[i+ 6], 9, -1069501632); c = GG(c, d, a, b, m[i+11], 14, 643717713); b = GG(b, c, d, a, m[i+ 0], 20, -373897302); a = GG(a, b, c, d, m[i+ 5], 5, -701558691); d = GG(d, a, b, c, m[i+10], 9, 38016083); c = GG(c, d, a, b, m[i+15], 14, -660478335); b = GG(b, c, d, a, m[i+ 4], 20, -405537848); a = GG(a, b, c, d, m[i+ 9], 5, 568446438); d = GG(d, a, b, c, m[i+14], 9, -1019803690); c = GG(c, d, a, b, m[i+ 3], 14, -187363961); b = GG(b, c, d, a, m[i+ 8], 20, 1163531501); a = GG(a, b, c, d, m[i+13], 5, -1444681467); d = GG(d, a, b, c, m[i+ 2], 9, -51403784); c = GG(c, d, a, b, m[i+ 7], 14, 1735328473); b = GG(b, c, d, a, m[i+12], 20, -1926607734); a = HH(a, b, c, d, m[i+ 5], 4, -378558); d = HH(d, a, b, c, m[i+ 8], 11, -2022574463); c = HH(c, d, a, b, m[i+11], 16, 1839030562); b = HH(b, c, d, a, m[i+14], 23, -35309556); a = HH(a, b, c, d, m[i+ 1], 4, -1530992060); d = HH(d, a, b, c, m[i+ 4], 11, 1272893353); c = HH(c, d, a, b, m[i+ 7], 16, -155497632); b = HH(b, c, d, a, m[i+10], 23, -1094730640); a = HH(a, b, c, d, m[i+13], 4, 681279174); d = HH(d, a, b, c, m[i+ 0], 11, -358537222); c = HH(c, d, a, b, m[i+ 3], 16, -722521979); b = HH(b, c, d, a, m[i+ 6], 23, 76029189); a = HH(a, b, c, d, m[i+ 9], 4, -640364487); d = HH(d, a, b, c, m[i+12], 11, -421815835); c = HH(c, d, a, b, m[i+15], 16, 530742520); b = HH(b, c, d, a, m[i+ 2], 23, -995338651); a = II(a, b, c, d, m[i+ 0], 6, -198630844); d = II(d, a, b, c, m[i+ 7], 10, 1126891415); c = II(c, d, a, b, m[i+14], 15, -1416354905); b = II(b, c, d, a, m[i+ 5], 21, -57434055); a = II(a, b, c, d, m[i+12], 6, 1700485571); d = II(d, a, b, c, m[i+ 3], 10, -1894986606); c = II(c, d, a, b, m[i+10], 15, -1051523); b = II(b, c, d, a, m[i+ 1], 21, -2054922799); a = II(a, b, c, d, m[i+ 8], 6, 1873313359); d = II(d, a, b, c, m[i+15], 10, -30611744); c = II(c, d, a, b, m[i+ 6], 15, -1560198380); b = II(b, c, d, a, m[i+13], 21, 1309151649); a = II(a, b, c, d, m[i+ 4], 6, -145523070); d = II(d, a, b, c, m[i+11], 10, -1120210379); c = II(c, d, a, b, m[i+ 2], 15, 718787259); b = II(b, c, d, a, m[i+ 9], 21, -343485551); a = (a + aa) >>> 0; b = (b + bb) >>> 0; c = (c + cc) >>> 0; d = (d + dd) >>> 0; } return util.endian([a, b, c, d]); }; // Auxiliary functions MD5._ff = function (a, b, c, d, x, s, t) { var n = a + (b & c | ~b & d) + (x >>> 0) + t; return ((n << s) | (n >>> (32 - s))) + b; }; MD5._gg = function (a, b, c, d, x, s, t) { var n = a + (b & d | c & ~d) + (x >>> 0) + t; return ((n << s) | (n >>> (32 - s))) + b; }; MD5._hh = function (a, b, c, d, x, s, t) { var n = a + (b ^ c ^ d) + (x >>> 0) + t; return ((n << s) | (n >>> (32 - s))) + b; }; MD5._ii = function (a, b, c, d, x, s, t) { var n = a + (c ^ (b | ~d)) + (x >>> 0) + t; return ((n << s) | (n >>> (32 - s))) + b; }; // Package private blocksize MD5._blocksize = 16; MD5._digestsize = 16; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/PBKDF2.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8, Binary = charenc.Binary; C.PBKDF2 = function (password, salt, keylen, options) { // Convert to byte arrays if (password.constructor == String) password = UTF8.stringToBytes(password); if (salt.constructor == String) salt = UTF8.stringToBytes(salt); /* else, assume byte arrays already */ // Defaults var hasher = options && options.hasher || C.SHA1, iterations = options && options.iterations || 1; // Pseudo-random function function PRF(password, salt) { return C.HMAC(hasher, salt, password, { asBytes: true }); } // Generate key var derivedKeyBytes = [], blockindex = 1; while (derivedKeyBytes.length < keylen) { var block = PRF(password, salt.concat(util.wordsToBytes([blockindex]))); for (var u = block, i = 1; i < iterations; i++) { u = PRF(password, u); for (var j = 0; j < block.length; j++) block[j] ^= u[j]; } derivedKeyBytes = derivedKeyBytes.concat(block); blockindex++; } // Truncate excess bytes derivedKeyBytes.length = keylen; return options && options.asBytes ? derivedKeyBytes : options && options.asString ? Binary.bytesToString(derivedKeyBytes) : util.bytesToHex(derivedKeyBytes); }; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/PBKDF2Async.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8, Binary = charenc.Binary; if (!C.nextTick) { // node.js has setTime out but prefer process.nextTick if (typeof process != 'undefined' && typeof process.nextTick !== 'undefined') { C.nextTick = process.nextTick; } else if (typeof setTimeout !== 'undefined') { C.nextTick = function (callback) { setTimeout(callback, 0); }; } } C.PBKDF2Async = function (password, salt, keylen, callback, options) { // Convert to byte arrays if (password.constructor == String) password = UTF8.stringToBytes(password); if (salt.constructor == String) salt = UTF8.stringToBytes(salt); /* else, assume byte arrays already */ // Defaults var hasher = options && options.hasher || C.SHA1, iterations = options && options.iterations || 1; // Progress callback option var progressChangeHandler = options && options.onProgressChange; var totalIterations = Math.ceil(keylen / hasher._digestsize) * iterations; function fireProgressChange(currentIteration) { if (progressChangeHandler) { var iterationsSoFar = derivedKeyBytes.length / hasher._digestsize * iterations + currentIteration; setTimeout(function () { progressChangeHandler(Math.round(iterationsSoFar / totalIterations * 100)); }, 0); } } // Pseudo-random function function PRF(password, salt) { return C.HMAC(hasher, salt, password, { asBytes: true }); } var nextTick = C.nextTick; // Generate key var derivedKeyBytes = [], blockindex = 1; var outer, inner; nextTick(outer = function () { if (derivedKeyBytes.length < keylen) { var block = PRF(password, salt.concat(util.wordsToBytes([blockindex]))); fireProgressChange(1); var u = block, i = 1; nextTick(inner = function () { if (i < iterations) { u = PRF(password, u); for (var j = 0; j < block.length; j++) block[j] ^= u[j]; i++; fireProgressChange(i); nextTick(inner); } else { derivedKeyBytes = derivedKeyBytes.concat(block); blockindex++; nextTick(outer); } }); } else { // Truncate excess bytes derivedKeyBytes.length = keylen; callback( options && options.asBytes ? derivedKeyBytes : options && options.asString ? Binary.bytesToString(derivedKeyBytes) : util.bytesToHex(derivedKeyBytes)); } }); }; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/Rabbit.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8, Binary = charenc.Binary; // Inner state var x = [], c = [], b; var Rabbit = C.Rabbit = { /** * Public API */ encrypt: function (message, password) { var // Convert to bytes m = UTF8.stringToBytes(message), // Generate random IV iv = util.randomBytes(8), // Generate key k = password.constructor == String ? // Derive key from passphrase C.PBKDF2(password, iv, 32, { asBytes: true }) : // else, assume byte array representing cryptographic key password; // Encrypt Rabbit._rabbit(m, k, util.bytesToWords(iv)); // Return ciphertext return util.bytesToBase64(iv.concat(m)); }, decrypt: function (ciphertext, password) { var // Convert to bytes c = util.base64ToBytes(ciphertext), // Separate IV and message iv = c.splice(0, 8), // Generate key k = password.constructor == String ? // Derive key from passphrase C.PBKDF2(password, iv, 32, { asBytes: true }) : // else, assume byte array representing cryptographic key password; // Decrypt Rabbit._rabbit(c, k, util.bytesToWords(iv)); // Return plaintext return UTF8.bytesToString(c); }, /** * Internal methods */ // Encryption/decryption scheme _rabbit: function (m, k, iv) { Rabbit._keysetup(k); if (iv) Rabbit._ivsetup(iv); for (var s = [], i = 0; i < m.length; i++) { if (i % 16 == 0) { // Iterate the system Rabbit._nextstate(); // Generate 16 bytes of pseudo-random data s[0] = x[0] ^ (x[5] >>> 16) ^ (x[3] << 16); s[1] = x[2] ^ (x[7] >>> 16) ^ (x[5] << 16); s[2] = x[4] ^ (x[1] >>> 16) ^ (x[7] << 16); s[3] = x[6] ^ (x[3] >>> 16) ^ (x[1] << 16); // Swap endian for (var j = 0; j < 4; j++) { s[j] = ((s[j] << 8) | (s[j] >>> 24)) & 0x00FF00FF | ((s[j] << 24) | (s[j] >>> 8)) & 0xFF00FF00; } // Convert words to bytes for (var b = 120; b >= 0; b -= 8) s[b / 8] = (s[b >>> 5] >>> (24 - b % 32)) & 0xFF; } m[i] ^= s[i % 16]; } }, // Key setup scheme _keysetup: function (k) { // Generate initial state values x[0] = k[0]; x[2] = k[1]; x[4] = k[2]; x[6] = k[3]; x[1] = (k[3] << 16) | (k[2] >>> 16); x[3] = (k[0] << 16) | (k[3] >>> 16); x[5] = (k[1] << 16) | (k[0] >>> 16); x[7] = (k[2] << 16) | (k[1] >>> 16); // Generate initial counter values c[0] = util.rotl(k[2], 16); c[2] = util.rotl(k[3], 16); c[4] = util.rotl(k[0], 16); c[6] = util.rotl(k[1], 16); c[1] = (k[0] & 0xFFFF0000) | (k[1] & 0xFFFF); c[3] = (k[1] & 0xFFFF0000) | (k[2] & 0xFFFF); c[5] = (k[2] & 0xFFFF0000) | (k[3] & 0xFFFF); c[7] = (k[3] & 0xFFFF0000) | (k[0] & 0xFFFF); // Clear carry bit b = 0; // Iterate the system four times for (var i = 0; i < 4; i++) Rabbit._nextstate(); // Modify the counters for (var i = 0; i < 8; i++) c[i] ^= x[(i + 4) & 7]; }, // IV setup scheme _ivsetup: function (iv) { // Generate four subvectors var i0 = util.endian(iv[0]), i2 = util.endian(iv[1]), i1 = (i0 >>> 16) | (i2 & 0xFFFF0000), i3 = (i2 << 16) | (i0 & 0x0000FFFF); // Modify counter values c[0] ^= i0; c[1] ^= i1; c[2] ^= i2; c[3] ^= i3; c[4] ^= i0; c[5] ^= i1; c[6] ^= i2; c[7] ^= i3; // Iterate the system four times for (var i = 0; i < 4; i++) Rabbit._nextstate(); }, // Next-state function _nextstate: function () { // Save old counter values for (var c_old = [], i = 0; i < 8; i++) c_old[i] = c[i]; // Calculate new counter values c[0] = (c[0] + 0x4D34D34D + b) >>> 0; c[1] = (c[1] + 0xD34D34D3 + ((c[0] >>> 0) < (c_old[0] >>> 0) ? 1 : 0)) >>> 0; c[2] = (c[2] + 0x34D34D34 + ((c[1] >>> 0) < (c_old[1] >>> 0) ? 1 : 0)) >>> 0; c[3] = (c[3] + 0x4D34D34D + ((c[2] >>> 0) < (c_old[2] >>> 0) ? 1 : 0)) >>> 0; c[4] = (c[4] + 0xD34D34D3 + ((c[3] >>> 0) < (c_old[3] >>> 0) ? 1 : 0)) >>> 0; c[5] = (c[5] + 0x34D34D34 + ((c[4] >>> 0) < (c_old[4] >>> 0) ? 1 : 0)) >>> 0; c[6] = (c[6] + 0x4D34D34D + ((c[5] >>> 0) < (c_old[5] >>> 0) ? 1 : 0)) >>> 0; c[7] = (c[7] + 0xD34D34D3 + ((c[6] >>> 0) < (c_old[6] >>> 0) ? 1 : 0)) >>> 0; b = (c[7] >>> 0) < (c_old[7] >>> 0) ? 1 : 0; // Calculate the g-values for (var g = [], i = 0; i < 8; i++) { var gx = (x[i] + c[i]) >>> 0; // Construct high and low argument for squaring var ga = gx & 0xFFFF, gb = gx >>> 16; // Calculate high and low result of squaring var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb, gl = (((gx & 0xFFFF0000) * gx) >>> 0) + (((gx & 0x0000FFFF) * gx) >>> 0) >>> 0; // High XOR low g[i] = gh ^ gl; } // Calculate new state values x[0] = g[0] + ((g[7] << 16) | (g[7] >>> 16)) + ((g[6] << 16) | (g[6] >>> 16)); x[1] = g[1] + ((g[0] << 8) | (g[0] >>> 24)) + g[7]; x[2] = g[2] + ((g[1] << 16) | (g[1] >>> 16)) + ((g[0] << 16) | (g[0] >>> 16)); x[3] = g[3] + ((g[2] << 8) | (g[2] >>> 24)) + g[1]; x[4] = g[4] + ((g[3] << 16) | (g[3] >>> 16)) + ((g[2] << 16) | (g[2] >>> 16)); x[5] = g[5] + ((g[4] << 8) | (g[4] >>> 24)) + g[3]; x[6] = g[6] + ((g[5] << 16) | (g[5] >>> 16)) + ((g[4] << 16) | (g[4] >>> 16)); x[7] = g[7] + ((g[6] << 8) | (g[6] >>> 24)) + g[5]; } }; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/SHA1.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8, Binary = charenc.Binary; // Public API var SHA1 = C.SHA1 = function (message, options) { var digestbytes = util.wordsToBytes(SHA1._sha1(message)); return options && options.asBytes ? digestbytes : options && options.asString ? Binary.bytesToString(digestbytes) : util.bytesToHex(digestbytes); }; // The core SHA1._sha1 = function (message) { // Convert to byte array if (message.constructor == String) message = UTF8.stringToBytes(message); /* else, assume byte array already */ var m = util.bytesToWords(message), l = message.length * 8, w = [], H0 = 1732584193, H1 = -271733879, H2 = -1732584194, H3 = 271733878, H4 = -1009589776; // Padding m[l >> 5] |= 0x80 << (24 - l % 32); m[((l + 64 >>> 9) << 4) + 15] = l; for (var i = 0; i < m.length; i += 16) { var a = H0, b = H1, c = H2, d = H3, e = H4; for (var j = 0; j < 80; j++) { if (j < 16) w[j] = m[i + j]; else { var n = w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16]; w[j] = (n << 1) | (n >>> 31); } var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + ( j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 : j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 : j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 : (H1 ^ H2 ^ H3) - 899497514); H4 = H3; H3 = H2; H2 = (H1 << 30) | (H1 >>> 2); H1 = H0; H0 = t; } H0 += a; H1 += b; H2 += c; H3 += d; H4 += e; } return [H0, H1, H2, H3, H4]; }; // Package private blocksize SHA1._blocksize = 16; SHA1._digestsize = 20; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/lib/SHA256.js ================================================ (function(){ var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; // Shortcuts var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8, Binary = charenc.Binary; // Constants var K = [ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 ]; // Public API var SHA256 = C.SHA256 = function (message, options) { var digestbytes = util.wordsToBytes(SHA256._sha256(message)); return options && options.asBytes ? digestbytes : options && options.asString ? Binary.bytesToString(digestbytes) : util.bytesToHex(digestbytes); }; // The core SHA256._sha256 = function (message) { // Convert to byte array if (message.constructor == String) message = UTF8.stringToBytes(message); /* else, assume byte array already */ var m = util.bytesToWords(message), l = message.length * 8, H = [ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ], w = [], a, b, c, d, e, f, g, h, i, j, t1, t2; // Padding m[l >> 5] |= 0x80 << (24 - l % 32); m[((l + 64 >> 9) << 4) + 15] = l; for (var i = 0; i < m.length; i += 16) { a = H[0]; b = H[1]; c = H[2]; d = H[3]; e = H[4]; f = H[5]; g = H[6]; h = H[7]; for (var j = 0; j < 64; j++) { if (j < 16) w[j] = m[j + i]; else { var gamma0x = w[j - 15], gamma1x = w[j - 2], gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ ((gamma0x << 14) | (gamma0x >>> 18)) ^ (gamma0x >>> 3), gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ ((gamma1x << 13) | (gamma1x >>> 19)) ^ (gamma1x >>> 10); w[j] = gamma0 + (w[j - 7] >>> 0) + gamma1 + (w[j - 16] >>> 0); } var ch = e & f ^ ~e & g, maj = a & b ^ a & c ^ b & c, sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)), sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); t1 = (h >>> 0) + sigma1 + ch + (K[j]) + (w[j] >>> 0); t2 = sigma0 + maj; h = g; g = f; f = e; e = (d + t1) >>> 0; d = c; c = b; b = a; a = (t1 + t2) >>> 0; } H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e; H[5] += f; H[6] += g; H[7] += h; } return H; }; // Package private blocksize SHA256._blocksize = 16; SHA256._digestsize = 32; })(); ================================================ FILE: cloudfunctions/regist/cryptojs/package.json ================================================ { "author": "Jeff Guo ", "name": "cryptojs", "tags": ["Hash", "MD5", "SHA1", "SHA-1", "SHA256", "SHA-256", "RC4", "Rabbit", "AES", "DES", "PBKDF2", "HMAC", "OFB", "CFB", "CTR", "CBC", "Base64"], "description": "Following googlecode project crypto-js, provide standard and secure cryptographic algorithms for NodeJS. Support MD5, SHA-1, SHA-256, RC4, Rabbit, AES, DES, PBKDF2, HMAC, OFB, CFB, CTR, CBC, Base64", "version": "2.5.3", "homepage": "https://github.com/gwjjeff/cryptojs", "repository": { "type": "git", "url": "git://github.com/gwjjeff/cryptojs.git" }, "main": "cryptojs.js", "engines": { "node": "*" }, "dependencies": {}, "devDependencies": {} } ================================================ FILE: cloudfunctions/regist/cryptojs/test/PBKDF2-test.js ================================================ var assert = require('assert'); var Crypto = require('../cryptojs').Crypto; (function test_PBKDF2() { assert.strictEqual(Crypto.PBKDF2("password", "ATHENA.MIT.EDUraeburn", 128 / 8), "cdedb5281bb2f801565a1122b2563515"); assert.strictEqual(Crypto.PBKDF2("password", "ATHENA.MIT.EDUraeburn", 256 / 8), "cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837"); assert.strictEqual(Crypto.PBKDF2("password", "ATHENA.MIT.EDUraeburn", 128 / 8, { iterations : 2 }), "01dbee7f4a9e243e988b62c73cda935d"); assert.strictEqual(Crypto.PBKDF2("password", "ATHENA.MIT.EDUraeburn", 256 / 8, { iterations : 2 }), "01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86"); assert.strictEqual(Crypto.PBKDF2("password", "ATHENA.MIT.EDUraeburn", 128 / 8, { iterations : 1200}), "5c08eb61fdf71e4e4ec3cf6ba1f5512b"); assert.strictEqual(Crypto.PBKDF2("password", "ATHENA.MIT.EDUraeburn", 256 / 8, { iterations : 1200}), "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13"); assert.strictEqual(Crypto.PBKDF2("password", "\x12\x34\x56\x78\x78\x56\x34\x12", 128 / 8, { iterations : 5 }), "d1daa78615f287e6a1c8b120d7062a49"); assert.strictEqual(Crypto.PBKDF2("password", "\x12\x34\x56\x78\x78\x56\x34\x12", 256 / 8, { iterations : 5 }), "d1daa78615f287e6a1c8b120d7062a493f98d203e6be49a6adf4fa574b6e64ee"); assert.strictEqual(Crypto.PBKDF2("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase equals block size", 128 / 8, { iterations : 1200 }), "139c30c0966bc32ba55fdbf212530ac9"); assert.strictEqual(Crypto.PBKDF2("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase equals block size", 256 / 8, { iterations : 1200 }), "139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1"); assert.strictEqual(Crypto.PBKDF2("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase exceeds block size", 128 / 8, { iterations : 1200 }), "9ccad6d468770cd51b10e6a68721be61"); assert.strictEqual(Crypto.PBKDF2("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase exceeds block size", 256 / 8, { iterations : 1200 }), "9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a"); assert.strictEqual(Crypto.PBKDF2([0xf0, 0x9d, 0x84, 0x9e], "EXAMPLE.COMpianist", 128 / 8, { iterations : 50 }), "6b9cf26d45455a43a5b8bb276a403b39"); assert.strictEqual(Crypto.PBKDF2([0xf0, 0x9d, 0x84, 0x9e], "EXAMPLE.COMpianist", 256 / 8, { iterations : 50 }), "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0c41e02c281ff3069e1e94f52"); })(); (function test_PBKSD2Async() { Crypto.PBKDF2Async("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase exceeds block size", 256 / 8, function(result) { assert.strictEqual(result, "9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a"); }, { iterations : 1200 }); })(); ================================================ FILE: cloudfunctions/regist/index.js ================================================ const appid = 'wxd6beb52c8602bff4'; //你的小程序appid const secret = 'b00457b478f63f2388ef03476bb5a60c'; //你的小程序secret /* 下 面 不 用 管 */ const cloud = require('wx-server-sdk'); cloud.init()//这里后面加的初始化 const TcbRouter = require('tcb-router'); //云函数路由 const rq = require('request'); const wxurl = 'https://api.weixin.qq.com'; var WXBizDataCrypt = require('./RdWXBizDataCrypt') // 用于手机号解密 cloud.init() // 云函数入口函数 exports.main = async(event, context) => { const app = new TcbRouter({ event }); //获取电话号码 app.router('phone', async(ctx) => { ctx.body = new Promise(resolve => { rq({ url: wxurl + '/sns/jscode2session?appid=' + appid + '&secret=' + secret + '&js_code=' + event.code + '&grant_type=authorization_code', method: "GET", json: true, }, function(error, response, body) { const decrypt1 = new WXBizDataCrypt(appid, body.session_key) // -解密第一步 const decrypt2 = decrypt1.decryptData(event.encryptedData, event.iv) // 解密第二步*/ resolve({ data: decrypt2 }) }); }); }); //获取openid app.router('getid', async(ctx) => { const wxContext = cloud.getWXContext() ctx.body = wxContext.OPENID; }); return app.serve(); } ================================================ FILE: cloudfunctions/regist/package.json ================================================ { "name": "regist", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "request": "^2.88.0", "tcb-router": "^1.1.2", "wx-server-sdk": "^2.0.4" } } ================================================ FILE: cloudfunctions/removeChat/config.json ================================================ { "permissions": { "openapi": [ ] } } ================================================ FILE: cloudfunctions/removeChat/index.js ================================================ // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() // 云函数入口函数 exports.main = async (event, context) => { try { await db.collection('rooms').doc(event.id).update({ data: { deleted: 1 } }) .then(console.log) .catch(console.error) } catch(e) { console.error(e) } } ================================================ FILE: cloudfunctions/removeChat/package.json ================================================ { "name": "removeChat", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "~2.2.0" } } ================================================ FILE: cloudfunctions/removeOrder/config.json ================================================ { "permissions": { "openapi": [ ] } } ================================================ FILE: cloudfunctions/removeOrder/index.js ================================================ // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() const _ = db.command // 云函数入口函数 exports.main = async (event, _context) => { try { return await db.collection('order').doc(event._id).remove() } catch (e) { console.error(e) } } ================================================ FILE: cloudfunctions/removeOrder/package.json ================================================ { "name": "removeOrder", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "~2.2.0" } } ================================================ FILE: cloudfunctions/sell/config.json ================================================ { "permissions": { "openapi": [ ] } } ================================================ FILE: cloudfunctions/sell/index.js ================================================ // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() const _ = db.command // 云函数入口函数 exports.main = async (event, _context) => { try { return await db.collection('order').doc(event._id).update({ // data 传入需要局部更新的数据 data: { status:event.status } }) } catch (e) { console.error(e) } } ================================================ FILE: cloudfunctions/sell/package.json ================================================ { "name": "node", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "~2.1.2" } } ================================================ FILE: cloudfunctions/sendMsg/config.json ================================================ { "permissions": { "openapi": [ ] } } ================================================ FILE: cloudfunctions/sendMsg/index.js ================================================ //编程小石头微信:2501902696 const cloud = require('wx-server-sdk') cloud.init() exports.main = async(event, context) => { try { const result = await cloud.openapi.subscribeMessage.send({ touser: event.openid, //要推送给那个用户 page: 'pages/index/index', //要跳转到那个小程序页面 data: {//推送的内容 thing3: { value: event.good }, thing1: { value: event.status, color: event.color }, thing2: { value: event.address }, name4: { value: event.nickName }, thing6: { value: event.describe } }, templateId: '6DGzsKqipoPxClnbkvwnxY9GqdXoLordLRdWTjJN1F0' //模板id }) console.log(result) return result } catch (err) { console.log(err) return err } } ================================================ FILE: cloudfunctions/sendMsg/package.json ================================================ { "name": "sendMsg", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "latest" } } ================================================ FILE: cloudfunctions/sendTip/config.json ================================================ { "permissions": { "openapi": [ ] } } ================================================ FILE: cloudfunctions/sendTip/index.js ================================================ const cloud = require('wx-server-sdk') cloud.init() exports.main = async(event, context) => { try { const result = await cloud.openapi.subscribeMessage.send({ touser: event.openid, //要推送给那个用户 page: 'pages/index/index', //要跳转到那个小程序页面 data: {//推送的内容 thing1: { value: event.nickName }, phrase2:{ value: '申请聊天' }, thing3:{ value: event.tip } }, templateId: 'XXmEjf37meLWQaEsOX6qkkufcVH-YKAL3cHyY9Lru0Q' //模板id }) console.log(result) return result } catch (err) { console.log(err) return err } } ================================================ FILE: cloudfunctions/sendTip/package.json ================================================ { "name": "sendTip", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "~2.2.0" } } ================================================ FILE: miniprogram/app.js ================================================ const config = require("config.js"); App({ openid: '', userinfo:'', roomlist:[], canReflect:true, onLaunch: function() { if (!wx.cloud) { console.error('请使用 2.2.3 或以上的基础库以使用云能力') } else { wx.cloud.init({ env: JSON.parse(config.data).env, traceUser: true, }) } this.systeminfo=wx.getSystemInfoSync(); } }) ================================================ FILE: miniprogram/app.json ================================================ { "cloud": true, "pages": [ "pages/start/start", "pages/index/index", "pages/login/login", "pages/publish/publish", "pages/my/my", "pages/detail/detail", "pages/order/list/list", "pages/order/detail/detail", "pages/kefu/kefu", "pages/about/about", "pages/sell/list/list", "pages/sell/detail/detail", "pages/search/search", "pages/edit/edit", "pages/web/web", "pages/message/message", "pages/detail/room/room", "pages/use/use", "pages/help/help", "pages/appreciateCode/appreciateCode" ], "window": { "backgroundColor": "#fbbd08", "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fbbd08", "navigationBarTitleText": "吉珠二手交易平台", "navigationBarTextStyle": "white" }, "sitemapLocation": "sitemap.json", "tabBar": { "color": "#707070", "selectedColor": "#000000", "list": [{ "pagePath": "pages/index/index", "text": "首页", "iconPath": "/images/tabbar/home.png", "selectedIconPath": "/images/tabbar/home_on.png" }, { "pagePath": "pages/publish/publish", "text": "发布", "iconPath": "/images/tabbar/publish.png", "selectedIconPath": "/images/tabbar/publish_on.png" }, { "pagePath": "pages/my/my", "text": "我的", "iconPath": "/images/tabbar/my.png", "selectedIconPath": "/images/tabbar/my_on.png" } ] }, "usingComponents": { "van-steps": "/vant/steps/index", "van-transition": "/vant/transition/index", "van-stepper": "/vant/stepper/index", "van-action-sheet": "/vant/action-sheet/index", "van-popup": "/vant/popup/index", "canvasdrawer": "/components/canvasdrawer/canvasdrawer", "tips": "components/add_tips/index", "welcome": "components/welcome/welcome", "van-dialog": "/vant/dialog/index", "van-button": "/vant/button/index", "van-picker": "/vant/picker/index", "van-icon": "/vant/icon/index", "van-uploader": "/vant/uploader/index", "van-checkbox": "/vant/checkbox/index", "van-checkbox-group": "/vant/checkbox-group/index", "van-divider": "/vant/divider/index", "van-notice-bar": "vant/notice-bar/index" } } ================================================ FILE: miniprogram/app.wxss ================================================ page { background: #fff; width: 100%; height: 100%; } .shadow { box-shadow: 0 0 18rpx rgb(236, 236, 236); } .text-cut { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .loadmore { width: 100%; display: flex; justify-content: center; align-items: center; padding: 30rpx 0; } .loadmore image { width: 50rpx; height: 50rpx; } .loadmore view { font-size: 28rpx; color: #b2b2b2; letter-spacing: 4rpx; } .totop { position: fixed; right: 30rpx; bottom: 80rpx; } .totop image { width: 100rpx; height: 100rpx; z-index: 9; } ================================================ FILE: miniprogram/common.wxml ================================================ ================================================ FILE: miniprogram/common.wxs ================================================ function commentTimeHandle(dateStr) { var publishTime = dateStr, date = getDate(publishTime), //获取dateStr的标准格式 console.log(date) 打印结果 Thu Sep 06 2018 18:47:00 GMT+0800 (中国标准时间) // 获取date 中的 年 月 日 时 分 秒 Y = date.getFullYear(), M = date.getMonth() + 1, D = date.getDate(), H = date.getHours(), m = date.getMinutes(), s = date.getSeconds(); // 对 月 日 时 分 秒 小于10时, 加0显示 例如: 09-09 09:01 if (M < 10) { M = '0' + M; } if (D < 10) { D = '0' + D; } if (H < 10) { H = '0' + H; } if (m < 10) { m = '0' + m; } if (s < 10) { s = '0' + s; } var nowTime = getDate().getTime(), //获取此时此刻日期的秒数 diffValue = (nowTime - publishTime) / 1000, // 获取此时 秒数 与 要处理的日期秒数 之间的差值 diff_days = parseInt(diffValue / 86400), // 一天86400秒 获取相差的天数 取整 diff_hours = parseInt(diffValue / 3600), // 一时3600秒 diff_minutes = parseInt(diffValue / 60), diff_secodes = parseInt(diffValue); if (diff_days > 0 && diff_days < 3) { //相差天数 0 < diff_days < 3 时, 直接返出 return diff_days + "天前"; } else if (diff_days <= 0 && diff_hours > 0) { return diff_hours + "小时前"; } else if (diff_hours <= 0 && diff_minutes > 0) { return diff_minutes + "分钟前"; } else if (diff_secodes < 60) { if (diff_secodes <= 0) { return "刚刚"; } else { return diff_secodes + "秒前"; } } else if (diff_days >= 3 && diff_days < 30) { return M + '月' + D + '日'; } else if (diff_days >= 30) { return M + '月' + D + '日'; } } function format(dateStr) { var publishTime = dateStr, date = getDate(publishTime), //获取dateStr的标准格式 console.log(date) 打印结果 Thu Sep 06 2018 18:47:00 GMT+0800 (中国标准时间) // 获取date 中的 年 月 日 时 分 秒 Y = date.getFullYear(), M = date.getMonth() + 1, D = date.getDate(), H = date.getHours(), m = date.getMinutes(), s = date.getSeconds(); // 对 月 日 时 分 秒 小于10时, 加0显示 例如: 09-09 09:01 if (M < 10) { M = '0' + M; } if (D < 10) { D = '0' + D; } if (H < 10) { H = '0' + H; } if (m < 10) { m = '0' + m; } if (s < 10) { s = '0' + s; } return Y+'-'+M+'-'+D+' '+H+':'+m } module.exports = { timelog: commentTimeHandle, format:format } ================================================ FILE: miniprogram/components/add_tips/README.md ================================================ # add-tips > **微信小程序UI插件** > 用于提示用户首次进入小程序时,点击右上角菜单进行【添加到我的小程序】操作 ## 文档 首先,把这个仓库下载/克隆到你的小程序目录,比如`/components/weplug-add-tips/` 然后,在首页`index.json`配置文件中,引入该组件: ``` json { "usingComponents": { "add-tips": "/components/weplug-add-tips/index" } } ``` 最后,在首页`index.wxml`文件中,调用该组件即可: ``` wxml ``` ## 参数 你可以传递两个参数进行自定义操作: ### 1. text:提示的文字内容 ``` wxml ``` ### 2. duration:提示关闭时间(单位秒) ``` wxml ``` ================================================ FILE: miniprogram/components/add_tips/index.js ================================================ const STORAGE_KEY = 'PLUG-ADD-MYAPP-KEY'; Component({ /** * 组件的属性列表 */ properties: { // 提示文字 text: { type: String, value: '点击「添加小程序」,下次访问更便捷 >' }, // 多少秒后关闭 duration: { type: Number, value: 5 } }, /** * 组件的初始数据 */ data: { SHOW_TOP: false, SHOW_MODAL: false }, ready: function () { // 判断是否已经显示过 let cache = wx.getStorageSync(STORAGE_KEY); if (cache) return; // 没显示过,则进行展示 this.setData({ SHOW_TOP: true }); // 关闭时间 setTimeout(() => { this.setData({ SHOW_TOP: false }) }, this.data.duration * 1000); }, /** * 组件的方法列表 */ methods: { // 显示全屏添加说明 showModal: function () { this.setData({ SHOW_TOP: false, SHOW_MODAL: true }); }, okHandler: function () { this.setData({ SHOW_MODAL: false }); wx.setStorage({ key: STORAGE_KEY, data: +new Date, }); } } }) ================================================ FILE: miniprogram/components/add_tips/index.json ================================================ { "component": true, "usingComponents": {} } ================================================ FILE: miniprogram/components/add_tips/index.wxml ================================================ {{text}} 1. 点击 2. 点击「添加到我的小程序」 3. 微信首页下拉,快速进入小程序 我知道了! ================================================ FILE: miniprogram/components/add_tips/index.wxss ================================================ .box { position: fixed; top: 0; /* left: 0; */ right: 0; z-index: 999; display: flex; justify-content: flex-end; align-items: flex-end; flex-direction: column; width: 600rpx; } .arrow { width: 0; height: 0; margin-right: 120rpx; border-width: 20rpx; border-style: solid; border-color: transparent transparent #fbbd08; } .body { background-color: #fbbd08; box-shadow: 0 10rpx 20rpx -10rpx #fbbd08; border-radius: 12rpx; display: flex; align-items: center; justify-content: center; height: 84rpx; padding: 0 20rpx; margin-right: 40rpx; } .body > text { color: #FFF; font-size: 28rpx; font-weight: 400; } .modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 999; background-color: rgba(255, 255, 255, 0.9); padding: 20px; } .modal > view { margin: 10px 0; display: flex; /* align-items: center; */ flex-direction: column; } .modal > view > text { font-size: 16px; font-weight: 400; margin-bottom: 5px; color: #333; } .modal > view > image { border-radius: 10px; } .ok-btn { width: 100%; margin-top: 40px; display: flex; align-items: center; justify-content: center; } .ok-btn > view { height: 40px; width: 120px; background-color: #fbbd08; box-shadow: 0 5px 10px -px #fbbd08; display: flex; align-items: center; justify-content: center; border-radius: 40px; } .ok-btn > view > text { font-size: 14px; color: #fff; font-weight: 400; } .btn-hover { opacity: 0.6; } ================================================ FILE: miniprogram/components/canvasdrawer/canvasdrawer.js ================================================ /* global Component wx */ Component({ properties: { painting: { type: Object, value: {view: []}, observer (newVal, oldVal) { if (!this.data.isPainting) { if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) { if (newVal && newVal.width && newVal.height) { this.setData({ showCanvas: true, isPainting: true }) this.readyPigment() } } else { if (newVal && newVal.mode !== 'same') { this.triggerEvent('getImage', {errMsg: 'canvasdrawer:samme params'}) } } } } } }, data: { showCanvas: false, width: 100, height: 100, tempFileList: [], isPainting: false }, ctx: null, cache: {}, ready () { wx.removeStorageSync('canvasdrawer_pic_cache') this.cache = wx.getStorageSync('canvasdrawer_pic_cache') || {} this.ctx = wx.createCanvasContext('canvasdrawer', this) }, methods: { readyPigment () { const { width, height, views } = this.data.painting this.setData({ width, height }) const inter = setInterval(() => { if (this.ctx) { clearInterval(inter) this.ctx.clearActions() this.ctx.save() this.getImagesInfo(views) } }, 100) }, getImagesInfo (views) { const imageList = [] for (let i = 0; i < views.length; i++) { if (views[i].type === 'image') { imageList.push(this.getImageInfo(views[i].url)) } } const loadTask = [] for (let i = 0; i < Math.ceil(imageList.length / 8); i++) { loadTask.push(new Promise((resolve, reject) => { Promise.all(imageList.splice(i * 8, 8)).then(res => { resolve(res) }).catch(res => { reject(res) }) })) } Promise.all(loadTask).then(res => { let tempFileList = [] for (let i = 0; i < res.length; i++) { tempFileList = tempFileList.concat(res[i]) } this.setData({ tempFileList }) this.startPainting() }) }, startPainting () { const { tempFileList, painting: { views } } = this.data console.log(tempFileList) for (let i = 0, imageIndex = 0; i < views.length; i++) { if (views[i].type === 'image') { this.drawImage({ ...views[i], url: tempFileList[imageIndex] }) imageIndex++ } else if (views[i].type === 'text') { if (!this.ctx.measureText) { wx.showModal({ title: '提示', content: '当前微信版本过低,无法使用 measureText 功能,请升级到最新微信版本后重试。' }) this.triggerEvent('getImage', {errMsg: 'canvasdrawer:version too low'}) return } else { this.drawText(views[i]) } } else if (views[i].type === 'rect') { this.drawRect(views[i]) } } this.ctx.draw(false, () => { wx.setStorageSync('canvasdrawer_pic_cache', this.cache) const system = wx.getSystemInfoSync().system if (/ios/i.test(system)) { this.saveImageToLocal() } else { // 延迟保存图片,解决安卓生成图片错位bug。 setTimeout(() => { this.saveImageToLocal() }, 800) } }) }, drawImage (params) { this.ctx.save() const { url, top = 0, left = 0, width = 0, height = 0, borderRadius = 0, deg = 0 } = params // if (borderRadius) { // this.ctx.beginPath() // this.ctx.arc(left + borderRadius, top + borderRadius, borderRadius, 0, 2 * Math.PI) // this.ctx.clip() // this.ctx.drawImage(url, left, top, width, height) // } else { if (deg !== 0) { this.ctx.translate(left + width/2, top + height/2) this.ctx.rotate(deg * Math.PI / 180) this.ctx.drawImage(url, -width/2, -height/2, width, height) } else { this.ctx.drawImage(url, left, top, width, height) } // } this.ctx.restore() }, drawText (params) { this.ctx.save() const { MaxLineNumber = 2, breakWord = false, color = 'black', content = '', fontSize = 16, top = 0, left = 0, lineHeight = 20, textAlign = 'left', width, bolder = false, textDecoration = 'none' } = params this.ctx.beginPath() this.ctx.setTextBaseline('top') this.ctx.setTextAlign(textAlign) this.ctx.setFillStyle(color) this.ctx.setFontSize(fontSize) if (!breakWord) { this.ctx.fillText(content, left, top) this.drawTextLine(left, top, textDecoration, color, fontSize, content) } else { let fillText = '' let fillTop = top let lineNum = 1 for (let i = 0; i < content.length; i++) { fillText += [content[i]] if (this.ctx.measureText(fillText).width > width) { if (lineNum === MaxLineNumber) { if (i !== content.length) { fillText = fillText.substring(0, fillText.length - 1) + '...' this.ctx.fillText(fillText, left, fillTop) this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText) fillText = '' break } } this.ctx.fillText(fillText, left, fillTop) this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText) fillText = '' fillTop += lineHeight lineNum ++ } } this.ctx.fillText(fillText, left, fillTop) this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText) } this.ctx.restore() if (bolder) { this.drawText({ ...params, left: left + 0.3, top: top + 0.3, bolder: false, textDecoration: 'none' }) } }, drawTextLine (left, top, textDecoration, color, fontSize, content) { if (textDecoration === 'underline') { this.drawRect({ background: color, top: top + fontSize * 1.2, left: left - 1, width: this.ctx.measureText(content).width + 3, height: 1 }) } else if (textDecoration === 'line-through') { this.drawRect({ background: color, top: top + fontSize * 0.6, left: left - 1, width: this.ctx.measureText(content).width + 3, height: 1 }) } }, drawRect (params) { this.ctx.save() const { background, top = 0, left = 0, width = 0, height = 0 } = params this.ctx.setFillStyle(background) this.ctx.fillRect(left, top, width, height) this.ctx.restore() }, getImageInfo (url) { return new Promise((resolve, reject) => { if (this.cache[url]) { resolve(this.cache[url]) } else { const objExp = new RegExp(/^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/) if (objExp.test(url)) { wx.getImageInfo({ src: url, complete: res => { if (res.errMsg === 'getImageInfo:ok') { this.cache[url] = res.path resolve(res.path) } else { this.triggerEvent('getImage', {errMsg: 'canvasdrawer:download fail'}) reject(new Error('getImageInfo fail')) } } }) } else { this.cache[url] = url resolve(url) } } }) }, saveImageToLocal () { const { width, height } = this.data wx.canvasToTempFilePath({ x: 0, y: 0, width, height, canvasId: 'canvasdrawer', complete: res => { if (res.errMsg === 'canvasToTempFilePath:ok') { this.setData({ showCanvas: false, isPainting: false, tempFileList: [] }) this.triggerEvent('getImage', {tempFilePath: res.tempFilePath, errMsg: 'canvasdrawer:ok'}) } else { this.triggerEvent('getImage', {errMsg: 'canvasdrawer:fail'}) } } }, this) } } }) ================================================ FILE: miniprogram/components/canvasdrawer/canvasdrawer.json ================================================ { "component": true } ================================================ FILE: miniprogram/components/canvasdrawer/canvasdrawer.wxml ================================================ ================================================ FILE: miniprogram/components/canvasdrawer/canvasdrawer.wxss ================================================ .board { position: fixed; top: 2000rpx; } ================================================ FILE: miniprogram/components/chatroom/chatroom.js ================================================ var time = require('../../utils/util.js'); const FATAL_REBUILD_TOLERANCE = 10 const SETDATA_SCROLL_TO_BOTTOM = { scrollTop: 100000, scrollWithAnimation: true, } Component({ properties: { envId: String, collection: String, groupId: String, groupName: String, userInfo: Object, onGetUserInfo: { type: Function, }, getOpenID: { type: Function, }, }, data: { chats: [], textInputValue: '', openId: '', scrollTop: 0, scrollToMessage: '', hasKeyboard: false, }, methods: { onGetUserInfo(e) { this.properties.onGetUserInfo(e) }, getOpenID() { return this.properties.getOpenID() }, mergeCommonCriteria(criteria) { return { groupId: this.data.groupId, ...criteria, } }, async initRoom() { this.try(async () => { await this.initOpenID() const { envId, collection } = this.properties const db = this.db = wx.cloud.database({ env: envId, }) const _ = db.command const { data: initList } = await db.collection(collection).where(this.mergeCommonCriteria()).orderBy('sendTimeTS', 'desc').get() console.log('init query chats', initList) this.setData({ chats: initList.reverse(), scrollTop: 10000, }) this.initWatch(initList.length ? { sendTimeTS: _.gt(initList[initList.length - 1].sendTimeTS), } : {}) }, '初始化失败') }, async initOpenID() { return this.try(async () => { const openId = await this.getOpenID() this.setData({ openId, }) }, '初始化 openId 失败') }, async initWatch(criteria) { this.try(() => { const { collection } = this.properties const db = this.db const _ = db.command console.warn(`开始监听`, criteria) this.messageListener = db.collection(collection).where(this.mergeCommonCriteria(criteria)).watch({ onChange: this.onRealtimeMessageSnapshot.bind(this), onError: e => { if (!this.inited || this.fatalRebuildCount >= FATAL_REBUILD_TOLERANCE) { this.showError(this.inited ? '监听错误,已断开' : '初始化监听失败', e, '重连', () => { this.initWatch(this.data.chats.length ? { sendTimeTS: _.gt(this.data.chats[this.data.chats.length - 1].sendTimeTS), } : {}) }) } else { this.initWatch(this.data.chats.length ? { sendTimeTS: _.gt(this.data.chats[this.data.chats.length - 1].sendTimeTS), } : {}) } }, }) }, '初始化监听失败') }, onRealtimeMessageSnapshot(snapshot) { console.warn(`收到消息`, snapshot) if (snapshot.type === 'init') { this.setData({ chats: [ ...this.data.chats, ...[...snapshot.docs].sort((x, y) => x.sendTimeTS - y.sendTimeTS), ], }) this.scrollToBottom() this.inited = true } else { let hasNewMessage = false let hasOthersMessage = false const chats = [...this.data.chats] for (const docChange of snapshot.docChanges) { switch (docChange.queueType) { case 'enqueue': { hasOthersMessage = docChange.doc._openid !== this.data.openId const ind = chats.findIndex(chat => chat._id === docChange.doc._id) if (ind > -1) { if (chats[ind].msgType === 'image' && chats[ind].tempFilePath) { chats.splice(ind, 1, { ...docChange.doc, tempFilePath: chats[ind].tempFilePath, }) } else chats.splice(ind, 1, docChange.doc) } else { hasNewMessage = true chats.push(docChange.doc) } break } } } this.setData({ chats: chats.sort((x, y) => x.sendTimeTS - y.sendTimeTS), }) if (hasOthersMessage || hasNewMessage) { this.scrollToBottom() } } }, async onConfirmSendText(e) { this.try(async () => { if (!e.detail.value) { return } const { collection } = this.properties const db = this.db const _ = db.command const doc = { _id: `${Math.random()}_${Date.now()}`, groupId: this.data.groupId, avatar: this.data.userInfo.avatarUrl, nickName: this.data.userInfo.nickName, msgType: 'text', textContent: e.detail.value, sendTime: new Date(), sendTimeTS: time.formatTime(new Date(),'Y/M/D h:m:s'), // fallback } this.setData({ textInputValue: '', chats: [ ...this.data.chats, { ...doc, _openid: this.data.openId, writeStatus: 'pending', }, ], }) this.scrollToBottom(true) await db.collection(collection).add({ data: doc, }) this.setData({ chats: this.data.chats.map(chat => { if (chat._id === doc._id) { return { ...chat, writeStatus: 'written', } } else return chat }), }) }, '发送文字失败') }, async onChooseImage(e) { wx.chooseImage({ count: 1, sourceType: ['album', 'camera'], success: async res => { const { envId, collection } = this.properties const doc = { _id: `${Math.random()}_${Date.now()}`, groupId: this.data.groupId, avatar: this.data.userInfo.avatarUrl, nickName: this.data.userInfo.nickName, msgType: 'image', sendTime: new Date(), sendTimeTS: time.formatTime(new Date(),'Y/M/D h:m:s'), // fallback } this.setData({ chats: [ ...this.data.chats, { ...doc, _openid: this.data.openId, tempFilePath: res.tempFilePaths[0], writeStatus: 0, }, ] }) this.scrollToBottom(true) const uploadTask = wx.cloud.uploadFile({ cloudPath: `${this.data.openId}/${Math.random()}_${Date.now()}.${res.tempFilePaths[0].match(/\.(\w+)$/)[1]}`, filePath: res.tempFilePaths[0], config: { env: envId, }, success: res => { this.try(async () => { await this.db.collection(collection).add({ data: { ...doc, imgFileID: res.fileID, }, }) }, '发送图片失败') }, fail: e => { this.showError('发送图片失败', e) }, }) uploadTask.onProgressUpdate(({ progress }) => { this.setData({ chats: this.data.chats.map(chat => { if (chat._id === doc._id) { return { ...chat, writeStatus: progress, } } else return chat }) }) }) }, }) }, onMessageImageTap(e) { wx.previewImage({ urls: [e.target.dataset.fileid], }) }, scrollToBottom(force) { if (force) { console.log('force scroll to bottom') this.setData(SETDATA_SCROLL_TO_BOTTOM) return } this.createSelectorQuery().select('.body').boundingClientRect(bodyRect => { this.createSelectorQuery().select(`.body`).scrollOffset(scroll => { if (scroll.scrollTop + bodyRect.height * 3 > scroll.scrollHeight) { console.log('should scroll to bottom') this.setData(SETDATA_SCROLL_TO_BOTTOM) } }).exec() }).exec() }, async onScrollToUpper() { if (this.db && this.data.chats.length) { const { collection } = this.properties const _ = this.db.command const { data } = await this.db.collection(collection).where(this.mergeCommonCriteria({ sendTimeTS: _.lt(this.data.chats[0].sendTimeTS), })).orderBy('sendTimeTS', 'desc').get() this.data.chats.unshift(...data.reverse()) this.setData({ chats: this.data.chats, scrollToMessage: `item-${data.length}`, scrollWithAnimation: false, }) } }, async try (fn, title) { try { await fn() } catch (e) { this.showError(title, e) } }, showError(title, content, confirmText, confirmCallback) { console.error(title, content) wx.showModal({ title, content: content.toString(), showCancel: confirmText ? true : false, confirmText, success: res => { res.confirm && confirmCallback() }, }) }, }, ready() { global.chatroom = this this.initRoom() this.fatalRebuildCount = 0 }, }) ================================================ FILE: miniprogram/components/chatroom/chatroom.json ================================================ { "component": true, "usingComponents": { } } ================================================ FILE: miniprogram/components/chatroom/chatroom.wxml ================================================ {{item.nickName}} {{item.writeStatus}}% {{item.sendTimeTS}} ··· {{item.textContent}} {{item.sendTimeTS}} ================================================ FILE: miniprogram/components/chatroom/chatroom.wxss ================================================ .chatroom { width: 100%; height: 100%; display: flex; flex-direction: column; } /* .chatroom .header { flex-basis: fit-content; display: flex; flex-direction: row; border-bottom: 1px solid #ddd; margin-top: -25px; padding: 20rpx 0 30rpx; font-size:25 rpx; } */ .chatroom .header .left { flex: 1; } .chatroom .header .middle { flex: 2; text-align: center; } .chatroom .header .right { flex: 1; } .chatroom .body { flex: 1; display: flex; flex-direction: column; background: rgb(237,237,237); padding-bottom: 16rpx; } .body .message { display: flex; flex-direction: row; position: relative; margin: 12rpx 0; } .body .message.message__self { flex-direction: row-reverse; } .body .message .avatar { position: relative; top: 5rpx; width: 60rpx; height: 60rpx; border-radius: 5rpx; margin: 15rpx; } .body .message .main { flex: 1; display: flex; flex-direction: column; align-items: flex-start; } .body .message.message__self .main { align-items: flex-end; } .body .message .nickname { font-size: 24rpx; color: #444; } .body .message .time { font-size: 24rpx; color: #444; } .body .message .text-content { border: 1px solid transparent; border-radius: 3px; background-color: #fff; margin: 2px 0 0 0; padding: 4px 10px; font-size: 30rpx; display: inline-block; } .body .message.message__self .text-content { background-color: paleturquoise; } .body .message .text-wrapper { display: flex; flex-direction: row; align-items: center; max-width: 80%; } .body .message.message__self .text-wrapper .loading{ font-size: 16rpx; margin-right: 18rpx; } .body .message .image-wrapper { display: flex; flex-direction: row; align-items: center; } .body .message .image-content { max-width: 240rpx; max-height: 240rpx; } .body .message.message__self .image-wrapper .loading { font-size: 20rpx; margin-right: 18rpx; } .chatroom .footer { flex-basis: fit-content; display: flex; flex-direction: row; border-top: 1px solid #ddd; font-size: 10rpx; padding: 20rpx 30rpx; background: rgb(246,246,246); } .chatroom .footer .message-sender { flex: 1; display: flex; flex-direction: row; } .message-sender .text-input { flex: 1; font-size: 16px; border: 1px solid transparent; border-radius: 5px; padding: 3px 6px; margin: 0 10px 0 5px; background: #fff; } .message-sender .btn-send-image { width: 50rpx; height: 50rpx; align-self: center; } button { font-size: 30rpx; } button.userinfo { background: darkturquoise; color: aliceblue; padding: 0 100rpx; border: 1px solid #ddd; border-radius: 20px; } ================================================ FILE: miniprogram/components/welcome/welcome.js ================================================ const STORAGE1_KEY = 'PLUG-WELCOME-MYAPP-KEY'; Component({ /** * 组件的属性列表 */ // properties: { // // 提示文字 // text: { // type: String, // value: '点击「添加小程序」,下次访问更便捷 >' // }, // // 多少秒后关闭 // duration: { // type: Number, // value: 5 // } // }, /** * 组件的初始数据 */ data: { SHOW_MODAL:false }, ready: function () { // 判断是否已经显示过 let cache = wx.getStorageSync(STORAGE1_KEY); if (cache) return; // 没显示过,则进行展示 this.setData({ SHOW_MODAL: true }); this.showModal(); }, /** * 组件的方法列表 */ methods: { // 显示全屏添加说明 showModal: function () { this.setData({ SHOW_MODAL: true }); }, okHandler: function () { this.setData({ SHOW_MODAL: false }); wx.setStorage({ key: STORAGE1_KEY, data: +new Date, }); wx.requestSubscribeMessage({ tmplIds: ['6DGzsKqipoPxClnbkvwnxY9GqdXoLordLRdWTjJN1F0','XXmEjf37meLWQaEsOX6qkkufcVH-YKAL3cHyY9Lru0Q'], //这里填入我们生成的模板id success(res) { console.log('授权成功', res) }, fail(res) { console.log('授权失败', res) } }) wx.navigateTo({ url: '/pages/help/help', }) } }, }) ================================================ FILE: miniprogram/components/welcome/welcome.json ================================================ { "component": true, "usingComponents": {} } ================================================ FILE: miniprogram/components/welcome/welcome.wxml ================================================ 1. 欢迎来到 易珠 小程序,感谢您的使用 2.同学们使用前可在(我的—用户手册)页面查看小程序使用详情,注册时请点击授权接受服务通知(并点击不在询问)以便能及时接收到信息 3. 关于为什么有广告出现问题,可在 (我的—使用说明) 页面处了解,感谢您的理解! 现在去康康>> ================================================ FILE: miniprogram/components/welcome/welcome.wxss ================================================ /* components/welcome.wxss */ .box { position: fixed; top: 0; /* left: 0; */ right: 0; z-index: 999; display: flex; justify-content: flex-end; align-items: flex-end; flex-direction: column; width: 600rpx; } .arrow { width: 0; height: 0; margin-right: 120rpx; border-width: 20rpx; border-style: solid; border-color: transparent transparent #fbbd08; } .body { background-color: #fbbd08; box-shadow: 0 10rpx 20rpx -10rpx #fbbd08; border-radius: 12rpx; display: flex; align-items: center; justify-content: center; height: 84rpx; padding: 0 20rpx; margin-right: 40rpx; } .body > text { color: #FFF; font-size: 28rpx; font-weight: 400; } .font{ size: 20px; } .modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 999; background-image: linear-gradient(to top, #dfe9f3 0%, white 100%); padding: 10px; } .modal > view { margin: 10px 0; display: flex; /* align-items: center; */ flex-direction: column; } .modal > view > text { font-size: 16px; font-weight: 400; margin-bottom: 5px; color: rgb(7, 7, 7); } .modal > view > image { border-radius: 10px; } .ok-btn { width: 100%; margin-top: 40px; display: flex; align-items: center; justify-content: center; } .ok-btn > view { height: 40px; width: 120px; background-color: #fbbd08; box-shadow: 0 5px 10px -px #fbbd08; display: flex; align-items: center; justify-content: center; border-radius: 40px; } .ok-btn > view > text { font-size: 14px; color: #fff; font-weight: 400; } .btn-hover { opacity: 0.6; } ================================================ FILE: miniprogram/config.js ================================================ var data = { //云开发环境id env: 'taoshaoji-46f0r', //分享配置 share_title: '吉珠二手交易平台', share_img: '/images/poster.jpg', //可以是网络地址,本地文件路径要填绝对位置 share_poster:'https://s2.ax1x.com/2019/11/20/Mhpqmt.png',//必须为网络地址 //客服联系方式 kefu: { qq: '859162716', weixin:'ttao527' }, //默认启动页背景图,防止请求失败完全空白 //可以是网络地址,本地文件路径要填绝对位置 bgurl: '', //校区 campus: [{ name: '竹园', id: 0 }, { name: '康园', id: 1 }, { name: '松园', id: 2 }, { name: '桂园', id: 3 }, { name: '梅园', id: 4 }, { name: '榕园', id: 5 }, { name: '松园', id: 6 }, ], //配置学院,建议不要添加太多,不然前端不好看 college: [{ name: '通用', id: -1 }, { name: '学习用品', id: 0 }, { name: '日用品', id: 1 }, { name: '装饰品', id: 2 }, { name: '衣物', id: 3 }, { name: '运动器材', id: 4 }, { name: '化妆品', id: 5 }, { name: '其他', id: 6 }, ], } //下面的就别动了 function formTime(creatTime) { let date = new Date(creatTime), Y = date.getFullYear(), M = date.getMonth() + 1, D = date.getDate(), H = date.getHours(), m = date.getMinutes(), s = date.getSeconds(); if (M < 10) { M = '0' + M; } if (D < 10) { D = '0' + D; } if (H < 10) { H = '0' + H; } if (m < 10) { m = '0' + m; } if (s < 10) { s = '0' + s; } return Y + '-' + M + '-' + D + ' ' + H + ':' + m + ':' + s; } function days() { let now = new Date(); let year = now.getFullYear(); let month = now.getMonth() + 1; let day = now.getDate(); if (month < 10) { month = '0' + month; } if (day < 10) { day = '0' + day; } let date = year + "" + month + day; return date; } module.exports = { data: JSON.stringify(data), formTime: formTime, days: days } ================================================ FILE: miniprogram/pages/about/about.js ================================================ // pages/about/about.js Page({ /** * 页面的初始数据 */ data: { imgs1: [{ url: 'tao.jpg', name: '是芒果千层呀', id: "0" }, { url: 'chen.jpg', name: '楚利略', id: "1" }, ], des: '随着人们节约环保的消费意识的增强,在商品极丰富的大学校园里,二手物品交易市场迅速发展。大学生的消费金额限制、其节约意识以及每年大量的新生入学和毕业生离校,给予大学二手交易市场巨大的发展空间。然而我们观察发现,当前校园内的二手交易市场缺乏一个可靠实用的校园交易平台。考虑到微信小程序,方便快捷即用即走,速度快,安全性强等的优点,我们选择它作为交易平台。\n注意:\n本微信小程序只是提供物品交易的平台,不涉及金钱交易!主要服务于大学校园的学生与教师。' }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { // 在页面中定义插屏广告 let interstitialAd = null // 在页面onLoad回调事件中创建插屏广告实例 if (wx.createInterstitialAd) { interstitialAd = wx.createInterstitialAd({ adUnitId: 'adunit-dfbad1c323913ca2' }) interstitialAd.onLoad(() => {}) interstitialAd.onError((err) => {}) interstitialAd.onClose(() => {}) } // 在适合的场景显示插屏广告 if (interstitialAd) { interstitialAd.show().catch((err) => { console.error(err) }) } }, //图片点击事件 img: function (event) { let arr = []; arr.push('https://7461-taoshaoji-46f0r-1302243411.tcb.qcloud.la/appreciate-code/appreciateimg.jpg?sign=7a94d719f891a5b8838fae33a1b79d22&t=1597422871') wx.previewImage({ current: 'current', // 当前显示图片的http链接 urls: arr // 需要预览的图片http链接列表 }) }, onReady: function () { }, //复制 copy(e) { wx.setClipboardData({ data: e.currentTarget.dataset.copy, success: res => { wx.showToast({ title: '复制' + e.currentTarget.dataset.name + '成功', icon: 'success', duration: 1000, }) } }) }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { } }) ================================================ FILE: miniprogram/pages/about/about.json ================================================ { "usingComponents": {} } ================================================ FILE: miniprogram/pages/about/about.wxml ================================================ 开发: {{item.name}} 程序简介 {{des}} 打赏我们 联系方式 公众号: 拈花我把酒 QQ群: 859162716 ================================================ FILE: miniprogram/pages/about/about.wxss ================================================ page { background: #eee; } .des_contain { width: 618rpx; height: 157rpx; border-radius: 10rpx; background: #fff; display: flex; box-sizing: border-box; flex-direction: column; justify-content: center; padding: 0 0 0 90rpx; } .imagesize { display: flex; justify-content: center; } .imagesize image { width: 400rpx; height: 400rpx; } .name { font-size: 36rpx; line-height: 50rpx; } .sign { margin-top: 10rpx; font-size: 28rpx; letter-spacing: 3rpx; line-height: 45rpx; color: #b8b8b8; } .avator_box { position: absolute; left: 0rpx; top: 0rpx; display: flex; padding: 44rpx 0 0 40rpx; } .avator { box-shadow: 0 0 10rpx #b8b8b8; width: 110rpx; height: 110rpx; border-radius: 20rpx; } .contain { width: 100%; background: #eee; display: flex; flex-direction: column; padding: 0 20rpx; box-sizing: border-box; } .title { margin-top: 20rpx; line-height: 45rpx; padding-left: 20rpx; font-size: 32rpx; letter-spacing: 3rpx; color: #000; } .description { width: 100%; padding: 24rpx 30rpx; background: #fff; border-radius: 10rpx; display: flex; box-sizing: border-box; flex-direction: column; } .description text { width: 100%; font-size: 28rpx; line-height: 44rpx; letter-spacing: 3rpx; } .tip { display: flex; align-items: center; } .tip view { font-size: 30rpx; letter-spacing: 2rpx; padding: 15rpx 0; width: 150rpx; display: flex; justify-content: space-between; } .tip text { margin-left: 20rpx; font-size: 28rpx; color: #008ecf; text-decoration-line: underline; } .main { background: #fff; margin: 0 3px; position: relative; padding: 4rpx 30px; color: #1c1111; font-size: 12px; display: flex; } .image { display: flex; flex-wrap: wrap; } .im { margin-left: 80rpx; margin-top: 35rpx; height: 145rpx; width: 145rpx; border-radius: 50%; } .txt { width: 230rpx; text-align: center } .t { margin-left: 26px; color: lightskyblue; } ================================================ FILE: miniprogram/pages/appreciateCode/appreciateCode.js ================================================ const db = wx.cloud.database(); const app = getApp(); Page({ /** * 页面的初始数据 */ data: { bigImg: '', isExist: Boolean, //如果存在的话就是真,不存在的话就是假 openid: app.openid }, onLoad() { this.getCodeFromSet() }, getCodeFromSet() { let that = this; let openid = app.openid console.log(openid) db.collection('appreciatecode').where({ _openid: openid, }).get().then(res => { if (res.data.length > 0) { that.setData({ isExist: true, bigImg: res.data[0].bigImg }) console.log(res.data[0].bigImg) console.log("isExist---->" + that.data.isExist) } else { that.setData({ isExist: false, }) console.log("isExist---->" + that.data.isExist) } }) }, changeBigImg() { let that = this; let openid = app.openid wx.chooseImage({ sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { wx.showLoading({ title: '上传中', }); // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 let filePath = res.tempFilePaths[0]; const name = Math.random() * 1000000; const cloudPath = 'appreciate-code/' + app.openid + '/' + name + filePath.match(/\.[^.]+?$/)[0] wx.cloud.uploadFile({ cloudPath, //云存储图片名字 filePath, //临时路径 success: res => { console.log('[上传图片] 成功:', res) that.setData({ bigImg: res.fileID, //云存储图片路径,可以把这个路径存到集合,要用的时候再取出来 }); let fileID = res.fileID; //把图片存到appreciatecode集合表 const db = wx.cloud.database(); if (that.data.isExist == false) { db.collection("appreciatecode").add({ data: { bigImg: fileID, }, success: function () { wx.showToast({ title: '赞赏码上传成功', 'icon': 'none', duration: 3000 }) console.log("这里是第一次,用add") that.setData({ isExist: true }) }, fail: function () { wx.showToast({ title: '赞赏码上传失败', 'icon': 'none', duration: 3000 }) } }); } else { db.collection("appreciatecode").where({ _openid: openid }).update({ data: { bigImg: fileID, }, success: function () { wx.showToast({ title: '赞赏码上传成功', 'icon': 'none', duration: 3000 }) console.log("这里是第二次,用update") }, fail: function () { wx.showToast({ title: '赞赏码上传失败', 'icon': 'none', duration: 3000 }) } }); } }, fail: e => { console.error('[上传图片] 失败:', e) }, complete: () => { wx.hideLoading() } }); } }) }, }) ================================================ FILE: miniprogram/pages/appreciateCode/appreciateCode.json ================================================ { "usingComponents": {} } ================================================ FILE: miniprogram/pages/appreciateCode/appreciateCode.wxml ================================================ 上传申明 1、为什么要上传赞赏码? 因为微信小程序中无法识别收款码或者提供其它财产交易方式,所以我们采用小程序能够识别的赞赏码来进行付款交易 2、如何获取付款码? 用户可以在微信中我的-支付-钱包中的收付款页面下方选项-赞赏码获取,然后保存赞赏码上传到本小程序中,便可实现在线交易。后续我们会努力拿到微信支付的接口权限,简化交易过程。 作者声明 赞赏码的用途和收款码类似。只能用于收款,用户不用担心会因此产生不必要的财产损失。我们会将赞赏码附加于订单详情页,买家可以通过扫描赞赏码向卖家进行费用支付。\nTip:如果卖家不想上传赞赏码,可以在线下和买家进行沟通,面对面扫一扫交易也可。 ================================================ FILE: miniprogram/pages/appreciateCode/appreciateCode.wxss ================================================ page { background: #eee; } .imagesize { display: flex; justify-content: center; } .imagesize image { width: 400rpx; height: 400rpx; } .contain { width: 100%; background: #eee; display: flex; flex-direction: column; padding: 0 20rpx; box-sizing: border-box; } .btn { background-image: linear-gradient(-225deg, #9EFBD3 0%, #57E9F2 48%, #45D4FB 100%); margin-bottom: 20rpx; width: 100%; height: 100rpx; display: flex; justify-content: center; align-items: center; border-radius: 100rpx; color: #fff; font-size: 40rpx; letter-spacing: 4rpx; border: none; } .shen_title { margin-top: 40rpx; font-size: 32rpx; letter-spacing: 2rpx; display: flex; justify-content: flex-start; align-items: center; } .about { width: 32rpx; height: 32rpx; padding-right: 10rpx; } .title { margin-top: 20rpx; line-height: 56rpx; padding-left: 20rpx; font-size: 32rpx; letter-spacing: 3rpx; color: #000; } .description { width: 100%; padding: 24rpx 30rpx; background: #fff; border-radius: 10rpx; display: flex; box-sizing: border-box; flex-direction: column; } .description text { width: 100%; font-size: 28rpx; line-height: 44rpx; letter-spacing: 3rpx; } .space { width: 100%; height: 20rpx; background: #eee; } .nocontent { width: 100%; height: calc(100% - 400rpx); display: flex; justify-content: center; align-items: center; flex-direction: column; box-sizing: border-box; } .image { display: flex; justify-content: center; align-items: center; } ================================================ FILE: miniprogram/pages/detail/detail.js ================================================ const app = getApp() const db = wx.cloud.database(); const config = require("../../config.js"); const _ = db.command; let obj = '' Page({ /** * 页面的初始数据 */ data: { first_title: true, place: '', roomID: '', goodssaller: '', openid: '', imgs: [], isShow: true, status: 0, avatarUrl: '', buyerInfo: [], isExist: Boolean, address:'' }, onLoad(e) { obj = e; this.getuserdetail(); this.data.id = e.scene; this.getPublish(e.scene); if (app.openid) { this.setData({ openid: app.openid }) } else { console.log("no openid"); wx.showModal({ title: '温馨提示', content: '该功能需要注册方可使用,是否马上去注册', success(res) { if (res.confirm) { wx.navigateTo({ url: '/pages/login/login', }) } } }) return false } this.getBuyer(this.data.openid) wx.showShareMenu({ withShareTicket: true, menus: ['shareAppMessage', 'shareTimeline'] }) }, //获取买家信息 getBuyer(m) { let that = this; db.collection('user').where({ _openid: m }).get({ success: function (res) { wx.hideLoading(); that.setData({ buyerInfo: res.data[0] }) } }) }, goo(e) { var myid = this.data.openid; var sallerid = this.data.goodssaller; wx.cloud.init({ env: 'taoshaoji-46f0r', traceUser: true }); //初始化数据库 const db = wx.cloud.database(); if (myid != sallerid) { db.collection('rooms').where({ p_b: myid, p_s: sallerid }).get().then(res => { console.log(res.data); if (res.data.length > 0) { this.setData({ roomID: res.data[0]._id }) db.collection("rooms").doc(res.data[0]._id).update({ data: { deleted:0 }, }), wx.navigateTo({ url: 'room/room?id=' + this.data.roomID, }) } else { db.collection('rooms').add({ data: { p_b: myid, p_s: sallerid, deleted:0 }, }).then(res => { console.log(res) this.setData({ roomID: res._id }) wx.navigateTo({ url: 'room/room?id=' + this.data.roomID, }) }) } }) } else { wx.showToast({ title: '无法和自己建立聊天', icon: 'none', duration: 1500 }) } }, changeTitle(e) { let that = this; that.setData({ first_title: e.currentTarget.dataset.id }) }, //获取发布信息 getPublish(e) { let that = this; db.collection('publish').doc(e).get({ success: function (res) { that.setData({ collegeName: JSON.parse(config.data).college[parseInt(res.data.collegeid) + 1], publishinfo: res.data }) that.getSeller(res.data._openid) } }) }, //获取卖家信息 getSeller(m, n) { let that = this; db.collection('user').where({ _openid: m }).get({ success: function (res) { console.log(res.data[0]._openid); that.setData({ userinfo: res.data[0], goodssaller: res.data[0]._openid }) that.getBook(n) } }) }, //回到首页 home() { wx.switchTab({ url: '/pages/index/index', }) }, //回到我的 my() { wx.switchTab({ url: '/pages/my/my', }) }, //购买检测 buy() { var myid = this.data.openid; var sallerid = this.data.goodssaller; let that = this; if (myid == sallerid) { wx.showToast({ title: '自己买不了自己的噢!', icon: 'none', duration: 1500 }) return false } if (!app.openid) { wx.showModal({ title: '温馨提示', content: '该功能需要注册方可使用,是否马上去注册', success(res) { if (res.confirm) { wx.navigateTo({ url: '/pages/login/login', }) } } }) return false } if (that.data.publishinfo.deliveryid == 1) { if (that.data.place == '') { wx.hideLoading(); wx.showToast({ title: '请输入您的收货地址', icon: 'none' }) return false } } that.getStatus(); }, //获取订单状态 getStatus() { let that = this; let _id = that.data.publishinfo._id; console.log(_id); db.collection('publish').doc(_id).get({ success(e) { if (e.data.status == 0) { that.creatOrder(_id); } if (e.data.status == 1) { wx.showToast({ title: '该物品刚刚被抢光了~', icon: 'none' }) } if (e.data.status == 2) { wx.showToast({ title: '该物品已出售', icon: 'none' }) } if (e.data.status == 3) { wx.showToast({ title: '该物品已下架', icon: 'none' }) } } }) }, //创建订单 creatOrder(iid) { let that = this; db.collection('order').where({ _id: iid }).get().then(res => { console.log(res.data); if (res.data.length > 0) { that.setData({ isExist: true }) console.log("isExist:" + that.data.isExist) } else { that.setData({ isExist: false }) console.log("isExist:" + that.data.isExist) } }) wx.showModal({ title: '确认提示', content: '是否确认下单购买此商品?', success(res) { if (res.confirm) { if (!that.data.isExist) { wx.cloud.callFunction({ // 云函数名称 name: 'node', // 传给云函数的参数 data: { _id: iid, status: 1 }, success: function (res) { console.log(res) }, fail: console.error }) wx.getUserInfo({ success: function (res) { that.setData({ buyerName: res.userInfo.nickName, avatarUrl: res.userInfo.avatarUrl, }) }, fail(){ console.log("调用getUserinfo失败") } }) db.collection('publish').doc({ iid }).update({ data: { status: 1 }, success() { wx.hideLoading(); // that.getList(); db.collection('order').add({ data: { creat: new Date().getTime(), status: 1, //0在售;1买家已付款,但卖家未发货;2买家确认收获,交易完成; price: that.data.publishinfo.price, //售价 deliveryid: that.data.publishinfo.deliveryid, //0自1配 ztplace: that.data.publishinfo.place, //自提时地址 psplace: that.data.place, //配送时买家填的地址 bookinfo: { describe: that.data.publishinfo.bookinfo.describe, pic: that.data.publishinfo.bookinfo.pic, good: that.data.publishinfo.bookinfo.good, }, buyerInfo: that.data.buyerInfo, seller: that.data.publishinfo._openid, sellid: that.data.publishinfo._id, _id: that.data.publishinfo._id, }, success() { that.getAddress() that.send(that.data.goodssaller) wx.showToast({ title: '成功预订!', icon: 'success', duration: 3000 }) setTimeout(function () { wx.switchTab({ url: '/pages/index/index', }) }, 3000) }, fail() { wx.hideLoading(); wx.showToast({ title: '发生异常,请及时和管理人员联系处理', icon: 'none' }) } }) }, fail() { wx.hideLoading(); wx.showToast({ title: '操作失败', icon: 'none' }) } }) that.onLoad(obj); } else { wx.cloud.callFunction({ // 云函数名称 name: 'node', // 传给云函数的参数 data: { _id: iid, status: 1 }, success: function (res) { console.log(res) }, fail: console.error }) db.collection('publish').doc({ iid }).update({ data: { status: 1 }, success() { wx.hideLoading(); // that.getList(); wx.cloud.callFunction({ // 云函数名称 name: 'pay', // 传给云函数的参数 data: { $url: "changeO", //云函数路由参数 _id: iid, status: 1 }, success() { that.getAddress() that.send(that.data.goodssaller) wx.showToast({ title: '成功预订!', icon: 'success', duration: 3000 }) }, fail() { wx.hideLoading(); wx.showToast({ title: '发生异常,请及时和管理人员联系处理', icon: 'none' }) } }) }, fail() { wx.hideLoading(); wx.showToast({ title: '操作失败', icon: 'none' }) } }) that.onLoad(obj); } } } }) }, //发送模板消息到指定用户,推送之前要先获取用户的openid send(openid) { let that = this; wx.cloud.callFunction({ name: "sendMsg", data: { openid: openid, status: '买家已预定', //0在售;1买家已付款,但卖家未发货;2买家确认收获,交易完成; address:that.data.address, describe: that.data.publishinfo.bookinfo.describe, good: that.data.publishinfo.bookinfo.good, nickName: that.data.buyerInfo.info.nickName, color: 'red' } }).then(res => { console.log("推送消息成功", res) }).catch(res => { console.log("推送消息失败", res) }) }, //路由 go(e) { wx.navigateTo({ url: e.currentTarget.dataset.go, }) }, //地址输入 placeInput(e) { this.data.place = e.detail.value }, //为了数据安全可靠,每次进入获取一次用户信息 getuserdetail() { if (!app.openid) { wx.cloud.callFunction({ name: 'regist', // 对应云函数名 data: { $url: "getid", //云函数路由参数 }, success: re => { db.collection('user').where({ _openid: re.result }).get({ success: function (res) { if (res.data.length !== 0) { app.openid = re.result; app.userinfo = res.data[0]; console.log(app) } console.log(res) } }) } }) } }, //图片点击事件 img: function (event) { let arr = []; arr.push(this.data.publishinfo.bookinfo.imgs); var src = event.currentTarget.dataset.src; //获取data-src // var imgList = that.data.result.images_fileID; //图片预览 wx.previewImage({ current: src, // 当前显示图片的http链接 urls: arr[0] // 需要预览的图片http链接列表 }) }, /** * 获取地址 */ getAddress() { let that = this; if (that.data.publishinfo.deliveryid == 0) { that.setData({ address: that.data.publishinfo.place }) } else { that.setData({ address: that.data.place }) } }, }) ================================================ FILE: miniprogram/pages/detail/detail.json ================================================ { "navigationBarTitleText": "物品详情" } ================================================ FILE: miniprogram/pages/detail/detail.wxml ================================================ {{publishinfo.bookinfo.good}} ¥{{publishinfo.price}}元 发布信息 物品详情 首页 我的 {{publishinfo.status==0?'立即购买':(publishinfo.status==1?'刚刚被抢光了':(publishinfo.status==2?'已出售':'已下架'))}} 私聊 ================================================ FILE: miniprogram/pages/detail/detail.wxss ================================================ .top_contain { display: flex; flex-direction: column; padding: 24rpx; box-sizing: border-box; } .chou { padding-top: 30rpx; } .top_img { width: 100%; display: flex; justify-content: center; } .top_img image { width: 300rpx; height: 300rpx; } .title { padding-top: 30rpx; font-size: 32rpx; font-weight: 600; letter-spacing: 2rpx; } .author { padding-top: 10rpx; font-size: 26rpx; color: rgb(172, 171, 171); letter-spacing: 2rpx; } .price_box { margin-top: 20rpx; display: flex; align-items: flex-end; } .now_price { font-size: 34rpx; color: rgb(255, 1, 1); } .pre_price { padding-left: 30rpx; font-size: 28rpx; color: rgb(172, 171, 171); text-decoration: line-through; } .blank { width: 100%; height: 24rpx; background: #eee; } .center_contain { width: 100%; height: 80rpx; display: flex; box-sizing: border-box; padding: 0 100rpx; justify-content: space-around; } .c_title { font-size: 30rpx; width: 140rpx; height: 100%; display: flex; letter-spacing: 2rpx; align-items: center; justify-content: center; } .title_on { font-size: 32rpx; font-weight: 600; color: #000; border-bottom: 4rpx solid #fbbd08; } .user_box { width: 100%; height: 148rpx; display: flex; padding: 24rpx; align-items: center; justify-content: space-between; box-sizing: border-box; } .user_box image { width: 100rpx; height: 100rpx; border-radius: 50%; } .des_box { height: 100%; width: 450rpx; display: flex; flex-direction: column; align-items: flex-start; justify-content: space-around; padding: 10rpx 0; } .user_name { font-size: 32rpx; letter-spacing: 2rpx; } .local_box { display: flex; align-items: center; } .local_box image { width: 30rpx; height: 30rpx; } .local_box view { padding-left: 5rpx; font-size: 28rpx; letter-spacing: 2rpx; color: rgb(150, 150, 150); } .sex { width: 100rpx; height: 100%; display: flex; justify-content: center; align-items: center; } .sex image { width: 50rpx; height: 50rpx; border-radius: 50%; } .notes_box { width: 100%; padding: 24rpx 24rpx 0 24rpx; display: flex; box-sizing: border-box; } .notes { width: 100%; background: rgb(238, 238, 238); color: #aaa; padding: 20rpx 20rpx 10rpx 20rpx; border-radius: 10rpx; display: flex; box-sizing: border-box; flex-direction: column; } .notes_text { letter-spacing: 2rpx; font-size: 28rpx; line-height: 45rpx; padding-bottom: 10rpx; } .time_box { width: 100%; padding: 24rpx 24rpx 0 24rpx; display: flex; box-sizing: border-box; justify-content: space-between; } .kind { font-size: 28rpx; letter-spacing: 2rpx; } .time { font-size: 28rpx; letter-spacing: 2rpx; color: #8c9aa8; } .deliver_box { width: 100%; padding: 24rpx 24rpx 0 24rpx; display: flex; box-sizing: border-box; justify-content: space-between; } .deliver_first { display: flex; align-items: center; } .deliver_title { font-size: 28rpx; letter-spacing: 2rpx; } .deliver_kind { font-size: 28rpx; letter-spacing: 2rpx; color: #a5a5a5; } .deliver_place { font-size: 28rpx; letter-spacing: 2rpx; } .palceInput_box { width: 100%; padding: 24rpx 24rpx 0 24rpx; display: flex; box-sizing: border-box; justify-content: center; } .palceInput_box input { width: 100%; height: 66rpx; border: 1rpx solid #eee; border-radius: 10rpx; font-size: 26rpx; padding: 0 20rpx; letter-spacing: 2rpx; } .detail_contain { width: 100%; padding: 24rpx; display: flex; margin: 0; flex-direction: column; box-sizing: border-box; } .detail_card { display: flex; width: 100%; box-sizing: border-box; padding: 30rpx 0; justify-content: space-between; } .detail_border { border-bottom: 1rpx solid #eee; } .detail_title { width: 20%; font-size: 28rpx; letter-spacing: 2rpx; line-height: 45rpx; } .detail_content { width: 78%; font-size: 27rpx; letter-spacing: 2rpx; line-height: 44rpx; color: #616161; } /*底部导航*/ .tabbar { width: 100%; height: 96rpx; background: #fff; opacity: 1; position: fixed; left: 0rpx; bottom: 0rpx; display: flex; padding: 10rpx; border-top: 1rpx solid #eee; align-items: center; box-sizing: border-box; z-index: 8; } .t_card { position: relative; width: 30%; height: 80rpx; display: flex; flex-direction: column; align-items: center; justify-content: center; box-sizing: border-box; } .t_card image { width: 40rpx; height: 40rpx; } .t_card text { display: flex; align-items: flex-start; justify-content: center; height: calc(100% - 50rpx); width: 100%; font-size: 24rpx; text-align: center; white-space: nowrap; padding-top: 4rpx; } .t_button { width: 100%; height: 100%; position: absolute; left: 0rpx; top: 0rpx; opacity: 0.01; z-index: 9; } .buy_box { width: 40%; height: 100%; display: flex; justify-content: center; align-items: center; box-sizing: border-box; } .buy { width: 90%; height: 70rpx; background: #fbbd08; color: #000; letter-spacing: 4rpx; font-size: 28rpx; border-radius: 35rpx; display: flex; justify-content: center; align-items: center; } .contact_box { z-index: 9; position: fixed; bottom: 110rpx; right: 40rpx; display: flex; width: 100rpx; flex-direction: column; align-items: center; background: rgba(255, 255, 255, 0.8); padding: 20rpx 0; border-radius: 50rpx 50rpx 20rpx 20rpx; box-shadow: 0 0 20rpx #f0f0f0 !important; } .contact_box image { width: 80rpx; height: 80rpx; } .image{ display:flex; justify-content: center; } .contact_box view { font-size: 26rpx; letter-spacing: 2rpx; margin-top: 10rpx; } .imgList { width: 100%; } .imgList .imgList-li { width: 100%; } .imgList .imgList-li .img { width: 400rpx; height: 400rpx; } ================================================ FILE: miniprogram/pages/detail/room/room.js ================================================ const app = getApp() Page({ data: { avatarUrl: './user-unlogin.png', userInfo: null, logged: false, takeSession: false, requestResult: '', //chatRoomEnvId: 'release-f8415a', chatRoomCollection: 'chatroom', chatRoomGroupId: '', chatRoomGroupName: '聊天室', // functions for used in chatroom components onGetUserInfo: null, getOpenID: null, }, onLoad: function (opentions) { // 获取用户信息 wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) { // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 wx.getUserInfo({ success: res => { this.setData({ avatarUrl: res.userInfo.avatarUrl, userInfo: res.userInfo }) } }) } } }) this.setData({ onGetUserInfo: this.onGetUserInfo, getOpenID: this.getOpenID, chatRoomGroupId: opentions.id }) wx.getSystemInfo({ success: res => { console.log('system info', res) if (res.safeArea) { const { top, bottom } = res.safeArea this.setData({ containerStyle: `padding-top: ${(/ios/i.test(res.system) ? 10 : 20) + top}px; padding-bottom: ${20 + res.windowHeight - bottom}px`, }) } }, }) }, getOpenID: async function () { if (app.openid) { return app.openid } const { result } = await wx.cloud.callFunction({ name: 'login', }) return result.openid }, onGetUserInfo: function (e) { if (!this.logged && e.detail.userInfo) { this.setData({ logged: true, avatarUrl: e.detail.userInfo.avatarUrl, userInfo: e.detail.userInfo }) } }, onGetUserInfo: function (e) { if (!this.logged && e.detail.userInfo) { this.setData({ logged: true, avatarUrl: e.detail.userInfo.avatarUrl, userInfo: e.detail.userInfo }) } }, onShareAppMessage() { return { title: '聊天室', path: '/pages/detail/room/room', } }, go(){ wx.navigateTo({ url: '/pages/message/message', }) } }) ================================================ FILE: miniprogram/pages/detail/room/room.json ================================================ { "usingComponents": { "chatroom": "/components/chatroom/chatroom" } } ================================================ FILE: miniprogram/pages/detail/room/room.wxml ================================================ ================================================ FILE: miniprogram/pages/detail/room/room.wxss ================================================ .container { height: 98%; position: absolute; /* top: 0; */ bottom: 0; left: 0; right: 0; padding-top: 80rpx; padding-bottom: 30rpx; width: 100%; display: flex; flex-direction: column; } .space { width: 100%; height: 15rpx; background: #eee; } ================================================ FILE: miniprogram/pages/edit/edit.js ================================================ const db = wx.cloud.database(); const app = getApp(); const config = require("../../config.js"); Page({ /** * 页面的初始数据 */ data: { ids: -1, wxnum: '', qqnum: '', email: '', checked:false, campus: JSON.parse(config.data).campus, }, onChange(event) { if(event.detail==true){ wx.requestSubscribeMessage({ tmplIds: ['6DGzsKqipoPxClnbkvwnxY9GqdXoLordLRdWTjJN1F0','XXmEjf37meLWQaEsOX6qkkufcVH-YKAL3cHyY9Lru0Q'], //这里填入我们生成的模板id success(res) { console.log('授权成功', res) }, fail(res) { console.log('授权失败', res) } }) } this.setData({ checked: event.detail, }); }, choose(e) { let that = this; that.setData({ ids: e.detail.value }) //下面这种办法无法修改页面数据 /* this.data.ids = e.detail.value;*/ }, onLoad() { this.getdetail(); }, getdetail() { let that = this; db.collection('user').where({ _openid: app.openid }).get({ success: function(res) { let info = res.data[0]; that.setData({ phone: info.phone, qqnum: info.qqnum, wxnum: info.wxnum, email: info.email, ids: info.campus.id, _id: info._id }) }, fail() { wx.showToast({ title: '获取失败', icon: 'none' }) let e = setTimeout( wx.navigateBack({}), 2000 ) } }) }, wxInput(e) { this.data.wxnum = e.detail.value; }, qqInput(e) { this.data.qqnum = e.detail.value; }, emInput(e) { this.data.email = e.detail.value; }, getUserInfo(e) { let that = this; console.log(e); let test = e.detail.errMsg.indexOf("ok"); if (test == '-1') { wx.showToast({ title: '请授权后方可使用', icon: 'none', duration: 2000 }); } else { that.setData({ userInfo: e.detail.userInfo }) that.check(); } }, //校检 check() { let that = this; //校检手机 let phone = that.data.phone; if (phone == '') { wx.showToast({ title: '请先获取您的电话', icon: 'none', duration: 2000 }); return false } //校检校区 let ids = that.data.ids; let campus = that.data.campus; if (ids == -1) { wx.showToast({ title: '请先获取您的校区', icon: 'none', duration: 2000 }); } //校检邮箱 let email = that.data.email; if (!(/^\w+((.\w+)|(-\w+))@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+).[A-Za-z0-9]+$/.test(email))) { wx.showToast({ title: '请输入常用邮箱', icon: 'none', duration: 2000 }); return false; } //校检QQ号 let qqnum = that.data.qqnum; if (qqnum !== '') { if (!(/^\s*[.0-9]{5,11}\s*$/.test(qqnum))) { wx.showToast({ title: '请输入正确QQ号', icon: 'none', duration: 2000 }); return false; } } //校检微信号 let wxnum = that.data.wxnum; if (wxnum !== '') { if (!(/^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$/.test(wxnum))) { wx.showToast({ title: '请输入正确微信号', icon: 'none', duration: 2000 }); return false; } } wx.showLoading({ title: '正在提交', }) db.collection('user').doc(that.data._id).update({ data: { phone: that.data.phone, campus: that.data.campus[that.data.ids], qqnum: that.data.qqnum, email: that.data.email, wxnum: that.data.wxnum, info: that.data.userInfo, updatedat: new Date().getTime(), }, success: function(res) { console.log(res) db.collection('user').doc(that.data._id).get({ success: function(res) { app.userinfo = res.data; app.openid = res.data._openid; wx.hideLoading(); wx.showToast({ title: '修改成功', icon: 'success' }) }, }) }, fail() { wx.hideLoading(); wx.showToast({ title: '注册失败,请重新提交', icon: 'none', }) } }) }, }) ================================================ FILE: miniprogram/pages/edit/edit.json ================================================ { "usingComponents": {} } ================================================ FILE: miniprogram/pages/edit/edit.wxml ================================================ 修改资料 当前选择:{{campus[ids].name}} 请选择您所在校区 授权接收订单消息通知 使用申明 1. 请确保微信号、qq号和邮箱百分百有效,之后将用于发送实时订单通知。 2. 在未经您同意及确认之前,本程序不会将您的注册信息用于任何其它商业目的。 3. 本程序将对您所提供的资料进行严格的管理及保护,本程序将使用相应的技术,防止您的个人资料丢失、被盗用或遭篡改。 4. 请您放心使用! ================================================ FILE: miniprogram/pages/edit/edit.wxss ================================================ .top-bg { position: absolute; top: 0rpx; left: 0rpx; width: 100%; height: 460rpx; background:#fbbd08; background-repeat: no-repeat; background-size: 100%; } .contain { position: absolute; top: 30rpx; left: 0rpx; width: 100%; padding: 0rpx 40rpx 0rpx 40rpx; box-sizing: border-box; } .card { border-radius: 32rpx; width: 100%; background: #fff; padding: 50rpx 60rpx; box-sizing: border-box; box-shadow: 0 0 20rpx #eee; } .title { width: 100%; text-align: center; font-size: 40rpx; font-weight: 600; letter-spacing: 6rpx; } .phone { justify-content: space-between; margin-top: 45rpx; width: 100%; height: 92rpx; background: #f1f3f8; border-radius: 10rpx; text-align: left; padding: 0 20rpx 0 36rpx; box-sizing: border-box; font-size: 32rpx; display: flex; align-items: center; color: #8c9aa8; border: none; } .phone::after { border: none; } .campus { margin-top: 24rpx; width: 100%; height: 92rpx; background: #f1f3f8; border-radius: 10rpx; text-align: left; padding: 0 20rpx 0 36rpx; box-sizing: border-box; font-size: 32rpx; display: flex; align-items: center; justify-content: space-between; color: #8c9aa8; } .right { width: 30rpx; height: 30rpx; } .contact { margin-top: 24rpx; width: 100%; height: 92rpx; background: #f1f3f8; border-radius: 10rpx; text-align: left; padding: 0 36rpx; box-sizing: border-box; font-size: 32rpx; display: flex; align-items: center; justify-content: space-between; color: #8c9aa8; } .contact input { width: 100%; height: 100%; } .pache { font-size: 32rpx; color: #8c9aa8; } .confirm { margin-top: 50rpx; width: 100%; height: 100rpx; display: flex; justify-content: center; align-items: center; background:linear-gradient(120deg, #e0c3fc 0%, #8ec5fc 100%); border-radius: 60rpx; color: #fff; font-size: 40rpx; letter-spacing: 4rpx; box-shadow: 0 0 20rpx #eee; border: none; } .confirm::after { border: none; } .shen_title { margin-top: 40rpx; font-size: 32rpx; letter-spacing: 2rpx; display: flex; justify-content: flex-start; align-items: center; } .about { width: 32rpx; height: 32rpx; padding-right: 10rpx; } .des { padding-left: 30rpx; padding-top: 20rpx; font-size: 26rpx; color: #acacac; letter-spacing: 2rpx; line-height: 42rpx; } ================================================ FILE: miniprogram/pages/help/help.js ================================================ var app = getApp(); var db = wx.cloud.database(); Page({ /** * 页面的初始数据 */ data: { list: [{ title: '小程序为什么会插入广告?', id: 0, des: ['对于本程序的正常运行,成本支出有以下几个方面', '1、程序部署上线,每年都需要微信认证300元。', '2、目前小程序每日CDN流量资费5元每天。', '3、云开发套餐,目前使用的是50元每月的套餐。', '小程序完全公益,不存在盈利目的,插入广告仅仅是为了本小程序的正常运行,望理解'], check: true, }, { title: '该程序收费吗?', id: 1, des: ['本程序是完全的公益项目,永久承诺不收取任何中介费,您可以随心所欲的发布自己的闲置物品和购买。如过您觉得本小程序不错,欢迎各位支持打赏我们,请我们喝阔落。'], check: false, }, { title: '该程序是做什么的?', id: 2, des: ['本程序主要是方便吉林大学珠海学院的同学发布自己不要了的二手书籍或者物品。', '如果您是其它学校的同学,可以访问【关于程序】页面,根据说明给自己学校也部署一个' ], check: false, }, { title: '本程序的通知形式?', id: 3, des: ['对于买家下单时,我们通过微信服务消息通知和邮件发送订单信息给卖家,通知与您联系完成交易', '当交易状态中途取消时,也会通过微信服务信息通知于您', '您也可以在订单详情页面通过买(卖)家留下的联系方式第一时间联系,这样更能提高效率'], check: false, }, { title: '为什么要留下联系方式?', id: 4, des: ['本程序交易完全由交易双方沟通。', '除非程序出现问题导致交易故障,平台不参与任何交易'], check: false, }, { title: '小程序发现异常(bug)怎么办?', id: 5, des: ['点击客服加群或关注公众号反馈,我们会有专人为您服务。您还可以向我们提出意见或者建议,我们会争取将小程序做得更好!!!希望我们能够一起打造一个完美的二手交易平台。'], check: false, }, ] }, onReady() {}, show(e) { var that = this; let ite = e.currentTarget.dataset.show; let list = that.data.list; if (!ite.check) { list[ite.id].check = true; } else { list[ite.id].check = false; } that.setData({ list: list }) }, //跳转页面 go(e) { wx.navigateTo({ url: e.currentTarget.dataset.go }) }, onLoad() { }, }) ================================================ FILE: miniprogram/pages/help/help.json ================================================ { "navigationBarTitleText": "使用说明", "navigationBarBackgroundColor": "#ffffff", "navigationBarTextStyle": "black" } ================================================ FILE: miniprogram/pages/help/help.wxml ================================================ {{item.id+1}}.{{item.title}} ================================================ FILE: miniprogram/pages/help/help.wxss ================================================ .contain { width: 100%; padding: 30rpx 30rpx; box-sizing: border-box; } .top { display: flex; justify-content: space-between; align-items: center; height: 50rpx; margin-top: 20rpx; } .title { font-size: 32rpx; font-weight: 600; letter-spacing: 2rpx; width: calc( 100% - 60rpx); line-height: 50rpx; } .ico { width: 50rpx; height: 50rpx; } .descontain { margin-top: 30rpx; background: #f8f8f8; border-radius: 15rpx; width: 100%; padding: 14rpx 24rpx 24rpx 24rpx; box-sizing: border-box; } .destext { padding-top: 10rpx; font-size: 29rpx; line-height: 44rpx; color: #a7adb8; letter-spacing: 1rpx; } .contains { width: 100%; padding-bottom: 30rpx; border-bottom: 1rpx solid #f8f8f8; } .bottom { left: 0rpx; bottom: 0rpx; right: 0rpx; position: fixed; align-items: center; display: flex; width: 100%; height: 100rpx; box-shadow: 0 0 24rpx rgba(0, 0, 0, 0.212); } button { width: 49%; height: 100%; background: #fff; display: flex; justify-content: center; align-items: center; border: none; } button::after { border: none; } .btxt { padding-left: 20rpx; font-size: 34rpx; letter-spacing: 2rpx; } .center { font-weight: 2%; border-right: 2rpx solid #a7adb8; height: 32rpx; } ================================================ FILE: miniprogram/pages/index/index.js ================================================ const app = getApp() const db = wx.cloud.database(); const config = require("../../config.js"); const _ = db.command; Page({ data: { college: JSON.parse(config.data).college, collegeCur: -2, showList: false, scrollTop: 0, nomore: false, adShow: false, list: [], banner: '', indexTip: '', openid: app.openid }, // 用户点击右上角分享给好友,要先在分享好友这里设置menus的两个参数,才可以分享朋友圈 onShareAppMessage: function () { wx.showShareMenu({ withShareTicket: true, menus: ['shareAppMessage', 'shareTimeline'] }) }, //用户点击右上角分享朋友圈 onShareTimeline: function () { return { title: '', query: { key: value }, imageUrl: '' } }, onLoad() { this.listkind(); this.getbanner(); }, //监测屏幕滚动 onPageScroll: function (e) { this.setData({ scrollTop: parseInt((e.scrollTop) * wx.getSystemInfoSync().pixelRatio) }) }, //获取上次布局记忆 listkind() { let that = this; wx.getStorage({ key: 'iscard', success: function (res) { that.setData({ iscard: res.data }) }, fail() { that.setData({ iscard: true, }) } }) }, //布局方式选择 changeCard() { let that = this; if (that.data.iscard) { that.setData({ iscard: false }) wx.setStorage({ key: 'iscard', data: false, }) } else { that.setData({ iscard: true }) wx.setStorage({ key: 'iscard', data: true, }) } }, //跳转搜索 search() { wx.navigateTo({ url: '/pages/search/search', }) }, //类别选择 collegeSelect(e) { this.setData({ collegeCur: e.currentTarget.dataset.id - 1, scrollLeft: (e.currentTarget.dataset.id - 3) * 100, showList: false, }) this.getList(); }, //选择全部 selectAll() { this.setData({ collegeCur: -2, scrollLeft: -200, showList: false, }) this.getList(); }, //展示列表小面板 showlist() { let that = this; if (that.data.showList) { that.setData({ showList: false, }) } else { that.setData({ showList: true, }) } }, getList() { console.log("调用了getlist") let that = this; if (that.data.collegeCur == -2) { var collegeid = _.neq(-2); //除-2之外所有 } else { var collegeid = that.data.collegeCur + '' //小程序搜索必须对应格式 } db.collection('publish').where({ status: 0, dura: _.gt(new Date().getTime()), collegeid: collegeid }).orderBy('creat', 'desc').limit(20).get({ success: function (res) { wx.stopPullDownRefresh(); //暂停刷新动作 if (res.data.length == 0) { that.setData({ nomore: true, list: [], }) return false; } if (res.data.length < 20) { that.setData({ nomore: true, page: 0, list: res.data, }) } else { that.setData({ page: 0, list: res.data, nomore: false, }) } } }) }, more() { let that = this; if (that.data.nomore || that.data.list.length < 20) { return false } let page = that.data.page + 1; if (that.data.collegeCur == -2) { var collegeid = _.neq(-2); //除-2之外所有 } else { var collegeid = that.data.collegeCur + '' //小程序搜索必须对应格式 } db.collection('publish').where({ status: 0, dura: _.gt(new Date().getTime()), collegeid: collegeid }).orderBy('creat', 'desc').skip(page * 20).limit(20).get({ success: function (res) { if (res.data.length == 0) { that.setData({ nomore: true }) return false; } if (res.data.length < 20) { that.setData({ nomore: true }) } that.setData({ page: page, list: that.data.list.concat(res.data) }) }, fail() { wx.showToast({ title: '获取失败', icon: 'none' }) } }) }, onReachBottom() { this.more(); }, //下拉刷新 onPullDownRefresh() { this.getList(); }, gotop() { wx.pageScrollTo({ scrollTop: 0 }) }, //跳转详情 detail(e) { let that = this; wx.navigateTo({ url: '/pages/detail/detail?scene=' + e.currentTarget.dataset.id, }) }, //获取轮播 getbanner() { let that = this; db.collection('banner').where({}).get({ success: function (res) { that.setData({ banner: res.data[0].list }) } }) }, //跳转轮播链接 goweb(e) { console.log(e.currentTarget.dataset.web.url) wx.navigateTo({ url: '/pages/web/web?url=' + e.currentTarget.dataset.web.url, }) }, onShareAppMessage() { return { title: JSON.parse(config.data).share_title, imageUrl: JSON.parse(config.data).share_img, path: '/pages/start/start' } }, onShow() { this.getList(), this.getTip() }, getTip() { let that = this db.collection('Tip').where({}).get({ success: function (res) { that.setData({ indexTip: res.data[0].tip }) console.log("zhelishixiaoxi" + res) }, }) }, }) ================================================ FILE: miniprogram/pages/index/index.json ================================================ { "enablePullDownRefresh": true } ================================================ FILE: miniprogram/pages/index/index.wxml ================================================ 搜索想要的物品,例如:杯子 全部 {{item.name}} {{item.name}}