royalrick / weapp Goto Github PK
View Code? Open in Web Editor NEW微信小程序服务端 SDK (for Golang)
Home Page: https://pkg.go.dev/github.com/medivhzhan/weapp/v3
License: Apache License 2.0
微信小程序服务端 SDK (for Golang)
Home Page: https://pkg.go.dev/github.com/medivhzhan/weapp/v3
License: Apache License 2.0
付款完毕之后 前端的同步回调并不会通知具体的状态,开发者希望调用查询接口来确认状态不是好吗?
// 获取小程序前点调用支付接口所需参数 params, err := payment.GetParams(res.AppID, res.MchID, res.NonceStr, res.PrePayID, time.Now()) if err != nil { // handle error return }
the paySign should use apikey not MchID, and here is the wechat app pay document
框架实现accessToken统一管理,默认可以用内存版本,分布式部署的可以实现redis接口版本,几乎所有接口都要携带取该字段
fmt.Printf("%#v", ntf),ntf 里面的 Sign 需要哪个字段去签名对比
// 拼凑签名
func createSignature(parts ...string) string {
sort.Strings(parts)
raw := sha1.Sum([]byte(strings.Join(parts, "")))
return hex.EncodeToString(raw[:])
}
sort.Strings(parts)
导致不符合 sha1( rawData + session_key ) 格式,签名校验失败
路径:weapp/message/template/template.go
// Mesage 模版消息体
type Mesage map[string]interface{}
Mesage应为Message
var (
req model_wechat.AuthReq
)
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 500, nil, "c.ShouldBindJSON:"+err.Error())
return
}
resp, err := weapp.Login(config.WechatConfig.Appid, config.WechatConfig.Secret, req.Code)
if err != nil {
response.Error(c, 500, nil, "weapp.Login:"+err.Error())
return
}
if err := resp.GetResponseError(); err != nil {
response.Error(c, 500, nil, "weapp.Login resp.GetResponseError:"+err.Error())
return
}
//处理用户信息
raw := sha1.Sum([]byte(req.UserInfo.RawData + resp.SessionKey))
wxUserInfo, err := weapp.DecryptUserInfo(resp.SessionKey, req.UserInfo.RawData, req.UserInfo.EncryptedData, hex.EncodeToString(raw[:]), req.UserInfo.IV)
if err != nil {
response.Error(c, 500, nil, "weapp.DecryptUserInfo:"+err.Error())
return
}
//处理用户手机号信息
var (
mobile *weapp.Mobile
)
//如果手机信息不为空
if !reflect.DeepEqual(req.PhoneInfo, model_wechat.PhoneInfo{}) {
mobile, err = weapp.DecryptMobile(resp.SessionKey, req.PhoneInfo.EncryptedData, req.PhoneInfo.Iv)
if err != nil {
response.Error(c, 500, nil, "weapp.DecryptMobile:"+err.Error()) //这里会报错 weapp.DecryptMobile:invalid character '¼' looking for beginning of value 每次character会变化,随机性的出现
return
}
}
go get github.com/medivhzhan/weapp@v2: no matching versions for query "v2"
server.go line 321
switch res.MsgType {
case MsgText:
msg := new(TextMessageResult)
if err := unmarshal(raw, tp, msg); err != nil {
return nil, err
}
if srv.textMessageHandler != nil {
srv.textMessageHandler(msg)
}
case MsgImg:
msg := new(ImageMessageResult)
if err := unmarshal(raw, tp, msg); err != nil {
return nil, err
}
if srv.imageMessageHandler != nil {
srv.imageMessageHandler(msg)
}
case MsgCard:
msg := new(CardMessageResult)
if err := unmarshal(raw, tp, msg); err != nil {
return nil, err
}
if srv.cardMessageHandler != nil {
srv.cardMessageHandler(msg)
}
希望添加返回值,将客服消息转发至网页版客服
源文档:
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/customer-message/trans.html
{
"ToUserName": "gh_123456789abc",
"FromUserName": "o7esq5PHRGBQYmeNyfG064wEFVpQ",
"CreateTime": "1620963428",
"MsgType": "event",
"Event": "subscribe_msg_sent_event",
"SubscribeMsgSentEvent": {
"List": {
"TemplateId": "BEwX0BO-T3MqK3Uc5oTU3CGBqzjpndk2jzUf7VfExd8",
"MsgID": "1864323726461255680",
"ErrorCode": "0",
"ErrorStatus": "success"
}
}
}
然后源码里面是绑定一个数组,真的是伤不起
现在开发SaaS系统的公司越来越多,对第三方平台接口的需要也越来越大,希望给予考虑。
非常感谢作者提供这样优秀的库,我们已经在项目中使用了。
最近微信升级了模板消息功能,什么时候能集成下呢?
`// Package template 模版消息
package subscribe
import (
// "fmt"
"encoding/json"
"errors"
"net/http"
"strings"
"github.com/medivhzhan/weapp"
"github.com/medivhzhan/weapp/util"
)
const (
sendAPI = "/cgi-bin/message/subscribe/send"
)
// Message 模版消息体
type Message map[string]interface{}
// Send 发送模板消息
//
// @openid 接收者(用户)的 openid
// @template 所需下发的模板消息的id
// @page 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
// @formid 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id
// @DaTa 模板内容,不填则下发空模板
// @emphasisKeyword 模板需要放大的关键词,不填则默认无放大
func Send(openid, template, page string, data Message,token string) error {
api, err := util.TokenAPI(weapp.BaseURL+sendAPI, token)
if err != nil {
return err
}
for key := range data {
data[key] = Message{"value": data[key]}
}
body := map[string]interface{}{
"touser": openid,
"template_id": template,
"page": page,
"data": data,
}
payload, err := json.Marshal(body)
if err != nil {
return err
}
res, err := http.Post(api, "application/json", strings.NewReader(string(payload)))
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode != 200 {
err = errors.New(weapp.WeChatServerError)
return err
}
var resp weapp.Response
if err = json.NewDecoder(res.Body).Decode(&resp); err != nil {
return err
}
// fmt.Println("订阅消息:",api,string(payload),resp)
if resp.Errcode != 0 {
return errors.New(resp.Errmsg)
}
return nil
}
`
您好,因为图片都不在服务器端存储,而是放到专门的图片存储服务器上面,目前IMGSecCheck 方法需要给本地图片的路径,是否能支持远程的图片URL,谢谢
微信退款时,在校验微信订单号和商户订单号是否传了其中一个时,却使用了商户退款单号进行判断
现有的XXX接口(比如DriverLicense)接收一个filename参数。这规定了服务器必须从本地路径获取图片。而这个图片具体存放的方式是根据服务器及存储设计而变化的,很可能不在本地服务器。考虑到此处图片非常敏感,也很可能没有一个安全的外部URL可以供微信服务器访问到。
建议在api设计上,最大程度与服务器的存储设计以及安全考量进行解藕,提议加入:
XXXByData接口,定义:(以DriverLicense举例)
func DriverLicenseByReader(token string, r io.Reader) (*DrivingLicenseResponse, error)
func (c *memory) Set(key string, val interface{}, timeout time.Duration) {
timer := time.AfterFunc(timeout, func() {
_ = c.Delete(key)
})
item := memoryItem{val, timer}
c.store.Store(key, item)
}
const time.Second time.Duration = 1000000000 // 1s
这里的timeout 应该是 timeout*time.Second
直播模块的商品id上来就有了,这不合理。
curl -F [email protected] "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=XXXXX” 这个接口没有支持到。
看文档没有预设微信支付相关的接口,不知道是不是没有打算在包中添加相关sdk
求问可以把token相关的cache公开或者增加一个set的接口吗?比如第三方平台开发小程序获取token的方式不太一样,可能需要手动进行一下设置。。
现在库里的所有 http 请求都是直接调用 http.Get
或者 http.Post
的,如果想要在做这些请求前后做一些操作没法实现,所以希望能添加大致这样的功能:
// HTTPClient 是一个泛化的 http.Client
type HTTPClient interface {
Do(req *http.Request) (*http.Response, error)
}
然后添加例如
LoginEx(client HTTPClient, appID, secret, code string) (lresp LoginResponse, err error)
Login 则改造成
func Login(appID, secret, code string) (lres LoginResponse, err error) {
return LoginEx(http.DefaultClient, appID, secret, code)
}
如接受我可以提交 PR,谢谢
安卓正常,ios提示:小程序提供的服务出现故障 请稍后再试
// PayCallback ...
// @title PayCallback
// @description 微信支付回调接口
// @router /pay_callback [get]
func (c *WechatPayController) PayCallback() {
// 必须在下单时指定的 notify_url 的路由处理器下
err := payment.HandlePaidNotify(c.Ctx.ResponseWriter, c.Ctx.Request, func(ntf payment.PaidNotify) (bool, string) { return true, "" })
logs.Error("pay_callback error:", err)
...
}
您好,我在使用支付相关接口时,发现该处理函数缺少资源释放操作,还请确认下。
// HandlePaidNotify 处理支付结果通知
func HandlePaidNotify(res http.ResponseWriter, req *http.Request, fuck func(PaidNotify) (bool, string)) error {
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return err
}
var ntf paidNotify
if err := xml.Unmarshal(body, &ntf); err != nil {
return err
}
if err := ntf.Check(); err != nil {
return err
}
replay := newReplay(fuck(ntf.PaidNotify))
b, err := xml.Marshal(replay)
if err != nil {
return err
}
res.WriteHeader(http.StatusOK)
_, err = res.Write(b)
return err
}
默认 info
,会打印 secret 等敏感信息
需要更新一下官方文档链接吗
请问最近有更新计划?小程序项目准备从PHP转GO,期待更加完善的SDK,类似PHP的Easywechat...
昨天从3.4.0升级到3.6.1,我只自定义了缓存,没自定义获取token的方法,结果当调用一个需要token的方法时就会死循环无限获取token。
赶紧回退了,刚看了看最近的改动,token部分确实有不少,还没来得及仔细看问题出在哪。
请问什么时候可以支持支付相关接口呢?现在两个版本共存总是觉得有点奇怪,没别的意思
文档里的 SubscribeMessageData{} 结构没有找到,当把消息模版参数转换为字符给 data 时,消息发送失败
刚发现生成的小程序码在开发者工具中打开,URL中的 &
字符被转义成 \u0026
了,搜了下资料,json 包会默认转义特殊字符。
res, err := coder.UnlimitedAppCode(wechat.GetToken())
defer res.Body.Close()
if err != nil {
util.CheckError(err, 41007)
}
qrName := fmt.Sprintf("storage/images/qr/qr_item_%d_%d.jpeg", itemId, memberId)
f, _ := os.Create(qrName)
defer f.Close()
contents, err := ioutil.ReadAll(res.Body)
io.Copy(f, bytes.NewReader(contents))
按上面这种方式保存,图片无法打开
package main
import (
"fmt"
"net/http"
"github.com/medivhzhan/weapp/v3/server"
)
func main() {
http.HandleFunc("/sub", func(w http.ResponseWriter, r *http.Request) {
srv, err := server.NewServer("appid", "", "", "mchID", "apiKey", false, nil)
if err != nil {
fmt.Printf("init server error: %s", err)
}
// 当用户触发订阅消息弹框后
srv.OnSubscribeMsgPopup(func(msg *server.SubscribeMsgPopupEvent) {
// Do something cool ...
})
// 当用户通过设置界面改变订阅消息事件内容
srv.OnSubscribeMsgChange(func(msg *server.SubscribeMsgChangeEvent) {
// Do something cool ...
})
if err := srv.Serve(w, r); err != nil {
fmt.Println(r)
return
}
})
http.ListenAndServe(":8082", nil)
}
I0918 09:11:59.652611 6 AuthUser.go:150] DecryptPhoneNumber params weAppSessionKey: DhdCKRNjmngLstiaaVQR6A== , encryptedPhone: h3NDDnf39Z76MgcWrgNzisq04RXWaF8Yr+3x+dRPbcn1v5akN71LyRlh9CzM2qHlSMEYiuLSNnHfdoZowcQmrJrK1b/15NUaO4u2dS0JBogKhoL3DPc+If+dXRnX8stCbJR6YvR4Md5hu2n/Oycf3nU/VwI5CmXL9um8g+66tUGJzQRhzDD2uHAjlZLpz1r2lZkUcRr56YRfq6/92FLA5w== ,ivPhone: LXxdk1o3Oa0N0+XgZvAUDg==
�[31m2018/09/18 09:11:59 [Recovery] 2018/09/18 - 09:11:59 panic recovered:
Host: aws-serverless-go-api.com
09:11:59
Accept: /
Accept-Encoding: gzip, deflate
Accept-Language: zh-cn
Content-Type: application/json
Referer: https://servicewechat.com/wx1c44031bd4ac4f81/0/page-frame.html
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89 MicroMessenger/6.7.2 NetType/WIFI Language/zh_CN
X-Amzn-Trace-Id: Root=1-5ba0c15f-da768fce121aab102b9eb018
X-Forwarded-For: 27.154.25.254
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Golambdaproxy-Apigw-Context: {"accountId":"638953167227","resourceId":"cr4s8x","stage":"qa","requestId":"e5f8cd0a-bb22-11e8-b4bb-4b38a3060d33","identity":{"cognitoIdentityPoolId":"","accountId":"","cognitoIdentityId":"","caller":"","apiKey":"","sourceIp":"27.154.25.254","cognitoAuthenticationType":"","cognitoAuthenticationProvider":"","userArn":"","userAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS
X-Golambdaproxy-Apigw-Stagevars: null
runtime error: slice bounds out of range
/usr/local/go/src/runtime/panic.go:502 (0x42ae08)
/usr/local/go/src/runtime/panic.go:35 (0x429cbd)
/go/src/vendor/github.com/medivhzhan/weapp/util/crypto.go:56 (0x93d510)
/go/src/vendor/github.com/medivhzhan/weapp/util/crypto.go:123 (0x93d510)
/go/src/vendor/github.com/medivhzhan/weapp/weapp.go:118 (0x93dab6)
版本: v3.6.0
package main
import (
"fmt"
"log"
"github.com/medivhzhan/weapp/v3"
"github.com/medivhzhan/weapp/v3/auth"
)
func main() {
sdk := weapp.NewClient("your-appid", "your-secret")
cli := sdk.NewAuth()
// 登录凭证校验
rsp, err := cli.Code2Session(&auth.Code2SessionRequest{})
if err != nil {
log.Fatal(err)
}
// 检查微信是否返回错误
if err := rsp.GetResponseError(); err != nil {
log.Println(err)
}
fmt.Println(rsp)
}
Code2Session 中调用 conbineURI,conbineURI 中调用 AccessToken,AccessToken 中又调用了 conbineURI (当 accessTokenGetter == nil 时)
https://github.com/medivhzhan/weapp/blob/master/analysis.go#L38
实际调用接口后返回的结构化的数据是 { "id": 3, "name": "25-29岁", "value": 34811 }
// SubscribeMessage 订阅消息
type SubscribeMessage struct {
ToUser string `json:"touser"`
TemplateID string `json:"template_id"`
Page string `json:"page,omitempty"`
MiniprogramState MiniprogramState `json:"miniprogram_state,omitempty"`
Data string `json:"data"`
}
这里的Data是string 但是下面的是SubscribeMessageData?
sender := weapp.SubscribeMessage{
ToUser: mpOpenID,
TemplateID: "template-id",
Page: "mock/page/path",
MiniprogramState:cli.MiniprogramStateDeveloper, // 或者: "developer"
Data:cli.SubscribeMessageData{
"first-key": {
Value: "value",
},
"second-key": {
Value: "value",
},
},
}
cli.MiniprogramStateDeveloper 这个引用的路径不正确 这里的是weapp.MiniprogramStateDeveloper
每次小程序用户提交解密数据后 后台解析报这个错 每次 'x1a'这个地方会有变化. invalid character '\x1a' looking for beginning of value
小程序直播会接入吗
func (cli *Client) DecryptUserInfo(sessionKey, rawData, encryptedData, signature, iv string) (*UserInfo, error) {
if encrypt.NewSigner(false, rawData, sessionKey).CompareWith(signature) {
return nil, errors.New("failed to validate signature")
}
// 对比签名
func (sign *Signer) CompareWith(signature string) bool {
return signature == sign.Sign()
}
为什么两个signature相等却判断为签名错误呢,代码应该写错了吧
https://github.com/medivhzhan/miniapp/blob/2e94375d23200d943a2f9cde2444862f7b114706/decrypt.go#L113
"feeds_img": "XXX" // 官方收录封面
live.go定义的struct 为int
解析报错 json: cannot unmarshal string into Go struct field LiveRoomItem.room_info.feeds_img of type int
希望可以帮忙删除一下这个issue,谢谢。
你好,
当用户登录方法Login
时, 小程序若绑定了开放平台, 应该还需要返回unionid
字段.
可否Login时也返回这个? 或者说Login时就返回struct.
谢啦
操作系统:win10
golang版本:1.14.1
正确传入 sessionkey , encrypted_data,iv 返回以下内容
invalid character '¶' looking for beginning of value
decryptUserData方法不一定用于封装的四个方法(DecryptMobile、DecryptShareInfo、DecryptUserInfo、DecryptRunData),还有其他的用途
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.