分类 江西小程序 下的文章

江西小程序-打造一款简单猜拳小程序(go+websocket+redis+mysql+小程序前端)(一)

本文环境基于centOS6.5

安装go1.8

下载go安装包,解压到/usr/local/,

cd /usr/local/src
wget http://golangtc.com/static/go/1.8/go1.8.linux-amd64.tar.gz
tar -zxvf go1.8.linux-amd64.tar.gz
mv go ../

设置环境变量,GOROOT和GOPATH

GOROOT就是go的安装路径

GOPATH
go install/go get和 go的工具等会用到GOPATH环境变量.
GOPATH是作为编译后二进制的存放目的地和import包时的搜索路径 (其实也是你的工作目录, 你可以在src下创建你自己的go源文件, 然后开始工作)。
GOPATH之下主要包含三个目录: bin、pkg、src
bin目录主要存放可执行文件; pkg目录存放编译好的库文件, 主要是*.a文件; src目录下主要存放go的源文件
不要把GOPATH设置成go的安装路径,

GOPATH可以是一个目录列表, go get下载的第三方库, 一般都会下载到列表的第一个目录里面
需要把GOPATH中的可执行目录也配置到环境变量中, 否则你自行下载的第三方go工具就无法使用了, 操作如下:
export $PATH:$GOPATH/bin

在/var/下新建go-project作为工作目录,

综合以上,做如下操作:

vi /etc/profile

GOROOT=/usr/local/go

export GOROOT

PATH=$PATH:$GOROOT/bin

GOPATH=/var/go-project

PATH=$PATH:$GOPATH/bin

export PATH

source /etc/profile
go version
go version go1.8 linux/amd64

测试是否安装成功

新建一个hello.go文件

package main

import "fmt"

func main() {
    fmt.Printf("hello, world\n")
}

通过 go 工具运行它

go run hello.go
hello, world

看到了“hello, world”信息,那么Go已被正确安装。

下载官方websocket包

使用的golang官方的net包下面的websocket,地址:
https://github.com/golang/net

go get github.com/golang/net

其中有一些注意事项:

Golang 官方的子仓库,应该使用 import "golang.org/x/net/websocket" 这种方式导入,通过 go
get 方式下载。如果使用 git clone,clone下来的目录,也应该使用
src/golang.org/x/net/websocket 这样的目录,所以做法就特别蛋疼

要先

go get github.com/golang/net/websocket

然后

mv github.com/golang/net/websocket golang.org/x/net/websocket

然后import的时候用 golang.org/x/net/websocket

特别的蛋疼,难道是不想人用github上面的?因为上面的不是稳定版本

于是,将/var/go-project/src/github.com/golang/net重命名成了/var/go-project/src/golang.org/x/net

然后,go install golang.org/x/net/websocket

简单实现websocket广播的server端代码(server.go):

package main
import (
    "golang.org/x/net/websocket"
    "fmt"
    "log"
    "net/http"
)

var (  
    JSON          = websocket.JSON              // codec for JSON  
    Message       = websocket.Message           // codec for string, []byte  
    ActiveClients = make(map[ClientConn]string) // map containing clients  
    User          = make(map[string]string)  
)  

type ClientConn struct {  
    websocket *websocket.Conn  
    clientIP string  
}

func echoHandler(ws *websocket.Conn) {
    var err error  
    for {  
        var reply string  
        if err = websocket.Message.Receive(ws, &reply); err != nil {  
            fmt.Println("can't receive")  
            break  
        }  

        client := ws.Request().RemoteAddr  
        fmt.Println("Client connected:", client) 

        sockCli := ClientConn{ws, client}  
        ActiveClients[sockCli] = client 
        fmt.Println("Number of clients connected:", len(ActiveClients))

        if ActiveClients[sockCli] != "" {  
            for cs, na := range ActiveClients {  
                if na != "" {  
                    if err = websocket.Message.Send(cs.websocket, reply); err != nil {  
                        log.Println("Could not send message to ", cs.clientIP, err.Error())  
                    }  
                }  
            }  
        }
    }  

}

func main() {
    http.Handle("/echo", websocket.Handler(echoHandler))
    http.Handle("/", http.FileServer(http.Dir(".")))

    err := http.ListenAndServe(":8080", nil)

    if err != nil {
        panic("ListenAndServe: " + err.Error())
    }
}

