下图是获取支付宝小程序用户信息的流程图

 由于支付宝小程序更新所以后来申请的小程序没有alipay.user.info.share的访问权限,所以后台的工作就是根据前台的code请求授权平台换取userid, 然后再根据项目需求,前端获取详细信息返回给后台储存到数据库里。

本来想用拼接字符串的方式加参数,但是就是报sign有问题的错,然后问了客服,给我截了下面这张图 

然后查go里面 encode的方法url.values的Encode()方法好像最方便,所以建议参数用url.values方法添加

    v := url.Values{}
	v.Set("app_id", env.ZfbAppId)// 项目的appid
	v.Set("charset", "UTF-8")
	v.Set("code", authCode)// 前端传的code
	v.Set("grant_type", "authorization_code")
	v.Set("method", "alipay.system.oauth.token")
	v.Set("sign_type", "RSA2")
	v.Set("timestamp", now)//时间 2006-01-02 15:04:05 格式
	v.Set("version", "1.0")

 然后就是签名,签名就是去掉表示签名的sign字段,然后去掉空字段、空格再把字段根据ASCII排序最后根据要求的格式加密再Base64一下就行了,由于没有官方go语言的SDK,所以需要自行签名

我用的是普通公钥方式,下图是支付宝需要的签名的加密编码方式

 百度了很久最后找别人总结出了一个方法。。。

func GetLoginSign(param url.Values, privateKey *rsa.PrivateKey) (string, error) {
	//param就是url参数,privateKey 是私钥
	if param == nil {
		param = make(url.Values, 0)
	}

	var pList = make([]string, 0, 0)
	for key := range param {
		var value = strings.TrimSpace(param.Get(key)) //*去空格 签名必须有的一步
		if len(value) > 0 {
			pList = append(pList, key+"="+value)
		}
	}
	sort.Strings(pList) //*根据ASCII码排序 签名必须有的一步
	var src = strings.Join(pList, "&")
	sig, err := crypto4go.RSASignWithKey([]byte(src), privateKey, crypto.SHA256)
	if err != nil {
		return "", err
	}
	s := base64.StdEncoding.EncodeToString(sig)
	return s, nil
}

这个方法的私钥也需要处理一下

	privateKey, _ = crypto4go.ParsePKCS1PrivateKey(crypto4go.FormatPKCS1PrivateKey(zfbPrivateKey))// zfbPrivateKey 是配置的私钥,privateKey是上面方法需要的参数

方法返回的就是需要的sign 

然后就是加上sign字段,再对url进行encode,最后请求,再根据需要处理返回的参数

    v.Set("sign", s) //s是GetLoginSign方法返回的sign
	sth := v.Encode()//对请求的参数进行encode
	aUrl := "https://openapi.alipay.com/gateway.do?" + sth
	resp, err := http.Get(aUrl)
	if err != nil {
		response.Response(c, 201, &gin.H{"message": "login taken 获取失败"})
		return
	}
	body, _ := ioutil.ReadAll(resp.Body)