golang 调用 网易云 滑块验证码 demo

用法PHP示例主要代码

	session_start();
	$verifier = new NECaptchaVerifier(YIDUN_CAPTCHA_ID, new SecretPair(YIDUN_CAPTCHA_SECRET_ID, YIDUN_CAPTCHA_SECRET_KEY));
	$validate = $_POST['NECaptchaValidate']; // 获得验证码二次校验数据
	if(get_magic_quotes_gpc()){// PHP 5.4之前默认会将参数值里的 \ 转义成 \\,这里做一下反转义
        $validate = stripcslashes($validate);
    }
	$user = "{'user':123456}"; // 当前用户信息,值可为空

    /** @var $result bool */
	$result = $verifier->verify($validate, $user);

SDK接入文档: http://support.dun.163.com/documents/15588062143475712?docId=69218161355051008 

 

 github示例地址

git remote -v

origin https://github.com/yidun/captcha-php-demo (fetch)

origin https://github.com/yidun/captcha-php-demo (push)

改为golang版本

* SecretPair.go

package captcha

type SecretPair struct {
	SecretId string
	SecretKey string
}

func NewSecretPair(secretId string, secretKey string) *SecretPair {
	return &SecretPair{
		SecretId: secretId,
		SecretKey: secretKey,
	}
}

https://stackoverflow.com/questions/16895294/how-to-set-timeout-for-http-get-requests-in-golang

golang http client

timeout := time.Duration(5 * time.Second)
client := http.Client{
    Timeout: timeout,
}
client.Get(url)

* NECaptchaVerifier.go

package captcha

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/Unknwon/com"
	"io/ioutil"
	"math/rand"
	"net/http"
	"sort"
	"strings"
	"time"
)

// @ref: https://github.com/yidun/captcha-php-demo
// @ref: http://support.dun.163.com/documents/15588062143475712?docId=69218161355051008
const (
	YIDUN_CAPTCHA_API_VERSION = "v2"
	YIDUN_CAPTCHA_API_TIMEOUT = 5
	YIDUN_CAPTCHA_API_URL     = "http://c.dun.163yun.com/api/v2/verify"
)

type NECaptchaVerifier struct {
	CaptchaID  string
	SecretPair SecretPair
}

type NEResponse struct {
	Msg    string `json:"msg"`
	Result bool   `json:"result"`
	Error  int    `json:"error"`
}

// 发起二次校验请求
// @param validate string 二次校验数据
// @param user 用户信息
func (this *NECaptchaVerifier) Verify(validate string, user string) (*NEResponse, error) {
	params := map[string]string{}
	params["captchaId"] = this.CaptchaID
	params["validate"] = validate
	params["user"] = user
	params["secretId"] = this.SecretPair.SecretId
	params["version"] = YIDUN_CAPTCHA_API_VERSION
	// time in millisecond
	params["timestamp"] = fmt.Sprintf("%d", time.Now().Unix()*1000)
	// random int
	rand.Seed(time.Now().UnixNano())
	params["nonce"] = fmt.Sprintf("%d", rand.Uint32())
	params["signature"] = genSignature(this.SecretPair.SecretKey, params)

	var result string
	var err error
	var ne NEResponse
	result, err = this.sendHttpResquest(params)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("send http request error: %s", err.Error()))
	}
	fmt.Println(result)

	// json deocode
	err = json.Unmarshal([]byte(result), &ne)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("json decode error: %s", err.Error()))
	}
	return &ne, err
}

// 计算参数签名
// @param secretKey 密钥对key
// @param params 请求参数
func genSignature(secretKey string, params map[string]string) string {
	var keys []string
	for key, _ := range params {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	buf := bytes.NewBufferString("")
	for _, key := range keys {
		buf.WriteString(key + params[key])
	}
	buf.WriteString(secretKey)
	fmt.Printf("signature=%s\n", buf.String())

	has := md5.Sum(buf.Bytes())
	return fmt.Sprintf("%x", has)
}

/**
 * 发送http请求
 * @param $params 请求参数
 */
func (*NECaptchaVerifier) sendHttpResquest(params map[string]string) (string, error) {
	client := &http.Client{
		Timeout: time.Second * YIDUN_CAPTCHA_API_TIMEOUT,
	}

	url := YIDUN_CAPTCHA_API_URL

	postString := http_build_query(params)
	req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(postString))
	if err != nil {
		return "", err
	}
	fmt.Printf("POST %s\n", url)
	fmt.Printf("[%s]\n", postString)
	for key, value := range params {
		fmt.Printf("%s = %s\n", key, value)
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Length", fmt.Sprintf("%d", len(postString)))
	req.Header.Set("Upgrade-Insecure-Requests", "1")

	resp, err := client.Do(req)
	defer resp.Body.Close()

	if err != nil {
		return "", err
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(body), nil
}

func http_build_query(params map[string]string) string {
	var a []string
	for k, v := range params {
		a = append(a, fmt.Sprintf("%s=%s", k, com.UrlEncode(v)))
	}
	return strings.Join(a, "&")
}

* SecretPair.go

package captcha

type SecretPair struct {
	SecretId  string
	SecretKey string
}

func NewSecretPair(secretId string, secretKey string) *SecretPair {
	return &SecretPair{
		SecretId:  secretId,
		SecretKey: secretKey,
	}
}

* Captcha.go

package captcha

import (
	"fmt"
	"github.com/kataras/iris/core/errors"
	"github.com/spf13/viper"
)

type Captcha struct {
	Validate string // $_POST["NECaptchaValidate"]
	Data     string // "{'user':123456}"
}

func (this *Captcha) Verify() (bool, error) {
	var verifier = NECaptchaVerifier{
		CaptchaID: viper.GetString("YIDUN_CAPTCHA_ID"),
		SecretPair: *NewSecretPair(
			viper.GetString("YIDUN_CAPTCHA_SECRET_ID"),
			viper.GetString("YIDUN_CAPTCHA_SECRET_KEY")),
	}
	fmt.Println(verifier)
	if len(this.Validate) < 1 {
		return false, errors.New("NECaptchaValidate can't be empty")
	}
	result, err := verifier.Verify(this.Validate, this.Data)
	fmt.Println(result)
	if err != nil {
		fmt.Println(err)
		return false, err
	}
	// {"msg":"PARAM_ERROR","result":false,"error":419}
	if !result.Result {
		return result.Result, errors.New(
			fmt.Sprintf("error:%d, msg:%s", result.Error, result.Msg))
	}
	// {"msg":OK, "result":true, "error"0}
	return result.Result, nil
}

 

* index.html





    
    
    易盾验证码-DEMO
    
    



php -S 0.0.0.0:8082

浏览器访问 http://127.0.0.1:8082

golang 调用 网易云 滑块验证码 demo_第1张图片

 

 

 

你可能感兴趣的:(golang)