运行服务端代码

go run server.go

客户端html代码,置于nginx下,通过域名访问,打开两个浏览器,可以实现简单聊天功能

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
    <title>Sample of websocket with golang</title>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>

    <script>
      $(function() {
        var ws = new WebSocket("ws://xxx.xx.xxx.xx:8080/echo");
        ws.onmessage = function(e) {
          $('<li>').text(event.data).appendTo($ul);
        };
        var $ul = $('#msg-list');
        $('#sendBtn').click(function(){
          var data = $('#name').val();
          ws.send(data);
        });
      });
    </script>
</head>
<body>
<input id="name" type="text"/>
<input type="button" id="sendBtn" value="send"/>
<ul id="msg-list"></ul>
</body>
</html>

江西小程序-微信小程序中远程调用接口及使用md5加密

背景:使用微信小程序调用https接口,md5加密当前时间戳,然后再md5(时间戳的md5+约定好的key)生成token,来实现简单校验。服务端接口,判断时间戳是否在有效时间内,然后生成token对比传过来的token。

微信小程序使用的开发语言是js,网上找到js实现md5加密的代码,融合进小程序内使用

在utils目录下新建md5.js文件

function safeAdd (x, y) {
  var lsw = (x & 0xFFFF) + (y & 0xFFFF)
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
  return (msw << 16) | (lsw & 0xFFFF)
}

/*
* Bitwise rotate a 32-bit number to the left.
*/
function bitRotateLeft (num, cnt) {
  return (num << cnt) | (num >>> (32 - cnt))
}

/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5cmn (q, a, b, x, s, t) {
  return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b)
}
function md5ff (a, b, c, d, x, s, t) {
  return md5cmn((b & c) | ((~b) & d), a, b, x, s, t)
}
function md5gg (a, b, c, d, x, s, t) {
  return md5cmn((b & d) | (c & (~d)), a, b, x, s, t)
}
function md5hh (a, b, c, d, x, s, t) {
  return md5cmn(b ^ c ^ d, a, b, x, s, t)
}
function md5ii (a, b, c, d, x, s, t) {
  return md5cmn(c ^ (b | (~d)), a, b, x, s, t)
}

/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function binlMD5 (x, len) {
  /* append padding */
  x[len >> 5] |= 0x80 << (len % 32)
  x[(((len + 64) >>> 9) << 4) + 14] = len

  var i
  var olda
  var oldb
  var oldc
  var oldd
  var a = 1732584193
  var b = -271733879
  var c = -1732584194
  var d = 271733878

  for (i = 0; i < x.length; i += 16) {
    olda = a
    oldb = b
    oldc = c
    oldd = d

    a = md5ff(a, b, c, d, x[i], 7, -680876936)
    d = md5ff(d, a, b, c, x[i + 1], 12, -389564586)
    c = md5ff(c, d, a, b, x[i + 2], 17, 606105819)
    b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330)
    a = md5ff(a, b, c, d, x[i + 4], 7, -176418897)
    d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426)
    c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341)
    b = md5ff(b, c, d, a, x[i + 7], 22, -45705983)
    a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416)
    d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417)
    c = md5ff(c, d, a, b, x[i + 10], 17, -42063)
    b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162)
    a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682)
    d = md5ff(d, a, b, c, x[i + 13], 12, -40341101)
    c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290)
    b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329)

    a = md5gg(a, b, c, d, x[i + 1], 5, -165796510)
    d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632)
    c = md5gg(c, d, a, b, x[i + 11], 14, 643717713)
    b = md5gg(b, c, d, a, x[i], 20, -373897302)
    a = md5gg(a, b, c, d, x[i + 5], 5, -701558691)
    d = md5gg(d, a, b, c, x[i + 10], 9, 38016083)
    c = md5gg(c, d, a, b, x[i + 15], 14, -660478335)
    b = md5gg(b, c, d, a, x[i + 4], 20, -405537848)
    a = md5gg(a, b, c, d, x[i + 9], 5, 568446438)
    d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690)
    c = md5gg(c, d, a, b, x[i + 3], 14, -187363961)
    b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501)
    a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467)
    d = md5gg(d, a, b, c, x[i + 2], 9, -51403784)
    c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473)
    b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734)

    a = md5hh(a, b, c, d, x[i + 5], 4, -378558)
    d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463)
    c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562)
    b = md5hh(b, c, d, a, x[i + 14], 23, -35309556)
    a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060)
    d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353)
    c = md5hh(c, d, a, b, x[i + 7], 16, -155497632)
    b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640)
    a = md5hh(a, b, c, d, x[i + 13], 4, 681279174)
    d = md5hh(d, a, b, c, x[i], 11, -358537222)
    c = md5hh(c, d, a, b, x[i + 3], 16, -722521979)
    b = md5hh(b, c, d, a, x[i + 6], 23, 76029189)
    a = md5hh(a, b, c, d, x[i + 9], 4, -640364487)
    d = md5hh(d, a, b, c, x[i + 12], 11, -421815835)
    c = md5hh(c, d, a, b, x[i + 15], 16, 530742520)
    b = md5hh(b, c, d, a, x[i + 2], 23, -995338651)

    a = md5ii(a, b, c, d, x[i], 6, -198630844)
    d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415)
    c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905)
    b = md5ii(b, c, d, a, x[i + 5], 21, -57434055)
    a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571)
    d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606)
    c = md5ii(c, d, a, b, x[i + 10], 15, -1051523)
    b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799)
    a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359)
    d = md5ii(d, a, b, c, x[i + 15], 10, -30611744)
    c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380)
    b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649)
    a = md5ii(a, b, c, d, x[i + 4], 6, -145523070)
    d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379)
    c = md5ii(c, d, a, b, x[i + 2], 15, 718787259)
    b = md5ii(b, c, d, a, x[i + 9], 21, -343485551)

    a = safeAdd(a, olda)
    b = safeAdd(b, oldb)
    c = safeAdd(c, oldc)
    d = safeAdd(d, oldd)
  }
  return [a, b, c, d]
}

/*
* Convert an array of little-endian words to a string
*/
function binl2rstr (input) {
  var i
  var output = ''
  var length32 = input.length * 32
  for (i = 0; i < length32; i += 8) {
    output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF)
  }
  return output
}

/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binl (input) {
  var i
  var output = []
  output[(input.length >> 2) - 1] = undefined
  for (i = 0; i < output.length; i += 1) {
    output[i] = 0
  }
  var length8 = input.length * 8
  for (i = 0; i < length8; i += 8) {
    output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32)
  }
  return output
}

/*
* Calculate the MD5 of a raw string
*/
function rstrMD5 (s) {
  return binl2rstr(binlMD5(rstr2binl(s), s.length * 8))
}

/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
function rstrHMACMD5 (key, data) {
  var i
  var bkey = rstr2binl(key)
  var ipad = []
  var opad = []
  var hash
  ipad[15] = opad[15] = undefined
  if (bkey.length > 16) {
    bkey = binlMD5(bkey, key.length * 8)
  }
  for (i = 0; i < 16; i += 1) {
    ipad[i] = bkey[i] ^ 0x36363636
    opad[i] = bkey[i] ^ 0x5C5C5C5C
  }
  hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8)
  return binl2rstr(binlMD5(opad.concat(hash), 512 + 128))
}

/*
* Convert a raw string to a hex string
*/
function rstr2hex (input) {
  var hexTab = '0123456789abcdef'
  var output = ''
  var x
  var i
  for (i = 0; i < input.length; i += 1) {
    x = input.charCodeAt(i)
    output += hexTab.charAt((x >>> 4) & 0x0F) +
    hexTab.charAt(x & 0x0F)
  }
  return output
}

/*
* Encode a string as utf-8
*/
function str2rstrUTF8 (input) {
  return unescape(encodeURIComponent(input))
}

/*
* Take string arguments and return either raw or hex encoded strings
*/
function rawMD5 (s) {
  return rstrMD5(str2rstrUTF8(s))
}
function hexMD5 (s) {
  return rstr2hex(rawMD5(s))
}
function rawHMACMD5 (k, d) {
  return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d))
}
function hexHMACMD5 (k, d) {
  return rstr2hex(rawHMACMD5(k, d))
}

function md5 (string, key, raw) {
  if (!key) {
    if (!raw) {
      return hexMD5(string)
    }
    return rawMD5(string)
  }
  if (!raw) {
    return hexHMACMD5(key, string)
  }
  return rawHMACMD5(key, string)
}

module.exports.md5 = md5

根据微信小程序文档

模块化 我们可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者
exports 才能对外暴露接口。

最后通过 module.exports.md5 = md5 将方法暴露出来,然后通过以下方式调用md5方法

var utilMd5 = require("../../utils/md5.js");
var d=new Date();
var callTime = parseInt(d.getTime()/1000);
console.log(utilMd5.md5(callTime));

完整的调用api接口示例如下:
如pages/index/index.js

var utilMd5 = require("../../utils/md5.js")

var app = getApp()
Page({
  data: {
    matchList: {},
    userInfo: {}
  },
  onLoad: function () {
    var d=new Date()
    var callTime = parseInt(d.getTime()/1000)
    var token = utilMd5.md5(utilMd5.md5(callTime)+"key")
    wx.request({
      url: 'https://api.xxxxx.com/xxxxxx',
      data: {},
      header: {
          'content-type': 'application/x-www-form-urlencoded',
          'callTime':callTime,
          'token':token
      },
      success: function(res) {
        console.log(res.data)
      },
      complete: function(res) {
        console.log(res.message)
      }
    })
  }
})

江西小程序-小程序七大能力

小程序七大能力解读:

线下扫码:用户可以在小程序中使用扫一扫。

对话分享:用户可以分享小程序或其中的任何一个页面给好友或群聊。

消息通知:商户可以发送模板消息给接受过服务的用户,用户可以在小程序内联系客服,支持文字和图片。

小程序切换:用户可以在使用小程序的过程中快速返回聊天。

历史列表:用户使用过的小程序会被放入列表,方便下次使用。

公众号关联:微信小程序可与公众号进行关联。

搜索查找:用户可直接根据名称或品牌搜索小程序。

江西小程序-给swoole的websocket server加上ssl

微信小程序的websocket必须是wss协议,
于是捣鼓给swoole的websocket server加入SSL支持。

第一步,准备好自己的域名,备案等,就不啰嗦了。

第二步,到阿里云申请免费的证书服务。
QQ图片20161221171227.png
按照提示一步步进行,最后下载得到一个pem文件和一个key文件。
将文件上传到服务器上。

第三步,将证书对应的域名,解析到swoole服务器的IP上。

第四步,重新编译安装swoole,加入ssl支持

cd swoole-src
phpize
./configure --enable-openssl
make && make install

当然,要先确保你的系统安装了openssl,php也安装了openssl扩展

第五步,编码,创建支持ssl的websocket服务

$ws = new swoole_websocket_server("0.0.0.0", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$key_dir = "/usr/local/ca";

$ws->set(array(
    'worker_num' => 4,
    'ssl_cert_file' => $key_dir.'/xxxxxxxxxxxx.pem',
    'ssl_key_file' => $key_dir.'/xxxxxxxxxxxx.key',
));

以上,基本实现了一个wss协议的websocket服务

ps:如基于web来连接wss,web也需要是https

nginx配置HTTPS支持

修改Nginx配置文件,让其包含新标记的证书和私钥:

server {
    server_name YOUR_DOMAINNAME_HERE;
    listen 443;
    ssl on;
    ssl_certificate /usr/local/nginx/conf/xxxxxxxxxxxx.pem;
    ssl_certificate_key /usr/local/nginx/conf/xxxxxxxxxxxx.key;
}

重启nginx。

crt文件可以直接用我们的pem文件替换

江西小程序-微信小程序基础概念介绍

产品定位及功能介绍

微信小程序是一种全新的连接用户与服务的方式,它可以在微信内被便捷地获取和传播,同时具有出色的使用体验。

小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。

框架提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,可以让开发者可以方便的聚焦于数据与逻辑上。

框架 提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。

微信小程序接入指南文档:https://mp.weixin.qq.com/debug/wxadoc/introduction/index.html

微信小程序设计指南文档:https://mp.weixin.qq.com/debug/wxadoc/design/index.html

微信小程序开发文档:https://mp.weixin.qq.com/debug/wxadoc/dev/index.html

微信小程序平台运营规范:https://mp.weixin.qq.com/debug/wxadoc/product/index.html